This is quarto.c in view mode; [Download] [Up]
/* * quarto.c * * Quickie program to filter PostScript (EPS) files and... * - extract selected pages * ... | quarto -p1,2,6-8 ... print those pages * - change page order (reverse, even, odd; etc) * ... | quarto -r ... print in reverse order * ... | quarto -p odd ... select the odd pages * - print "N-up" (quarto/octavo; N=2,3,4,6,8,9) layouts * ... | quarto -4 -c -b ... print 4 (small) pages per side * * For printing books or booklets in signatures, e.g., * quarto -2 -S 4 ... * means that a signature is 4 sheets, 2 (small) pages per side. * The page ordering is such that you can run them through a copier * printing 2 pages onto 1 double-sided page (or take every other sheet, * flip it over, and glue it back to back on the previous sheet). * * Currently only tested and used with a NeXT printer + Letter-size paper, * with input in portrait orientation. It should be easy to fix for * other varieties; check PBox, the test pattern, the calculation of 'Scale', * and the macro 'pgx()' (used by the 'putNup()' routines). If you can * print out test patterns (the "-d" option) you're close if not working. * * Enjoy at your own peril, but please send me any improvements. * * Also, if you like this program and get good use out of it, consider * sending $4.37 to: * Bob Greene * Media Lab Crew Treasurer * MIT Media Lab * 20 Ames Street * Cambridge, MA 02139 * * Say "Yo Bob! I'm dying to find out how your boys did at Henley. * Did they really row in the nude because you are too poor * to buy uniforms? Perhaps this miserly contribution will help." * * * M. J. Hawley * MIT media Laboratory * 20 Ames Street * Cambridge, MA 02139 * mike@media-lab.mit.edu * Copyright (c) MIT Media Laboratory 1991. * Top secret! Burn before reading! This means you!! * * * Notes -- version 1.1 * * - added signature printing and fixed the nested-page bug (November, 1992) */ #include <stdio.h> #include <ctype.h> #include <sys/types.h> /* * Some general utilities ---------------------------------------- */ char *av0; #define Case break; case #define Default break; default static char *_arg, *_argp; /* use by 'for_each_argument */ extern char *av0; /* will hold name of the command */ #define argument (_arg=(*_argp? _argp : av[++i==ac? --i : i]),_argp+=strlen(_argp),_arg) #define for_each_argument av0 = av[0]; for (i=1;i<ac && *av[i]=='-';i++)\ for (_argp = &av[i][1]; *_argp;)\ switch(*_argp++) extern char *malloc(), *index(); extern int atoi(); extern double atof(); stripnl(s) char *s; { /* remove trailing \n and space from 's' */ char *p = s + strlen(s)-1; while (p>s && (*p=='\n' || *p == ' ')) *p-- = '\0'; } char * skipsp(s) char *s; { while (*s==' ' || *s=='\t' || *s == '\n') ++s; return s; } error(a,b,c,d,e,f) int a,b,c,d,e,f; { /* printf an error msg */ fprintf(stderr,(char *)a,b,c,d,e,f); fprintf(stderr,"\n"); } /* ---------------------------------------------------------------- */ FILE *Input, *Output; char *CurFile; typedef struct { float x, y; } Point; typedef struct { Point o, c; } Rectangle; #define HS(r) (r.c.x-r.o.x) #define VS(r) (r.c.y-r.o.y) Rectangle BBox = { 0, 0, 612, 792 }; /* bbox of the document */ Rectangle PBox = { 10, 14, 600, 780 }; /* Letter-sized page-bounding box */ /* These values probably depend on the printer and * paper size; use the test pattern to adjust them for now. */ Rectangle NullRect = {0,0,0,0}; int TestPattern = 0; /* if true, overlay a test pattern on the page*/ int ListPages = 0; /* if true, list pages in the document (no print) */ #define _N_up 1 int N_up = 1; /* default # pages to fit on a sheet */ #define _Gutter 12. float Gutter= _Gutter; #define _CutMarks 0 #define _Borders 1 int CutMarks=_CutMarks, /* print cutmarks around shrunken pages */ Borders=_Borders; /* print dashed borders around shrunken pages */ int ReversePages = 0; int Signatures = 0; /* determine signature page order */ float Scale = .45; /* Scale is normally set by the tiling routines; */ int ScaleSet = 0; /* made a user option just in case. */ int Rotate = 0; /* will be true when landscaping for -2,6,8 */ #define MaxP 1024 #define Trailer (MaxP-1) int Page[MaxP], PageLen[MaxP]; Rectangle PageBbox[MaxP], pageBbox; int NP=0; findPageOffsets(){ char s[4192], *s2=s+2; int i,prevpos=0,prevp=0,p,nested=0; FILE *f = Input; for(i=0;i<MaxP;i++){ Page[i]=PageLen[i]=0; PageBbox[i] = NullRect; } rewind(f); while (fgets(s,sizeof s,f)){ if (s[0]=='%' && s[1]=='%'){ if (strncmp(s2,"BeginDocument",13)==0 || strncmp(s2,"BeginBinary",11)==0){ nested++; } else if (strncmp(s2,"EndDocument",11)==0 || strncmp(s2,"EndBinary",9)==0){ if (nested>0) nested--; } else if (nested==0){ if (strncmp(s2,"Page:",5)==0){ sscanf(s,"%%%%Page: %*s %d",&p); Page[p] = ftell(f)-strlen(s); PageLen[prevp] = Page[p] - prevpos; prevp = p; prevpos = Page[p]; NP++; } else if (strncmp(s2,"Trailer",7)==0){ Page[Trailer] = ftell(f)-strlen(s); PageLen[prevp] = Page[Trailer] - prevpos; prevpos = Page[Trailer]; } else if (strncmp(s2,"BoundingBox:",12)==0){ char *q = skipsp(index(s,':')+1); if (isdigit(*q)) sscanf(q,"%f %f %f %f", &BBox.o.x,&BBox.o.y,&BBox.c.x,&BBox.c.y); } else if (strncmp(s2,"PageBoundingBox:",16)==0){ Rectangle r; char *q = skipsp(index(s,':')+1); if (isdigit(*q)){ sscanf(q,"%f %f %f %f", &r.o.x,&r.o.y,&r.c.x,&r.c.y); if (NP) PageBbox[NP] = r; } } } } } PageLen[Trailer] = ftell(f) - prevpos; pageBbox = PageBbox[1]; /* hack ... */ /* * Some NeXT programs put out PageBoundingBoxes * with various origins for each page, * but draw relative to the *first* PageBoundingBox. * See "hack", below. */ } showPageOffsets() { char s[4192]; int i,j; FILE *f = Input; printf("file: %s, %d pages\n",CurFile,NP); printf("%8s %8s\n","offset","length"); for (i=j=0;j<=NP;i++){ if (Page[i] || i==0){ fseek(f,Page[i],0); fgets(s,sizeof s,f); printf("%8d %8d -- %s%s",Page[i], PageLen[i],i?"":"(header) ",s); j++; } } fseek(f,Page[Trailer],0); fgets(s,sizeof s,f); printf("%8d %8d -- (trailer) %s",Page[Trailer],PageLen[Trailer],s); } static char *_s = (char *)0; static int _sn = 0; char * readPage(n){ size_t r; if (_s) *_s = '\0'; if (Page[n] || (n==0 && PageLen[n])){ if (_sn < PageLen[n]){ _sn = 2*PageLen[n]; _s = (_s? (char *)realloc(_s,_sn) : (char *)malloc(_sn)); if (!_s) error("%s: no memory!",av0), exit(1); } rewind(Input); fseek(Input,Page[n],0); *_s = '\0'; fread(_s,PageLen[n], (size_t)1, Input); } return _s; } copyPage(n) /* * Write the 'n'th page in 'f' onto 'o'. */ { char *s = readPage(n); if (*s) fwrite(s,PageLen[n],1,Output); } P(a,b,c,d,e,f,g,h,i){ fprintf(Output,(char *)a,b,c,d,e,f,g,h,i); fprintf(Output,"\n"); } putProlog(n){ char *date, *ctime(); time_t t; time(&t); date = ctime(&t); stripnl(date); P("%%!PS-Adobe-2.0"); P("%%%%Creator: %s, file: %s",av0,CurFile); P("%%%%CreationDate: %s",date); P("%%%%Pages: (atend)",n); P("%%%%BoundingBox: 0 0 612 792"); /* should have options to set */ P("%%%%EndComments"); P(""); P("%% ---------------------- (routines for \"%s\")",av0); P("/q_W %f def /q_H %f def /q_margin 4 def",BBox.c.x,BBox.c.y); P("/q_factor %f def",Scale); P("/q_bbox {"); if (Borders){ P(" /q_y 0 q_factor mul def"); P(" /q_x 0 q_factor mul def"); P(" /q_w q_W q_margin 2 mul add def"); P(" /q_h q_H q_margin 2 mul add def"); P(" q_x q_margin sub q_y q_margin sub moveto"); P(" .2 setgray"); P(" 0 setlinewidth"); P(" q_w 0 rlineto"); P(" 0 q_h rlineto"); P(" 0 q_w sub 0 rlineto"); P(" 0 0 q_h sub rlineto"); P(" stroke"); } P("} def"); P(""); P("/q_cuts {"); if (CutMarks){ P(" /q_y 0 q_factor mul q_margin sub def"); P(" /q_x 0 q_factor mul q_margin sub def"); P(" /q_w q_W q_margin 2 mul add def"); P(" /q_h q_H q_margin 2 mul add def"); P(" /q_d 10 q_factor mul def"); P(" 0 setgray"); P(" 0 setlinewidth"); P(" q_x q_d sub q_y moveto -1 -1 rmoveto"); P(" q_d 0 rlineto 0 0 q_d sub rlineto stroke"); P(" q_x q_d add q_w add q_y moveto 1 -1 rmoveto"); P(" 0 q_d sub 0 rlineto 0 0 q_d sub rlineto stroke"); P(" q_x q_d add q_w add q_y q_h add moveto 1 1 rmoveto"); P(" 0 q_d sub 0 rlineto 0 q_d rlineto stroke"); P(" q_x q_d sub q_y q_h add moveto -1 1 rmoveto"); P(" q_d 0 rlineto 0 0 q_d rlineto stroke"); } P("} def"); P(""); P("/StartShrunkenPage {"); P(" /q_y exch def /q_x exch def"); P(" gsave"); P(" q_x q_y translate"); P(" q_factor q_factor scale"); if (Rotate) P(" -90 rotate"); P("} def"); P(""); P("/EndShrunkenPage {"); P(" grestore"); P("} def"); P(""); if (N_up!=1){ P("/oldshowpage {showpage} bind def"); P("/showpage { } bind def"); } P(""); P("/q_circ { %% x y size ... draw circle + crosshairs"); P(" /q_size exch def /q_y exch def /q_x exch def"); P(" 0 setlinewidth"); P(" q_x q_y moveto"); P(" q_size 0 rlineto"); P(" -2 q_size mul 0 rlineto"); P(" q_size 0 rlineto"); P(" 0 q_size rlineto"); P(" 0 -2 q_size mul rlineto"); P(" stroke"); P(" q_x q_y moveto"); P(" q_x q_y q_size 2 div 0 360 arc stroke"); P("} def"); P(""); P("/q_box { %% lx ly ux uy ... draw a box"); P(" /q_uy exch def /q_ux exch def /q_ly exch def /q_lx exch def"); P(" q_lx q_ly moveto"); P(" q_ux q_ly lineto"); P(" q_ux q_uy lineto"); P(" q_lx q_uy lineto"); P(" q_lx q_ly lineto"); P(" stroke"); P("} def"); P(""); P("/q_testPattern {"); P(" 0 setgray 0 setlinewidth"); P(" %f %f %f %f q_box", PBox.o.x,PBox.o.y,PBox.c.x,PBox.c.y); P(" %f %f moveto 8 0 rlineto stroke", PBox.o.x-4,VS(PBox)/2+PBox.o.y); P(" %f %f moveto -8 0 rlineto stroke", PBox.c.x+4,VS(PBox)/2+PBox.o.y); P(" %f %f moveto 0 8 rlineto stroke", HS(PBox)/2+PBox.o.x,PBox.o.y-4); P(" %f %f moveto 0 -8 rlineto stroke", HS(PBox)/2+PBox.o.x,PBox.c.y+4); P(" %f %f 5 q_circ",HS(PBox)/2+PBox.o.x,VS(PBox)/2+PBox.o.y); P("} def"); P(""); P("%% ----------------------(end of \"%s\" routines)\n",av0); copyPage(0); /* put out the previous document header page */ } ShowPage(){ if (TestPattern) P("q_testPattern"); P("q_sheet restore\noldshowpage"); } putTrailer(n){ copyPage(Trailer); P("%%%%Pages: %d %d",n,n); } static Point center(r) Rectangle r; { Point c; c.x = HS(r)/2. + r.o.x; c.y = VS(r)/2. + r.o.y; return c; } static Point add(a,b) Point a,b; { a.x += b.x; a.y += b.y; return a; } static Point sub(a,b) Point a,b; { a.x -= b.x; a.y -= b.y; return a; } hideOriginalPages(s) char *s; { s[2] = 'p'; while ((s = index(s,'\n')+1) != (char *)1) if (strncmp(s,"%%Page:",7)==0) s[2] = 'p'; } pput(n,p) Point p; { char *s = readPage(n); Rectangle r; if (*s){ hideOriginalPages(s); r = pageBbox; /* PageBbox[n]; ... Thus endeth the hack. */ P("%f %f StartShrunkenPage",p.x,p.y); P("%f %f translate",-1.*Scale*r.o.x,-1.*Scale*r.o.y); fwrite(s,PageLen[n],1,Output); P("EndShrunkenPage"); } } float fmin(a,b) float a,b; { return a<b? a : b; } #define maxQ 16 #define up_decls \ int i, j, N = (NP+(N_up-1))/N_up, page[maxQ];\ float gap = Gutter;\ Point c, p, g, b, q[maxQ];\ g.x=g.y = gap/2.; b = BBox.c #define nup_init() c = center(PBox); \ b.x *= Scale; b.y *= Scale; \ putProlog(N) #define pgx(inc,d) pput(i*N_up+j+1,p); page[j] = *_s; q[j++]=p; p.d += inc #define putbox() for (j=0; j<N_up;j++) \ if (page[j])\ P("%f %f StartShrunkenPage q_bbox q_cuts EndShrunkenPage",\ q[j].x,q[j].y); \ ShowPage() put2up(){ up_decls; if (!ScaleSet) Scale = fmin((VS(PBox)/2.-(2.*gap))/b.x,((HS(PBox)-(2.*gap))/b.y)); nup_init(); for (i=0;i<N;i++){ P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1); j = 0; p = c; p.y += g.x + b.x; p.x -= b.y/2.; pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); putbox(); /* put out boxes, cut marks, & ShowPage */ } return N; } put3up(){ up_decls; if (!ScaleSet) Scale = fmin((VS(PBox)/3.-(2.*gap))/b.x,((HS(PBox)-(2.*gap))/b.y)); nup_init(); for (i=0;i<N;i++){ P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1); j = 0; p = c; p.y += g.x + 1.5*b.x; p.x -= b.y/2.; pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); putbox(); /* put out boxes, cut marks, & ShowPage */ } return N; } put6up(){ up_decls; if (!ScaleSet) Scale = fmin((VS(PBox)/3.-(2.*gap))/b.x,((HS(PBox)/2.-(2.*gap))/b.y)); nup_init(); for (i=0;i<N;i++){ P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1); j = 0; p = c; p.y += gap + 1.5*b.x; p.x += g.x; pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); p = c; p.y += gap + 1.5*b.x; p.x -= g.x + b.y; pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); putbox(); /* put out boxes, cut marks, & ShowPage */ } return N; } put8up(){ up_decls; if (!ScaleSet) Scale = fmin((VS(PBox)/4.-(2.*gap))/b.x,((HS(PBox)/2.-(2.*gap))/b.y)); nup_init(); for (i=0;i<N;i++){ P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1); j = 0; p = c; p.y += 1.5*gap + 2.*b.x; p.x += g.x; pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); p = c; p.y += 1.5*gap + 2.*b.x; p.x -= g.x + b.y; pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); pgx(-(gap+b.x),y); putbox(); /* put out boxes, cut marks, & ShowPage */ } return N; } put4up(){ up_decls; if (!ScaleSet) Scale = .5*fmin((HS(PBox)-(2.*gap))/b.x,(VS(PBox)-(2.*gap))/b.y); nup_init(); for (i=0;i<N;i++){ P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1); j = 0; p = c; p.x -= g.x + b.x; p.y += g.y; pgx(gap+b.x,x); pgx(gap+b.x,x); p = c; p.x -= g.x + b.x; p.y -= g.y + b.y; pgx(gap+b.x,x); pgx(gap+b.x,x); putbox(); /* put out boxes, cut marks, & ShowPage */ } return N; } put9up(){ up_decls; if (!ScaleSet) Scale = .333*fmin((HS(PBox)-(3.*gap))/b.x,(VS(PBox)-(2.*gap))/b.y); nup_init(); for (i=0;i<N;i++){ P("\n%%%%Page: %d %d\n/q_sheet save def",i+1,i+1); j = 0; p = c; p.x -= g.x + 1.5*b.x; p.y += g.y + .5*b.y; pgx(g.x+b.x,x); pgx(g.x+b.x,x); pgx(g.x+b.x,x); p = c; p.x -= g.x + 1.5*b.x; p.y -= .5*b.y; pgx(g.x+b.x,x); pgx(g.x+b.x,x); pgx(g.x+b.x,x); p = c; p.x -= g.x + 1.5*b.x; p.y -= g.y + 1.5*b.y; pgx(g.x+b.x,x); pgx(g.x+b.x,x); pgx(g.x+b.x,x); putbox(); /* put out boxes, cut marks, & ShowPage */ } return N; } putpages(){ int i; char *s, *p, *index(); putProlog(NP); for (i=1;i<=NP;i++){ s = readPage(i); if (*s){ p = index(s,'\n'); if (p){ p+1; fprintf(Output,"%%%%Page: %d %d\n",i,i); fwrite(p,PageLen[i] - (p-s),1,Output); fprintf(Output,"q_bbox\n"); } } else { /* emit blank page, e.g., for signatures */ fprintf(Output,"%%%%Page: %d %d\n",i,i); fprintf(Output,"q_bbox\n"); } } } char *SelectPages = (char *)0; ReorderPages(){ int i,j; int pages[MaxP], po[MaxP], pl[MaxP], np=0; Rectangle pr[MaxP]; bzero(pages,sizeof(pages)); if (SelectPages){ char *s = skipsp(SelectPages); int start=0,end; while (*s){ if (strncmp(s,"even",4)==0){ for (i=2;i<=NP;i+=2) pages[np++]=i; s+=4; } else if (strncmp(s,"odd",3)==0){ for (i=1;i<=NP;i+=2) pages[np++]=i; s+=3; } else if (strncmp(s,"blank",5)==0){ pages[np++]=NP+1; s+=5; } else if (strncmp(s,"all",3)==0){ for (i=1;i<=NP;i++) pages[np++]=i; s+=3; } else if (*s == '-'){ start = 1; ++s; end = atoi(s); while (isdigit(*s)) ++s; for (i=start;i<=end;i++) pages[np++] = i; } else if (isdigit(*s)){ pages[np++] = atoi(s); while (isdigit(*s) || isspace(*s)) ++s; if (*s == '-'){ ++s; while (*s && !isdigit(*s)) ++s; end = *s? atoi(s) : NP; while (*s && isdigit(*s)) ++s; for (i=pages[np-1]+1;i<=end;i++) pages[np++] = i; } } else ++s; while (*s== ',' || *s=='-' || isspace(*s)) ++s; } for (i=0;i<np;i++){ po[i] = Page[pages[i]]; pl[i] = PageLen[pages[i]]; pr[i] = PageBbox[pages[i]]; } for (i=0;i<np;i++){ Page[i+1] = po[i]; PageLen[i+1] = pl[i]; PageBbox[i+1] = pr[i]; } for (i=np+1;i<=NP;i++) Page[i] = PageLen[i] = 0; NP = np; } else for (i=0;i<NP;i++) pages[i] = i+1; if (ReversePages){ #define swap(t, a,b) t = a; a = b; b = t for (i=1,j=NP; i<j; i++,j--){ int t; Rectangle r; swap(t, pages[i],pages[j]); swap(t, Page[i],Page[j]); swap(t, PageLen[i],PageLen[j]); swap(r,PageBbox[i],PageBbox[j]); } } if (Signatures){ /* reorder appropriately for 2-sided signatures of 'Signature' sheets per packet. With signatures of 2 sheets, a page ordering of 1 2 3 4 5 6 7 8 9 10 11 12 . . . becomes 8 1 2 7 6 3 4 5 16 9 10 15 . . . */ int i, p, s, *P, tmp, PP, page[MaxP]; int SidesPerSig = Signatures*2, PagesPerSig = SidesPerSig*2, NumSigs = (NP + PagesPerSig - 1) / PagesPerSig; bzero(page,sizeof(page)); for (s=0,i=0; s<NumSigs; s++){ for (p=0, P = page+s*PagesPerSig+1;p<SidesPerSig;p++, P+=2) *P = pages[i++]; for (p=0, P-=3 ;p<SidesPerSig;p++, P-=2) *P = pages[i++]; for (p=0, P=page+s*PagesPerSig+2; p<PagesPerSig;p++,P+=4) tmp=P[0],P[0]=P[1],P[1]=tmp; } PP = NP; NP = PagesPerSig*NumSigs; for (i=0;i<NP;i++) if (page[i]>PP || !page[i]) page[i]=NP; for (i=0;i<NP;i++){ po[i+1] = Page[page[i]]; pl[i+1] = PageLen[page[i]]; pr[i+1] = PageBbox[page[i]]; } for (i=0;i<NP;i++){ Page[i+1] = po[i+1]; PageLen[i+1] = pl[i+1]; PageBbox[i+1] = pr[i+1]; } fprintf(stderr,"%d %d-page signatures:\n ",NumSigs,Signatures); for (i=0;i<NP;i++){ if (i && i%4 == 0) fprintf(stderr," "); if (i && i%PagesPerSig == 0) fprintf(stderr,"\n "); if (page[i]==NP) fprintf(stderr," . "); else fprintf(stderr,"%2d ",page[i]); } fprintf(stderr,"\n"); } } doFile(s) char *s; { FILE *f = fopen(s,"r"); int n; if (!f) return error("%s: couldn't open %s",av0,s); Input = f; findPageOffsets(); if (ListPages) showPageOffsets(); else { ReorderPages(); switch (N_up){ case 2: n=put2up(); Case 3: n=put3up(); Case 4: n=put4up(); Case 6: n=put6up(); Case 8: n=put8up(); Case 9: n=put9up(); Default:n=putpages(); } putTrailer(n); } fclose(f); } savetmp(s,f) char *s; FILE *f; /* * Copy 'f' into a tmp file; put the name in s, * and return 1 if success. */ { FILE *o; int n, F, O; char b[8192]; strcpy(s,"/tmp/quartoXXXXXX"); mktemp(s); strcat(s,".eps"); if (o = fopen(s,"w")){ F = fileno(f); O = fileno(o); while ((n=read(F,b,sizeof b))>0) write(O,b,n); fclose(o); return 1; } else return 0; } use(){ error("use: %s [-[234689]] [-p <pages>] [-S #] [-bcdlr] [-g #] [PS file]",av0); error("Select pages from a PostScript file, and print in a tiled format."); error("(The input must contain EPS-like directives '%%%%Page:...')"); error(" -p... print the given pages; e.g., '-p1,2,4-8,12-'"); error(" '-p -4' prints through page four;"); error(" '-p 12-' prints from page 12 through the end;"); error(" numbers are original ordinal page numbers, starting at 1"); error(" also, '-p even', '-p odd', '-p1-4,1-4,1-4,1-4' etc."); error(" 'blank' or 0 inserts a blank page; 'all' inserts all the pages"); error(" -2 print 2 tiled, shrunken pages per page;"); error(" # may be 2,3,4,6,8 or 9 (default 1);"); error(" portrait or landscape layout will be chosen accordingly."); error(" -b %sprint borders around each tiled page.", _Borders?"don't ":""); error(" -c %sprint cut-marks for each tiled page.", _CutMarks?"don't ":""); error(" -d overlay a test pattern on the page."); error(" (a box around the paper sheet border, "); error(" and a circle and cross in the middle;"); error(" intended to help calibrate for different printers)"); error(" -S # reorder pages to print them in signatures of # sheets;"); error(" e.g., '-2 -S 3' prints pages 2-up per page for signatures"); error(" of 3 double-sided sheets that will be folded and bound together."); error(" -g # set the gap between tiles to # (%3f)",_Gutter); error(" -l list the pages+offsets (don't output any PostScript)."); error(" -r reverse the page order"); exit(1); } main(ac,av) char *av[]; { int i; for_each_argument { case 'l': ListPages = 1; Case 'p': SelectPages = argument; Case 'r': ReversePages = 1; Case 'd': TestPattern = !TestPattern; Case 'c': CutMarks = !CutMarks; Case 'b': Borders = !Borders; Case '1': N_up = 1; Case '2': N_up = 2; Rotate = 1; Case '3': N_up = 3; Rotate = 1; Case '4': N_up = 4; Case '6': N_up = 6; Rotate = 1; Case '8': N_up = 8; Rotate = 1; Case '9': N_up = 9; Case 'g': Gutter = atof(argument); Case 's': Scale = atof(argument); ScaleSet++; /* not mentioned as option */ Case 'S': Signatures = atof(argument); if (N_up != 2) error("You may want to specify -2 sheets per page."); Default : use(); } Output = stdout; if (i==ac){ char s[1024]; if (savetmp(s,stdin)) CurFile="stdin", doFile(s), unlink(s); else error("%s: couldn't save stdin to a tmp file.",av0), exit(1); } else if ((i+1)==ac) CurFile=av[i], doFile(av[i++]); else error("%s: accepts only one file, or stdin...\n",av0), use(); exit(0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.