1*219b2ee8SDavid du Colombier /* 2*219b2ee8SDavid du Colombier * 3*219b2ee8SDavid du Colombier * postprint - PostScript translator for ASCII files. 4*219b2ee8SDavid du Colombier * 5*219b2ee8SDavid du Colombier * A simple program that translates ASCII files into PostScript. All it really 6*219b2ee8SDavid du Colombier * does is expand tabs and backspaces, handle character quoting, print text lines, 7*219b2ee8SDavid du Colombier * and control when pages are started based on the requested number of lines per 8*219b2ee8SDavid du Colombier * page. 9*219b2ee8SDavid du Colombier * 10*219b2ee8SDavid du Colombier * The PostScript prologue is copied from *prologue before any of the input files 11*219b2ee8SDavid du Colombier * are translated. The program expects that the following procedures are defined 12*219b2ee8SDavid du Colombier * in that file: 13*219b2ee8SDavid du Colombier * 14*219b2ee8SDavid du Colombier * setup 15*219b2ee8SDavid du Colombier * 16*219b2ee8SDavid du Colombier * mark ... setup - 17*219b2ee8SDavid du Colombier * 18*219b2ee8SDavid du Colombier * Handles special initialization stuff that depends on how the program 19*219b2ee8SDavid du Colombier * was called. Expects to find a mark followed by key/value pairs on the 20*219b2ee8SDavid du Colombier * stack. The def operator is applied to each pair up to the mark, then 21*219b2ee8SDavid du Colombier * the default state is set up. 22*219b2ee8SDavid du Colombier * 23*219b2ee8SDavid du Colombier * pagesetup 24*219b2ee8SDavid du Colombier * 25*219b2ee8SDavid du Colombier * page pagesetup - 26*219b2ee8SDavid du Colombier * 27*219b2ee8SDavid du Colombier * Does whatever is needed to set things up for the next page. Expects 28*219b2ee8SDavid du Colombier * to find the current page number on the stack. 29*219b2ee8SDavid du Colombier * 30*219b2ee8SDavid du Colombier * l 31*219b2ee8SDavid du Colombier * 32*219b2ee8SDavid du Colombier * string l - 33*219b2ee8SDavid du Colombier * 34*219b2ee8SDavid du Colombier * Prints string starting in the first column and then goes to the next 35*219b2ee8SDavid du Colombier * line. 36*219b2ee8SDavid du Colombier * 37*219b2ee8SDavid du Colombier * L 38*219b2ee8SDavid du Colombier * 39*219b2ee8SDavid du Colombier * mark string column string column ... L mark 40*219b2ee8SDavid du Colombier * 41*219b2ee8SDavid du Colombier * Prints each string on the stack starting at the horizontal position 42*219b2ee8SDavid du Colombier * selected by column. Used when tabs and spaces can be sufficiently well 43*219b2ee8SDavid du Colombier * compressed to make the printer overhead worthwhile. Always used when 44*219b2ee8SDavid du Colombier * we have to back up. 45*219b2ee8SDavid du Colombier * 46*219b2ee8SDavid du Colombier * LL 47*219b2ee8SDavid du Colombier * 48*219b2ee8SDavid du Colombier * mark string column string column ... LL mark 49*219b2ee8SDavid du Colombier * 50*219b2ee8SDavid du Colombier * Like L, but only used to prevent potential PostScript stack overflow 51*219b2ee8SDavid du Colombier * from too many string/column pairs. Stays on the current line. It will 52*219b2ee8SDavid du Colombier * not be needed often!! 53*219b2ee8SDavid du Colombier * 54*219b2ee8SDavid du Colombier * done 55*219b2ee8SDavid du Colombier * 56*219b2ee8SDavid du Colombier * done 57*219b2ee8SDavid du Colombier * 58*219b2ee8SDavid du Colombier * Makes sure the last page is printed. Only needed when we're printing 59*219b2ee8SDavid du Colombier * more than one page on each sheet of paper. 60*219b2ee8SDavid du Colombier * 61*219b2ee8SDavid du Colombier * Almost everything has been changed in this version of postprint. The program 62*219b2ee8SDavid du Colombier * is more intelligent, especially about tabs, spaces, and backspacing, and as a 63*219b2ee8SDavid du Colombier * result output files usually print faster. Output files also now conform to 64*219b2ee8SDavid du Colombier * Adobe's file structuring conventions, which is undoubtedly something I should 65*219b2ee8SDavid du Colombier * have done in the first version of the program. If the number of lines per page 66*219b2ee8SDavid du Colombier * is set to 0, which can be done using the -l option, pointsize will be used to 67*219b2ee8SDavid du Colombier * guess a reasonable value. The estimate is based on the values of LINESPP, 68*219b2ee8SDavid du Colombier * POINTSIZE, and pointsize, and assumes LINESPP lines would fit on a page if 69*219b2ee8SDavid du Colombier * we printed in size POINTSIZE. Selecting a point size using the -s option and 70*219b2ee8SDavid du Colombier * adding -l0 to the command line forces the guess to be made. 71*219b2ee8SDavid du Colombier * 72*219b2ee8SDavid du Colombier * Many default values, like the magnification and orientation, are defined in 73*219b2ee8SDavid du Colombier * the prologue, which is where they belong. If they're changed (by options), an 74*219b2ee8SDavid du Colombier * appropriate definition is made after the prologue is added to the output file. 75*219b2ee8SDavid du Colombier * The -P option passes arbitrary PostScript through to the output file. Among 76*219b2ee8SDavid du Colombier * other things it can be used to set (or change) values that can't be accessed by 77*219b2ee8SDavid du Colombier * other options. 78*219b2ee8SDavid du Colombier * 79*219b2ee8SDavid du Colombier */ 80*219b2ee8SDavid du Colombier 81*219b2ee8SDavid du Colombier #include <stdio.h> 82*219b2ee8SDavid du Colombier #include <signal.h> 83*219b2ee8SDavid du Colombier #include <ctype.h> 84*219b2ee8SDavid du Colombier #ifdef plan9 85*219b2ee8SDavid du Colombier #define isascii(c) ((unsigned char)(c)<=0177) 86*219b2ee8SDavid du Colombier #endif 87*219b2ee8SDavid du Colombier #include <sys/types.h> 88*219b2ee8SDavid du Colombier #include <fcntl.h> 89*219b2ee8SDavid du Colombier 90*219b2ee8SDavid du Colombier #include "comments.h" /* PostScript file structuring comments */ 91*219b2ee8SDavid du Colombier #include "gen.h" /* general purpose definitions */ 92*219b2ee8SDavid du Colombier #include "path.h" /* for the prologue */ 93*219b2ee8SDavid du Colombier #include "ext.h" /* external variable declarations */ 94*219b2ee8SDavid du Colombier #include "postprint.h" /* a few special definitions */ 95*219b2ee8SDavid du Colombier 96*219b2ee8SDavid du Colombier char *optnames = "a:c:ef:l:m:n:o:p:r:s:t:x:y:A:C:E:J:L:P:R:DI"; 97*219b2ee8SDavid du Colombier 98*219b2ee8SDavid du Colombier char *prologue = POSTPRINT; /* default PostScript prologue */ 99*219b2ee8SDavid du Colombier char *formfile = FORMFILE; /* stuff for multiple pages per sheet */ 100*219b2ee8SDavid du Colombier 101*219b2ee8SDavid du Colombier int formsperpage = 1; /* page images on each piece of paper */ 102*219b2ee8SDavid du Colombier int copies = 1; /* and this many copies of each sheet */ 103*219b2ee8SDavid du Colombier 104*219b2ee8SDavid du Colombier int linespp = LINESPP; /* number of lines per page */ 105*219b2ee8SDavid du Colombier int pointsize = POINTSIZE; /* in this point size */ 106*219b2ee8SDavid du Colombier int tabstops = TABSTOPS; /* tabs set at these columns */ 107*219b2ee8SDavid du Colombier int crmode = 0; /* carriage return mode - 0, 1, or 2 */ 108*219b2ee8SDavid du Colombier int extended = TRUE; /* use escapes for unprintable chars */ 109*219b2ee8SDavid du Colombier 110*219b2ee8SDavid du Colombier int col = 1; /* next character goes in this column */ 111*219b2ee8SDavid du Colombier int line = 1; /* on this line */ 112*219b2ee8SDavid du Colombier 113*219b2ee8SDavid du Colombier int stringcount = 0; /* number of strings on the stack */ 114*219b2ee8SDavid du Colombier int stringstart = 1; /* column where current one starts */ 115*219b2ee8SDavid du Colombier 116*219b2ee8SDavid du Colombier Fontmap fontmap[] = FONTMAP; /* for translating font names */ 117*219b2ee8SDavid du Colombier char *fontname = "Courier"; /* use this PostScript font */ 118*219b2ee8SDavid du Colombier 119*219b2ee8SDavid du Colombier int page = 0; /* page we're working on */ 120*219b2ee8SDavid du Colombier int printed = 0; /* printed this many pages */ 121*219b2ee8SDavid du Colombier 122*219b2ee8SDavid du Colombier FILE *fp_in = stdin; /* read from this file */ 123*219b2ee8SDavid du Colombier FILE *fp_out = stdout; /* and write stuff here */ 124*219b2ee8SDavid du Colombier FILE *fp_acct = NULL; /* for accounting data */ 125*219b2ee8SDavid du Colombier 126*219b2ee8SDavid du Colombier /*****************************************************************************/ 127*219b2ee8SDavid du Colombier 128*219b2ee8SDavid du Colombier main(agc, agv) 129*219b2ee8SDavid du Colombier 130*219b2ee8SDavid du Colombier int agc; 131*219b2ee8SDavid du Colombier char *agv[]; 132*219b2ee8SDavid du Colombier 133*219b2ee8SDavid du Colombier { 134*219b2ee8SDavid du Colombier 135*219b2ee8SDavid du Colombier /* 136*219b2ee8SDavid du Colombier * 137*219b2ee8SDavid du Colombier * A simple program that translates ASCII files into PostScript. If there's more 138*219b2ee8SDavid du Colombier * than one input file, each begins on a new page. 139*219b2ee8SDavid du Colombier * 140*219b2ee8SDavid du Colombier */ 141*219b2ee8SDavid du Colombier 142*219b2ee8SDavid du Colombier argc = agc; /* other routines may want them */ 143*219b2ee8SDavid du Colombier argv = agv; 144*219b2ee8SDavid du Colombier 145*219b2ee8SDavid du Colombier prog_name = argv[0]; /* really just for error messages */ 146*219b2ee8SDavid du Colombier 147*219b2ee8SDavid du Colombier init_signals(); /* sets up interrupt handling */ 148*219b2ee8SDavid du Colombier header(); /* PostScript header and prologue */ 149*219b2ee8SDavid du Colombier options(); /* handle the command line options */ 150*219b2ee8SDavid du Colombier setup(); /* for PostScript */ 151*219b2ee8SDavid du Colombier arguments(); /* followed by each input file */ 152*219b2ee8SDavid du Colombier done(); /* print the last page etc. */ 153*219b2ee8SDavid du Colombier account(); /* job accounting data */ 154*219b2ee8SDavid du Colombier 155*219b2ee8SDavid du Colombier exit(x_stat); /* not much could be wrong */ 156*219b2ee8SDavid du Colombier 157*219b2ee8SDavid du Colombier } /* End of main */ 158*219b2ee8SDavid du Colombier 159*219b2ee8SDavid du Colombier /*****************************************************************************/ 160*219b2ee8SDavid du Colombier 161*219b2ee8SDavid du Colombier init_signals() 162*219b2ee8SDavid du Colombier 163*219b2ee8SDavid du Colombier { 164*219b2ee8SDavid du Colombier 165*219b2ee8SDavid du Colombier /* 166*219b2ee8SDavid du Colombier * 167*219b2ee8SDavid du Colombier * Makes sure we handle interrupts. 168*219b2ee8SDavid du Colombier * 169*219b2ee8SDavid du Colombier */ 170*219b2ee8SDavid du Colombier 171*219b2ee8SDavid du Colombier if ( signal(SIGINT, interrupt) == SIG_IGN ) { 172*219b2ee8SDavid du Colombier signal(SIGINT, SIG_IGN); 173*219b2ee8SDavid du Colombier signal(SIGQUIT, SIG_IGN); 174*219b2ee8SDavid du Colombier signal(SIGHUP, SIG_IGN); 175*219b2ee8SDavid du Colombier } else { 176*219b2ee8SDavid du Colombier signal(SIGHUP, interrupt); 177*219b2ee8SDavid du Colombier signal(SIGQUIT, interrupt); 178*219b2ee8SDavid du Colombier } /* End else */ 179*219b2ee8SDavid du Colombier 180*219b2ee8SDavid du Colombier signal(SIGTERM, interrupt); 181*219b2ee8SDavid du Colombier 182*219b2ee8SDavid du Colombier } /* End of init_signals */ 183*219b2ee8SDavid du Colombier 184*219b2ee8SDavid du Colombier /*****************************************************************************/ 185*219b2ee8SDavid du Colombier 186*219b2ee8SDavid du Colombier header() 187*219b2ee8SDavid du Colombier 188*219b2ee8SDavid du Colombier { 189*219b2ee8SDavid du Colombier 190*219b2ee8SDavid du Colombier int ch; /* return value from getopt() */ 191*219b2ee8SDavid du Colombier int old_optind = optind; /* for restoring optind - should be 1 */ 192*219b2ee8SDavid du Colombier 193*219b2ee8SDavid du Colombier /* 194*219b2ee8SDavid du Colombier * 195*219b2ee8SDavid du Colombier * Scans the option list looking for things, like the prologue file, that we need 196*219b2ee8SDavid du Colombier * right away but could be changed from the default. Doing things this way is an 197*219b2ee8SDavid du Colombier * attempt to conform to Adobe's latest file structuring conventions. In particular 198*219b2ee8SDavid du Colombier * they now say there should be nothing executed in the prologue, and they have 199*219b2ee8SDavid du Colombier * added two new comments that delimit global initialization calls. Once we know 200*219b2ee8SDavid du Colombier * where things really are we write out the job header, follow it by the prologue, 201*219b2ee8SDavid du Colombier * and then add the ENDPROLOG and BEGINSETUP comments. 202*219b2ee8SDavid du Colombier * 203*219b2ee8SDavid du Colombier */ 204*219b2ee8SDavid du Colombier 205*219b2ee8SDavid du Colombier while ( (ch = getopt(argc, argv, optnames)) != EOF ) 206*219b2ee8SDavid du Colombier if ( ch == 'L' ) 207*219b2ee8SDavid du Colombier prologue = optarg; 208*219b2ee8SDavid du Colombier else if ( ch == '?' ) 209*219b2ee8SDavid du Colombier error(FATAL, ""); 210*219b2ee8SDavid du Colombier 211*219b2ee8SDavid du Colombier optind = old_optind; /* get ready for option scanning */ 212*219b2ee8SDavid du Colombier 213*219b2ee8SDavid du Colombier fprintf(stdout, "%s", CONFORMING); 214*219b2ee8SDavid du Colombier fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION); 215*219b2ee8SDavid du Colombier fprintf(stdout, "%s %s\n", DOCUMENTFONTS, ATEND); 216*219b2ee8SDavid du Colombier fprintf(stdout, "%s %s\n", PAGES, ATEND); 217*219b2ee8SDavid du Colombier fprintf(stdout, "%s", ENDCOMMENTS); 218*219b2ee8SDavid du Colombier 219*219b2ee8SDavid du Colombier if ( cat(prologue) == FALSE ) 220*219b2ee8SDavid du Colombier error(FATAL, "can't read %s", prologue); 221*219b2ee8SDavid du Colombier 222*219b2ee8SDavid du Colombier if ( DOROUND ) 223*219b2ee8SDavid du Colombier cat(ROUNDPAGE); 224*219b2ee8SDavid du Colombier 225*219b2ee8SDavid du Colombier fprintf(stdout, "%s", ENDPROLOG); 226*219b2ee8SDavid du Colombier fprintf(stdout, "%s", BEGINSETUP); 227*219b2ee8SDavid du Colombier fprintf(stdout, "mark\n"); 228*219b2ee8SDavid du Colombier 229*219b2ee8SDavid du Colombier } /* End of header */ 230*219b2ee8SDavid du Colombier 231*219b2ee8SDavid du Colombier /*****************************************************************************/ 232*219b2ee8SDavid du Colombier 233*219b2ee8SDavid du Colombier options() 234*219b2ee8SDavid du Colombier 235*219b2ee8SDavid du Colombier { 236*219b2ee8SDavid du Colombier 237*219b2ee8SDavid du Colombier int ch; /* return value from getopt() */ 238*219b2ee8SDavid du Colombier 239*219b2ee8SDavid du Colombier /* 240*219b2ee8SDavid du Colombier * 241*219b2ee8SDavid du Colombier * Reads and processes the command line options. Added the -P option so arbitrary 242*219b2ee8SDavid du Colombier * PostScript code can be passed through. Expect it could be useful for changing 243*219b2ee8SDavid du Colombier * definitions in the prologue for which options have not been defined. 244*219b2ee8SDavid du Colombier * 245*219b2ee8SDavid du Colombier * Although any PostScript font can be used, things will only work well for 246*219b2ee8SDavid du Colombier * constant width fonts. 247*219b2ee8SDavid du Colombier * 248*219b2ee8SDavid du Colombier */ 249*219b2ee8SDavid du Colombier 250*219b2ee8SDavid du Colombier while ( (ch = getopt(argc, argv, optnames)) != EOF ) { 251*219b2ee8SDavid du Colombier switch ( ch ) { 252*219b2ee8SDavid du Colombier 253*219b2ee8SDavid du Colombier case 'a': /* aspect ratio */ 254*219b2ee8SDavid du Colombier fprintf(stdout, "/aspectratio %s def\n", optarg); 255*219b2ee8SDavid du Colombier break; 256*219b2ee8SDavid du Colombier 257*219b2ee8SDavid du Colombier case 'c': /* copies */ 258*219b2ee8SDavid du Colombier copies = atoi(optarg); 259*219b2ee8SDavid du Colombier fprintf(stdout, "/#copies %s store\n", optarg); 260*219b2ee8SDavid du Colombier break; 261*219b2ee8SDavid du Colombier 262*219b2ee8SDavid du Colombier case 'e': /* obsolete - it's now always on */ 263*219b2ee8SDavid du Colombier extended = TRUE; 264*219b2ee8SDavid du Colombier break; 265*219b2ee8SDavid du Colombier 266*219b2ee8SDavid du Colombier case 'f': /* use this PostScript font */ 267*219b2ee8SDavid du Colombier fontname = get_font(optarg); 268*219b2ee8SDavid du Colombier fprintf(stdout, "/font /%s def\n", fontname); 269*219b2ee8SDavid du Colombier break; 270*219b2ee8SDavid du Colombier 271*219b2ee8SDavid du Colombier case 'l': /* lines per page */ 272*219b2ee8SDavid du Colombier linespp = atoi(optarg); 273*219b2ee8SDavid du Colombier break; 274*219b2ee8SDavid du Colombier 275*219b2ee8SDavid du Colombier case 'm': /* magnification */ 276*219b2ee8SDavid du Colombier fprintf(stdout, "/magnification %s def\n", optarg); 277*219b2ee8SDavid du Colombier break; 278*219b2ee8SDavid du Colombier 279*219b2ee8SDavid du Colombier case 'n': /* forms per page */ 280*219b2ee8SDavid du Colombier formsperpage = atoi(optarg); 281*219b2ee8SDavid du Colombier fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg); 282*219b2ee8SDavid du Colombier fprintf(stdout, "/formsperpage %s def\n", optarg); 283*219b2ee8SDavid du Colombier break; 284*219b2ee8SDavid du Colombier 285*219b2ee8SDavid du Colombier case 'o': /* output page list */ 286*219b2ee8SDavid du Colombier out_list(optarg); 287*219b2ee8SDavid du Colombier break; 288*219b2ee8SDavid du Colombier 289*219b2ee8SDavid du Colombier case 'p': /* landscape or portrait mode */ 290*219b2ee8SDavid du Colombier if ( *optarg == 'l' ) 291*219b2ee8SDavid du Colombier fprintf(stdout, "/landscape true def\n"); 292*219b2ee8SDavid du Colombier else fprintf(stdout, "/landscape false def\n"); 293*219b2ee8SDavid du Colombier break; 294*219b2ee8SDavid du Colombier 295*219b2ee8SDavid du Colombier case 'r': /* carriage return mode */ 296*219b2ee8SDavid du Colombier crmode = atoi(optarg); 297*219b2ee8SDavid du Colombier break; 298*219b2ee8SDavid du Colombier 299*219b2ee8SDavid du Colombier case 's': /* point size */ 300*219b2ee8SDavid du Colombier pointsize = atoi(optarg); 301*219b2ee8SDavid du Colombier fprintf(stdout, "/pointsize %s def\n", optarg); 302*219b2ee8SDavid du Colombier break; 303*219b2ee8SDavid du Colombier 304*219b2ee8SDavid du Colombier case 't': /* tabstops */ 305*219b2ee8SDavid du Colombier tabstops = atoi(optarg); 306*219b2ee8SDavid du Colombier break; 307*219b2ee8SDavid du Colombier 308*219b2ee8SDavid du Colombier case 'x': /* shift things horizontally */ 309*219b2ee8SDavid du Colombier fprintf(stdout, "/xoffset %s def\n", optarg); 310*219b2ee8SDavid du Colombier break; 311*219b2ee8SDavid du Colombier 312*219b2ee8SDavid du Colombier case 'y': /* and vertically on the page */ 313*219b2ee8SDavid du Colombier fprintf(stdout, "/yoffset %s def\n", optarg); 314*219b2ee8SDavid du Colombier break; 315*219b2ee8SDavid du Colombier 316*219b2ee8SDavid du Colombier case 'A': /* force job accounting */ 317*219b2ee8SDavid du Colombier case 'J': 318*219b2ee8SDavid du Colombier if ( (fp_acct = fopen(optarg, "a")) == NULL ) 319*219b2ee8SDavid du Colombier error(FATAL, "can't open accounting file %s", optarg); 320*219b2ee8SDavid du Colombier break; 321*219b2ee8SDavid du Colombier 322*219b2ee8SDavid du Colombier case 'C': /* copy file straight to output */ 323*219b2ee8SDavid du Colombier if ( cat(optarg) == FALSE ) 324*219b2ee8SDavid du Colombier error(FATAL, "can't read %s", optarg); 325*219b2ee8SDavid du Colombier break; 326*219b2ee8SDavid du Colombier 327*219b2ee8SDavid du Colombier case 'E': /* text font encoding */ 328*219b2ee8SDavid du Colombier fontencoding = optarg; 329*219b2ee8SDavid du Colombier break; 330*219b2ee8SDavid du Colombier 331*219b2ee8SDavid du Colombier case 'L': /* PostScript prologue file */ 332*219b2ee8SDavid du Colombier prologue = optarg; 333*219b2ee8SDavid du Colombier break; 334*219b2ee8SDavid du Colombier 335*219b2ee8SDavid du Colombier case 'P': /* PostScript pass through */ 336*219b2ee8SDavid du Colombier fprintf(stdout, "%s\n", optarg); 337*219b2ee8SDavid du Colombier break; 338*219b2ee8SDavid du Colombier 339*219b2ee8SDavid du Colombier case 'R': /* special global or page level request */ 340*219b2ee8SDavid du Colombier saverequest(optarg); 341*219b2ee8SDavid du Colombier break; 342*219b2ee8SDavid du Colombier 343*219b2ee8SDavid du Colombier case 'D': /* debug flag */ 344*219b2ee8SDavid du Colombier debug = ON; 345*219b2ee8SDavid du Colombier break; 346*219b2ee8SDavid du Colombier 347*219b2ee8SDavid du Colombier case 'I': /* ignore FATAL errors */ 348*219b2ee8SDavid du Colombier ignore = ON; 349*219b2ee8SDavid du Colombier break; 350*219b2ee8SDavid du Colombier 351*219b2ee8SDavid du Colombier case '?': /* don't understand the option */ 352*219b2ee8SDavid du Colombier error(FATAL, ""); 353*219b2ee8SDavid du Colombier break; 354*219b2ee8SDavid du Colombier 355*219b2ee8SDavid du Colombier default: /* don't know what to do for ch */ 356*219b2ee8SDavid du Colombier error(FATAL, "missing case for option %c\n", ch); 357*219b2ee8SDavid du Colombier break; 358*219b2ee8SDavid du Colombier } /* End switch */ 359*219b2ee8SDavid du Colombier } /* End while */ 360*219b2ee8SDavid du Colombier 361*219b2ee8SDavid du Colombier argc -= optind; /* get ready for non-option args */ 362*219b2ee8SDavid du Colombier argv += optind; 363*219b2ee8SDavid du Colombier 364*219b2ee8SDavid du Colombier } /* End of options */ 365*219b2ee8SDavid du Colombier 366*219b2ee8SDavid du Colombier /*****************************************************************************/ 367*219b2ee8SDavid du Colombier 368*219b2ee8SDavid du Colombier char *get_font(name) 369*219b2ee8SDavid du Colombier 370*219b2ee8SDavid du Colombier char *name; /* name the user asked for */ 371*219b2ee8SDavid du Colombier 372*219b2ee8SDavid du Colombier { 373*219b2ee8SDavid du Colombier 374*219b2ee8SDavid du Colombier int i; /* for looking through fontmap[] */ 375*219b2ee8SDavid du Colombier 376*219b2ee8SDavid du Colombier /* 377*219b2ee8SDavid du Colombier * 378*219b2ee8SDavid du Colombier * Called from options() to map a user's font name into a legal PostScript name. 379*219b2ee8SDavid du Colombier * If the lookup fails *name is returned to the caller. That should let you choose 380*219b2ee8SDavid du Colombier * any PostScript font, although things will only work well for constant width 381*219b2ee8SDavid du Colombier * fonts. 382*219b2ee8SDavid du Colombier * 383*219b2ee8SDavid du Colombier */ 384*219b2ee8SDavid du Colombier 385*219b2ee8SDavid du Colombier for ( i = 0; fontmap[i].name != NULL; i++ ) 386*219b2ee8SDavid du Colombier if ( strcmp(name, fontmap[i].name) == 0 ) 387*219b2ee8SDavid du Colombier return(fontmap[i].val); 388*219b2ee8SDavid du Colombier 389*219b2ee8SDavid du Colombier return(name); 390*219b2ee8SDavid du Colombier 391*219b2ee8SDavid du Colombier } /* End of get_font */ 392*219b2ee8SDavid du Colombier 393*219b2ee8SDavid du Colombier /*****************************************************************************/ 394*219b2ee8SDavid du Colombier 395*219b2ee8SDavid du Colombier setup() 396*219b2ee8SDavid du Colombier 397*219b2ee8SDavid du Colombier { 398*219b2ee8SDavid du Colombier 399*219b2ee8SDavid du Colombier /* 400*219b2ee8SDavid du Colombier * 401*219b2ee8SDavid du Colombier * Handles things that must be done after the options are read but before the 402*219b2ee8SDavid du Colombier * input files are processed. linespp (lines per page) can be set using the -l 403*219b2ee8SDavid du Colombier * option. If it's not positive we calculate a reasonable value using the 404*219b2ee8SDavid du Colombier * requested point size - assuming LINESPP lines fit on a page in point size 405*219b2ee8SDavid du Colombier * POINTSIZE. 406*219b2ee8SDavid du Colombier * 407*219b2ee8SDavid du Colombier */ 408*219b2ee8SDavid du Colombier 409*219b2ee8SDavid du Colombier writerequest(0, stdout); /* global requests eg. manual feed */ 410*219b2ee8SDavid du Colombier setencoding(fontencoding); 411*219b2ee8SDavid du Colombier fprintf(stdout, "setup\n"); 412*219b2ee8SDavid du Colombier 413*219b2ee8SDavid du Colombier if ( formsperpage > 1 ) { 414*219b2ee8SDavid du Colombier if ( cat(formfile) == FALSE ) 415*219b2ee8SDavid du Colombier error(FATAL, "can't read %s", formfile); 416*219b2ee8SDavid du Colombier fprintf(stdout, "%d setupforms\n", formsperpage); 417*219b2ee8SDavid du Colombier } /* End if */ 418*219b2ee8SDavid du Colombier 419*219b2ee8SDavid du Colombier fprintf(stdout, "%s", ENDSETUP); 420*219b2ee8SDavid du Colombier 421*219b2ee8SDavid du Colombier if ( linespp <= 0 ) 422*219b2ee8SDavid du Colombier linespp = LINESPP * POINTSIZE / pointsize; 423*219b2ee8SDavid du Colombier 424*219b2ee8SDavid du Colombier } /* End of setup */ 425*219b2ee8SDavid du Colombier 426*219b2ee8SDavid du Colombier /*****************************************************************************/ 427*219b2ee8SDavid du Colombier 428*219b2ee8SDavid du Colombier arguments() 429*219b2ee8SDavid du Colombier 430*219b2ee8SDavid du Colombier { 431*219b2ee8SDavid du Colombier 432*219b2ee8SDavid du Colombier /* 433*219b2ee8SDavid du Colombier * 434*219b2ee8SDavid du Colombier * Makes sure all the non-option command line arguments are processed. If we get 435*219b2ee8SDavid du Colombier * here and there aren't any arguments left, or if '-' is one of the input files 436*219b2ee8SDavid du Colombier * we'll translate stdin. 437*219b2ee8SDavid du Colombier * 438*219b2ee8SDavid du Colombier */ 439*219b2ee8SDavid du Colombier 440*219b2ee8SDavid du Colombier if ( argc < 1 ) 441*219b2ee8SDavid du Colombier text(); 442*219b2ee8SDavid du Colombier else { /* at least one argument is left */ 443*219b2ee8SDavid du Colombier while ( argc > 0 ) { 444*219b2ee8SDavid du Colombier if ( strcmp(*argv, "-") == 0 ) 445*219b2ee8SDavid du Colombier fp_in = stdin; 446*219b2ee8SDavid du Colombier else if ( (fp_in = fopen(*argv, "r")) == NULL ) 447*219b2ee8SDavid du Colombier error(FATAL, "can't open %s", *argv); 448*219b2ee8SDavid du Colombier text(); 449*219b2ee8SDavid du Colombier if ( fp_in != stdin ) 450*219b2ee8SDavid du Colombier fclose(fp_in); 451*219b2ee8SDavid du Colombier argc--; 452*219b2ee8SDavid du Colombier argv++; 453*219b2ee8SDavid du Colombier } /* End while */ 454*219b2ee8SDavid du Colombier } /* End else */ 455*219b2ee8SDavid du Colombier 456*219b2ee8SDavid du Colombier } /* End of arguments */ 457*219b2ee8SDavid du Colombier 458*219b2ee8SDavid du Colombier /*****************************************************************************/ 459*219b2ee8SDavid du Colombier 460*219b2ee8SDavid du Colombier done() 461*219b2ee8SDavid du Colombier 462*219b2ee8SDavid du Colombier { 463*219b2ee8SDavid du Colombier 464*219b2ee8SDavid du Colombier /* 465*219b2ee8SDavid du Colombier * 466*219b2ee8SDavid du Colombier * Finished with all the input files, so mark the end of the pages with a TRAILER 467*219b2ee8SDavid du Colombier * comment, make sure the last page prints, and add things like the PAGES comment 468*219b2ee8SDavid du Colombier * that can only be determined after all the input files have been read. 469*219b2ee8SDavid du Colombier * 470*219b2ee8SDavid du Colombier */ 471*219b2ee8SDavid du Colombier 472*219b2ee8SDavid du Colombier fprintf(stdout, "%s", TRAILER); 473*219b2ee8SDavid du Colombier fprintf(stdout, "done\n"); 474*219b2ee8SDavid du Colombier fprintf(stdout, "%s %s\n", DOCUMENTFONTS, fontname); 475*219b2ee8SDavid du Colombier fprintf(stdout, "%s %d\n", PAGES, printed); 476*219b2ee8SDavid du Colombier 477*219b2ee8SDavid du Colombier } /* End of done */ 478*219b2ee8SDavid du Colombier 479*219b2ee8SDavid du Colombier /*****************************************************************************/ 480*219b2ee8SDavid du Colombier 481*219b2ee8SDavid du Colombier account() 482*219b2ee8SDavid du Colombier 483*219b2ee8SDavid du Colombier { 484*219b2ee8SDavid du Colombier 485*219b2ee8SDavid du Colombier /* 486*219b2ee8SDavid du Colombier * 487*219b2ee8SDavid du Colombier * Writes an accounting record to *fp_acct provided it's not NULL. Accounting is 488*219b2ee8SDavid du Colombier * requested using the -A or -J options. 489*219b2ee8SDavid du Colombier * 490*219b2ee8SDavid du Colombier */ 491*219b2ee8SDavid du Colombier 492*219b2ee8SDavid du Colombier if ( fp_acct != NULL ) 493*219b2ee8SDavid du Colombier fprintf(fp_acct, " print %d\n copies %d\n", printed, copies); 494*219b2ee8SDavid du Colombier 495*219b2ee8SDavid du Colombier } /* End of account */ 496*219b2ee8SDavid du Colombier 497*219b2ee8SDavid du Colombier /*****************************************************************************/ 498*219b2ee8SDavid du Colombier 499*219b2ee8SDavid du Colombier text() 500*219b2ee8SDavid du Colombier 501*219b2ee8SDavid du Colombier { 502*219b2ee8SDavid du Colombier 503*219b2ee8SDavid du Colombier int ch; /* next input character */ 504*219b2ee8SDavid du Colombier 505*219b2ee8SDavid du Colombier /* 506*219b2ee8SDavid du Colombier * 507*219b2ee8SDavid du Colombier * Translates *fp_in into PostScript. Intercepts space, tab, backspace, newline, 508*219b2ee8SDavid du Colombier * return, and formfeed. Everything else goes to oput(), which handles quoting 509*219b2ee8SDavid du Colombier * (if needed) and escapes for nonascii characters if extended is TRUE. The 510*219b2ee8SDavid du Colombier * redirect(-1) call forces the initial output to go to /dev/null - so stuff 511*219b2ee8SDavid du Colombier * that formfeed() does at the end of each page goes to /dev/null rather than 512*219b2ee8SDavid du Colombier * the real output file. 513*219b2ee8SDavid du Colombier * 514*219b2ee8SDavid du Colombier */ 515*219b2ee8SDavid du Colombier 516*219b2ee8SDavid du Colombier redirect(-1); /* get ready for the first page */ 517*219b2ee8SDavid du Colombier formfeed(); /* force PAGE comment etc. */ 518*219b2ee8SDavid du Colombier 519*219b2ee8SDavid du Colombier while ( (ch = getc(fp_in)) != EOF ) 520*219b2ee8SDavid du Colombier switch ( ch ) { 521*219b2ee8SDavid du Colombier case '\n': 522*219b2ee8SDavid du Colombier newline(); 523*219b2ee8SDavid du Colombier break; 524*219b2ee8SDavid du Colombier 525*219b2ee8SDavid du Colombier case '\t': 526*219b2ee8SDavid du Colombier case '\b': 527*219b2ee8SDavid du Colombier case ' ': 528*219b2ee8SDavid du Colombier spaces(ch); 529*219b2ee8SDavid du Colombier break; 530*219b2ee8SDavid du Colombier 531*219b2ee8SDavid du Colombier case '\014': 532*219b2ee8SDavid du Colombier formfeed(); 533*219b2ee8SDavid du Colombier break; 534*219b2ee8SDavid du Colombier 535*219b2ee8SDavid du Colombier case '\r': 536*219b2ee8SDavid du Colombier if ( crmode == 1 ) 537*219b2ee8SDavid du Colombier spaces(ch); 538*219b2ee8SDavid du Colombier else if ( crmode == 2 ) 539*219b2ee8SDavid du Colombier newline(); 540*219b2ee8SDavid du Colombier break; 541*219b2ee8SDavid du Colombier 542*219b2ee8SDavid du Colombier default: 543*219b2ee8SDavid du Colombier oput(ch); 544*219b2ee8SDavid du Colombier break; 545*219b2ee8SDavid du Colombier } /* End switch */ 546*219b2ee8SDavid du Colombier 547*219b2ee8SDavid du Colombier formfeed(); /* next file starts on a new page? */ 548*219b2ee8SDavid du Colombier 549*219b2ee8SDavid du Colombier } /* End of text */ 550*219b2ee8SDavid du Colombier 551*219b2ee8SDavid du Colombier /*****************************************************************************/ 552*219b2ee8SDavid du Colombier 553*219b2ee8SDavid du Colombier formfeed() 554*219b2ee8SDavid du Colombier 555*219b2ee8SDavid du Colombier { 556*219b2ee8SDavid du Colombier 557*219b2ee8SDavid du Colombier /* 558*219b2ee8SDavid du Colombier * 559*219b2ee8SDavid du Colombier * Called whenever we've finished with the last page and want to get ready for the 560*219b2ee8SDavid du Colombier * next one. Also used at the beginning and end of each input file, so we have to 561*219b2ee8SDavid du Colombier * be careful about what's done. The first time through (up to the redirect() call) 562*219b2ee8SDavid du Colombier * output goes to /dev/null. 563*219b2ee8SDavid du Colombier * 564*219b2ee8SDavid du Colombier * Adobe now recommends that the showpage operator occur after the page level 565*219b2ee8SDavid du Colombier * restore so it can be easily redefined to have side-effects in the printer's VM. 566*219b2ee8SDavid du Colombier * Although it seems reasonable I haven't implemented it, because it makes other 567*219b2ee8SDavid du Colombier * things, like selectively setting manual feed or choosing an alternate paper 568*219b2ee8SDavid du Colombier * tray, clumsy - at least on a per page basis. 569*219b2ee8SDavid du Colombier * 570*219b2ee8SDavid du Colombier */ 571*219b2ee8SDavid du Colombier 572*219b2ee8SDavid du Colombier if ( fp_out == stdout ) /* count the last page */ 573*219b2ee8SDavid du Colombier printed++; 574*219b2ee8SDavid du Colombier 575*219b2ee8SDavid du Colombier endline(); /* print the last line */ 576*219b2ee8SDavid du Colombier 577*219b2ee8SDavid du Colombier fprintf(fp_out, "cleartomark\n"); 578*219b2ee8SDavid du Colombier fprintf(fp_out, "showpage\n"); 579*219b2ee8SDavid du Colombier fprintf(fp_out, "saveobj restore\n"); 580*219b2ee8SDavid du Colombier fprintf(fp_out, "%s %d %d\n", ENDPAGE, page, printed); 581*219b2ee8SDavid du Colombier 582*219b2ee8SDavid du Colombier if ( ungetc(getc(fp_in), fp_in) == EOF ) 583*219b2ee8SDavid du Colombier redirect(-1); 584*219b2ee8SDavid du Colombier else redirect(++page); 585*219b2ee8SDavid du Colombier 586*219b2ee8SDavid du Colombier fprintf(fp_out, "%s %d %d\n", PAGE, page, printed+1); 587*219b2ee8SDavid du Colombier fprintf(fp_out, "/saveobj save def\n"); 588*219b2ee8SDavid du Colombier fprintf(fp_out, "mark\n"); 589*219b2ee8SDavid du Colombier writerequest(printed+1, fp_out); 590*219b2ee8SDavid du Colombier fprintf(fp_out, "%d pagesetup\n", printed+1); 591*219b2ee8SDavid du Colombier 592*219b2ee8SDavid du Colombier line = 1; 593*219b2ee8SDavid du Colombier 594*219b2ee8SDavid du Colombier } /* End of formfeed */ 595*219b2ee8SDavid du Colombier 596*219b2ee8SDavid du Colombier /*****************************************************************************/ 597*219b2ee8SDavid du Colombier 598*219b2ee8SDavid du Colombier newline() 599*219b2ee8SDavid du Colombier 600*219b2ee8SDavid du Colombier { 601*219b2ee8SDavid du Colombier 602*219b2ee8SDavid du Colombier /* 603*219b2ee8SDavid du Colombier * 604*219b2ee8SDavid du Colombier * Called when we've read a newline character. The call to startline() ensures 605*219b2ee8SDavid du Colombier * that at least an empty string is on the stack. 606*219b2ee8SDavid du Colombier * 607*219b2ee8SDavid du Colombier */ 608*219b2ee8SDavid du Colombier 609*219b2ee8SDavid du Colombier startline(); 610*219b2ee8SDavid du Colombier endline(); /* print the current line */ 611*219b2ee8SDavid du Colombier 612*219b2ee8SDavid du Colombier if ( ++line > linespp ) /* done with this page */ 613*219b2ee8SDavid du Colombier formfeed(); 614*219b2ee8SDavid du Colombier 615*219b2ee8SDavid du Colombier } /* End of newline */ 616*219b2ee8SDavid du Colombier 617*219b2ee8SDavid du Colombier /*****************************************************************************/ 618*219b2ee8SDavid du Colombier 619*219b2ee8SDavid du Colombier spaces(ch) 620*219b2ee8SDavid du Colombier 621*219b2ee8SDavid du Colombier int ch; /* next input character */ 622*219b2ee8SDavid du Colombier 623*219b2ee8SDavid du Colombier { 624*219b2ee8SDavid du Colombier 625*219b2ee8SDavid du Colombier int endcol; /* ending column */ 626*219b2ee8SDavid du Colombier int i; /* final distance - in spaces */ 627*219b2ee8SDavid du Colombier 628*219b2ee8SDavid du Colombier /* 629*219b2ee8SDavid du Colombier * 630*219b2ee8SDavid du Colombier * Counts consecutive spaces, tabs, and backspaces and figures out where the next 631*219b2ee8SDavid du Colombier * string should start. Once that's been done we try to choose an efficient way 632*219b2ee8SDavid du Colombier * to output the required number of spaces. The choice is between using procedure 633*219b2ee8SDavid du Colombier * l with a single string on the stack and L with several string and column pairs. 634*219b2ee8SDavid du Colombier * We usually break even, in terms of the size of the output file, if we need four 635*219b2ee8SDavid du Colombier * consecutive spaces. More means using L decreases the size of the file. For now 636*219b2ee8SDavid du Colombier * if there are less than 6 consecutive spaces we just add them to the current 637*219b2ee8SDavid du Colombier * string, otherwise we end that string, follow it by its starting position, and 638*219b2ee8SDavid du Colombier * begin a new one that starts at endcol. Backspacing is always handled this way. 639*219b2ee8SDavid du Colombier * 640*219b2ee8SDavid du Colombier */ 641*219b2ee8SDavid du Colombier 642*219b2ee8SDavid du Colombier startline(); /* so col makes sense */ 643*219b2ee8SDavid du Colombier endcol = col; 644*219b2ee8SDavid du Colombier 645*219b2ee8SDavid du Colombier do { 646*219b2ee8SDavid du Colombier if ( ch == ' ' ) 647*219b2ee8SDavid du Colombier endcol++; 648*219b2ee8SDavid du Colombier else if ( ch == '\t' ) 649*219b2ee8SDavid du Colombier endcol += tabstops - ((endcol - 1) % tabstops); 650*219b2ee8SDavid du Colombier else if ( ch == '\b' ) 651*219b2ee8SDavid du Colombier endcol--; 652*219b2ee8SDavid du Colombier else if ( ch == '\r' ) 653*219b2ee8SDavid du Colombier endcol = 1; 654*219b2ee8SDavid du Colombier else break; 655*219b2ee8SDavid du Colombier } while ( ch = getc(fp_in) ); /* if ch is 0 we'd quit anyway */ 656*219b2ee8SDavid du Colombier 657*219b2ee8SDavid du Colombier ungetc(ch, fp_in); /* wasn't a space, tab, or backspace */ 658*219b2ee8SDavid du Colombier 659*219b2ee8SDavid du Colombier if ( endcol < 1 ) /* can't move past left edge */ 660*219b2ee8SDavid du Colombier endcol = 1; 661*219b2ee8SDavid du Colombier 662*219b2ee8SDavid du Colombier if ( (i = endcol - col) >= 0 && i < 6 ) 663*219b2ee8SDavid du Colombier for ( ; i > 0; i-- ) 664*219b2ee8SDavid du Colombier oput((int)' '); 665*219b2ee8SDavid du Colombier else { 666*219b2ee8SDavid du Colombier endstring(); 667*219b2ee8SDavid du Colombier col = stringstart = endcol; 668*219b2ee8SDavid du Colombier } /* End else */ 669*219b2ee8SDavid du Colombier 670*219b2ee8SDavid du Colombier } /* End of spaces */ 671*219b2ee8SDavid du Colombier 672*219b2ee8SDavid du Colombier /*****************************************************************************/ 673*219b2ee8SDavid du Colombier 674*219b2ee8SDavid du Colombier startline() 675*219b2ee8SDavid du Colombier 676*219b2ee8SDavid du Colombier { 677*219b2ee8SDavid du Colombier 678*219b2ee8SDavid du Colombier /* 679*219b2ee8SDavid du Colombier * 680*219b2ee8SDavid du Colombier * Called whenever we want to be certain we're ready to start pushing characters 681*219b2ee8SDavid du Colombier * into an open string on the stack. If stringcount is positive we've already 682*219b2ee8SDavid du Colombier * started, so there's nothing to do. The first string starts in column 1. 683*219b2ee8SDavid du Colombier * 684*219b2ee8SDavid du Colombier */ 685*219b2ee8SDavid du Colombier 686*219b2ee8SDavid du Colombier if ( stringcount < 1 ) { 687*219b2ee8SDavid du Colombier putc('(', fp_out); 688*219b2ee8SDavid du Colombier stringstart = col = 1; 689*219b2ee8SDavid du Colombier stringcount = 1; 690*219b2ee8SDavid du Colombier } /* End if */ 691*219b2ee8SDavid du Colombier 692*219b2ee8SDavid du Colombier } /* End of startline */ 693*219b2ee8SDavid du Colombier 694*219b2ee8SDavid du Colombier /*****************************************************************************/ 695*219b2ee8SDavid du Colombier 696*219b2ee8SDavid du Colombier endstring() 697*219b2ee8SDavid du Colombier 698*219b2ee8SDavid du Colombier { 699*219b2ee8SDavid du Colombier 700*219b2ee8SDavid du Colombier /* 701*219b2ee8SDavid du Colombier * 702*219b2ee8SDavid du Colombier * End the current string and start a new one. 703*219b2ee8SDavid du Colombier * 704*219b2ee8SDavid du Colombier */ 705*219b2ee8SDavid du Colombier 706*219b2ee8SDavid du Colombier if ( stringcount > 100 ) { /* don't put too much on the stack */ 707*219b2ee8SDavid du Colombier fprintf(fp_out, ")%d LL\n(", stringstart-1); 708*219b2ee8SDavid du Colombier stringcount = 2; /* kludge - don't let endline() use l */ 709*219b2ee8SDavid du Colombier } else { 710*219b2ee8SDavid du Colombier fprintf(fp_out, ")%d(", stringstart-1); 711*219b2ee8SDavid du Colombier stringcount++; 712*219b2ee8SDavid du Colombier } /* End else */ 713*219b2ee8SDavid du Colombier 714*219b2ee8SDavid du Colombier } /* End of endstring */ 715*219b2ee8SDavid du Colombier 716*219b2ee8SDavid du Colombier /*****************************************************************************/ 717*219b2ee8SDavid du Colombier 718*219b2ee8SDavid du Colombier endline() 719*219b2ee8SDavid du Colombier 720*219b2ee8SDavid du Colombier { 721*219b2ee8SDavid du Colombier 722*219b2ee8SDavid du Colombier /* 723*219b2ee8SDavid du Colombier * 724*219b2ee8SDavid du Colombier * Generates a call to the PostScript procedure that processes all the text on 725*219b2ee8SDavid du Colombier * the stack - provided stringcount is positive. If one string is on the stack 726*219b2ee8SDavid du Colombier * the fast procedure (ie. l) is used to print the line, otherwise the slower 727*219b2ee8SDavid du Colombier * one that processes string and column pairs is used. 728*219b2ee8SDavid du Colombier * 729*219b2ee8SDavid du Colombier */ 730*219b2ee8SDavid du Colombier 731*219b2ee8SDavid du Colombier if ( stringcount == 1 ) 732*219b2ee8SDavid du Colombier fprintf(fp_out, ")l\n"); 733*219b2ee8SDavid du Colombier else if ( stringcount > 1 ) 734*219b2ee8SDavid du Colombier fprintf(fp_out, ")%d L\n", stringstart-1); 735*219b2ee8SDavid du Colombier 736*219b2ee8SDavid du Colombier stringcount = 0; 737*219b2ee8SDavid du Colombier 738*219b2ee8SDavid du Colombier } /* End of endline */ 739*219b2ee8SDavid du Colombier 740*219b2ee8SDavid du Colombier /*****************************************************************************/ 741*219b2ee8SDavid du Colombier 742*219b2ee8SDavid du Colombier oput(ch) 743*219b2ee8SDavid du Colombier 744*219b2ee8SDavid du Colombier int ch; /* next output character */ 745*219b2ee8SDavid du Colombier 746*219b2ee8SDavid du Colombier { 747*219b2ee8SDavid du Colombier 748*219b2ee8SDavid du Colombier /* 749*219b2ee8SDavid du Colombier * 750*219b2ee8SDavid du Colombier * Responsible for adding all printing characters from the input file to the 751*219b2ee8SDavid du Colombier * open string on top of the stack. 752*219b2ee8SDavid du Colombier * 753*219b2ee8SDavid du Colombier */ 754*219b2ee8SDavid du Colombier 755*219b2ee8SDavid du Colombier if ( isascii(ch) && isprint(ch) ) { 756*219b2ee8SDavid du Colombier startline(); 757*219b2ee8SDavid du Colombier if ( ch == '(' || ch == ')' || ch == '\\' ) 758*219b2ee8SDavid du Colombier putc('\\', fp_out); 759*219b2ee8SDavid du Colombier putc(ch, fp_out); 760*219b2ee8SDavid du Colombier col++; 761*219b2ee8SDavid du Colombier } else if ( extended == TRUE ) { 762*219b2ee8SDavid du Colombier startline(); 763*219b2ee8SDavid du Colombier fprintf(fp_out, "\\%.3o", ch & 0377); 764*219b2ee8SDavid du Colombier col++; 765*219b2ee8SDavid du Colombier } /* End if */ 766*219b2ee8SDavid du Colombier 767*219b2ee8SDavid du Colombier } /* End of oput */ 768*219b2ee8SDavid du Colombier 769*219b2ee8SDavid du Colombier /*****************************************************************************/ 770*219b2ee8SDavid du Colombier 771*219b2ee8SDavid du Colombier redirect(pg) 772*219b2ee8SDavid du Colombier 773*219b2ee8SDavid du Colombier int pg; /* next page we're printing */ 774*219b2ee8SDavid du Colombier 775*219b2ee8SDavid du Colombier { 776*219b2ee8SDavid du Colombier 777*219b2ee8SDavid du Colombier static FILE *fp_null = NULL; /* if output is turned off */ 778*219b2ee8SDavid du Colombier 779*219b2ee8SDavid du Colombier /* 780*219b2ee8SDavid du Colombier * 781*219b2ee8SDavid du Colombier * If we're not supposed to print page pg, fp_out will be directed to /dev/null, 782*219b2ee8SDavid du Colombier * otherwise output goes to stdout. 783*219b2ee8SDavid du Colombier * 784*219b2ee8SDavid du Colombier */ 785*219b2ee8SDavid du Colombier 786*219b2ee8SDavid du Colombier if ( pg >= 0 && in_olist(pg) == ON ) 787*219b2ee8SDavid du Colombier fp_out = stdout; 788*219b2ee8SDavid du Colombier else if ( (fp_out = fp_null) == NULL ) 789*219b2ee8SDavid du Colombier fp_out = fp_null = fopen("/dev/null", "w"); 790*219b2ee8SDavid du Colombier 791*219b2ee8SDavid du Colombier } /* End of redirect */ 792*219b2ee8SDavid du Colombier 793*219b2ee8SDavid du Colombier /*****************************************************************************/ 794*219b2ee8SDavid du Colombier 795