/* # poster - resize a postscript image to print on larger media and/or multiple sheets # # This program scales a PostScript page to a given size (a poster). # The output can be tiled on multiple sheets, and output # media size can be chosen independently. # Each tile (sheet) of a will bear cropmarks and slightly overlapping # image for easier poster assembly. # In principle it requires the input file to adhere to 'eps' # (encapsulated postscript) conventions but it will work for many # 'normal' postscript files as well. # # Compile this program with: # cc -O -o poster poster.c -lm # or something alike. # # Maybe you want to change the `DefaultMedia' and `DefaultImage' # settings in the few lines below, to reflect your local situation. # Names can to be chosen from the `mediatable' further down. # # The `Gv_gs_orientbug 1' disables a feature of this program to # ask for landscape previewing of rotated images. # Our currently installed combination of ghostview 1.5 with ghostscript 3.33 # cannot properly do a landscape viewing of the `poster' output. # The problem does not exist in combination with an older ghostscript 2.x, # and has the attention of the ghostview authors. # (The problem is in the evaluation of the `setpagedevice' call.) # If you have a different previewing environment, # you might want to set `Gv_gs_orientbug 0' # # -------------------------------------------------------------- # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; # The full text of the GNU General Public License is supplied # with 'poster' in the file LICENSE. # # Copyright (C) 1999 Jos T.J. van Eijndhoven # -------------------------------------------------------------- # email: J.T.J.v.Eijndhoven@ele.tue.nl */ #define Gv_gs_orientbug 1 #define DefaultMedia "A4" #define DefaultImage "A4" #define DefaultCutMargin "5%" #define DefaultWhiteMargin "0" #define BUFSIZE 1024 #include #include #include #include #include #include extern char *optarg; /* silently set by getopt() */ extern int optind, opterr; /* silently set by getopt() */ static void usage(); static void dsc_head1(); static int dsc_infile( double ps_bb[4]); static void dsc_head2( void); static void printposter( void); static void printprolog(); static void tile ( int row, int col); static void printfile( void); static void postersize( char *scalespec, char *posterspec); static void box_convert( char *boxspec, double psbox[4]); static void boxerr( char *spec); static void margin_convert( char *spec, double margin[2]); static int mystrncasecmp( const char *s1, const char *s2, int n); int verbose; char *myname; char *infile; int rotate, nrows, ncols; int manualfeed = 0; int tail_cntl_D = 0; #define Xl 0 #define Yb 1 #define Xr 2 #define Yt 3 #define X 0 #define Y 1 double posterbb[4]; /* final image in ps units */ double imagebb[4]; /* original image in ps units */ double mediasize[4]; /* [34] = size of media to print on, [01] not used! */ double cutmargin[2]; double whitemargin[2]; double scale; /* linear scaling factor */ /* defaults: */ char *imagespec = NULL; char *posterspec = NULL; char *mediaspec = NULL; char *cutmarginspec = NULL; char *whitemarginspec = NULL; char *scalespec = NULL; char *filespec = NULL; /* media sizes in ps units (1/72 inch) */ static char *mediatable[][2] = { { "Letter", "612,792"}, { "Legal", "612,1008"}, { "Tabloid", "792,1224"}, { "Ledger", "792,1224"}, { "Executive","540,720"}, { "Monarch", "279,540"}, { "Statement","396,612"}, { "Folio", "612,936"}, { "Quarto", "610,780"}, { "C5", "459,649"}, { "B4", "729,1032"}, { "B5", "516,729"}, { "Dl", "312,624"}, { "A0", "2380,3368"}, { "A1", "1684,2380"}, { "A2", "1190,1684"}, { "A3", "842,1190"}, { "A4", "595,842"}, { "A5", "420,595"}, { "A6", "297,421"}, /* as fall-back: linear units of measurement: */ { "p", "1,1"}, { "i", "72,72"}, { "ft", "864,864"}, { "mm", "2.83465,2.83465"}, { "cm", "28.3465,28.3465"}, { "m", "2834.65,2834.65"}, { NULL, NULL} }; int main( int argc, char *argv[]) { int opt; double ps_bb[4]; int got_bb; myname = argv[0]; while ((opt = getopt( argc, argv, "vfi:c:w:m:p:s:o:")) != EOF) { switch( opt) { case 'v': verbose++; break; case 'f': manualfeed = 1; break; case 'i': imagespec = optarg; break; case 'c': cutmarginspec = optarg; break; case 'w': whitemarginspec = optarg; break; case 'm': mediaspec = optarg; break; case 'p': posterspec = optarg; break; case 's': scalespec = optarg; break; case 'o': filespec = optarg; break; default: usage(); break; } } /*** check command line arguments ***/ if (scalespec && posterspec) { fprintf( stderr, "Please don't specify both -s and -o, ignoring -s!\n"); scalespec = NULL; } if (optind < argc) infile = argv[ optind]; else { fprintf( stderr, "Filename argument missing!\n"); usage(); } /*** decide on media size ***/ if (!mediaspec) { mediaspec = DefaultMedia; if (verbose) fprintf( stderr, "Using default media of %s\n", mediaspec); } box_convert( mediaspec, mediasize); if (mediasize[3] < mediasize[2]) { fprintf( stderr, "Media should always be specified in portrait format!\n"); exit(1); } if (mediasize[2]-mediasize[0] <= 10.0 || mediasize[3]-mediasize[1] <= 10.0) { fprintf( stderr, "Media size is ridiculous!\n"); exit(1); } /*** defaulting poster size ? **/ if (!scalespec && !posterspec) { /* inherit postersize from given media size */ posterspec = mediaspec; if (verbose) fprintf( stderr, "Defaulting poster size to media size of %s\n", mediaspec); } /*** decide the cutmargin size, after knowing media size ***/ if (!cutmarginspec) { /* if (!strcmp( posterspec, mediaspec)) */ /* zero cutmargin if printing to 1 sheet */ /* marginspec = "0%"; else */ cutmarginspec = DefaultCutMargin; if (verbose) fprintf( stderr, "Using default cutmargin of %s\n", cutmarginspec); } margin_convert( cutmarginspec, cutmargin); /*** decide the whitemargin size, after knowing media size ***/ if (!whitemarginspec) { whitemarginspec = DefaultWhiteMargin; if (verbose) fprintf( stderr, "Using default whitemargin of %s\n", whitemarginspec); } margin_convert( whitemarginspec, whitemargin); /******************* now start doing things **************************/ /* open output file */ if (filespec) { if (!freopen( filespec, "w", stdout)) { fprintf( stderr, "Cannot open '%s' for writing!\n", filespec); exit(1); } else if (verbose) fprintf( stderr, "Opened '%s' for writing\n", filespec); } /******* I might need to read some input to find picture size ********/ /* start DSC header on output */ dsc_head1(); /* pass input DSC lines to output, get BoundingBox spec if there */ got_bb = dsc_infile( ps_bb); /**** decide the input image bounding box ****/ if (!got_bb && !imagespec) { imagespec = DefaultImage; if (verbose) fprintf( stderr, "Using default input image of %s\n", imagespec); } if (imagespec) box_convert( imagespec, imagebb); else { int i; for (i=0; i<4; i++) imagebb[i] = ps_bb[i]; } if (verbose > 1) fprintf( stderr, " Input image is: [%g,%g,%g,%g]\n", imagebb[0], imagebb[1], imagebb[2], imagebb[3]); if (imagebb[2]-imagebb[0] <= 0.0 || imagebb[3]-imagebb[1] <= 0.0) { fprintf( stderr, "Input image should have positive size!\n"); exit(1); } /*** decide on the scale factor and poster size ***/ postersize( scalespec, posterspec); if (verbose > 1) fprintf( stderr, " Output image is: [%g,%g,%g,%g]\n", posterbb[0], posterbb[1], posterbb[2], posterbb[3]); dsc_head2(); printposter(); exit (0); } static void usage() { fprintf( stderr, "Usage: %s infile\n\n", myname); fprintf( stderr, "options are:\n"); fprintf( stderr, " -v: be verbose\n"); fprintf( stderr, " -f: ask manual feed on plotting/printing device\n"); fprintf( stderr, " -i: specify input image size\n"); fprintf( stderr, " -c: horizontal and vertical cutmargin\n"); fprintf( stderr, " -w: horizontal and vertical additional white margin\n"); fprintf( stderr, " -m: media paper size\n"); fprintf( stderr, " -p: output poster size\n"); fprintf( stderr, " -s: linear scale factor for poster\n"); fprintf( stderr, " -o: output redirection to named file\n\n"); fprintf( stderr, " At least one of -s -p -m is mandatory, and don't give both -s and -p\n"); fprintf( stderr, " is like 'A4', '3x3letter', '10x25cm', '200x200+10,10p'\n"); fprintf( stderr, " is either a simple or %%\n\n"); fprintf( stderr, " Defaults are: '-m%s', '-c%s', '-i' read from input file.\n", DefaultMedia, DefaultCutMargin); fprintf( stderr, " and output written to stdout.\n"); exit(1); } #define exch( x, y) {double h; h=x; x=y; y=h;} static void postersize( char *scalespec, char *posterspec) { /* exactly one the arguments is NULL ! */ /* media and image sizes are fixed already */ int nx0, ny0, nx1, ny1; double sizex, sizey; /* size of the scaled image in ps units */ double drawablex, drawabley; /* effective drawable size of media */ double mediax, mediay; double tmpposter[4]; /* available drawing area per sheet: */ drawablex = mediasize[2] - 2.0*cutmargin[0]; drawabley = mediasize[3] - 2.0*cutmargin[1]; /*** decide on number of pages ***/ if (scalespec) { /* user specified scale factor */ scale = atof( scalespec); if (scale < 0.01 || scale > 1.0e6) { fprintf( stderr, "Illegal scale value %s!\n", scalespec); exit(1); } sizex = (imagebb[2] - imagebb[0]) * scale + 2*whitemargin[0]; sizey = (imagebb[3] - imagebb[1]) * scale + 2*whitemargin[1]; /* without rotation */ nx0 = ceil( sizex / drawablex); ny0 = ceil( sizey / drawabley); /* with rotation */ nx1 = ceil( sizex / drawabley); ny1 = ceil( sizey / drawablex); } else { /* user specified output size */ box_convert( posterspec, tmpposter); if (tmpposter[0]!=0.0 || tmpposter[1]!=0.0) { fprintf( stderr, "Poster lower-left coordinates are assumed 0!\n"); tmpposter[0] = tmpposter[1] = 0.0; } if (tmpposter[2]-tmpposter[0] <= 0.0 || tmpposter[3]-tmpposter[1] <= 0.0) { fprintf( stderr, "Poster should have positive size!\n"); exit(1); } if ((tmpposter[3]-tmpposter[1]) < (tmpposter[2]-tmpposter[0])) { /* hmmm... landscape spec, change to portrait for now */ exch( tmpposter[0], tmpposter[1]); exch( tmpposter[2], tmpposter[3]); } /* Should we tilt the poster to landscape style? */ if ((imagebb[3] - imagebb[1]) < (imagebb[2] - imagebb[0])) { /* image has landscape format ==> make landscape poster */ exch( tmpposter[0], tmpposter[1]); exch( tmpposter[2], tmpposter[3]); } /* without rotation */ /* assuming tmpposter[0],[1] = 0,0 */ nx0 = ceil( 0.95 * tmpposter[2] / mediasize[2]); ny0 = ceil( 0.95 * tmpposter[3] / mediasize[3]); /* with rotation */ nx1 = ceil( 0.95 * tmpposter[2] / mediasize[3]); ny1 = ceil( 0.95 * tmpposter[3] / mediasize[2]); /* (rotation is considered as media versus image, which is totally */ /* independent of the portrait or landscape style of the final poster) */ } /* decide for rotation to get the minimum page count */ rotate = nx0*ny0 > nx1*ny1; ncols = rotate ? nx1 : nx0; nrows = rotate ? ny1 : ny0; if (verbose) fprintf( stderr, "Deciding for %d column%s and %d row%s of %s pages.\n", ncols, (ncols==1)?"":"s", nrows, (nrows==1)?"":"s", rotate?"landscape":"portrait"); if (nrows * ncols > 400) { fprintf( stderr, "However %dx%d pages seems ridiculous to me!\n", ncols, nrows); exit(1); } mediax = ncols * (rotate ? drawabley : drawablex); mediay = nrows * (rotate ? drawablex : drawabley); if (!scalespec) /* no scaling number given by user */ { double scalex, scaley; scalex = (mediax - 2*whitemargin[0]) / (imagebb[2] - imagebb[0]); scaley = (mediay - 2*whitemargin[1]) / (imagebb[3] - imagebb[1]); scale = (scalex < scaley) ? scalex : scaley; if (verbose) fprintf( stderr, "Deciding for a scale factor of %g\n", scale); sizex = scale * (imagebb[2] - imagebb[0]); sizey = scale * (imagebb[3] - imagebb[1]); } /* set poster size as if it were a continuous surface without margins */ posterbb[0] = (mediax - sizex) / 2.0; /* center picture on paper */ posterbb[1] = (mediay - sizey) / 2.0; /* center picture on paper */ posterbb[2] = posterbb[0] + sizex; posterbb[3] = posterbb[1] + sizey; } static void margin_convert( char *spec, double margin[2]) { double x; int i, n; if (1==sscanf( spec, "%lf%n", &x, &n) && x==0.0 && n==strlen(spec)) { /* margin spec of 0, dont bother about a otherwise mandatory unit */ margin[0] = margin[1] = 0.0; } else if (spec[ strlen( spec) - 1] == '%') { /* margin relative to media size */ if (1 != sscanf( spec, "%lf%%", &x)) { fprintf( stderr, "Illegal margin specification!\n"); exit( 1); } margin[0] = 0.01 * x * mediasize[2]; margin[1] = 0.01 * x * mediasize[3]; } else { /* absolute margin value */ double marg[4]; box_convert( spec, marg); margin[0] = marg[2]; margin[1] = marg[3]; } for (i=0; i<2; i++) { if (margin[i] < 0 || 2.0*margin[i] >= mediasize[i+2]) { fprintf( stderr, "Margin value '%s' out of range!\n", spec); exit(1); } } } static void box_convert( char *boxspec, double psbox[4]) { /* convert user textual box spec into numbers in ps units */ /* box = [fixed x fixed][+ fixed , fixed] unit */ /* fixed = digits [ . digits] */ /* unit = medianame | i | cm | mm | m | p */ double mx, my, ox, oy, ux, uy; int n, r, i, l, inx; char *spec; mx = my = 1.0; ox = oy = 0.0; spec = boxspec; /* read 'fixed x fixed' */ if (isdigit( spec[0])) { r = sscanf( spec, "%lfx%lf%n", &mx, &my, &n); if (r != 2) { r = sscanf( spec, "%lf*%lf%n", &mx, &my, &n); if (r != 2) boxerr( boxspec); } spec += n; } /* read '+ fixed , fixed' */ if (1 < (r = sscanf( spec, "+%lf,%lf%n", &ox, &oy, &n))) { if (r != 2) boxerr( boxspec); spec += n; } /* read unit */ l = strlen( spec); for (n=i=0; mediatable[i][0]; i++) { if (!mystrncasecmp( mediatable[i][0], spec, l)) { /* found */ n++; inx = i; if (l == strlen( mediatable[i][0])) { /* match is exact */ n = 1; break; } } } if (!n) boxerr( boxspec); if (n>1) { fprintf( stderr, "Your box spec '%s' is not unique! (give more chars)\n", spec); exit(1); } sscanf( mediatable[inx][1], "%lf,%lf", &ux, &uy); psbox[0] = ox * ux; psbox[1] = oy * uy; psbox[2] = mx * ux; psbox[3] = my * uy; if (verbose > 1) fprintf( stderr, " Box_convert: '%s' into [%g,%g,%g,%g]\n", boxspec, psbox[0], psbox[1], psbox[2], psbox[3]); for (i=0; i<2; i++) { if (psbox[i] < 0.0 || psbox[i+2] < psbox[i]) { fprintf( stderr, "Your specification `%s' leads to " "negative values!\n", boxspec); exit(1); } } } static void boxerr( char *spec) { int i; fprintf( stderr, "I don't understand your box specification `%s'!\n", spec); fprintf( stderr, "The proper format is: ([text] meaning optional text)\n"); fprintf( stderr, " [multiplier][offset]unit\n"); fprintf( stderr, " with multiplier: numberxnumber\n"); fprintf( stderr, " with offset: +number,number\n"); fprintf( stderr, " with unit one of:"); for (i=0; mediatable[i][0]; i++) fprintf( stderr, "%c%-10s", (i%7)?' ':'\n', mediatable[i][0]); fprintf( stderr, "\nYou can use a shorthand for these unit names,\n" "provided it resolves unique.\n"); exit( 1); } /*********************************************/ /* output first part of DSC header */ /*********************************************/ static void dsc_head1() { printf ("%%!PS-Adobe-3.0\n"); printf ("%%%%Creator: %s\n", myname); } /*********************************************/ /* pass some DSC info from the infile in the new DSC header */ /* such as document fonts and */ /* extract BoundingBox info from the PS file */ /*********************************************/ static int dsc_infile( double ps_bb[4]) { char *c, buf[BUFSIZE]; int gotall, atend, level, dsc_cont, inbody, got_bb; if (freopen (infile, "r", stdin) == NULL) { fprintf (stderr, "%s: fail to open file '%s'!\n", myname, infile); exit (1); } got_bb = 0; dsc_cont = inbody = gotall = level = atend = 0; while (!gotall && (gets(buf) != NULL)) { if (buf[0] != '%') { dsc_cont = 0; if (!inbody) inbody = 1; if (!atend) gotall = 1; continue; } if (!strncmp( buf, "%%+",3) && dsc_cont) { puts( buf); continue; } dsc_cont = 0; if (!strncmp( buf, "%%EndComments", 13)) { inbody = 1; if (!atend) gotall = 1; } else if (!strncmp( buf, "%%BeginDocument", 15) || !strncmp( buf, "%%BeginData", 11)) level++; else if (!strncmp( buf, "%%EndDocument", 13) || !strncmp( buf, "%%EndData", 9)) level--; else if (!strncmp( buf, "%%Trailer", 9) && level == 0) inbody = 2; else if (!strncmp( buf, "%%BoundingBox:", 14) && inbody!=1 && !level) { for (c=buf+14; *c==' ' || *c=='\t'; c++); if (!strncmp( c, "(atend)", 7)) atend = 1; else { sscanf( c, "%lf %lf %lf %lf", ps_bb, ps_bb+1, ps_bb+2, ps_bb+3); got_bb = 1; } } else if (!strncmp( buf, "%%Document", 10) && inbody!=1 && !level) /* several kinds of doc props */ { for (c=buf+10; *c && *c!=' ' && *c!='\t'; c++); for (; *c==' ' || *c=='\t'; c++); if (!strncmp( c, "(atend)", 7)) atend = 1; else { /* pass this DSC to output */ puts( buf); dsc_cont = 1; } } } return got_bb; } /*********************************************/ /* output last part of DSC header */ /*********************************************/ static void dsc_head2() { printf ("%%%%Pages: %d\n", nrows*ncols); #ifndef Gv_gs_orientbug printf ("%%%%Orientation: %s\n", rotate?"Landscape":"Portrait"); #endif printf ("%%%%DocumentMedia: %s %d %d 0 white ()\n", mediaspec, (int)(mediasize[2]), (int)(mediasize[3])); printf ("%%%%BoundingBox: 0 0 %d %d\n", (int)(mediasize[2]), (int)(mediasize[3])); printf ("%%%%EndComments\n\n"); printf ("%% Print poster %s in %dx%d tiles with %.3g magnification\n", infile, nrows, ncols, scale); } /*********************************************/ /* output the poster, create tiles if needed */ /*********************************************/ static void printposter() { int row, col; printprolog(); for (row = 1; row <= nrows; row++) for (col = 1; col <= ncols; col++) tile( row, col); printf ("%%%%EOF\n"); if (tail_cntl_D) { printf("%c", 0x4); } } /*******************************************************/ /* output PS prolog of the scaling and tiling routines */ /*******************************************************/ static void printprolog() { printf( "%%%%BeginProlog\n"); printf( "/cutmark %% - cutmark -\n" "{ %% draw cutline\n" " 0.23 setlinewidth 0 setgray\n" " clipmargin\n" " dup 0 moveto\n" " dup neg leftmargin add 0 rlineto stroke\n" " %% draw sheet alignment mark\n" " dup dup neg moveto\n" " dup 0 rlineto\n" " dup dup lineto\n" " 0 rlineto\n" " closepath fill\n" "} bind def\n\n"); printf( "%% usage: row col tileprolog ps-code tilepilog\n" "%% these procedures output the tile specified by row & col\n" "/tileprolog\n" "{ %%def\n" " gsave\n" " leftmargin botmargin translate\n" " do_turn {exch} if\n" " /colcount exch def\n" " /rowcount exch def\n" " %% clip page contents\n" " clipmargin neg dup moveto\n" " pagewidth clipmargin 2 mul add 0 rlineto\n" " 0 pageheight clipmargin 2 mul add rlineto\n" " pagewidth clipmargin 2 mul add neg 0 rlineto\n" " closepath clip\n" " %% set page contents transformation\n" " do_turn\n" " { pagewidth 0 translate\n" " 90 rotate\n" " } if\n" " pagewidth colcount 1 sub mul neg\n" " pageheight rowcount 1 sub mul neg\n" " do_turn {exch} if\n" " translate\n" " posterxl posteryb translate\n" " sfactor dup scale\n" " imagexl neg imageyb neg translate\n" " tiledict begin\n" " 0 setgray 0 setlinecap 1 setlinewidth\n" " 0 setlinejoin 10 setmiterlimit [] 0 setdash newpath\n" "} bind def\n\n"); printf( "/tileepilog\n" "{ end %% of tiledict\n" " grestore\n" " %% print the cutmarks\n" " gsave\n" " leftmargin botmargin translate\n" " pagewidth pageheight translate cutmark 90 rotate cutmark\n" " 0 pagewidth translate cutmark 90 rotate cutmark\n" " 0 pageheight translate cutmark 90 rotate cutmark\n" " 0 pagewidth translate cutmark 90 rotate cutmark\n" " grestore\n" " %% print the page label\n" " 0 setgray\n" " leftmargin clipmargin 3 mul add clipmargin labelsize add neg botmargin add moveto\n" " (Grid \\( ) show\n" " rowcount strg cvs show\n" " ( , ) show\n" " colcount strg cvs show\n" " ( \\)) show\n" " showpage\n" "} bind def\n\n"); printf( "%%%%EndProlog\n\n"); printf( "%%%%BeginSetup\n"); printf( "%% Try to inform the printer about the desired media size:\n" "/setpagedevice where %% level-2 page commands available...\n" "{ pop %% ignore where found\n" " 3 dict dup /PageSize [ %d %d ] put\n" " dup /Duplex false put\n%s" " setpagedevice\n" "} if\n", (int)(mediasize[2]), (int)(mediasize[3]), manualfeed?" dup /ManualFeed true put\n":""); printf( "/sfactor %.10f def\n" "/leftmargin %d def\n" "/botmargin %d def\n" "/pagewidth %d def\n" "/pageheight %d def\n" "/imagexl %d def\n" "/imageyb %d def\n" "/posterxl %d def\n" "/posteryb %d def\n" "/do_turn %s def\n" "/strg 10 string def\n" "/clipmargin 6 def\n" "/labelsize 9 def\n" "/tiledict 250 dict def\n" "tiledict begin\n" "%% delay users showpage until cropmark is printed.\n" "/showpage {} def\n" "/setpagedevice { pop } def\n" "end\n", scale, (int)(cutmargin[0]), (int)(cutmargin[1]), (int)(mediasize[2]-2.0*cutmargin[0]), (int)(mediasize[3]-2.0*cutmargin[1]), (int)imagebb[0], (int)imagebb[1], (int)posterbb[0], (int)posterbb[1], rotate?"true":"false"); printf( "/Helvetica findfont labelsize scalefont setfont\n"); printf( "%%%%EndSetup\n"); } /*****************************/ /* output one tile at a time */ /*****************************/ static void tile ( int row, int col) { static int page=1; if (verbose) fprintf( stderr, "print page %d\n", page); printf ("\n%%%%Page: %d %d\n", page, page); printf ("%d %d tileprolog\n", row, col); printf ("%%%%BeginDocument: %s\n", infile); printfile (); printf ("\n%%%%EndDocument\n"); printf ("tileepilog\n"); page++; } /******************************/ /* copy the PS file to output */ /******************************/ static void printfile () { /* use a double line buffer, so that when I print */ /* a line, I know whether it is the last or not */ /* I surely dont want to print a 'cntl_D' on the last line */ /* The double buffer removes the need to scan each line for each page*/ /* Furthermore allows cntl_D within binary transmissions */ char buf[2][BUFSIZE]; int bp; char *c; if (freopen (infile, "r", stdin) == NULL) { fprintf (stderr, "%s: fail to open file '%s'!\n", myname, infile); printf ("/systemdict /showpage get exec\n"); printf ("%%%%EOF\n"); exit (1); } /* fill first buffer for the first time */ fgets( buf[bp=0], BUFSIZE, stdin); /* read subsequent lines by rotating the buffers */ while (fgets(buf[1-bp], BUFSIZE, stdin)) { /* print line from the previous fgets */ /* do not print postscript comment lines: those (DSC) lines */ /* sometimes disturb proper previewing of the result with ghostview */ if (buf[bp][0] != '%') fputs( buf[bp], stdout); bp = 1-bp; } /* print buf from last successfull fgets, after removing cntlD */ for (c=buf[bp]; *c && *c != '\04'; c++); if (*c == '\04') { tail_cntl_D = 1; *c = '\0'; } if (buf[bp][0] != '%' && strlen( buf[bp])) fputs( buf[bp], stdout); } static int mystrncasecmp( const char *s1, const char *s2, int n) { /* compare case-insensitive s1 and s2 for at most n chars */ /* return 0 if equal. */ /* Although standard available on some machines, */ /* this function seems not everywhere around... */ char c1, c2; int i; if (!s1) s1 = ""; if (!s2) s2 = ""; for (i=0; i