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.