|
|
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: while ( fscanf(fp, "%s", sizedata[maxrast].name) != EOF ) { ! 817: i = 0; ! 818: while ( fscanf(fp, "%d", &n) != EOF && n < 100 ) ! 819: sizedata[maxrast].sizes[i++] = n; ! 820: sizedata[maxrast].sizes[i] = 999; ! 821: if ( ++maxrast >= MAXFONTS ) ! 822: error(FATAL, "too many fonts in %s", name); ! 823: } /* End while */ ! 824: ! 825: fclose(fp); ! 826: ! 827: } /* End of rastlist */ ! 828: ! 829: ! 830: /*****************************************************************************/ ! 831: ! 832: ! 833: arguments() ! 834: ! 835: ! 836: { ! 837: ! 838: ! 839: FILE *fp; /* next input file */ ! 840: ! 841: ! 842: /* ! 843: * ! 844: * All the rest of the command line options are input files we want to ! 845: * translate. If we get here and there are no more arguments, or if '-' is ! 846: * in the list of file names, we'll process stdin. ! 847: * ! 848: */ ! 849: ! 850: ! 851: if (argc < 1) ! 852: conv(stdin); ! 853: else ! 854: while (argc > 0) { ! 855: if (strcmp(*argv, "-") == 0) ! 856: fp = stdin; ! 857: else if ((fp = fopen(*argv, "r")) == NULL) ! 858: error(FATAL, "can't open %s", *argv); ! 859: conv(fp); ! 860: fclose(fp); ! 861: argc--; ! 862: argv++; ! 863: } ! 864: ! 865: } /* End of arguments */ ! 866: ! 867: ! 868: /*****************************************************************************/ ! 869: ! 870: ! 871: print_file() ! 872: ! 873: ! 874: { ! 875: ! 876: ! 877: char buf[BUFSIZ]; /* IPR command line built up here */ ! 878: ! 879: ! 880: /* ! 881: * ! 882: * Finished with all the input files and everything the printer needs to ! 883: * know is in FILE *tf. We'll close the file because we're all done with ! 884: * it, and then call IPR if we haven't been writing to stdout. ! 885: * ! 886: */ ! 887: ! 888: ! 889: fclose(tf); /* everything's in the file */ ! 890: ! 891: if ( tf != stdout || debug ) { ! 892: sprintf(buf, "%s -Limpress -r -o '-Downer \"'\"%s\"'\"'\", jobheader on, pagecollation on, pagereversal on\" %s 0</dev/null 1>/dev/null 2>&1 &", ! 893: IPR, username, tempfile); ! 894: if ( debug ) ! 895: fprintf(stderr, "executing %s\n", buf); ! 896: else system(buf); ! 897: } /* End if */ ! 898: ! 899: } /* End of print_file */ ! 900: ! 901: ! 902: /*****************************************************************************/ ! 903: ! 904: ! 905: acct_file() ! 906: ! 907: ! 908: { ! 909: ! 910: ! 911: /* ! 912: * ! 913: * If we want to do accounting *acctfile will be the name of the file where ! 914: * we put the accounting data. If for some reason we can't open the file ! 915: * we'll just quit. I've called the routine from main() before anything is ! 916: * written to the output file. ! 917: * ! 918: */ ! 919: ! 920: ! 921: if ( acctfile != NULL && *acctfile != '\0' ) { ! 922: if ( (fp_acct = fopen(acctfile, "a")) == NULL ) { ! 923: fp_acct = stderr; ! 924: x_stat |= NO_ACCTFILE; ! 925: error(FATAL, "can't open accounting file"); ! 926: exit(x_stat); ! 927: } ! 928: if ( tf != stdout ) ! 929: x_stat |= DO_ACCT; ! 930: } ! 931: ! 932: } /* End of acct_file */ ! 933: ! 934: ! 935: /*****************************************************************************/ ! 936: ! 937: ! 938: account() ! 939: ! 940: ! 941: { ! 942: ! 943: ! 944: FILE *f; /* just the job's page count */ ! 945: ! 946: ! 947: /* ! 948: * ! 949: * Writes an accounting record, usually to *fp_acct, for the current job. ! 950: * All this stuff is set up for our MHCC printers. In some cases we'll ! 951: * know most everything about the job (called with -J option) and all ! 952: * we'll do is write a page count to *jacctfile. In other cases we'll want ! 953: * a more complete record and all the stuff will go to *fp_acct. You'll ! 954: * undoubtedly want to change this stuff to suit your own needs. ! 955: * ! 956: */ ! 957: ! 958: if ( x_stat & DO_ACCT ) { ! 959: if ( jacctfile == NULL || *jacctfile == '\0' ) { ! 960: fprintf(fp_acct, " user = %-10s", username); ! 961: fprintf(fp_acct, " paper = %-10d", acctpages * copies); ! 962: x_stat &= ~DO_ACCT; ! 963: fprintf(fp_acct, " exit_status = 0%-6o", x_stat); ! 964: fprintf(fp_acct, " type = t "); ! 965: if ( tf == stdout ) ! 966: fprintf(fp_acct, " ??"); ! 967: fprintf(fp_acct, "\n"); ! 968: } else { ! 969: if ( (f = fopen(jacctfile, "a")) != NULL ) { ! 970: fprintf(f, "%d\n", acctpages); ! 971: fclose(f); ! 972: } ! 973: x_stat &= ~DO_ACCT; ! 974: } /* End else */ ! 975: } ! 976: ! 977: } /* End of account */ ! 978: ! 979: ! 980: /*****************************************************************************/ ! 981: ! 982: ! 983: done() ! 984: ! 985: ! 986: { ! 987: ! 988: ! 989: /* ! 990: * ! 991: * Finished with everything so we want to make sure accounting is handled ! 992: * properly and the right exit status is returned to the caller. We'll also ! 993: * delete the temporary file if x_stat != 0. ! 994: * ! 995: */ ! 996: ! 997: ! 998: account(); ! 999: ! 1000: if ( tf != stdout && x_stat != 0 ) ! 1001: unlink(tempfile); ! 1002: ! 1003: exit(x_stat); ! 1004: ! 1005: } /* End of done */ ! 1006: ! 1007: ! 1008: /*****************************************************************************/ ! 1009: ! 1010: ! 1011: conv(fp) ! 1012: ! 1013: ! 1014: register FILE *fp; ! 1015: ! 1016: ! 1017: { ! 1018: ! 1019: ! 1020: register int c, k; ! 1021: int m, n, i, n1, m1; ! 1022: char str[100], buf[300]; ! 1023: ! 1024: ! 1025: /* ! 1026: * ! 1027: * Controls the translation of troff's device independent output language ! 1028: * to Impress. Some of the commands, like slant and height, are no-ops ! 1029: * on Imagen's bitmap printers even though routines are called to do the ! 1030: * processing. ! 1031: * ! 1032: */ ! 1033: ! 1034: ! 1035: lineno = 1; /* line in current file */ ! 1036: x_stat |= FILE_STARTED; /* we'll clear it when done with *fp */ ! 1037: ! 1038: while ((c = getc(fp)) != EOF) { ! 1039: ! 1040: switch (c) { ! 1041: ! 1042: case '\n': /* just count this line */ ! 1043: lineno++; ! 1044: break; ! 1045: ! 1046: case ' ': /* when input is text */ ! 1047: case 0: /* occasional noise creeps in */ ! 1048: break; ! 1049: ! 1050: case '0': case '1': case '2': case '3': case '4': ! 1051: case '5': case '6': case '7': case '8': case '9': ! 1052: /* two motion digits plus a character */ ! 1053: hmot((c-'0')*10 + getc(fp)-'0'); ! 1054: put1(getc(fp)); ! 1055: break; ! 1056: ! 1057: case 'c': /* single ascii character */ ! 1058: put1(getc(fp)); ! 1059: break; ! 1060: ! 1061: case 'C': /* special character */ ! 1062: fscanf(fp, "%s", str); ! 1063: put1s(str); ! 1064: break; ! 1065: ! 1066: case 'N': /* character at position n */ ! 1067: fscanf(fp, "%d", &m); ! 1068: oput(m); ! 1069: break; ! 1070: ! 1071: case 'D': /* drawing function */ ! 1072: fgets(buf, sizeof(buf), fp); ! 1073: lineno++; ! 1074: switch (buf[0]) { ! 1075: case 'l': /* draw a line */ ! 1076: sscanf(buf+1, "%d %d", &n, &m); ! 1077: drawline(n, m); ! 1078: break; ! 1079: ! 1080: case 'c': /* circle */ ! 1081: sscanf(buf+1, "%d", &n); ! 1082: drawcirc(n); ! 1083: break; ! 1084: ! 1085: case 'e': /* ellipse */ ! 1086: sscanf(buf+1, "%d %d", &m, &n); ! 1087: drawellip(m, n); ! 1088: break; ! 1089: ! 1090: case 'a': /* arc */ ! 1091: sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1); ! 1092: drawarc(n, m, n1, m1); ! 1093: break; ! 1094: ! 1095: case '~': /* wiggly line */ ! 1096: drawwig(buf+1); ! 1097: break; ! 1098: ! 1099: default: ! 1100: error(FATAL, "unknown drawing function %s", buf); ! 1101: break; ! 1102: } ! 1103: break; ! 1104: ! 1105: case 's': /* use this point size */ ! 1106: fscanf(fp, "%d", &n); /* ignore fractional sizes */ ! 1107: setsize(t_size(n)); ! 1108: break; ! 1109: ! 1110: case 'f': /* use font mounted here */ ! 1111: fscanf(fp, "%s", str); ! 1112: setfont(t_font(str)); ! 1113: break; ! 1114: ! 1115: case 'H': /* absolute horizontal motion */ ! 1116: /* ! 1117: * ! 1118: * The simple scan I've commented out didn't handle negative numbers right ! 1119: * and believe it or not we did get jobs that asked for negative absolute ! 1120: * positions. Even though negative absolute coordinates probably are a ! 1121: * mistake it makes more sense to handle the numbers properly. ! 1122: * ! 1123: while ((c = getc(fp)) == ' ') ! 1124: ; ! 1125: k = 0; ! 1126: do { ! 1127: k = 10 * k + c - '0'; ! 1128: } while (isdigit(c = getc(fp))); ! 1129: ungetc(c, fp); ! 1130: hgoto(k); ! 1131: * ! 1132: */ ! 1133: fscanf(fp, "%d", &n); ! 1134: hgoto(n); ! 1135: break; ! 1136: ! 1137: case 'h': /* relative horizontal motion */ ! 1138: /* ! 1139: * ! 1140: * Again the same potential problem with negative numbers exists here. In ! 1141: * fact it makes a lot more sense to expect negative relative motions even ! 1142: * though I never did see them. Anyway just to be safe I've made the same ! 1143: * change - take it out if you want. ! 1144: * ! 1145: while ((c = getc(fp)) == ' ') ! 1146: ; ! 1147: k = 0; ! 1148: do { ! 1149: k = 10 * k + c - '0'; ! 1150: } while (isdigit(c = getc(fp))); ! 1151: ungetc(c, fp); ! 1152: hmot(k); ! 1153: * ! 1154: */ ! 1155: fscanf(fp, "%d", &n); ! 1156: hmot(n); ! 1157: break; ! 1158: ! 1159: case 'w': /* word space */ ! 1160: break; ! 1161: ! 1162: case 'V': /* absolute vertical position */ ! 1163: fscanf(fp, "%d", &n); ! 1164: vgoto(n); ! 1165: break; ! 1166: ! 1167: case 'v': /* relative vertical motion */ ! 1168: fscanf(fp, "%d", &n); ! 1169: vmot(n); ! 1170: break; ! 1171: ! 1172: case 'p': /* new page */ ! 1173: fscanf(fp, "%d", &n); ! 1174: t_page(n); ! 1175: break; ! 1176: ! 1177: case 'n': /* end of line */ ! 1178: while ( (c = getc(fp)) != '\n' && c != EOF ) ; ! 1179: t_newline(); ! 1180: lineno++; ! 1181: break; ! 1182: ! 1183: case '#': /* comment */ ! 1184: while ( (c = getc(fp)) != '\n' && c != EOF ) ; ! 1185: lineno++; ! 1186: break; ! 1187: ! 1188: case 'x': /* device control function */ ! 1189: devcntrl(fp); ! 1190: break; ! 1191: ! 1192: default: ! 1193: error(!FATAL, "unknown input character %o %c", c, c); ! 1194: done(); ! 1195: } ! 1196: } ! 1197: ! 1198: x_stat &= ~FILE_STARTED; ! 1199: ! 1200: } /* End of conv */ ! 1201: ! 1202: ! 1203: /*****************************************************************************/ ! 1204: ! 1205: ! 1206: devcntrl(fp) ! 1207: ! 1208: ! 1209: FILE *fp; /* current input file */ ! 1210: ! 1211: ! 1212: { ! 1213: ! 1214: ! 1215: char str[20], str1[50], buf[50]; ! 1216: int c, n, x, y; ! 1217: ! 1218: ! 1219: /* ! 1220: * ! 1221: * Called form conv() to process the rest of a device control function. ! 1222: * There's a whole family of them and they all begin with the string ! 1223: * "x ". The rest of the command consists of the function name followed ! 1224: * by zero or more arguments that depend on the particular command. We've ! 1225: * already read the "x" from the input file, that's why the routine was ! 1226: * called. The whole rest of the input line is assumed to be part of the ! 1227: * device control command. ! 1228: * ! 1229: */ ! 1230: ! 1231: ! 1232: fscanf(fp, "%s", str); /* get the control function name */ ! 1233: ! 1234: switch ( str[0] ) { /* only the first character counts now */ ! 1235: case 'i': /* initialize */ ! 1236: fileinit(); ! 1237: t_init(0); ! 1238: break; ! 1239: ! 1240: case 'T': /* device name */ ! 1241: fscanf(fp, "%s", devname); ! 1242: break; ! 1243: ! 1244: case 't': /* trailer */ ! 1245: t_trailer(); ! 1246: break; ! 1247: ! 1248: case 'p': /* pause -- can restart */ ! 1249: t_reset('p'); ! 1250: break; ! 1251: ! 1252: case 's': /* stop */ ! 1253: t_reset('s'); ! 1254: break; ! 1255: ! 1256: case 'r': /* resolution assumed when prepared */ ! 1257: fscanf(fp, "%d", &res); ! 1258: break; ! 1259: ! 1260: case 'f': /* load font in a position */ ! 1261: fscanf(fp, "%d %s", &n, str); ! 1262: fgets(buf, sizeof buf, fp); /* in case there's a filename */ ! 1263: ungetc('\n', fp); /* fgets goes too far */ ! 1264: str1[0] = 0; /* in case there's nothing to come in */ ! 1265: sscanf(buf, "%s", str1); ! 1266: loadfont(n, str, str1); ! 1267: break; ! 1268: ! 1269: /* these don't belong here... */ ! 1270: case 'H': /* char height */ ! 1271: fscanf(fp, "%d", &n); ! 1272: t_charht(n); ! 1273: break; ! 1274: ! 1275: case 'S': /* slant */ ! 1276: fscanf(fp, "%d", &n); ! 1277: t_slant(n); ! 1278: break; ! 1279: ! 1280: case 'I': ! 1281: case 'B': ! 1282: x = hpos * xfac + xoffset + .5; ! 1283: y = vpos * yfac + yoffset + .5; ! 1284: ! 1285: /* force 32x32 alignment, imagen 3.2 software does this ! 1286: ** anyway, but this should fix others ! 1287: */ ! 1288: putc(ASETAV, tf); putint(y&~0x1f, tf); ! 1289: putc(ASETAH, tf); putint(x&~0x1f, tf); ! 1290: ! 1291: if (str[0] == 'I') { ! 1292: fscanf(fp, "%d %s", &n, buf); ! 1293: iglyphpage(tf, buf, n, x&0x1f, y&0x1f); ! 1294: } else if (str[0] == 'B') { ! 1295: fscanf(fp, "%d %s", &n, buf); ! 1296: glyphpage(tf, buf, n, x&0x1f, y&0x1f); ! 1297: } ! 1298: ! 1299: /* position back where it belongs */ ! 1300: putc(ASETAV, tf); putint(y, tf); lasty = y; ! 1301: putc(ASETAH, tf); putint(x, tf); lastx = x; ! 1302: break; ! 1303: } ! 1304: ! 1305: while ( (c = getc(fp)) != '\n' && c != EOF ) ; ! 1306: ! 1307: lineno++; ! 1308: ! 1309: } /* End of devcntrl */ ! 1310: ! 1311: ! 1312: /*****************************************************************************/ ! 1313: ! 1314: ! 1315: fileinit() ! 1316: ! 1317: ! 1318: { ! 1319: ! 1320: ! 1321: int i, fin; ! 1322: char *filebase; ! 1323: char temp[100]; ! 1324: ! 1325: ! 1326: /* ! 1327: * ! 1328: * Called from t_init(), which in turn is called from devcntrl(), whenever we get ! 1329: * an "x init" command. There are a few lines of code here that set things up for ! 1330: * emulating another device. ! 1331: * ! 1332: */ ! 1333: ! 1334: ! 1335: sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname); ! 1336: if ( (fin = open(temp, 0)) < 0 ) ! 1337: error(FATAL, "can't open tables for %s", temp); ! 1338: ! 1339: read(fin, &dev, sizeof(struct dev)); ! 1340: ! 1341: nfonts = dev.nfonts; ! 1342: ! 1343: if ( strcmp(devname, realdev) != 0 ) { /* device emulation */ ! 1344: close(fin); ! 1345: strcpy(devname, realdev); ! 1346: sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname); ! 1347: if ( (fin = open(temp, 0)) < 0 ) ! 1348: error(FATAL, "can't open tables for %s", temp); ! 1349: read(fin, &dev, sizeof(struct dev)); ! 1350: } /* End if */ ! 1351: ! 1352: nsizes = dev.nsizes; ! 1353: nchtab = dev.nchtab; ! 1354: ! 1355: if ( (filebase = malloc(dev.filesize)) == NULL ) ! 1356: error(FATAL, "no memory for description file"); ! 1357: ! 1358: read(fin, filebase, dev.filesize); /* all at once */ ! 1359: ! 1360: pstab = (short *) filebase; ! 1361: chtab = pstab + nsizes + 1; ! 1362: chname = (char *) (chtab + dev.nchtab); ! 1363: ! 1364: for ( i = 1; i <= nfonts; i++ ) { ! 1365: fontbase[i] = NULL; ! 1366: widthtab[i] = codetab[i] = fitab[i] = NULL; ! 1367: } /* End for */ ! 1368: ! 1369: close(fin); ! 1370: ! 1371: } /* End of fileinit */ ! 1372: ! 1373: ! 1374: /*****************************************************************************/ ! 1375: ! 1376: ! 1377: fontprint(i) ! 1378: ! 1379: ! 1380: int i; /* font's index in fontbase[] */ ! 1381: ! 1382: ! 1383: { ! 1384: ! 1385: ! 1386: int j, n; ! 1387: char *p; ! 1388: ! 1389: ! 1390: /* ! 1391: * ! 1392: * Just a debugging routine that dumps most of the important information about ! 1393: * the font that's mounted in position i. ! 1394: * ! 1395: */ ! 1396: ! 1397: ! 1398: fprintf(tf, "font %d:\n", i); ! 1399: ! 1400: p = (char *) fontbase[i]; ! 1401: n = fontbase[i]->nwfont & BMASK; ! 1402: ! 1403: fprintf(tf, "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n", ! 1404: p, n, fontbase[i]->specfont, fontbase[i]->namefont, widthtab[i], fitab[i]); ! 1405: ! 1406: fprintf(tf, "widths:\n"); ! 1407: for ( j = 0; j <= n; j++ ) { ! 1408: fprintf(tf, " %2d", widthtab[i][j] & BMASK); ! 1409: if ( j % 20 == 19 ) putc('\n', tf); ! 1410: } /* End for */ ! 1411: ! 1412: fprintf(tf, "\ncodetab:\n"); ! 1413: for ( j = 0; j <= n; j++ ) { ! 1414: fprintf(tf, " %2d", codetab[i][j] & BMASK); ! 1415: if ( j % 20 == 19 ) putc('\n', tf); ! 1416: } /* End for */ ! 1417: ! 1418: fprintf(tf, "\nfitab:\n"); ! 1419: for ( j = 0; j <= dev.nchtab + 128-32; j++ ) { ! 1420: fprintf(tf, " %2d", fitab[i][j] & BMASK); ! 1421: if ( j % 20 == 19 ) putc('\n', tf); ! 1422: } /* End for */ ! 1423: ! 1424: putc('\n', tf); ! 1425: ! 1426: } /* End of fontprint */ ! 1427: ! 1428: ! 1429: /*****************************************************************************/ ! 1430: ! 1431: ! 1432: loadfont(n, s, s1) ! 1433: ! 1434: ! 1435: int n; ! 1436: char *s, *s1; ! 1437: ! 1438: ! 1439: { ! 1440: ! 1441: ! 1442: char temp[80]; ! 1443: int fin, nw; ! 1444: ! 1445: ! 1446: /* ! 1447: * ! 1448: * Called to to load font info for font *s on position n using the binary tables ! 1449: * located in directory *s1 (if it's not NULL or the empty string). ! 1450: * ! 1451: */ ! 1452: ! 1453: ! 1454: if ( n < 0 || n > NFONT ) /* make sure it's a legal position */ ! 1455: error(FATAL, "illegal fp command %d %s", n, s); ! 1456: ! 1457: /* ! 1458: * ! 1459: * If the font's already loaded on position n there's nothing to do. ! 1460: * ! 1461: */ ! 1462: ! 1463: if ( fontbase[n] != NULL && strcmp(s, fontbase[n]->namefont) == 0 ) ! 1464: return; ! 1465: ! 1466: /* ! 1467: * ! 1468: * If *s1 isn't NULL or the NULL string that's what we'll use for the font ! 1469: * directory, otherwise use *fontdir. ! 1470: * ! 1471: */ ! 1472: ! 1473: if ( s1 == NULL || s1[0] == '\0' ) ! 1474: sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, s); ! 1475: else sprintf(temp, "%s/%s.out", s1, s); ! 1476: ! 1477: if ( (fin = open(temp, 0)) < 0 ) { ! 1478: sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, mapfont(s)); ! 1479: if ( (fin = open(temp, 0)) < 0 ) ! 1480: error(FATAL, "can't open font table %s", temp); ! 1481: } /* End if */ ! 1482: ! 1483: if ( fontbase[n] != NULL ) /* something's already there */ ! 1484: free(fontbase[n]); /* so release the memory first */ ! 1485: ! 1486: fontbase[n] = (struct Font *) malloc(3*255 + dev.nchtab + (128-32) + sizeof(struct Font)); ! 1487: if ( fontbase[n] == NULL ) ! 1488: error(FATAL, "Out of space in loadfont %s", s); ! 1489: ! 1490: read(fin, fontbase[n], 3*255 + nchtab+128-32 + sizeof(struct Font)); ! 1491: close(fin); ! 1492: ! 1493: if ( smnt == 0 && fontbase[n]->specfont == 1 ) ! 1494: smnt = n; ! 1495: ! 1496: nw = fontbase[n]->nwfont & BMASK; ! 1497: widthtab[n] = (char *) fontbase[n] + sizeof(struct Font); ! 1498: codetab[n] = (char *) widthtab[n] + 2 * nw; ! 1499: fitab[n] = (char *) widthtab[n] + 3 * nw; ! 1500: ! 1501: t_fp(n, fontbase[n]->namefont, fontbase[n]->intname); ! 1502: ! 1503: if ( debug == ON ) ! 1504: fontprint(n); ! 1505: ! 1506: } /* End of loadfont */ ! 1507: ! 1508: ! 1509: /*****************************************************************************/ ! 1510: ! 1511: ! 1512: char *mapfont(name) ! 1513: ! 1514: ! 1515: char *name; /* name of the font troff wants */ ! 1516: ! 1517: ! 1518: { ! 1519: ! 1520: ! 1521: int i; /* loop index for fontmap[] */ ! 1522: ! 1523: ! 1524: /* ! 1525: * ! 1526: * Only called from loadfont() when we haven't been able to open the font file ! 1527: * that troff asked for. We take the font name and map it into an appropriate ! 1528: * substitute. If the initial lookup fails we do a simple mapping that should ! 1529: * be good enough most of the time. ! 1530: * ! 1531: * This stuff should only be needed when we're emulating another printer like ! 1532: * the APS-5. ! 1533: * ! 1534: */ ! 1535: ! 1536: ! 1537: for ( i = 0; fontmap[i].name != NULL; i++ ) ! 1538: if ( strcmp(name, fontmap[i].name) == 0 ) ! 1539: return(fontmap[i].use); ! 1540: ! 1541: switch ( *++name ) { ! 1542: case 'I': ! 1543: case 'B': ! 1544: return(name); ! 1545: ! 1546: case 'X': ! 1547: return("BI"); ! 1548: ! 1549: default: ! 1550: return("R"); ! 1551: } /* End switch */ ! 1552: ! 1553: } /* End of mapfont */ ! 1554: ! 1555: ! 1556: /*****************************************************************************/ ! 1557: ! 1558: ! 1559: convint(c) ! 1560: ! 1561: ! 1562: unsigned char c; ! 1563: ! 1564: ! 1565: { ! 1566: ! 1567: ! 1568: /* ! 1569: * ! 1570: * Converts a character to a proper 2's complement integer. Really just used ! 1571: * on 3b's when we're reading raster tables in the old format. There's ! 1572: * really no need to make this a separate routine - at least I don't ! 1573: * think there is. Should just redefine CONVINT() macro so it does this ! 1574: * stuff. ! 1575: * ! 1576: */ ! 1577: ! 1578: ! 1579: return((c & 0200) ? ((256 - c) * -1) : c); ! 1580: ! 1581: } /* End of convint */ ! 1582: ! 1583: ! 1584: /*****************************************************************************/ ! 1585: ! 1586: ! 1587: t_init(reinit) ! 1588: ! 1589: ! 1590: int reinit; ! 1591: ! 1592: ! 1593: { ! 1594: ! 1595: ! 1596: int i; ! 1597: FILE *tmpfile(); ! 1598: ! 1599: ! 1600: /* ! 1601: * ! 1602: * Called to initialize the printer and associated variables. reinit will ! 1603: * be zero when the "x init" command was found in the output file, while ! 1604: * it will be non-zero when the routine is called to set things up for a ! 1605: * new page. ! 1606: * ! 1607: */ ! 1608: ! 1609: ! 1610: if (! reinit) { ! 1611: for (i = 0; i < nchtab; i++) ! 1612: if (strcmp(&chname[chtab[i]], "l.") == 0) ! 1613: break; ! 1614: if (i < nchtab) { ! 1615: drawdot = i + 128; ! 1616: drawsize = 1; ! 1617: } else { ! 1618: drawdot = '.'; ! 1619: drawsize = 2; /* half size */ ! 1620: } ! 1621: ! 1622: xfac = (float) pres / res * aspect; ! 1623: yfac = (float) pres / res; ! 1624: ! 1625: putc(ASETPEN, tf); ! 1626: putc(penwidth, tf); ! 1627: ! 1628: if ( mode == LANDSCAPE ) { ! 1629: putc(ASETHV, tf); ! 1630: putc(0107, tf); ! 1631: angle = ROT_270; ! 1632: } /* End if */ ! 1633: } ! 1634: ! 1635: hpos = vpos = 0; ! 1636: setsize(t_size(10)); /* start somewhere */ ! 1637: ! 1638: } /* End of t_init */ ! 1639: ! 1640: ! 1641: /*****************************************************************************/ ! 1642: ! 1643: ! 1644: t_page(pg) ! 1645: ! 1646: ! 1647: { ! 1648: ! 1649: ! 1650: register int i, j, n; ! 1651: register unsigned char *p; ! 1652: ! 1653: ! 1654: /* ! 1655: * ! 1656: * Get the printer and everything else ready for a new page. If the -o ! 1657: * option has been used only selected pages will be printed. If output ! 1658: * is ON when this routine is called we'll write the endpage Impress ! 1659: * command to the output file. If we're supposed to be doing output for ! 1660: * page pg we'll write the APAGE command out, and that will cause the ! 1661: * horizontal and vertical positions (in Impress) to be set to zero. hpos ! 1662: * and vpos are initialized in routine t_init(), although I really don't ! 1663: * see any reason why we couldn't just skip the call and do it here. ! 1664: * ! 1665: */ ! 1666: ! 1667: ! 1668: if ( debug == ON ) ! 1669: fprintf(stderr, "t_page %d, output=%d\n", pg, output); ! 1670: ! 1671: pageno = pg; ! 1672: ! 1673: if ( output == ON ) /* doing output for last page */ ! 1674: putc(AENDP, tf); ! 1675: ! 1676: if ( (output = in_olist(pg)) == ON ) { /* print this page */ ! 1677: putc(APAGE, tf); ! 1678: acctpages++; ! 1679: } ! 1680: ! 1681: lastx = lasty = -1; ! 1682: t_init(1); /* setup for this page */ ! 1683: ! 1684: } /* End of t_page */ ! 1685: ! 1686: ! 1687: /*****************************************************************************/ ! 1688: ! 1689: ! 1690: t_newline() ! 1691: ! 1692: ! 1693: { ! 1694: ! 1695: ! 1696: /* ! 1697: * ! 1698: * Read an "n a b" command in the input file and are ready to start a new ! 1699: * line. There really isn't much else this routine can do besides set the ! 1700: * horizontal position to zero. Anyway troff takes care of any needed ! 1701: * positioning before it starts printing text. ! 1702: * ! 1703: */ ! 1704: ! 1705: ! 1706: hpos = 0; ! 1707: ! 1708: } /* End of t_newline */ ! 1709: ! 1710: ! 1711: /*****************************************************************************/ ! 1712: ! 1713: ! 1714: t_size(n) ! 1715: ! 1716: ! 1717: int n; /* convert this point size */ ! 1718: ! 1719: ! 1720: { ! 1721: ! 1722: ! 1723: int i; ! 1724: ! 1725: ! 1726: /* ! 1727: * ! 1728: * Converts a point size into an internal size that can be used as an ! 1729: * index into the pstab[] array. Actually the internal size is defined as ! 1730: * one plus the index of the least upper bound of n in pstab[] or nsizes ! 1731: * if n is larger than all the listed sizes. ! 1732: * ! 1733: */ ! 1734: ! 1735: if (n <= pstab[0]) ! 1736: return(1); ! 1737: else if (n >= pstab[nsizes-1]) ! 1738: return(nsizes); ! 1739: for (i = 0; n > pstab[i]; i++) ; ! 1740: ! 1741: return(i+1); ! 1742: ! 1743: } /* End of t_size */ ! 1744: ! 1745: ! 1746: /*****************************************************************************/ ! 1747: ! 1748: ! 1749: t_charht(n) ! 1750: ! 1751: ! 1752: int n; /* use this as the character height */ ! 1753: ! 1754: ! 1755: { ! 1756: ! 1757: ! 1758: /* ! 1759: * ! 1760: * Although it can be done on some typesetters, like the APS-5, it's ignored ! 1761: * on Imagen's bitmap printers like the Imprint-10 and the 8/300. It would ! 1762: * be absurd to keep any extra raster files around just so we could implement ! 1763: * this command, and right now there's no Impress command to do it to ! 1764: * downloaded glyphs. ! 1765: * ! 1766: */ ! 1767: ! 1768: ! 1769: } /* End of t_charht */ ! 1770: ! 1771: ! 1772: /*****************************************************************************/ ! 1773: ! 1774: ! 1775: t_slant(n) ! 1776: ! 1777: ! 1778: int n; /* slant characters this many degrees */ ! 1779: ! 1780: ! 1781: { ! 1782: ! 1783: ! 1784: /* ! 1785: * ! 1786: * As with troff's height command, there's no simple way to slant characters ! 1787: * on Imagen's bitmap printers and it's really not worth any effort to try ! 1788: * and make it work. ! 1789: * ! 1790: */ ! 1791: ! 1792: ! 1793: } /* End of t_slant */ ! 1794: ! 1795: ! 1796: /*****************************************************************************/ ! 1797: ! 1798: ! 1799: t_font(s) ! 1800: ! 1801: ! 1802: char *s; ! 1803: ! 1804: ! 1805: { ! 1806: ! 1807: ! 1808: int n; ! 1809: ! 1810: ! 1811: /* ! 1812: * ! 1813: * Just converts the string *s into an integer and checks to make sure the ! 1814: * number is a legal font position. If it's not we'll print an error message ! 1815: * and then quit. di10 handled bad requests a little differently. Instead ! 1816: * of treating mistakes as FATAL errors it would return 1 as the font ! 1817: * number. ! 1818: * ! 1819: */ ! 1820: ! 1821: ! 1822: if ( (n = atoi(s)) < 0 || n > nfonts ) ! 1823: error(FATAL, "illegal font position %d", n); ! 1824: ! 1825: return(n); ! 1826: ! 1827: } /* End of t_font */ ! 1828: ! 1829: ! 1830: /*****************************************************************************/ ! 1831: ! 1832: ! 1833: t_reset(c) ! 1834: ! 1835: ! 1836: int c; /* pause or restart */ ! 1837: ! 1838: ! 1839: { ! 1840: ! 1841: ! 1842: /* ! 1843: * ! 1844: * Called from devcntrl() when we've found an "x stop" or "x pause" command. ! 1845: * There's really nothing we need to do for Imagen's bitmap printers, and ! 1846: * leaving the final cleanup (ie. AEOF code etc.) to someone else means ! 1847: * we should be able to cat a bunch of troff output files together and ! 1848: * have them all printed properly. ! 1849: * ! 1850: */ ! 1851: ! 1852: ! 1853: } /* End of t_reset */ ! 1854: ! 1855: ! 1856: /*****************************************************************************/ ! 1857: ! 1858: ! 1859: t_wrapup() ! 1860: ! 1861: ! 1862: { ! 1863: ! 1864: ! 1865: /* ! 1866: * ! 1867: * We're finished with all the input files and all that's left to do is ! 1868: * end the last page we were working on and then mark the end of the Impress ! 1869: * file. ! 1870: * ! 1871: */ ! 1872: ! 1873: ! 1874: putc(AENDP, tf); ! 1875: putc(AEOF, tf); ! 1876: ! 1877: } /* End of t_wrapup */ ! 1878: ! 1879: ! 1880: /*****************************************************************************/ ! 1881: ! 1882: ! 1883: t_trailer() ! 1884: ! 1885: ! 1886: { ! 1887: ! 1888: ! 1889: /* ! 1890: * ! 1891: * Called from devcntrl() when an "x trailer" command is found. There's ! 1892: * nothing we need to do here for Imagen's printers. ! 1893: * ! 1894: */ ! 1895: ! 1896: ! 1897: ! 1898: } /* End of t_trailer */ ! 1899: ! 1900: ! 1901: /*****************************************************************************/ ! 1902: ! 1903: ! 1904: hgoto(n) ! 1905: ! 1906: ! 1907: int n; /* where we want to be */ ! 1908: ! 1909: ! 1910: { ! 1911: ! 1912: ! 1913: /* ! 1914: * ! 1915: * Want to be at this absolute horizontal position next - usually will ! 1916: * get these motion commands right before printing a character. ! 1917: * ! 1918: */ ! 1919: ! 1920: ! 1921: hpos = n; ! 1922: ! 1923: } /* End of hgoto */ ! 1924: ! 1925: ! 1926: /*****************************************************************************/ ! 1927: ! 1928: ! 1929: hmot(n) ! 1930: ! 1931: ! 1932: int n; /* move this far from where we are */ ! 1933: ! 1934: ! 1935: { ! 1936: ! 1937: ! 1938: /* ! 1939: * ! 1940: * Handles relative horizontal motion. troff's current positon as recorded ! 1941: * in hpos is changed by n units. ! 1942: * ! 1943: */ ! 1944: ! 1945: ! 1946: hpos += n; ! 1947: ! 1948: } /* End of hmot */ ! 1949: ! 1950: ! 1951: /*****************************************************************************/ ! 1952: ! 1953: ! 1954: vgoto(n) ! 1955: ! 1956: ! 1957: int n; /* new vertical position */ ! 1958: ! 1959: ! 1960: { ! 1961: ! 1962: ! 1963: /* ! 1964: * ! 1965: * Moves vertically in troff's coordinate system to absolute position n. ! 1966: * ! 1967: */ ! 1968: ! 1969: ! 1970: vpos = n; ! 1971: ! 1972: } /* End of vgoto */ ! 1973: ! 1974: ! 1975: /*****************************************************************************/ ! 1976: ! 1977: ! 1978: vmot(n) ! 1979: ! 1980: ! 1981: int n; /* move this far vertically */ ! 1982: ! 1983: ! 1984: { ! 1985: ! 1986: ! 1987: /* ! 1988: * ! 1989: * Handles relative vertical motion of n units in troff's coordinate system. ! 1990: * ! 1991: */ ! 1992: ! 1993: ! 1994: vpos += n; ! 1995: ! 1996: } /* End of vmot */ ! 1997: ! 1998: ! 1999: /*****************************************************************************/ ! 2000: ! 2001: ! 2002: put1s(s) ! 2003: ! 2004: ! 2005: register char *s; ! 2006: ! 2007: ! 2008: { ! 2009: ! 2010: ! 2011: static int i = 0; /* last one we found - usually */ ! 2012: ! 2013: ! 2014: /* ! 2015: * ! 2016: * Does whatever is necessary to have special character *s printed. If we're ! 2017: * doing output on this page we'll look the character up using chname[] and ! 2018: * chtab[]. The first array contains all the special character names ! 2019: * separated by '\0' that are mentioned in the typesetter's DESC file, while ! 2020: * chname[i] points to the start of character i in chname[]. Both arrays ! 2021: * come from the DESC.out file for printer *devname which is found in ! 2022: * *fontdir (wherever that might be). ! 2023: * ! 2024: */ ! 2025: ! 2026: ! 2027: if ( output == OFF ) ! 2028: return; ! 2029: ! 2030: if ( debug ) ! 2031: printf("%s", s); ! 2032: ! 2033: if (strcmp(s, &chname[chtab[i]]) != 0) ! 2034: for (i = 0; i < nchtab; i++) ! 2035: if (strcmp(&chname[chtab[i]], s) == 0) ! 2036: break; ! 2037: if (i < nchtab) ! 2038: put1(i + 128); ! 2039: else ! 2040: i = 0; ! 2041: ! 2042: } /* End of put1s */ ! 2043: ! 2044: ! 2045: /*****************************************************************************/ ! 2046: ! 2047: ! 2048: put1(c) ! 2049: ! 2050: ! 2051: register int c; /* print this character */ ! 2052: ! 2053: ! 2054: { ! 2055: ! 2056: ! 2057: char *pw; ! 2058: register char *p; ! 2059: register int i, j, k; ! 2060: int ofont, code; ! 2061: ! 2062: ! 2063: /* ! 2064: * ! 2065: * Arranges to have character c printed. If c < 128 it's a simple ASCII character, ! 2066: * otherwise it's a special character. We subtract 32 from c because non-graphic ! 2067: * ASCII characters aren't included in the tables. ! 2068: * ! 2069: */ ! 2070: ! 2071: ! 2072: lastc = c; /* charlib() may need the real name */ ! 2073: c -= 32; ! 2074: ! 2075: if ( c <= 0 ) { ! 2076: if ( debug == ON ) ! 2077: fprintf(tf, "non-exist 0%o\n", lastc); ! 2078: return; ! 2079: } /* End if */ ! 2080: ! 2081: k = ofont = font; ! 2082: i = fitab[font][c] & BMASK; ! 2083: ! 2084: if ( i != 0 ) { /* it's on this font */ ! 2085: p = codetab[font]; ! 2086: pw = widthtab[font]; ! 2087: } else if ( smnt > 0 ) { /* on special (we hope) */ ! 2088: for ( k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1) ) { ! 2089: if ( k == 0 ) continue; ! 2090: if ( (i = fitab[k][c] & BMASK) != 0 ) { ! 2091: p = codetab[k]; ! 2092: pw = widthtab[k]; ! 2093: setfont(k); ! 2094: break; ! 2095: } /* End if */ ! 2096: } /* End for */ ! 2097: } /* End else */ ! 2098: ! 2099: if ( i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts ) { ! 2100: if ( debug == ON ) ! 2101: fprintf(tf, "not found 0%o\n", lastc); ! 2102: if ( font != ofont ) setfont(ofont); ! 2103: return; ! 2104: } /* End if */ ! 2105: ! 2106: lastw = ((pw[i] & BMASK) * pstab[size-1] + dev.unitwidth/2) / dev.unitwidth; ! 2107: ! 2108: if ( debug == ON ) { ! 2109: if ( isprint(lastc) ) ! 2110: fprintf(tf, "%c %d\n", lastc, code); ! 2111: else fprintf(tf, "%03o %d\n", lastc, code); ! 2112: } else oput(code); ! 2113: ! 2114: if ( font != ofont ) ! 2115: setfont(ofont); ! 2116: ! 2117: } /* End of put1 */ ! 2118: ! 2119: ! 2120: /*****************************************************************************/ ! 2121: ! 2122: ! 2123: setsize(n) ! 2124: ! 2125: ! 2126: int n; /* new internal size */ ! 2127: ! 2128: ! 2129: { ! 2130: ! 2131: ! 2132: /* ! 2133: * ! 2134: * We want to use internal size n for now, where n is an index into *pstab ! 2135: * where we can find the closest available approximation to the requested ! 2136: * point size. ! 2137: * ! 2138: */ ! 2139: ! 2140: ! 2141: size = n; ! 2142: ! 2143: } /* End of setsize */ ! 2144: ! 2145: ! 2146: /*****************************************************************************/ ! 2147: ! 2148: ! 2149: t_fp(n, s, si) ! 2150: ! 2151: ! 2152: int n; /* font position to update */ ! 2153: char *s; /* it now contains this font */ ! 2154: char *si; /* and this is its internal number */ ! 2155: ! 2156: ! 2157: { ! 2158: ! 2159: ! 2160: /* ! 2161: * ! 2162: * Called when we've loaded font *s in position n. The font position info ! 2163: * is recorded in fontname[]. ! 2164: * ! 2165: */ ! 2166: ! 2167: ! 2168: fontname[n].name = s; ! 2169: fontname[n].number = atoi(si); ! 2170: if ( n == lastfont ) lastfont = -1; /* force getfontdata() call */ ! 2171: ! 2172: } /* End of t_fp */ ! 2173: ! 2174: ! 2175: /*****************************************************************************/ ! 2176: ! 2177: ! 2178: setfont(n) ! 2179: ! 2180: ! 2181: int n; /* this will be the current font */ ! 2182: ! 2183: ! 2184: { ! 2185: ! 2186: ! 2187: /* ! 2188: * ! 2189: * Job now wants to use the font loaded in position n. The variable font ! 2190: * keeps track of which one we're currently using. If the requested positon ! 2191: * is out of range we'll just quit. ! 2192: * ! 2193: */ ! 2194: ! 2195: ! 2196: if ( output == OFF ) ! 2197: return; ! 2198: ! 2199: if (n < 0 || n > NFONT) ! 2200: error(FATAL, "illegal font %d", n); ! 2201: ! 2202: font = n; ! 2203: ! 2204: } /* End of setfont */ ! 2205: ! 2206: ! 2207: /*****************************************************************************/ ! 2208: ! 2209: ! 2210: oput(c) ! 2211: ! 2212: ! 2213: int c; /* want to print this character */ ! 2214: ! 2215: ! 2216: { ! 2217: ! 2218: ! 2219: int x, y; /* current scaled position */ ! 2220: int member; /* glyph number for c in current family */ ! 2221: ! 2222: ! 2223: /* ! 2224: * ! 2225: * Arranges to print the character whose code is c in the current font. ! 2226: * The old and new raster file formats are supported. ! 2227: * ! 2228: */ ! 2229: ! 2230: ! 2231: if ( output == OFF ) ! 2232: return; ! 2233: ! 2234: if ( rastformat == OLD_FORMAT ) { ! 2235: xychar(c, fontname[font].name, pstab[size-1], lastw, tf); ! 2236: return; ! 2237: } /* End if */ ! 2238: ! 2239: if ( font != lastfont || size != lastsize ) { ! 2240: if ( isresident(fontname[font].name) == FALSE ) ! 2241: getrastdata(fontname[font].name, mapsize(fontname[font].name, pstab[size-1])); ! 2242: else getresdata(fontname[font].name, mapsize(fontname[font].name, pstab[size-1]), tf); ! 2243: lastfont = font; ! 2244: lastsize = size; ! 2245: } /* End if */ ! 2246: ! 2247: member = download(c, lastw, angle, tf); ! 2248: ! 2249: x = hpos * xfac + xoffset + .5; ! 2250: y = vpos * yfac + yoffset + .5; ! 2251: ! 2252: if ( y != lasty ) { ! 2253: putc(ASETAV, tf); ! 2254: putint(y, tf); ! 2255: lasty = y; ! 2256: } /* End if */ ! 2257: ! 2258: if ( ABS(x - lastx) > SLOP ) { ! 2259: putc(ASETAH, tf); ! 2260: putint(x, tf); ! 2261: lastx = x + fam->advance[member]; ! 2262: } else lastx += fam->advance[member]; ! 2263: ! 2264: putc(member, tf); ! 2265: ! 2266: } /* End of oput */ ! 2267: ! 2268: ! 2269: /*****************************************************************************/ ! 2270: ! 2271: ! 2272: mapsize(name, ps) ! 2273: ! 2274: ! 2275: char *name; /* name of the font */ ! 2276: int ps; /* point size troff wants to use */ ! 2277: ! 2278: ! 2279: { ! 2280: ! 2281: ! 2282: int i, j; ! 2283: ! 2284: ! 2285: /* ! 2286: * ! 2287: * Uses the data that's been filled in from RASTLIST to map point size ! 2288: * ps font font *name into the best size available in our raster tables. ! 2289: * If no RASTLIST file was used rastsize will be zero and we'll just ! 2290: * assume that any size that's aske for is available. ! 2291: * ! 2292: */ ! 2293: ! 2294: ! 2295: if ( maxrast == 0 ) /* don't have any size data */ ! 2296: return(ps); ! 2297: ! 2298: for ( i = 0; i < maxrast; i++ ) ! 2299: if ( strcmp(name, sizedata[i].name) == 0 ) ! 2300: break; ! 2301: ! 2302: if ( i >= maxrast ) /* didn't find the font */ ! 2303: error(FATAL, "missing raster list data for font %s", name); ! 2304: ! 2305: for ( j = 1, ps = (ps * pres) / rres; ps >= sizedata[i].sizes[j]; j++ ) ; ! 2306: ! 2307: return(sizedata[i].sizes[--j]); ! 2308: ! 2309: } /* End of mapsize */ ! 2310: ! 2311: ! 2312: /*****************************************************************************/ ! 2313: ! 2314:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.