|
|
1.1 ! root 1: ! 2: /* ! 3: * ! 4: * dimpress - cleaned up and modified code borrowed from di10. ! 5: * ! 6: * ! 7: * troff post-processor for Imagen printers. Output is written in ! 8: * version 2.0 Impress, although it does still work for earlier versions. ! 9: * Raster files in either the old format or in Imagen's Rst format can ! 10: * be used for character generation. Drawing functions are handled by ! 11: * the routines in file impdraw.c. I rewrote most of those routines so they ! 12: * use the graphics primitives avaliable in version 1.9 (and later) Impress. ! 13: * If you're printer is still running older systems you'll probably need ! 14: * to get the original version of draw.c and use it instead. ! 15: * ! 16: * All the code should work properly for any printer that accepts Impress. ! 17: * By default I've got things set up for the 8/300, but you can use the ! 18: * -T option to select a different printer. If you choose a new printer ! 19: * name not supported under the -T option you'll probably want to add code ! 20: * to do the proper initialization. There really are only six variables ! 21: * that need to be changed for different printers. They include realdev, ! 22: * penwidth, pres, xoff, yoff, and possibly bitdir. The printer variables ! 23: * are defined in dimpress.h (PR_INIT) and that's what's used to initialize ! 24: * the prdata[] array. If you make changes just be sure that the list ends ! 25: * with an entry that has its prname field set to NULL. ! 26: * ! 27: * ! 28: * output language from troff: ! 29: * all numbers are character strings ! 30: * ! 31: * sn size in points ! 32: * fn font as number from 1-n ! 33: * cx ascii character x ! 34: * Cxyz funny char xyz. terminated by white space ! 35: * Hn go to absolute horizontal position n ! 36: * Vn go to absolute vertical position n (down is positive) ! 37: * hn go n units horizontally (relative) ! 38: * vn ditto vertically ! 39: * nnc move right nn, then print c (exactly 2 digits!) ! 40: * (this wart is an optimization that shrinks output file size ! 41: * about 35% and run-time about 15% while preserving ascii-ness) ! 42: * Dt ...\n draw operation 't': ! 43: * Dl x y line from here by x,y ! 44: * Dc d circle of diameter d with left side here ! 45: * De x y ellipse of axes x,y with left side here ! 46: * Da x y r arc counter-clockwise by x,y of radius r ! 47: * D~ x y x y ... wiggly line by x,y then x,y ... ! 48: * nb a end of line (information only -- no action needed) ! 49: * b = space before line, a = after ! 50: * p new page begins -- set v to 0 ! 51: * #...\n comment ! 52: * x ...\n device control functions: ! 53: * x i init ! 54: * x T s name of device is s ! 55: * x r n h v resolution is n/inch ! 56: * h = min horizontal motion, v = min vert ! 57: * x p pause (can restart) ! 58: * x s stop -- done for ever ! 59: * x t generate trailer ! 60: * x f n s font position n contains font s ! 61: * x H n set character height to n ! 62: * x S n set slant to N ! 63: * ! 64: * Subcommands like "i" are often spelled out like "init". ! 65: * ! 66: */ ! 67: ! 68: #include <stdio.h> ! 69: #include <signal.h> ! 70: #include <math.h> ! 71: #include <ctype.h> ! 72: #include <time.h> ! 73: ! 74: #include "gen.h" /* general purpose definitions */ ! 75: #include "ext.h" /* external variable definitions */ ! 76: #include "init.h" /* just used for BITDIR definition */ ! 77: #include "rast.h" /* raster file definitions */ ! 78: #include "dev.h" /* typesetter and font descriptions */ ! 79: #include "impcodes.h" /* Impress 2.0 opcode definitions */ ! 80: #include "dimpress.h" /* defs just used by this program */ ! 81: #include "spectab.h" ! 82: ! 83: ! 84: /* ! 85: * ! 86: * A few names we'll need when we're printing files. devname[] is what troff ! 87: * thought was going to be the output device while realdev[] is the name ! 88: * of the printer we're really going to be using. There may be occasions when ! 89: * we want to send the output to a given printer (*realdev) but we want to ! 90: * use the raster tables that were built for a different one (*rastdev). If ! 91: * rastdev isn't NULL we'll assume that this is the name of the device's ! 92: * raster files that we want to use. In otherwords if *rastdev hasn't been ! 93: * set by an option *realdev will be used in combination with *bitdir to ! 94: * define *rastdir. ! 95: * ! 96: */ ! 97: ! 98: ! 99: char devname[20] = ""; /* troff's target printer */ ! 100: char *realdev = NULL; /* name of the printer we're really using */ ! 101: char *rastdev = NULL; /* use raster tables made for this guy */ ! 102: ! 103: ! 104: /* ! 105: * ! 106: * There's a bunch of stuff we'll want to know about the raster files we're ! 107: * planning on using for this job. The most important, obviously is where ! 108: * they're located. The routines that access the raster files all assume ! 109: * they're in directory *rastdir, so it better be set up right before we ! 110: * try to print anything. I've decided to have this program build up the ! 111: * *rastdir string from *bitdir and either *rastdev or *realdev. All this ! 112: * stuff will be done after the options are read. One of the reasons I'm ! 113: * doing things this way is because we could want to do something like ! 114: * print a troff file generated for the APS-5 on an Imprint-10 using the ! 115: * raster files built for an 8/300. While that may sound rediculous the ! 116: * raster tables can use up a lot of disk space and we may not want to ! 117: * waste the space keeping complete sets of raster files for two or three ! 118: * different devices. Anyway we should be able to do something reasonable ! 119: * no matter what devices and raster files are requested. ! 120: * ! 121: * *bitdir is initialized to BITDIR (file init.h) and can be changed using ! 122: * the -B option. The raster files for a particular device, say the 8/300 ! 123: * which is being called i300, will be found in directory *bitdir/rasti300. ! 124: * It's defined in file glob.c because resident font routines need the ! 125: * directory. ! 126: * ! 127: * We'll also need to know the format of the raster files we're using before ! 128: * we can have any characters printed. rastformat keeps track of which ! 129: * style is being used. It's initialized in routine rastsetup() using ! 130: * info in file *rastdir/RASTDATA - if it exists. Right now if rastsetup() ! 131: * can't read the RASTDATA file it assumes that the raster files are the ! 132: * old versetec format and have a resolution of 240 dots per inch. I've ! 133: * done things this way just to make sure we can use the post-processor ! 134: * with the old raster files without having to add an appropriate RASTDATA ! 135: * file to the directory. Eventually it may not be a bad idea to just ! 136: * quit if we can't read the file. ! 137: * ! 138: */ ! 139: ! 140: ! 141: int rastformat; ! 142: ! 143: ! 144: /* ! 145: * ! 146: * Although I originally had ideas about not using a RASTERLIST file, I now ! 147: * think it's probably a pretty good idea to use one. We could get around the ! 148: * missing size problems by linking raster files for unavailble sizes to ones ! 149: * we really have. That approach would cost more in downloading glyphs, but ! 150: * more we'd probably be able to place the glyphs a little better because ! 151: * we'd be able to set the character advance separately. Anyway it's really ! 152: * not all that clear which approach is better. I've allowed for use of a ! 153: * RASTERLIST file (routine rastlist()) but I've also decided that if it's ! 154: * not there we'll continue on with the program assuming we have every size ! 155: * that jobs ask for. If the job asks for a non-existent file it will die ! 156: * in routine getrastdata(). ! 157: * ! 158: * The following data structures are used to keep track of any RASTLIST ! 159: * data we may have read. If maxrast is zero then there isn't any data ! 160: * and we'll assume, when we do the lookups, that all fonts can be printed ! 161: * in any size. ! 162: * ! 163: */ ! 164: ! 165: ! 166: int maxrast = 0; /* number of RASTERLIST font entries */ ! 167: Sizedata sizedata[MAXFONTS]; /* available raster size data */ ! 168: ! 169: ! 170: /* ! 171: * ! 172: * Standard things needed after we've read troff's font and device tables. ! 173: * The binary files are all built by makedev and will be looked for in the ! 174: * target printer's dev directory located in *fontdir. Actually that's not ! 175: * quite right. There are mapping problems, both for fonts and characters, ! 176: * that will exist if we try and use font files for a device that don't ! 177: * exactly map into the raster files that are being used. For example if ! 178: * we used the character code field in the normal APS-5 font tables when ! 179: * we print jobs generated for the APS-5 we'd be guaranteed to get garbage. ! 180: * To get around that problem I have the post-processor first look in ! 181: * *rastdir for the dev directory. If it's not there then we look in *fontdir. ! 182: * ! 183: */ ! 184: ! 185: ! 186: struct dev dev; /* DESC.out starts this way */ ! 187: struct Font *fontbase[NFONT+1]; /* starts each FONT.out file */ ! 188: short *pstab; /* typesetter knows these sizes */ ! 189: int nsizes = 1; /* sizes in *pstab list */ ! 190: int nfonts; /* number of font positions */ ! 191: int smnt; /* index of first special font */ ! 192: int nchtab; /* number of special character names */ ! 193: char *chname; /* special character strings */ ! 194: short *chtab; /* used to locate character names */ ! 195: char *fitab[NFONT+1]; /* locates char info on each font */ ! 196: char *widthtab[NFONT+1]; /* widtab would be a better name */ ! 197: char *codetab[NFONT+1]; /* codes to get characters printed */ ! 198: ! 199: ! 200: /* ! 201: * ! 202: * Variables that we use to keep track of troff's requests. All these ! 203: * guys are set from values in the input files. ! 204: * ! 205: */ ! 206: ! 207: ! 208: int size = 1; /* current size - internal value */ ! 209: int font = 1; /* font position we're using now */ ! 210: int hpos = 0; /* troff's current horizontal position */ ! 211: int vpos = 0; /* same but vertically */ ! 212: int lastw = 0; /* width of the last input character */ ! 213: int lastc = 0; /* and its name (or index) */ ! 214: ! 215: ! 216: /* ! 217: * ! 218: * We'll also want to keep track of some of the same things, but for the ! 219: * target printer. ! 220: * ! 221: */ ! 222: ! 223: ! 224: int lastsize = -1; /* last internal size we used */ ! 225: int lastfont = -1; /* last font we told printer about */ ! 226: int lastx = -1; /* printer's current position */ ! 227: int lasty = -1; ! 228: ! 229: ! 230: /* ! 231: * ! 232: * The following structure is used to keep track of the fonts that are ! 233: * loaded in various positions. Both fields are filled in by routine t_fp() ! 234: * using values in the binary font files. ! 235: * ! 236: */ ! 237: ! 238: ! 239: struct { ! 240: char *name; /* name of the font loaded here */ ! 241: int number; /* its internal number */ ! 242: } fontname[NFONT+1]; ! 243: ! 244: ! 245: /* ! 246: * ! 247: * A few variables that are really just used for drawing things. Although ! 248: * they're declared here most are only really used in draw.c. The pen ! 249: * width and the step sizes can be changed by options. The step sizes DX ! 250: * and DY control how far we move horizontally or vertically between ! 251: * adjacent dots when drawing curves. They'll have no effect if we're ! 252: * using Impress graphics commands for all graphics. Decreasing DX and DY ! 253: * improves pictures but increases the size and complexity of the output ! 254: * files. Because Impress complies and prints pages on the fly you may ! 255: * not be able to draw fairly simple figures if the step sizes are too ! 256: * small. ! 257: * ! 258: */ ! 259: ! 260: ! 261: int drawdot = '.'; /* draw with this character */ ! 262: int drawsize = 1; /* shrink size by this factor */ ! 263: int penwidth = 1; /* use this as the pen diameter */ ! 264: int DX = 6; /* horiz step when using drawdot */ ! 265: int DY = 6; /* same but for vertical step */ ! 266: ! 267: ! 268: /* ! 269: * ! 270: * We may want to shift things around on the output page a little. In ! 271: * particular moving everything right on the output pages is normal because ! 272: * the left 3/8 inch or so of each page on an Imprint-10 isn't visible. ! 273: * All this stuff could be done more efficiently by defining a new ! 274: * coordinate system to match the requested offsets rather than doing ! 275: * the calculations each time. I've left things this way for now because ! 276: * that's the way we originally did stuff in di10. ! 277: * ! 278: * The xoff and yoff values are in inches while the xoffset and yoffset ! 279: * numbers are pixels. We'll set the pixel values after we're sure about ! 280: * the target printer's resolution. xoff and yoff can be changed by options. ! 281: * xfac and yfac are scaling factors used to convert coordinates in the ! 282: * input files to appropiate values in the target printers coordinate ! 283: * system. Their values are set in t_init() because we can only do it ! 284: * properly after we've gotten the printer's resolution (from options) ! 285: * and read the "x res" command in each input file. ! 286: * ! 287: */ ! 288: ! 289: ! 290: float xoff; /* shift right by this many inches */ ! 291: float yoff; /* and down by this much */ ! 292: ! 293: int xoffset; /* pixel values = xoff * pres */ ! 294: int yoffset; /* = yoff * pres */ ! 295: float xfac = 1.0; /* scaling factor for x */ ! 296: float yfac = 1.0; /* scaling factor for y */ ! 297: ! 298: ! 299: /* ! 300: * ! 301: * A few miscellaneous variable declarations. I've added landscape mode ! 302: * to the post-processor. It's requested using the -l option. Might also ! 303: * be reasonable to add a new device control command to request landscape ! 304: * mode, although I haven't done it yet. None of this stuff will work with ! 305: * printer resident fonts. ! 306: * ! 307: */ ! 308: ! 309: ! 310: int mode = PORTRAIT; /* landscape or portrait mode */ ! 311: int angle = ROT_0; /* ROT_270 for LNADSCAPE mode */ ! 312: int output = 0; /* do we do output at all? */ ! 313: int pageno = -1; /* output page number */ ! 314: int copies = 1; /* ask IPR for this many */ ! 315: float aspect = 1; /* default aspect ratio */ ! 316: int cancenter = TRUE; /* try to improve char placement? */ ! 317: int center = 0; /* for alphanumeric characters only */ ! 318: ! 319: ! 320: /* ! 321: * ! 322: * We'll really need to deal with three possibly different resolutions ! 323: * when we're printing files. The first is the resolution used by troff in ! 324: * preparing the input file. Next is the resolution of the target printer. ! 325: * Imprint-10s are 240 and 8/300s are 300 dots per inch. Finially we'll need ! 326: * or at least want to know the resolution of the raster files we're using ! 327: * to print the file. Obviously we'll get the best results when all three ! 328: * numbers agree, but no matter what we should be able to do something ! 329: * reasonable with any set of numbers. ! 330: * ! 331: */ ! 332: ! 333: ! 334: int res; /* resolution assumed in input file */ ! 335: int pres; /* resolution of the target printer */ ! 336: int rres; /* raster file resolution */ ! 337: ! 338: ! 339: /* ! 340: * ! 341: * The data about the different printers supported by the program is ! 342: * stored in prdata[]. It's initialized using PR_INIT which is defined ! 343: * in dimpress.h. The fields in structure Prdata are used to define the ! 344: * printer name, resolution, x and y offsets (in inches), and the string ! 345: * that should be used for *bitdir. ! 346: * ! 347: */ ! 348: ! 349: ! 350: Prdata prdata[] = PR_INIT; /* printer data */ ! 351: ! 352: int pr_num = PR_NUM; /* printer we're using - index in prdata[] */ ! 353: ! 354: ! 355: /* ! 356: * ! 357: * Many of the printer dependent variables can be set by several different ! 358: * options. Most times we'll want to use the -T option, but there may be ! 359: * occasions when we want to override one or more of the default values. ! 360: * These variables keep track of whether we've tried to set values by other ! 361: * options. ! 362: * ! 363: */ ! 364: ! 365: ! 366: int setpenwidth = FALSE; /* changed by the -P option */ ! 367: int setxoff = FALSE; /* -x option */ ! 368: int setyoff = FALSE; /* -y option */ ! 369: int setpres = FALSE; /* -r option */ ! 370: ! 371: ! 372: /* ! 373: * ! 374: * A few variables that are really only used if we're doing accounting. ! 375: * Much of the accounting stuff has been designed for our own use at ! 376: * MHCC and may not suit your needs. ! 377: * ! 378: */ ! 379: ! 380: ! 381: char *acctfile = NULL; /* append accounting record to this file */ ! 382: char *jacctfile = NULL; /* just a page count for this job */ ! 383: int acctpages = 0; /* charge for this many pages */ ! 384: char *username = NULL; /* guy whose running this program */ ! 385: ! 386: ! 387: /* ! 388: * ! 389: * If we're emulating another device we'll want to use the following array to ! 390: * help map font names available on that device into PostScript fonts. It's ! 391: * initialized using FONTMAP (file dpost.h) and may be changed in routine ! 392: * getfontmap(). In particular if there's a file that matches the device name ! 393: * in directory *fontdir/devpost/fontmaps, getfontmap() will use it instead of ! 394: * the default - haven't implemented it and probably never will. ! 395: * ! 396: */ ! 397: ! 398: ! 399: Fontmap fontmap[100] = FONTMAP; /* just for device emulation */ ! 400: ! 401: ! 402: /* ! 403: * ! 404: * Output and accounting FILE definitions. If you invoke this program with ! 405: * the -t option everything goes to stdout, otherwise it will be written ! 406: * to *tempfile and then passed along to Imagen's spooler using IPR. ! 407: * ! 408: */ ! 409: ! 410: char *tempfile = NULL; /* output file name if no -t option used */ ! 411: ! 412: FILE *tf = NULL; /* and Impress output goes here */ ! 413: FILE *fp_acct = stderr; /* accounting stuff written here */ ! 414: ! 415: ! 416: extern int maxdots; /* defined and used in draw.c */ ! 417: ! 418: ! 419: /*****************************************************************************/ ! 420: ! 421: ! 422: main(agc, agv) ! 423: ! 424: ! 425: int agc; ! 426: char *agv[]; ! 427: ! 428: ! 429: { ! 430: ! 431: ! 432: /* ! 433: * ! 434: * Post-processor that's used to translate troff's device independent ! 435: * output language into Impress (version 2.0 right now). A call to Imagen's ! 436: * spooling package, through IPR, is made in print_file() provided ! 437: * the output hasn't gone to stdout. Using the -t option or initializing ! 438: * tf to be stdout forces output to stdout. If there are any processing ! 439: * errors x_stat will be non-zero and done() will remove *tempfile before ! 440: * quitting. ! 441: * ! 442: */ ! 443: ! 444: ! 445: argc = agc; /* global so everyone can use them */ ! 446: argv = agv; ! 447: ! 448: prog_name = argv[0]; /* just used for error messages */ ! 449: ! 450: init_signals(); /* sets up interrupt handling */ ! 451: options(); /* command line options */ ! 452: initialize(); /* must be done after options */ ! 453: rastsetup(); /* set all the raster file stuff up */ ! 454: rastlist(); /* get availble font and size list */ ! 455: resfonts(tf); /* setup for any resident fonts */ ! 456: acct_file(); /* open accounting file - maybe */ ! 457: ! 458: arguments(); /* translate all the input files */ ! 459: t_wrapup(); /* mark the end of job for Impress */ ! 460: print_file(); /* print the file we just built */ ! 461: ! 462: done(); /* everything probably went OK */ ! 463: ! 464: } /* End of main */ ! 465: ! 466: ! 467: /*****************************************************************************/ ! 468: ! 469: ! 470: init_signals() ! 471: ! 472: ! 473: { ! 474: ! 475: ! 476: int done(); /* handles them if we're catching sigs */ ! 477: ! 478: ! 479: /* ! 480: * ! 481: * Makes sure we handle any interrupts properly. It wasn't done right ! 482: * in di10. ! 483: * ! 484: */ ! 485: ! 486: ! 487: if ( signal(SIGINT, done) == SIG_IGN ) { ! 488: signal(SIGINT, SIG_IGN); ! 489: signal(SIGQUIT, SIG_IGN); ! 490: signal(SIGHUP, SIG_IGN); ! 491: } else { ! 492: signal(SIGHUP, done); ! 493: signal(SIGQUIT, done); ! 494: } /* End else */ ! 495: ! 496: } /* End of init_signals */ ! 497: ! 498: ! 499: /*****************************************************************************/ ! 500: ! 501: ! 502: options() ! 503: ! 504: ! 505: { ! 506: ! 507: ! 508: int ch; /* option name returned from getopt */ ! 509: char *names = "u:c:tx:y:r:a:o:p:LP:n:d:F:f:B:f:R:T:AJ:"; ! 510: ! 511: extern char *optarg; /* option argument set by getopt() */ ! 512: extern int optind; ! 513: ! 514: ! 515: /* ! 516: * ! 517: * Processes the command line options. The original stuff stuff done in ! 518: * di10 has been changed a little. I've also used getopt() to scan the ! 519: * options. ! 520: * ! 521: * The most confusing options are -B and -R. The *bitdir string is the ! 522: * directory where we expect to find the raster file directories. They all ! 523: * start with "rast" and end with a device name. I've got things set up so ! 524: * that they're in /usr/lib/raster, but di10 looked for directory rasti10 ! 525: * in *fontdir (/usr/lib/font/devi10). The -B option changes the value ! 526: * of *bitdir. If you're running DWB and want this program to replace di10 ! 527: * call it using the option "-B /usr/lib/font/devi10". The -R option ! 528: * sets the value of string *rastdev. If that string isn't NULL then ! 529: * "/rast*rastdev" will be appended to the end of *bitdir to locate the ! 530: * raster file directory that we really want to use. By default rastdev is ! 531: * NULL so *realdev will be used in its place. ! 532: * ! 533: * The -c option doesn't work right now. If you want to implement it you'll ! 534: * probably just need to change the IPR system() call that's made in ! 535: * print_file(). ! 536: * ! 537: */ ! 538: ! 539: ! 540: while ( (ch = getopt(argc, argv, names)) != EOF ) { ! 541: switch ( ch ) { ! 542: case 'u': ! 543: username = optarg; ! 544: break; ! 545: ! 546: case 'c': ! 547: copies = atoi(optarg); ! 548: break; ! 549: ! 550: case 't': ! 551: tf = stdout; ! 552: break; ! 553: ! 554: case 'x': ! 555: xoff = atof(optarg); ! 556: setxoff = TRUE; ! 557: break; ! 558: ! 559: case 'y': ! 560: yoff = atof(optarg); ! 561: setyoff = TRUE; ! 562: break; ! 563: ! 564: ! 565: case 'r': ! 566: pres = atoi(optarg); ! 567: setpres = TRUE; ! 568: break; ! 569: ! 570: case 'a': ! 571: aspect = atof(optarg); ! 572: break; ! 573: ! 574: case 'o': ! 575: out_list(optarg); ! 576: break; ! 577: ! 578: case 'p': /* pixels of resolution */ ! 579: if ( (DX = DY = atoi(optarg)) <= 0 ) ! 580: DX = DY = 1; ! 581: break; ! 582: ! 583: case 'L': /* landscape mode */ ! 584: mode = LANDSCAPE; ! 585: break; ! 586: ! 587: case 'P': /* pen diameter for drawing */ ! 588: if ( (penwidth = atoi(optarg)) > 20 ) ! 589: penwidth = 20; ! 590: else if ( penwidth < 1 ) penwidth = 1; ! 591: setpenwidth = TRUE; ! 592: break; ! 593: ! 594: case 'n': /* a limit for drawing routines */ ! 595: if ( (maxdots = atoi(optarg)) <= 0 ) ! 596: maxdots = 32000; ! 597: break; ! 598: ! 599: case 'd': ! 600: if ( (debug = atoi(optarg)) == 0 ) ! 601: debug = 1; ! 602: tf = stdout; ! 603: break; ! 604: ! 605: case 'F': /* font table directory */ ! 606: fontdir = optarg; ! 607: break; ! 608: ! 609: case 'B': /* rast* directories found here */ ! 610: bitdir = optarg; ! 611: break; ! 612: ! 613: case 'f': /* use this resident font file */ ! 614: resfile = optarg; ! 615: break; ! 616: ! 617: case 'R': /* use this guys raster files */ ! 618: rastdev = optarg; ! 619: break; ! 620: ! 621: case 'T': /* target printer */ ! 622: for ( pr_num = 0; prdata[pr_num].prname != NULL; pr_num++ ) ! 623: if ( strcmp(optarg, prdata[pr_num].prname) == 0 ) ! 624: break; ! 625: if ( prdata[pr_num].prname == NULL ) ! 626: error(FATAL, "don't know printer %s", optarg); ! 627: break; ! 628: ! 629: /* These options were added for the MHCC */ ! 630: ! 631: case 'A': ! 632: x_stat |= DO_ACCT; ! 633: break; ! 634: ! 635: case 'J': ! 636: jacctfile = optarg; ! 637: x_stat |= DO_ACCT; ! 638: break; ! 639: ! 640: case '?': ! 641: error(FATAL, ""); ! 642: break; ! 643: ! 644: default: ! 645: error(FATAL, "don't know option %s", argv[1]); ! 646: break; ! 647: } ! 648: } ! 649: ! 650: argc -= optind; /* get ready for non-options args */ ! 651: argv += optind; ! 652: ! 653: } /* End of options */ ! 654: ! 655: ! 656: /*****************************************************************************/ ! 657: ! 658: ! 659: initialize() ! 660: ! 661: ! 662: { ! 663: ! 664: ! 665: char *mktemp(); ! 666: #ifdef V9 ! 667: char *getlogin(); ! 668: #endif ! 669: ! 670: ! 671: /* ! 672: * ! 673: * Much of this stuff can only be done properly after the command line ! 674: * options have been processed, so make sure it's called (from main()) ! 675: * after options(). ! 676: * ! 677: */ ! 678: ! 679: #ifdef V9 ! 680: if (username == NULL && (username = getlogin()) == NULL ) ! 681: #endif ! 682: #ifdef SYSV ! 683: if ( (username = cuserid((char *) 0)) == NULL ) ! 684: #endif ! 685: username = "???"; ! 686: ! 687: if (tf != stdout) { ! 688: tempfile = mktemp("/tmp/dimpXXXXX"); ! 689: if ((tf = fopen(tempfile, "w")) == NULL) ! 690: error(FATAL, "can't open temporary file %s", tempfile); ! 691: } /* End if */ ! 692: ! 693: if ( realdev == NULL ) ! 694: realdev = prdata[pr_num].prname; ! 695: ! 696: if ( setpres == FALSE ) ! 697: pres = prdata[pr_num].pres; ! 698: ! 699: if ( setxoff == FALSE ) ! 700: xoff = prdata[pr_num].xoff; ! 701: ! 702: if ( setyoff == FALSE ) ! 703: yoff = prdata[pr_num].yoff; ! 704: ! 705: if ( setpenwidth == FALSE ) ! 706: penwidth = prdata[pr_num].penwidth; ! 707: ! 708: if ( bitdir == NULL ) ! 709: bitdir = prdata[pr_num].bitdir; ! 710: ! 711: if ( resfile == NULL ) ! 712: resfile = prdata[pr_num].prname; ! 713: ! 714: res = rres = pres; /* just to be safe */ ! 715: ! 716: xoffset = pres * xoff; /* set the pixel offsets */ ! 717: yoffset = pres * yoff; ! 718: ! 719: } /* End of initialize */ ! 720: ! 721: ! 722: /*****************************************************************************/ ! 723: ! 724: ! 725: rastsetup() ! 726: ! 727: ! 728: { ! 729: ! 730: ! 731: static char rastname[100]; /* rastdir string saved here */ ! 732: char temp[100]; /* for pathnames and reads from *fp */ ! 733: FILE *fp; /* RASTDATA and RASTLIST files */ ! 734: int ch; /* just used to skip lines in *fp */ ! 735: ! 736: ! 737: /* ! 738: * ! 739: * We'll need to know a bunch of stuff about the raster files before we can ! 740: * actually use them. First of all we need to figure out where they are. ! 741: * Strings *bitdir and either *rastdev or *realdev will be used to initialize ! 742: * *rastdir. Once we've got rastname set up we'll need to determine the ! 743: * format of the raster files and their resolution. All that stuff should ! 744: * be in file *rastdir/RASTDATA. If the file's not there or we can't read ! 745: * it we'll assume the files are written in the old format at a resolution ! 746: * of 240 dots per inch. I've done things this way because RASTDATA is new ! 747: * and won't be part of the of raster file directory unless you add it. ! 748: * This way nothing has to be done to the old raster file directory. ! 749: * ! 750: */ ! 751: ! 752: ! 753: sprintf(rastname, "%s/rast%s", bitdir, (rastdev == NULL) ? realdev : rastdev); ! 754: rastdir = rastname; ! 755: ! 756: sprintf(temp, "%s/%s", rastdir, RASTDATA); ! 757: if ( (fp = fopen(temp, "r")) == NULL ) { ! 758: rastformat = OLD_FORMAT; ! 759: rres = 240; ! 760: return; ! 761: } /* End if */ ! 762: ! 763: while ( fscanf(fp, "%s", temp) != EOF ) ! 764: if ( strcmp(temp, "format") == 0 ) { ! 765: fscanf(fp, "%s", temp); ! 766: if ( strcmp(temp, "old") == 0 ) ! 767: rastformat = OLD_FORMAT; ! 768: else rastformat = RST_FORMAT; ! 769: } else if ( strcmp(temp, "resolution") == 0 ) ! 770: fscanf(fp, "%d", &rres); ! 771: else while ( (ch = getc(fp)) != '\n' && ch != EOF ) ; ! 772: ! 773: fclose(fp); ! 774: ! 775: } /* End of rastsetup */ ! 776: ! 777: ! 778: /*****************************************************************************/ ! 779: ! 780: ! 781: rastlist() ! 782: ! 783: ! 784: { ! 785: ! 786: ! 787: int n; /* next size for current font */ ! 788: int i; /* next size goes here */ ! 789: char name[100]; /* pathname for RASTERLIST file */ ! 790: FILE *fp; ! 791: ! 792: ! 793: /* ! 794: * ! 795: * If we're not using the old format raster files we'll want to read the ! 796: * list of available fonts and sizes in *rastdir. The file that's got all ! 797: * the info is called RASTLIST (defined in init.h). The format is exactly ! 798: * the same as Brian's original file. Under the old format all this stuff ! 799: * is done in routine initfontdata(). ! 800: * ! 801: * For now if we can't open RASTERLIST and were not using the old format ! 802: * raster files we'll just return to the caller. That really just means ! 803: * we'll assume we can handle any font + size request that may come our ! 804: * way. If that's not the case we better make up a complete RASTERLIST file. ! 805: * ! 806: */ ! 807: ! 808: ! 809: if ( rastformat == OLD_FORMAT ) /* don't bother doing it here */ ! 810: return; ! 811: ! 812: sprintf(name, "%s/%s", rastdir, RASTLIST); ! 813: if ( (fp = fopen(name, "r")) == NULL ) ! 814: return; ! 815: ! 816: /* name should be no more than L_FNAME characters */ ! 817: while ( fscanf(fp, "%10s", sizedata[maxrast].name) != EOF ) { ! 818: i = 0; ! 819: while ( fscanf(fp, "%d", &n) != EOF && n < 100 ) ! 820: sizedata[maxrast].sizes[i++] = n; ! 821: sizedata[maxrast].sizes[i] = 999; ! 822: if ( ++maxrast >= MAXFONTS ) ! 823: error(FATAL, "too many fonts in %s", name); ! 824: } /* End while */ ! 825: ! 826: fclose(fp); ! 827: ! 828: } /* End of rastlist */ ! 829: ! 830: ! 831: /*****************************************************************************/ ! 832: ! 833: ! 834: arguments() ! 835: ! 836: ! 837: { ! 838: ! 839: ! 840: FILE *fp; /* next input file */ ! 841: ! 842: ! 843: /* ! 844: * ! 845: * All the rest of the command line options are input files we want to ! 846: * translate. If we get here and there are no more arguments, or if '-' is ! 847: * in the list of file names, we'll process stdin. ! 848: * ! 849: */ ! 850: ! 851: ! 852: if (argc < 1) ! 853: conv(stdin); ! 854: else ! 855: while (argc > 0) { ! 856: if (strcmp(*argv, "-") == 0) ! 857: fp = stdin; ! 858: else if ((fp = fopen(*argv, "r")) == NULL) ! 859: error(FATAL, "can't open %s", *argv); ! 860: conv(fp); ! 861: fclose(fp); ! 862: argc--; ! 863: argv++; ! 864: } ! 865: ! 866: } /* End of arguments */ ! 867: ! 868: ! 869: /*****************************************************************************/ ! 870: ! 871: ! 872: print_file() ! 873: ! 874: ! 875: { ! 876: ! 877: ! 878: char buf[BUFSIZ]; /* IPR command line built up here */ ! 879: ! 880: ! 881: /* ! 882: * ! 883: * Finished with all the input files and everything the printer needs to ! 884: * know is in FILE *tf. We'll close the file because we're all done with ! 885: * it, and then call IPR if we haven't been writing to stdout. ! 886: * ! 887: */ ! 888: ! 889: ! 890: fclose(tf); /* everything's in the file */ ! 891: ! 892: if ( tf != stdout || debug ) { ! 893: sprintf(buf, "%s -Limpress -r -o '-Downer \"'\"%s\"'\"'\", jobheader on, pagecollation on, pagereversal on\" %s 0</dev/null 1>/dev/null 2>&1 &", ! 894: IPR, username, tempfile); ! 895: if ( debug ) ! 896: fprintf(stderr, "executing %s\n", buf); ! 897: else system(buf); ! 898: } /* End if */ ! 899: ! 900: } /* End of print_file */ ! 901: ! 902: ! 903: /*****************************************************************************/ ! 904: ! 905: ! 906: acct_file() ! 907: ! 908: ! 909: { ! 910: ! 911: ! 912: /* ! 913: * ! 914: * If we want to do accounting *acctfile will be the name of the file where ! 915: * we put the accounting data. If for some reason we can't open the file ! 916: * we'll just quit. I've called the routine from main() before anything is ! 917: * written to the output file. ! 918: * ! 919: */ ! 920: ! 921: ! 922: if ( acctfile != NULL && *acctfile != '\0' ) { ! 923: if ( (fp_acct = fopen(acctfile, "a")) == NULL ) { ! 924: fp_acct = stderr; ! 925: x_stat |= NO_ACCTFILE; ! 926: error(FATAL, "can't open accounting file"); ! 927: exit(x_stat); ! 928: } ! 929: if ( tf != stdout ) ! 930: x_stat |= DO_ACCT; ! 931: } ! 932: ! 933: } /* End of acct_file */ ! 934: ! 935: ! 936: /*****************************************************************************/ ! 937: ! 938: ! 939: account() ! 940: ! 941: ! 942: { ! 943: ! 944: ! 945: FILE *f; /* just the job's page count */ ! 946: ! 947: ! 948: /* ! 949: * ! 950: * Writes an accounting record, usually to *fp_acct, for the current job. ! 951: * All this stuff is set up for our MHCC printers. In some cases we'll ! 952: * know most everything about the job (called with -J option) and all ! 953: * we'll do is write a page count to *jacctfile. In other cases we'll want ! 954: * a more complete record and all the stuff will go to *fp_acct. You'll ! 955: * undoubtedly want to change this stuff to suit your own needs. ! 956: * ! 957: */ ! 958: ! 959: if ( x_stat & DO_ACCT ) { ! 960: if ( jacctfile == NULL || *jacctfile == '\0' ) { ! 961: fprintf(fp_acct, " user = %-10s", username); ! 962: fprintf(fp_acct, " paper = %-10d", acctpages * copies); ! 963: x_stat &= ~DO_ACCT; ! 964: fprintf(fp_acct, " exit_status = 0%-6o", x_stat); ! 965: fprintf(fp_acct, " type = t "); ! 966: if ( tf == stdout ) ! 967: fprintf(fp_acct, " ??"); ! 968: fprintf(fp_acct, "\n"); ! 969: } else { ! 970: if ( (f = fopen(jacctfile, "a")) != NULL ) { ! 971: fprintf(f, "%d\n", acctpages); ! 972: fclose(f); ! 973: } ! 974: x_stat &= ~DO_ACCT; ! 975: } /* End else */ ! 976: } ! 977: ! 978: } /* End of account */ ! 979: ! 980: ! 981: /*****************************************************************************/ ! 982: ! 983: ! 984: done() ! 985: ! 986: ! 987: { ! 988: ! 989: ! 990: /* ! 991: * ! 992: * Finished with everything so we want to make sure accounting is handled ! 993: * properly and the right exit status is returned to the caller. We'll also ! 994: * delete the temporary file if x_stat != 0. ! 995: * ! 996: */ ! 997: ! 998: ! 999: account(); ! 1000: ! 1001: if ( tf != stdout && x_stat != 0 ) ! 1002: unlink(tempfile); ! 1003: ! 1004: exit(x_stat); ! 1005: ! 1006: } /* End of done */ ! 1007: ! 1008: ! 1009: /*****************************************************************************/ ! 1010: ! 1011: ! 1012: conv(fp) ! 1013: ! 1014: ! 1015: register FILE *fp; ! 1016: ! 1017: ! 1018: { ! 1019: ! 1020: ! 1021: register int c, k; ! 1022: int m, n, i, n1, m1; ! 1023: char str[100]; ! 1024: ! 1025: ! 1026: /* ! 1027: * ! 1028: * Controls the translation of troff's device independent output language ! 1029: * to Impress. Some of the commands, like slant and height, are no-ops ! 1030: * on Imagen's bitmap printers even though routines are called to do the ! 1031: * processing. ! 1032: * ! 1033: */ ! 1034: ! 1035: ! 1036: lineno = 1; /* line in current file */ ! 1037: x_stat |= FILE_STARTED; /* we'll clear it when done with *fp */ ! 1038: ! 1039: while ((c = getc(fp)) != EOF) { ! 1040: ! 1041: switch (c) { ! 1042: ! 1043: case '\n': /* just count this line */ ! 1044: lineno++; ! 1045: break; ! 1046: ! 1047: case ' ': /* when input is text */ ! 1048: case 0: /* occasional noise creeps in */ ! 1049: break; ! 1050: ! 1051: case '0': case '1': case '2': case '3': case '4': ! 1052: case '5': case '6': case '7': case '8': case '9': ! 1053: /* two motion digits plus a character */ ! 1054: hmot((c-'0')*10 + getc(fp)-'0'); ! 1055: put1(getc(fp)); ! 1056: break; ! 1057: ! 1058: case 'c': /* single ascii character */ ! 1059: put1(getc(fp)); ! 1060: break; ! 1061: ! 1062: case 'C': /* special character */ ! 1063: fscanf(fp, "%s", str); ! 1064: put1s(str); ! 1065: break; ! 1066: ! 1067: case 'N': /* character at position n */ ! 1068: fscanf(fp, "%d", &m); ! 1069: oput(m); ! 1070: break; ! 1071: ! 1072: case 'D': /* drawing function */ ! 1073: lineno++; ! 1074: switch ((c=getc(fp))) { ! 1075: case 'p': /* draw a path */ ! 1076: while (fscanf(fp, "%d %d", &n, &m) == 2) ! 1077: drawline(n, m); ! 1078: break; ! 1079: ! 1080: case 'l': /* draw a line */ ! 1081: fscanf(fp, "%d %d %c", &n, &m, &n1); ! 1082: drawline(n, m); ! 1083: break; ! 1084: ! 1085: case 'c': /* circle */ ! 1086: fscanf(fp, "%d", &n); ! 1087: drawcirc(n); ! 1088: break; ! 1089: ! 1090: case 'e': /* ellipse */ ! 1091: fscanf(fp, "%d %d", &m, &n); ! 1092: drawellip(m, n); ! 1093: break; ! 1094: ! 1095: case 'a': /* arc */ ! 1096: fscanf(fp, "%d %d %d %d", &n, &m, &n1, &m1); ! 1097: drawarc(n, m, n1, m1); ! 1098: break; ! 1099: ! 1100: case 'q': /* spline */ ! 1101: drawspline(fp, 1); ! 1102: break; ! 1103: ! 1104: case '~': /* wiggly line */ ! 1105: drawspline(fp, 2); ! 1106: break; ! 1107: ! 1108: default: ! 1109: error(FATAL, "unknown drawing function %c", c); ! 1110: break; ! 1111: } ! 1112: break; ! 1113: ! 1114: case 's': /* use this point size */ ! 1115: fscanf(fp, "%d", &n); /* ignore fractional sizes */ ! 1116: setsize(t_size(n)); ! 1117: break; ! 1118: ! 1119: case 'f': /* use font mounted here */ ! 1120: fscanf(fp, "%s", str); ! 1121: setfont(t_font(str)); ! 1122: break; ! 1123: ! 1124: case 'H': /* absolute horizontal motion */ ! 1125: /* ! 1126: * ! 1127: * The simple scan I've commented out didn't handle negative numbers right ! 1128: * and believe it or not we did get jobs that asked for negative absolute ! 1129: * positions. Even though negative absolute coordinates probably are a ! 1130: * mistake it makes more sense to handle the numbers properly. ! 1131: * ! 1132: while ((c = getc(fp)) == ' ') ! 1133: ; ! 1134: k = 0; ! 1135: do { ! 1136: k = 10 * k + c - '0'; ! 1137: } while (isdigit(c = getc(fp))); ! 1138: ungetc(c, fp); ! 1139: hgoto(k); ! 1140: * ! 1141: */ ! 1142: fscanf(fp, "%d", &n); ! 1143: hgoto(n); ! 1144: break; ! 1145: ! 1146: case 'h': /* relative horizontal motion */ ! 1147: /* ! 1148: * ! 1149: * Again the same potential problem with negative numbers exists here. In ! 1150: * fact it makes a lot more sense to expect negative relative motions even ! 1151: * though I never did see them. Anyway just to be safe I've made the same ! 1152: * change - take it out if you want. ! 1153: * ! 1154: while ((c = getc(fp)) == ' ') ! 1155: ; ! 1156: k = 0; ! 1157: do { ! 1158: k = 10 * k + c - '0'; ! 1159: } while (isdigit(c = getc(fp))); ! 1160: ungetc(c, fp); ! 1161: hmot(k); ! 1162: * ! 1163: */ ! 1164: fscanf(fp, "%d", &n); ! 1165: hmot(n); ! 1166: break; ! 1167: ! 1168: case 'w': /* word space */ ! 1169: break; ! 1170: ! 1171: case 'V': /* absolute vertical position */ ! 1172: fscanf(fp, "%d", &n); ! 1173: vgoto(n); ! 1174: break; ! 1175: ! 1176: case 'v': /* relative vertical motion */ ! 1177: fscanf(fp, "%d", &n); ! 1178: vmot(n); ! 1179: break; ! 1180: ! 1181: case 'p': /* new page */ ! 1182: fscanf(fp, "%d", &n); ! 1183: t_page(n); ! 1184: break; ! 1185: ! 1186: case 'n': /* end of line */ ! 1187: while ( (c = getc(fp)) != '\n' && c != EOF ) ; ! 1188: t_newline(); ! 1189: lineno++; ! 1190: break; ! 1191: ! 1192: case '#': /* comment */ ! 1193: while ( (c = getc(fp)) != '\n' && c != EOF ) ; ! 1194: lineno++; ! 1195: break; ! 1196: ! 1197: case 'x': /* device control function */ ! 1198: devcntrl(fp); ! 1199: break; ! 1200: ! 1201: default: ! 1202: error(!FATAL, "unknown input character %o %c", c, c); ! 1203: done(); ! 1204: } ! 1205: } ! 1206: ! 1207: x_stat &= ~FILE_STARTED; ! 1208: ! 1209: } /* End of conv */ ! 1210: ! 1211: ! 1212: /*****************************************************************************/ ! 1213: ! 1214: ! 1215: devcntrl(fp) ! 1216: ! 1217: ! 1218: FILE *fp; /* current input file */ ! 1219: ! 1220: ! 1221: { ! 1222: ! 1223: ! 1224: char str[20], str1[50], buf[50]; ! 1225: int c, n, x, y; ! 1226: ! 1227: ! 1228: /* ! 1229: * ! 1230: * Called from conv() to process the rest of a device control function. ! 1231: * There's a whole family of them and they all begin with the string ! 1232: * "x ". The rest of the command consists of the function name followed ! 1233: * by zero or more arguments that depend on the particular command. We've ! 1234: * already read the "x" from the input file, that's why the routine was ! 1235: * called. The whole rest of the input line is assumed to be part of the ! 1236: * device control command. ! 1237: * ! 1238: */ ! 1239: ! 1240: ! 1241: fscanf(fp, "%s", str); /* get the control function name */ ! 1242: ! 1243: switch ( str[0] ) { /* only the first character counts now */ ! 1244: case 'i': /* initialize */ ! 1245: fileinit(); ! 1246: t_init(0); ! 1247: break; ! 1248: ! 1249: case 'T': /* device name */ ! 1250: fscanf(fp, "%s", devname); ! 1251: break; ! 1252: ! 1253: case 't': /* trailer */ ! 1254: t_trailer(); ! 1255: break; ! 1256: ! 1257: case 'p': /* pause -- can restart */ ! 1258: t_reset('p'); ! 1259: break; ! 1260: ! 1261: case 's': /* stop */ ! 1262: t_reset('s'); ! 1263: break; ! 1264: ! 1265: case 'r': /* resolution assumed when prepared */ ! 1266: fscanf(fp, "%d", &res); ! 1267: break; ! 1268: ! 1269: case 'f': /* load font in a position */ ! 1270: fscanf(fp, "%d %s", &n, str); ! 1271: fgets(buf, sizeof buf, fp); /* in case there's a filename */ ! 1272: ungetc('\n', fp); /* fgets goes too far */ ! 1273: str1[0] = 0; /* in case there's nothing to come in */ ! 1274: sscanf(buf, "%s", str1); ! 1275: loadfont(n, str, str1); ! 1276: break; ! 1277: ! 1278: /* these don't belong here... */ ! 1279: case 'H': /* char height */ ! 1280: fscanf(fp, "%d", &n); ! 1281: t_charht(n); ! 1282: break; ! 1283: ! 1284: case 'S': /* slant */ ! 1285: fscanf(fp, "%d", &n); ! 1286: t_slant(n); ! 1287: break; ! 1288: ! 1289: case 'I': ! 1290: case 'B': ! 1291: x = hpos * xfac + xoffset + .5; ! 1292: y = vpos * yfac + yoffset + .5; ! 1293: ! 1294: /* force 32x32 alignment, imagen 3.2 software does this ! 1295: ** anyway, but this should fix others ! 1296: */ ! 1297: putc(ASETAV, tf); putint(y&~0x1f, tf); ! 1298: putc(ASETAH, tf); putint(x&~0x1f, tf); ! 1299: ! 1300: if (str[0] == 'I') { ! 1301: fscanf(fp, "%d %s", &n, buf); ! 1302: iglyphpage(tf, buf, n, x&0x1f, y&0x1f); ! 1303: } else if (str[0] == 'B') { ! 1304: fscanf(fp, "%d %s", &n, buf); ! 1305: glyphpage(tf, buf, n, x&0x1f, y&0x1f); ! 1306: } ! 1307: ! 1308: /* position back where it belongs */ ! 1309: putc(ASETAV, tf); putint(y, tf); lasty = y; ! 1310: putc(ASETAH, tf); putint(x, tf); lastx = x; ! 1311: break; ! 1312: ! 1313: case 'X': ! 1314: fscanf(fp, "%s", str); /* line style */ ! 1315: break; ! 1316: } ! 1317: ! 1318: while ( (c = getc(fp)) != '\n' && c != EOF ) ; ! 1319: ! 1320: lineno++; ! 1321: ! 1322: } /* End of devcntrl */ ! 1323: ! 1324: ! 1325: /*****************************************************************************/ ! 1326: ! 1327: ! 1328: fileinit() ! 1329: ! 1330: ! 1331: { ! 1332: ! 1333: ! 1334: int i, fin; ! 1335: char *filebase; ! 1336: char temp[100]; ! 1337: ! 1338: ! 1339: /* ! 1340: * ! 1341: * Called from t_init(), which in turn is called from devcntrl(), whenever we get ! 1342: * an "x init" command. There are a few lines of code here that set things up for ! 1343: * emulating another device. ! 1344: * ! 1345: */ ! 1346: ! 1347: ! 1348: sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname); ! 1349: if ( (fin = open(temp, 0)) < 0 ) ! 1350: error(FATAL, "can't open tables for %s", temp); ! 1351: ! 1352: read(fin, &dev, sizeof(struct dev)); ! 1353: ! 1354: nfonts = dev.nfonts; ! 1355: ! 1356: if ( strcmp(devname, realdev) != 0 ) { /* device emulation */ ! 1357: close(fin); ! 1358: strcpy(devname, realdev); ! 1359: sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname); ! 1360: if ( (fin = open(temp, 0)) < 0 ) ! 1361: error(FATAL, "can't open tables for %s", temp); ! 1362: read(fin, &dev, sizeof(struct dev)); ! 1363: } /* End if */ ! 1364: ! 1365: nsizes = dev.nsizes; ! 1366: nchtab = dev.nchtab; ! 1367: ! 1368: if ( (filebase = malloc(dev.filesize)) == NULL ) ! 1369: error(FATAL, "no memory for description file"); ! 1370: ! 1371: read(fin, filebase, dev.filesize); /* all at once */ ! 1372: ! 1373: pstab = (short *) filebase; ! 1374: chtab = pstab + nsizes + 1; ! 1375: chname = (char *) (chtab + dev.nchtab); ! 1376: ! 1377: for ( i = 1; i <= nfonts; i++ ) { ! 1378: fontbase[i] = NULL; ! 1379: widthtab[i] = codetab[i] = fitab[i] = NULL; ! 1380: } /* End for */ ! 1381: ! 1382: close(fin); ! 1383: ! 1384: } /* End of fileinit */ ! 1385: ! 1386: ! 1387: /*****************************************************************************/ ! 1388: ! 1389: ! 1390: fontprint(i) ! 1391: ! 1392: ! 1393: int i; /* font's index in fontbase[] */ ! 1394: ! 1395: ! 1396: { ! 1397: ! 1398: ! 1399: int j, n; ! 1400: char *p; ! 1401: ! 1402: ! 1403: /* ! 1404: * ! 1405: * Just a debugging routine that dumps most of the important information about ! 1406: * the font that's mounted in position i. ! 1407: * ! 1408: */ ! 1409: ! 1410: ! 1411: fprintf(tf, "font %d:\n", i); ! 1412: ! 1413: p = (char *) fontbase[i]; ! 1414: n = fontbase[i]->nwfont & BMASK; ! 1415: ! 1416: /* name should be no more than L_FNAME characters long */ ! 1417: fprintf(tf, "base=0%o, nchars=%d, spec=%d, name=%.10s, widtab=0%o, fitab=0%o\n", ! 1418: p, n, fontbase[i]->specfont, fontbase[i]->namefont, widthtab[i], fitab[i]); ! 1419: ! 1420: fprintf(tf, "widths:\n"); ! 1421: for ( j = 0; j <= n; j++ ) { ! 1422: fprintf(tf, " %2d", widthtab[i][j] & BMASK); ! 1423: if ( j % 20 == 19 ) putc('\n', tf); ! 1424: } /* End for */ ! 1425: ! 1426: fprintf(tf, "\ncodetab:\n"); ! 1427: for ( j = 0; j <= n; j++ ) { ! 1428: fprintf(tf, " %2d", codetab[i][j] & BMASK); ! 1429: if ( j % 20 == 19 ) putc('\n', tf); ! 1430: } /* End for */ ! 1431: ! 1432: fprintf(tf, "\nfitab:\n"); ! 1433: for ( j = 0; j <= dev.nchtab + 128-32; j++ ) { ! 1434: fprintf(tf, " %2d", fitab[i][j] & BMASK); ! 1435: if ( j % 20 == 19 ) putc('\n', tf); ! 1436: } /* End for */ ! 1437: ! 1438: putc('\n', tf); ! 1439: ! 1440: } /* End of fontprint */ ! 1441: ! 1442: ! 1443: /*****************************************************************************/ ! 1444: ! 1445: ! 1446: loadfont(n, s, s1) ! 1447: ! 1448: ! 1449: int n; ! 1450: char *s, *s1; ! 1451: ! 1452: ! 1453: { ! 1454: ! 1455: ! 1456: char temp[80]; ! 1457: int fin, nw; ! 1458: ! 1459: ! 1460: /* ! 1461: * ! 1462: * Called to to load font info for font *s on position n using the binary tables ! 1463: * located in directory *s1 (if it's not NULL or the empty string). ! 1464: * ! 1465: */ ! 1466: ! 1467: ! 1468: if ( n < 0 || n > NFONT ) /* make sure it's a legal position */ ! 1469: error(FATAL, "illegal fp command %d %s", n, s); ! 1470: ! 1471: /* ! 1472: * ! 1473: * If the font's already loaded on position n there's nothing to do. ! 1474: * ! 1475: */ ! 1476: ! 1477: if ( fontbase[n] != NULL && strncmp(s, fontbase[n]->namefont, L_FNAME) == 0 ) ! 1478: return; ! 1479: ! 1480: /* ! 1481: * ! 1482: * If *s1 isn't NULL or the NULL string that's what we'll use for the font ! 1483: * directory, otherwise use *fontdir. ! 1484: * ! 1485: */ ! 1486: ! 1487: if ( s1 == NULL || s1[0] == '\0' ) ! 1488: sprintf(temp, "%s/dev%s/%.10s.out", fontdir, devname, s); ! 1489: else sprintf(temp, "%s/%.10s.out", s1, s); ! 1490: ! 1491: if ( (fin = open(temp, 0)) < 0 ) { ! 1492: sprintf(temp, "%s/dev%s/%.10s.out", fontdir, devname, mapfont(s)); ! 1493: if ( (fin = open(temp, 0)) < 0 ) ! 1494: error(FATAL, "can't open font table %s", temp); ! 1495: } /* End if */ ! 1496: ! 1497: if ( fontbase[n] != NULL ) /* something's already there */ ! 1498: free(fontbase[n]); /* so release the memory first */ ! 1499: ! 1500: fontbase[n] = (struct Font *) malloc(3*255 + dev.nchtab + (128-32) + sizeof(struct Font)); ! 1501: if ( fontbase[n] == NULL ) ! 1502: error(FATAL, "Out of space in loadfont %s", s); ! 1503: ! 1504: read(fin, fontbase[n], 3*255 + nchtab+128-32 + sizeof(struct Font)); ! 1505: close(fin); ! 1506: ! 1507: if ( smnt == 0 && fontbase[n]->specfont == 1 ) ! 1508: smnt = n; ! 1509: ! 1510: nw = fontbase[n]->nwfont & BMASK; ! 1511: widthtab[n] = (char *) fontbase[n] + sizeof(struct Font); ! 1512: codetab[n] = (char *) widthtab[n] + 2 * nw; ! 1513: fitab[n] = (char *) widthtab[n] + 3 * nw; ! 1514: ! 1515: t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); ! 1516: ! 1517: if ( debug == ON ) ! 1518: fontprint(n); ! 1519: ! 1520: } /* End of loadfont */ ! 1521: ! 1522: ! 1523: /*****************************************************************************/ ! 1524: ! 1525: ! 1526: char *mapfont(name) ! 1527: ! 1528: ! 1529: char *name; /* name of the font troff wants */ ! 1530: ! 1531: ! 1532: { ! 1533: ! 1534: ! 1535: int i; /* loop index for fontmap[] */ ! 1536: ! 1537: ! 1538: /* ! 1539: * ! 1540: * Only called from loadfont() when we haven't been able to open the font file ! 1541: * that troff asked for. We take the font name and map it into an appropriate ! 1542: * substitute. If the initial lookup fails we do a simple mapping that should ! 1543: * be good enough most of the time. ! 1544: * ! 1545: * This stuff should only be needed when we're emulating another printer like ! 1546: * the APS-5. ! 1547: * ! 1548: */ ! 1549: ! 1550: ! 1551: for ( i = 0; fontmap[i].name != NULL && i < L_FNAME; i++ ) ! 1552: if ( strncmp(name, fontmap[i].name, L_FNAME) == 0 ) ! 1553: return(fontmap[i].use); ! 1554: ! 1555: switch ( *++name ) { ! 1556: case 'I': ! 1557: case 'B': ! 1558: return(name); ! 1559: ! 1560: case 'X': ! 1561: return("BI"); ! 1562: ! 1563: default: ! 1564: return("R"); ! 1565: } /* End switch */ ! 1566: ! 1567: } /* End of mapfont */ ! 1568: ! 1569: ! 1570: /*****************************************************************************/ ! 1571: ! 1572: ! 1573: convint(c) ! 1574: ! 1575: ! 1576: unsigned char c; ! 1577: ! 1578: ! 1579: { ! 1580: ! 1581: ! 1582: /* ! 1583: * ! 1584: * Converts a character to a proper 2's complement integer. Really just used ! 1585: * on 3b's when we're reading raster tables in the old format. There's ! 1586: * really no need to make this a separate routine - at least I don't ! 1587: * think there is. Should just redefine CONVINT() macro so it does this ! 1588: * stuff. ! 1589: * ! 1590: */ ! 1591: ! 1592: ! 1593: return((c & 0200) ? ((256 - c) * -1) : c); ! 1594: ! 1595: } /* End of convint */ ! 1596: ! 1597: ! 1598: /*****************************************************************************/ ! 1599: ! 1600: ! 1601: t_init(reinit) ! 1602: ! 1603: ! 1604: int reinit; ! 1605: ! 1606: ! 1607: { ! 1608: ! 1609: ! 1610: int i; ! 1611: FILE *tmpfile(); ! 1612: ! 1613: ! 1614: /* ! 1615: * ! 1616: * Called to initialize the printer and associated variables. reinit will ! 1617: * be zero when the "x init" command was found in the output file, while ! 1618: * it will be non-zero when the routine is called to set things up for a ! 1619: * new page. ! 1620: * ! 1621: */ ! 1622: ! 1623: ! 1624: if (! reinit) { ! 1625: for (i = 0; i < nchtab; i++) ! 1626: if (strcmp(&chname[chtab[i]], "l.") == 0) ! 1627: break; ! 1628: if (i < nchtab) { ! 1629: drawdot = i + 128; ! 1630: drawsize = 1; ! 1631: } else { ! 1632: drawdot = '.'; ! 1633: drawsize = 2; /* half size */ ! 1634: } ! 1635: ! 1636: xfac = (float) pres / res * aspect; ! 1637: yfac = (float) pres / res; ! 1638: ! 1639: putc(ASETPEN, tf); ! 1640: putc(penwidth, tf); ! 1641: ! 1642: if ( mode == LANDSCAPE ) { ! 1643: putc(ASETHV, tf); ! 1644: putc(0107, tf); ! 1645: angle = ROT_270; ! 1646: } /* End if */ ! 1647: } ! 1648: ! 1649: hpos = vpos = 0; ! 1650: setsize(t_size(10)); /* start somewhere */ ! 1651: ! 1652: } /* End of t_init */ ! 1653: ! 1654: ! 1655: /*****************************************************************************/ ! 1656: ! 1657: ! 1658: t_page(pg) ! 1659: ! 1660: ! 1661: { ! 1662: ! 1663: ! 1664: register int i, j, n; ! 1665: register unsigned char *p; ! 1666: ! 1667: ! 1668: /* ! 1669: * ! 1670: * Get the printer and everything else ready for a new page. If the -o ! 1671: * option has been used only selected pages will be printed. If output ! 1672: * is ON when this routine is called we'll write the endpage Impress ! 1673: * command to the output file. If we're supposed to be doing output for ! 1674: * page pg we'll write the APAGE command out, and that will cause the ! 1675: * horizontal and vertical positions (in Impress) to be set to zero. hpos ! 1676: * and vpos are initialized in routine t_init(), although I really don't ! 1677: * see any reason why we couldn't just skip the call and do it here. ! 1678: * ! 1679: */ ! 1680: ! 1681: ! 1682: if ( debug == ON ) ! 1683: fprintf(stderr, "t_page %d, output=%d\n", pg, output); ! 1684: ! 1685: pageno = pg; ! 1686: ! 1687: if ( output == ON ) /* doing output for last page */ ! 1688: putc(AENDP, tf); ! 1689: ! 1690: if ( (output = in_olist(pg)) == ON ) { /* print this page */ ! 1691: putc(APAGE, tf); ! 1692: acctpages++; ! 1693: } ! 1694: ! 1695: lastx = lasty = -1; ! 1696: t_init(1); /* setup for this page */ ! 1697: ! 1698: } /* End of t_page */ ! 1699: ! 1700: ! 1701: /*****************************************************************************/ ! 1702: ! 1703: ! 1704: t_newline() ! 1705: ! 1706: ! 1707: { ! 1708: ! 1709: ! 1710: /* ! 1711: * ! 1712: * Read an "n a b" command in the input file and are ready to start a new ! 1713: * line. There really isn't much else this routine can do besides set the ! 1714: * horizontal position to zero. Anyway troff takes care of any needed ! 1715: * positioning before it starts printing text. ! 1716: * ! 1717: */ ! 1718: ! 1719: ! 1720: hpos = 0; ! 1721: ! 1722: } /* End of t_newline */ ! 1723: ! 1724: ! 1725: /*****************************************************************************/ ! 1726: ! 1727: ! 1728: t_size(n) ! 1729: ! 1730: ! 1731: int n; /* convert this point size */ ! 1732: ! 1733: ! 1734: { ! 1735: ! 1736: ! 1737: int i; ! 1738: ! 1739: ! 1740: /* ! 1741: * ! 1742: * Converts a point size into an internal size that can be used as an ! 1743: * index into the pstab[] array. Actually the internal size is defined as ! 1744: * one plus the index of the least upper bound of n in pstab[] or nsizes ! 1745: * if n is larger than all the listed sizes. ! 1746: * ! 1747: */ ! 1748: ! 1749: if (n <= pstab[0]) ! 1750: return(1); ! 1751: else if (n >= pstab[nsizes-1]) ! 1752: return(nsizes); ! 1753: for (i = 0; n > pstab[i]; i++) ; ! 1754: ! 1755: return(i+1); ! 1756: ! 1757: } /* End of t_size */ ! 1758: ! 1759: ! 1760: /*****************************************************************************/ ! 1761: ! 1762: ! 1763: t_charht(n) ! 1764: ! 1765: ! 1766: int n; /* use this as the character height */ ! 1767: ! 1768: ! 1769: { ! 1770: ! 1771: ! 1772: /* ! 1773: * ! 1774: * Although it can be done on some typesetters, like the APS-5, it's ignored ! 1775: * on Imagen's bitmap printers like the Imprint-10 and the 8/300. It would ! 1776: * be absurd to keep any extra raster files around just so we could implement ! 1777: * this command, and right now there's no Impress command to do it to ! 1778: * downloaded glyphs. ! 1779: * ! 1780: */ ! 1781: ! 1782: ! 1783: } /* End of t_charht */ ! 1784: ! 1785: ! 1786: /*****************************************************************************/ ! 1787: ! 1788: ! 1789: t_slant(n) ! 1790: ! 1791: ! 1792: int n; /* slant characters this many degrees */ ! 1793: ! 1794: ! 1795: { ! 1796: ! 1797: ! 1798: /* ! 1799: * ! 1800: * As with troff's height command, there's no simple way to slant characters ! 1801: * on Imagen's bitmap printers and it's really not worth any effort to try ! 1802: * and make it work. ! 1803: * ! 1804: */ ! 1805: ! 1806: ! 1807: } /* End of t_slant */ ! 1808: ! 1809: ! 1810: /*****************************************************************************/ ! 1811: ! 1812: ! 1813: t_font(s) ! 1814: ! 1815: ! 1816: char *s; ! 1817: ! 1818: ! 1819: { ! 1820: ! 1821: ! 1822: int n; ! 1823: ! 1824: ! 1825: /* ! 1826: * ! 1827: * Just converts the string *s into an integer and checks to make sure the ! 1828: * number is a legal font position. If it's not we'll print an error message ! 1829: * and then quit. di10 handled bad requests a little differently. Instead ! 1830: * of treating mistakes as FATAL errors it would return 1 as the font ! 1831: * number. ! 1832: * ! 1833: */ ! 1834: ! 1835: ! 1836: if ( (n = atoi(s)) < 0 || n > nfonts ) ! 1837: error(FATAL, "illegal font position %d", n); ! 1838: ! 1839: return(n); ! 1840: ! 1841: } /* End of t_font */ ! 1842: ! 1843: ! 1844: /*****************************************************************************/ ! 1845: ! 1846: ! 1847: t_reset(c) ! 1848: ! 1849: ! 1850: int c; /* pause or restart */ ! 1851: ! 1852: ! 1853: { ! 1854: ! 1855: ! 1856: /* ! 1857: * ! 1858: * Called from devcntrl() when we've found an "x stop" or "x pause" command. ! 1859: * There's really nothing we need to do for Imagen's bitmap printers, and ! 1860: * leaving the final cleanup (ie. AEOF code etc.) to someone else means ! 1861: * we should be able to cat a bunch of troff output files together and ! 1862: * have them all printed properly. ! 1863: * ! 1864: */ ! 1865: ! 1866: ! 1867: } /* End of t_reset */ ! 1868: ! 1869: ! 1870: /*****************************************************************************/ ! 1871: ! 1872: ! 1873: t_wrapup() ! 1874: ! 1875: ! 1876: { ! 1877: ! 1878: ! 1879: /* ! 1880: * ! 1881: * We're finished with all the input files and all that's left to do is ! 1882: * end the last page we were working on and then mark the end of the Impress ! 1883: * file. ! 1884: * ! 1885: */ ! 1886: ! 1887: ! 1888: putc(AENDP, tf); ! 1889: putc(AEOF, tf); ! 1890: ! 1891: } /* End of t_wrapup */ ! 1892: ! 1893: ! 1894: /*****************************************************************************/ ! 1895: ! 1896: ! 1897: t_trailer() ! 1898: ! 1899: ! 1900: { ! 1901: ! 1902: ! 1903: /* ! 1904: * ! 1905: * Called from devcntrl() when an "x trailer" command is found. There's ! 1906: * nothing we need to do here for Imagen's printers. ! 1907: * ! 1908: */ ! 1909: ! 1910: ! 1911: ! 1912: } /* End of t_trailer */ ! 1913: ! 1914: ! 1915: /*****************************************************************************/ ! 1916: ! 1917: ! 1918: hgoto(n) ! 1919: ! 1920: ! 1921: int n; /* where we want to be */ ! 1922: ! 1923: ! 1924: { ! 1925: ! 1926: ! 1927: /* ! 1928: * ! 1929: * Want to be at this absolute horizontal position next - usually will ! 1930: * get these motion commands right before printing a character. ! 1931: * ! 1932: */ ! 1933: ! 1934: ! 1935: hpos = n; ! 1936: ! 1937: } /* End of hgoto */ ! 1938: ! 1939: ! 1940: /*****************************************************************************/ ! 1941: ! 1942: ! 1943: hmot(n) ! 1944: ! 1945: ! 1946: int n; /* move this far from where we are */ ! 1947: ! 1948: ! 1949: { ! 1950: ! 1951: ! 1952: /* ! 1953: * ! 1954: * Handles relative horizontal motion. troff's current positon as recorded ! 1955: * in hpos is changed by n units. ! 1956: * ! 1957: */ ! 1958: ! 1959: ! 1960: hpos += n; ! 1961: ! 1962: } /* End of hmot */ ! 1963: ! 1964: ! 1965: /*****************************************************************************/ ! 1966: ! 1967: ! 1968: vgoto(n) ! 1969: ! 1970: ! 1971: int n; /* new vertical position */ ! 1972: ! 1973: ! 1974: { ! 1975: ! 1976: ! 1977: /* ! 1978: * ! 1979: * Moves vertically in troff's coordinate system to absolute position n. ! 1980: * ! 1981: */ ! 1982: ! 1983: ! 1984: vpos = n; ! 1985: ! 1986: } /* End of vgoto */ ! 1987: ! 1988: ! 1989: /*****************************************************************************/ ! 1990: ! 1991: ! 1992: vmot(n) ! 1993: ! 1994: ! 1995: int n; /* move this far vertically */ ! 1996: ! 1997: ! 1998: { ! 1999: ! 2000: ! 2001: /* ! 2002: * ! 2003: * Handles relative vertical motion of n units in troff's coordinate system. ! 2004: * ! 2005: */ ! 2006: ! 2007: ! 2008: vpos += n; ! 2009: ! 2010: } /* End of vmot */ ! 2011: ! 2012: ! 2013: /*****************************************************************************/ ! 2014: ! 2015: ! 2016: put1s(s) ! 2017: ! 2018: ! 2019: register char *s; ! 2020: ! 2021: ! 2022: { ! 2023: ! 2024: ! 2025: static int i = 0; /* last one we found - usually */ ! 2026: ! 2027: ! 2028: /* ! 2029: * ! 2030: * Does whatever is necessary to have special character *s printed. If we're ! 2031: * doing output on this page we'll look the character up using chname[] and ! 2032: * chtab[]. The first array contains all the special character names ! 2033: * separated by '\0' that are mentioned in the typesetter's DESC file, while ! 2034: * chname[i] points to the start of character i in chname[]. Both arrays ! 2035: * come from the DESC.out file for printer *devname which is found in ! 2036: * *fontdir (wherever that might be). ! 2037: * ! 2038: */ ! 2039: ! 2040: ! 2041: if ( output == OFF ) ! 2042: return; ! 2043: ! 2044: if ( debug ) ! 2045: printf("%s", s); ! 2046: ! 2047: if (strcmp(s, &chname[chtab[i]]) != 0) ! 2048: for (i = 0; i < nchtab; i++) ! 2049: if (strcmp(&chname[chtab[i]], s) == 0) ! 2050: break; ! 2051: if (i < nchtab) ! 2052: put1(i + 128); ! 2053: else ! 2054: i = 0; ! 2055: ! 2056: } /* End of put1s */ ! 2057: ! 2058: ! 2059: /*****************************************************************************/ ! 2060: ! 2061: ! 2062: put1(c) ! 2063: ! 2064: ! 2065: register int c; /* print this character */ ! 2066: ! 2067: ! 2068: { ! 2069: ! 2070: ! 2071: char *pw; ! 2072: register char *p; ! 2073: register int i, j, k; ! 2074: int ofont, code; ! 2075: ! 2076: ! 2077: /* ! 2078: * ! 2079: * Arranges to have character c printed. If c < 128 it's a simple ASCII character, ! 2080: * otherwise it's a special character. We subtract 32 from c because non-graphic ! 2081: * ASCII characters aren't included in the tables. ! 2082: * ! 2083: */ ! 2084: ! 2085: ! 2086: lastc = c; /* charlib() may need the real name */ ! 2087: c -= 32; ! 2088: ! 2089: if ( c <= 0 ) { ! 2090: if ( debug == ON ) ! 2091: fprintf(tf, "non-exist 0%o\n", lastc); ! 2092: return; ! 2093: } /* End if */ ! 2094: ! 2095: k = ofont = font; ! 2096: i = fitab[font][c] & BMASK; ! 2097: ! 2098: if ( i != 0 ) { /* it's on this font */ ! 2099: p = codetab[font]; ! 2100: pw = widthtab[font]; ! 2101: } else if ( smnt > 0 ) { /* on special (we hope) */ ! 2102: for ( k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1) ) { ! 2103: if ( k == 0 ) continue; ! 2104: if ( (i = fitab[k][c] & BMASK) != 0 ) { ! 2105: p = codetab[k]; ! 2106: pw = widthtab[k]; ! 2107: setfont(k); ! 2108: break; ! 2109: } /* End if */ ! 2110: } /* End for */ ! 2111: } /* End else */ ! 2112: ! 2113: if ( i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts ) { ! 2114: if ( debug == ON ) ! 2115: fprintf(tf, "not found 0%o\n", lastc); ! 2116: if ( font != ofont ) setfont(ofont); ! 2117: return; ! 2118: } /* End if */ ! 2119: ! 2120: lastw = ((pw[i] & BMASK) * pstab[size-1] + dev.unitwidth/2) / dev.unitwidth; ! 2121: ! 2122: if ( debug == ON ) { ! 2123: if ( isprint(lastc) ) ! 2124: fprintf(tf, "%c %d\n", lastc, code); ! 2125: else fprintf(tf, "%03o %d\n", lastc, code); ! 2126: } else oput(code); ! 2127: ! 2128: if ( font != ofont ) ! 2129: setfont(ofont); ! 2130: ! 2131: } /* End of put1 */ ! 2132: ! 2133: ! 2134: /*****************************************************************************/ ! 2135: ! 2136: ! 2137: setsize(n) ! 2138: ! 2139: ! 2140: int n; /* new internal size */ ! 2141: ! 2142: ! 2143: { ! 2144: ! 2145: ! 2146: /* ! 2147: * ! 2148: * We want to use internal size n for now, where n is an index into *pstab ! 2149: * where we can find the closest available approximation to the requested ! 2150: * point size. ! 2151: * ! 2152: */ ! 2153: ! 2154: ! 2155: size = n; ! 2156: ! 2157: } /* End of setsize */ ! 2158: ! 2159: ! 2160: /*****************************************************************************/ ! 2161: ! 2162: ! 2163: t_fp(n, s, si) ! 2164: ! 2165: ! 2166: int n; /* font position to update */ ! 2167: char *s; /* it now contains this font */ ! 2168: char *si; /* and this is its internal number */ ! 2169: ! 2170: ! 2171: { ! 2172: ! 2173: ! 2174: /* ! 2175: * ! 2176: * Called when we've loaded font *s in position n. The font position info ! 2177: * is recorded in fontname[]. ! 2178: * ! 2179: */ ! 2180: ! 2181: ! 2182: fontname[n].name = s; ! 2183: fontname[n].number = atoi(si); ! 2184: if ( n == lastfont ) lastfont = -1; /* force getfontdata() call */ ! 2185: ! 2186: } /* End of t_fp */ ! 2187: ! 2188: ! 2189: /*****************************************************************************/ ! 2190: ! 2191: ! 2192: setfont(n) ! 2193: ! 2194: ! 2195: int n; /* this will be the current font */ ! 2196: ! 2197: ! 2198: { ! 2199: ! 2200: ! 2201: /* ! 2202: * ! 2203: * Job now wants to use the font loaded in position n. The variable font ! 2204: * keeps track of which one we're currently using. If the requested positon ! 2205: * is out of range we'll just quit. ! 2206: * ! 2207: */ ! 2208: ! 2209: ! 2210: if ( output == OFF ) ! 2211: return; ! 2212: ! 2213: if (n < 0 || n > NFONT) ! 2214: error(FATAL, "illegal font %d", n); ! 2215: ! 2216: font = n; ! 2217: ! 2218: } /* End of setfont */ ! 2219: ! 2220: ! 2221: /*****************************************************************************/ ! 2222: ! 2223: ! 2224: oput(c) ! 2225: ! 2226: ! 2227: int c; /* want to print this character */ ! 2228: ! 2229: ! 2230: { ! 2231: ! 2232: ! 2233: int x, y; /* current scaled position */ ! 2234: int member; /* glyph number for c in current family */ ! 2235: ! 2236: ! 2237: /* ! 2238: * ! 2239: * Arranges to print the character whose code is c in the current font. ! 2240: * The old and new raster file formats are supported. ! 2241: * ! 2242: */ ! 2243: ! 2244: ! 2245: if ( output == OFF ) ! 2246: return; ! 2247: ! 2248: if ( rastformat == OLD_FORMAT ) { ! 2249: xychar(c, fontname[font].name, pstab[size-1], lastw, tf); ! 2250: return; ! 2251: } /* End if */ ! 2252: ! 2253: if ( font != lastfont || size != lastsize ) { ! 2254: if ( isresident(fontname[font].name) == FALSE ) ! 2255: getrastdata(fontname[font].name, mapsize(fontname[font].name, pstab[size-1])); ! 2256: else getresdata(fontname[font].name, mapsize(fontname[font].name, pstab[size-1]), tf); ! 2257: lastfont = font; ! 2258: lastsize = size; ! 2259: } /* End if */ ! 2260: ! 2261: member = download(c, lastw, angle, tf); ! 2262: ! 2263: x = hpos * xfac + xoffset + .5; ! 2264: y = vpos * yfac + yoffset + .5; ! 2265: ! 2266: if ( y != lasty ) { ! 2267: putc(ASETAV, tf); ! 2268: putint(y, tf); ! 2269: lasty = y; ! 2270: } /* End if */ ! 2271: ! 2272: if ( ABS(x - lastx) > SLOP ) { ! 2273: putc(ASETAH, tf); ! 2274: putint(x, tf); ! 2275: lastx = x + fam->advance[member]; ! 2276: } else lastx += fam->advance[member]; ! 2277: ! 2278: putc(member, tf); ! 2279: ! 2280: } /* End of oput */ ! 2281: ! 2282: ! 2283: /*****************************************************************************/ ! 2284: ! 2285: ! 2286: mapsize(name, ps) ! 2287: char *name; /* name of the font */ ! 2288: int ps; /* point size troff wants to use */ ! 2289: { ! 2290: int i, j; ! 2291: /* ! 2292: * Uses the data that's been filled in from RASTLIST to map point size ! 2293: * ps font font *name into the best size available in our raster tables. ! 2294: * If no RASTLIST file was used rastsize will be zero and we'll just ! 2295: * assume that any size that's aske for is available. ! 2296: */ ! 2297: if ( maxrast == 0 ) /* don't have any size data */ ! 2298: return(ps); ! 2299: ! 2300: for ( i = 0; i < maxrast; i++ ) ! 2301: if ( strncmp(name, sizedata[i].name, L_FNAME) == 0 ) ! 2302: break; ! 2303: ! 2304: if ( i >= maxrast ) /* didn't find the font */ ! 2305: error(FATAL, "missing raster list data for font %s", name); ! 2306: ! 2307: for ( j = 1, ps = (ps * pres) / rres; ps >= sizedata[i].sizes[j]; j++ ) ; ! 2308: ! 2309: return(sizedata[i].sizes[--j]); ! 2310: ! 2311: } /* End of mapsize */ ! 2312: ! 2313: ! 2314: /*****************************************************************************/ ! 2315: ! 2316:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.