Article View: comp.lang.postscript
Article #1284Summary: saving trees - a tool needed
From: Chris Jankowski
Date: Wed, 08 Nov 1989 05:47
Date: Wed, 08 Nov 1989 05:47
651 lines
17065 bytes
17065 bytes
Original question:
=================
>If I have a simple document (no graphics and other fancies) already
>formatted in Postscript how can I print a selection of pages from it?
Summary (in order of work required):
=======
1. Use psrev from Transcript package by Adobe (RTFM again).
2. Use a C program, source appended.
3. Write your own program - algorithm outlines appended.
Thanks to all who responded.
Details:
=======
3. Algorithm.
-------------
From: raymond@bosco.Berkeley.EDU (Raymond Chen)
raymond@math.berkeley.edu
[1] Copy everything from the beginning of the file to the
"%%EndProlog" line.
[2] When you hit a "%%Page" directive, increment your internal page number
counter. If you want this page, start copying, and stop when you
hit the next "%%Page" directive.
[3] Repeat for each page of the document, until you hit a "%%Trailer"
directive. Copy everything after "%%Trailer" to your output file.
-----------------
From: J Greely <jgreely@cis.ohio-state.edu>
if the first line of the file doesn't start with '%!PS-Adobe',
scream bloody murder and die
save all lines before the first '%%Page:' line in a file
named header
parse out the sheet number from the '%%Page:' line
save everything before the next '%%Page:' line in a file
named <sheet number>. Don't save the '%%Page:' line!
keep doing this until you can't find another '%%Page:' line
the last page is not followed by another '%%Page:', so stop
at the '%%Trailer' line
save everything from the '%%Trailer' line on in a file named
trailer
You now have a set of files (header,1..<pages>,trailer). To print
them, do the following:
print header, inserting '%%Pages: (atend)' as the second line.
If you don't do this, your output won't conform.
print the desired pages, prefixed by a '%%Page:' comment
containing the sheet order. For strict conformance,
they *must* be numbered sequentially starting at 1,
but printers don't care (Adobe's own software cheats
on this)
print trailer
print the actual pagecount, as a '%%Pages: n' comment. For
conformance with version 1.0, this must be the last
'%%Pages:' line in the document. Unfortunately, the
relevant sentence was deleted from version 2.0, so
you're only safe if you delete all other '%%Pages:'
lines in the trailer.
If you're not interested in rearranging pages, you can speed things
up quite a bit by discarding undesired pages as you read them, and
hacking '%%Page:' lines on the fly.
Note that everything I say ignores some of the advanced comment
structures possible in version 2.0, like embedded documents (which may
contain their own comment structures, including '%%Trailer'). For
details about this, read the Adobe Document Structuring Conventions
document, version 2.1.
2. C source code.
=================
I compiled the following program in att universe and it does what I want.
From: Jingbai Wang <jbw@unix.cis.pitt.edu>
/* Here is a program I developed called psscribe.c that is self-instructive*/
/* Copyright (C) 1989 by Jingbai Wang
This program is released to public as shareware.
Any individual and institution can use, modify and distribute
it freely provided the copyright note and the following box
are retained. One exeption is that profitable distribution (i.e., charge
over the cost of materials and ship&handling) should have author's written
permission.
*/
/* **********************************************************************
* This program is an auxiliary program for Scribe TEC.mak *
* desgined by myself. *
* It is used to manipulate Scribe PostScript output files *
* or equally standard PostScript output from a text formatter *
* such that a long .ps file can be cut into shorter ones *
* and double-sided documents can be separated into two *
* .ps files for even-sided and odd-sided pages *
* *
* The user can set up the programs for other purposes too *
* Copyright by Jingbai Wang August 1988 *
************************************************************************/
/*
It is intended to have it adoptable to any systems. It is in my mind
for VMS, MSDOS/PC-DOS and unix for the time being.
*/
#define STRSIZE 1024
#define FILEMAX 100
#define PROLENGTH 3600000
#include <string.h>
#include <math.h>
#include <stdio.h>
#define CLS fprintf(stderr, "\n\n\n\n");
/* Global variables */
char psfile[80]="",
Prolog[PROLENGTH],
outfile1[FILEMAX][80],
outfile[80],
evenfile[80],
oddfile[80],
prestring[80]="";
FILE *psfileptr, *Oddpage, *Evenpage, *Allpage;
int partnum=0,
filestart[FILEMAX],
fileend[FILEMAX],
currentpage=0,
file_flag=0;
long int prolength=0,
pageend[1000];
char string[1024];
get_prolog()
{
int l;
prolength = 0;
while(1){
fgets(&Prolog[prolength], 1024, psfileptr);
if( memcmp(&Prolog[prolength], "%%EndProlog", 11)==0)
{while (Prolog[++prolength] != 0) ;
return;
}
else while (Prolog[++prolength] != 0) ;
}
}
main(argc, argv)
int argc;
char *argv[];
{
start_up();
if (argc>1) {strcpy(psfile, argv[1]); file_flag=1;}
pro_info();
}
get_file()
{
int status, len, i, dot_check;
dot_check=0;
if(file_flag==0)
{CLS;
fprintf(stdout, "\n PostScript file name (path and name)> ");
scanf("%s", psfile);
}
len=strlen(psfile);
for (i=0; i<len; i++)
if (psfile[i]=='.') {dot_check=1;}
if (dot_check==0) {strcat(psfile, ".ps");}
if ( (psfileptr=fopen(psfile, "r"))==NULL)
{fprintf(stderr, " .ps file not found "); exit(-1);}
}
pro_info()
{
int yes, i, junk;
fflush(stdin);
start:
CLS;
fprintf(stderr, "\n 1. Get page mapping information\n");
fprintf(stderr, " 2. Extract some pages from the document\n");
fprintf(stderr, " 3. Divide document into parts\n");
fprintf(stderr, " 4. Split document into even and odd pages\n");
fprintf(stderr, " 5. Reverse the page numbers \n");
fprintf(stderr, " 6. Merge a few .ps files together\n");
fprintf(stderr, " 7. Fix converted zeta.plt file\n");
fprintf(stderr, " 8. quit\n\n\n");
select:
fprintf(stderr, " Select a number from above ==> ");
fflush(stdin);
scanf("%d", &yes);
fflush(stdin);
switch(yes)
{
case 1: get_file(); page_map(); break;
case 2: partnum=1; get_file(); get_prolog(); extract(); break;
case 3: get_file(); get_prolog();
fprintf(stderr, "\n\n How many parts to divide>");
scanf("%d", &partnum);
fflush(stdin); divide(); break;
case 4: get_file(); get_prolog(); even_odd(); break;
case 5: get_file(); get_prolog(); reverse_page(); break;
case 6: merge(); break;
case 7: get_file(); fix_zeta();break;
case 8: exit(-1);
default: fprintf(stderr, "%c", 7); goto select;
}
#if unix|ultrix
scanf("%c", &junk);
fflush(stdin);
#endif
hit_continue();
clear_up();
goto start;
}
even_odd()
{
long int i;
int len;
fprintf(stderr, " Output file name odd pages > ");
scanf("%s", oddfile);
fprintf(stderr, " Output file name even pages > ");
scanf("%s", evenfile);
Evenpage=fopen(evenfile, "w");
Oddpage=fopen(oddfile, "w");
for (i=0; i<prolength; i++)
{ fprintf(Evenpage, "%c", Prolog[i]);
fprintf(Oddpage, "%c", Prolog[i]);
}
while(1)
{
if( fgets(string, 1024, psfileptr)==NULL)
{
fclose(psfileptr);
fclose(Evenpage);
fclose(Oddpage);
return;
}
fprintf(Oddpage, "%s", string);
if (memcmp(string, "%%Page:", 7)==0) {
len=strlen(string); string[len-2]=0;
fprintf(stderr, "[%s]", &string[8]);
}
if( fgets(string, 1024, psfileptr)==NULL)
{
fclose(psfileptr);
fclose(Evenpage);
fclose(Oddpage);
return;
}
fprintf(Evenpage, "%s", string);
if (memcmp(string, "%%Page:", 7)==0)
{
len=strlen(string); string[len-2]=0;
fprintf(stderr, "[%s]", &string[8]);
}
}
}
extract()
{
fprintf(stderr, "\n Filename for output > ");
scanf("%s", outfile);
Allpage=fopen(outfile, "w");
fprintf(stderr, " Starting page >");
scanf("%d", &filestart[0]);
fflush(stdin);
fprintf(stderr, " End page >");
scanf("%d", &fileend[0]);
fflush(stdin);
while(currentpage<filestart[0])
{
if( (fgets(string, 1024, psfileptr))==NULL)
{fclose(Allpage); fclose(psfileptr);return;}
if (memcmp(string, "%%Page:", 7)==0) currentpage++;
}
strcpy(prestring,string);
go(0); fclose(Allpage); fclose(psfileptr);
}
divide()
{
int i;
for (i=0; i<partnum; i++)
{
fprintf(stderr, "\n Filename for output part %d> ", i+1);
scanf("%s", outfile1[i]);
if (i==0)
{ fprintf(stderr, " Part %d starts at page # >", i+1);
scanf("%d", &filestart[i]);
fflush(stdin);
}
else filestart[i]=fileend[i-1]+1;
fprintf(stderr, " Part %d ends at page # >", i+1);
scanf("%d", &fileend[i]);
fflush(stdin);
}
if (filestart[0]>1){
while(currentpage<filestart[0])
{
if( (fgets(string, 1024, psfileptr))==NULL) return;
if (memcmp(string, "%%Page:", 7)==0) currentpage++;
}
strcpy(prestring,string);
}
for (i=0; i<partnum; i++)
{
fprintf(stdout, "\n%s:\n", outfile1[i]);
Allpage=fopen(outfile1[i], "w");
go(i); fclose(Allpage);
}
fclose(psfileptr);
}
go(number)
int number;
{
int i;
int len;
for (i=0; i<prolength; i++)
fprintf(Allpage, "%c", Prolog[i]);
len=strlen(prestring);
if (len>0) { fprintf(Allpage, "%s", prestring);
prestring[len-2]=0;
fprintf(stderr, "[%s]", &prestring[8]); }
while(1)
{
if( fgets(string, 1024, psfileptr)==NULL)
{
return;
}
if (memcmp(string, "%%Page:", 7)==0) {currentpage++;
if (currentpage>fileend[number]) {strcpy(prestring, string);
return;}
len=strlen(string); string[len-2]=0;
fprintf(stdout, "[%s]", &string[8]); string[len-2]=32;
}
fprintf(Allpage, "%s", string);
}
}
page_map()
{
int count, len;
fprintf(stderr, " Map file filename for output (2 <Return> for screen)-> ");
fflush(stdin);
scanf("%s", outfile);
if (outfile[0]=='2') Allpage=stdout;
else Allpage=fopen(outfile, "w");
fprintf(stderr , "\n\n");
while(1)
{
if( fgets(string, 1024, psfileptr)==NULL)
{
fclose(psfileptr);
if (Allpage!=stdout) fclose(Allpage);
fflush(stdin);
return;
}
if (memcmp(string, "%%Page:", 7)==0) {currentpage++;
len=strlen(string); string[len-1]=0; count++;
if (count>10) {count=0; fprintf(Allpage, "\n");}
fprintf(Allpage, "[%s]", &string[8]);
}
}
}
reverse_page()
{
int i;
long int j;
fprintf(stderr, " Filename for output file -> ");
fflush(stdin);
scanf("%s", outfile);
Allpage=fopen(outfile, "w");
for (i=0; i<prolength; i++)
{fprintf(Allpage, "%c", Prolog[i]); Prolog[i]=0;}
prolength=0; currentpage=0;
pageend[0]=0;
while(1)
{
if( fgets(string, 1024, psfileptr)==NULL)
{
fclose(psfileptr);
goto out;
}
strcat(Prolog, string);
if (memcmp(string, "%%Page:", 7)==0) {currentpage++;
pageend[currentpage]=prolength;
}
prolength += strlen(string);
}
out:
for (j=pageend[currentpage]; j<prolength; j++)
fprintf(Allpage, "%c", Prolog[j]);
for (i=currentpage; i>0; i--)
{
for (j=pageend[i-1]; j<pageend[i]; j++)
fprintf(Allpage, "%c", Prolog[j]);
}
fclose(Allpage);
}
start_up()
{
char junk;
CLS;
fprintf(stderr, " Welcome to Textformatter .ps File Manager\n");
fprintf(stderr, " by JB Wang, 1989\n\n");
fprintf(stderr, " This utility program can be used to 1) extract certain pages to be\n\
printed; 2) divide the .ps file into a few smaller files; 3) split \n\
the document into two files for odd and even pages; 4) reverse the\n\
page numbering; 5) Merge .ps files in intelligent way; 6) Fix a converted\n\
zeta.plt PostScript file at Pitt\n\n");
fprintf(stderr, "\
Text formatter .ps output file is composed of a prologue, a main body\n\
of pages, and a trailer. Each page carries two page numbers,\n\
that is, the physical page number (printed) and a counter number\n\
that accumulates from 1 to the end. The program can provide the\n\
mapping information between these two numbers in the following format\n\
[page_number counter_number].\n\n");
fprintf(stderr, " This program uses the counter number instead of the physical number.\n\
Therefore, you are advised to get the mapping information before\n\
you output files.\n\n\n");
fprintf(stderr, " Hit <Return> to continue -->");
scanf("%c", &junk);
fflush(stdin);
}
merge()
{
int i;
fprintf(stderr, "\n\n How many files to merge? ");
scanf("%d", &partnum);
fflush(stdin);
if (file_flag==1)
{strcpy(outfile, psfile);
fprintf(stderr, "\n Filename for output > %s", outfile);
}
else {
fprintf(stderr, "\n Filename for output > ");
scanf("%s", outfile);
}
Allpage=fopen(outfile, "w");
for (i=0; i<partnum; i++)
{
again:
fprintf(stderr, " File %d to merge >", i+1);
scanf("%s", outfile1[i]);
if ( (psfileptr=fopen(outfile1[i], "r"))==NULL)
{fprintf(stderr, " .ps file not found "); goto again;}
fclose(psfileptr);
}
for (i=0; i<partnum; i++)
{
psfileptr=fopen(outfile1[i], "r");
if (i>0) get_prolog();
while(fgets(string, 1024, psfileptr)!=NULL)
fprintf(Allpage, "%s", string);
fclose(psfileptr);
}
}
fix_zeta()
{
int i;
char ch;
fprintf(stderr, "\n Filename for output > ");
scanf("%s", outfile);
for (i=0; i<685; i++)
fgetc(psfileptr);
if (fgetc(psfileptr)!='d')
{ fclose(psfileptr);
fprintf(stderr, "\n Wrong version of converted .lps file");
return;
}
fgetc(psfileptr); fgetc(psfileptr);
Allpage=fopen(outfile, "w");
fprintf(Allpage, "%%!\n\
/s { 72 mul 300 div } def /steps { 72 mul 2032 div } def /d { count 0 gt { s exch s exch moveto { count 0 gt \n\
{ s exch s exch lineto } { exit } ifelse } loop 0.3 setlinewidth stroke clear } if } def /g { count 0 gt { s exch s exch moveto\n\
{ count 0 gt { s exch s exch lineto } { exit } ifelse } loop [3 5] 0 setdash 0.5 setlinewidth stroke clear [] 0 setdash } if } def\n\
/h { /Courier findfont 6 scalefont setfont -6 -26 moveto } def /f { -6 -16 moveto } def\n\
/n { d newpath } def /a0 { arc stroke } def /a1 { arcn stroke } def /mr { moveto rotate } def\n\
/cf { /Courier findfont } def /ss { scalefont setfont } def /ur { rotate } def /dd { [] 0 setdash } def d\n");
while ((ch=fgetc(psfileptr))!=EOF)
fprintf(Allpage, "%c", ch);
fclose(psfileptr);
fclose(Allpage);
}
hit_continue()
{
char junk;
fprintf(stderr, "\n\n Hit <Return> to continue -->");
fflush(stdin);
fflush(stdin);
fflush(stdin);
scanf("%c", &junk);
fflush(stdin);
}
clear_up()
{
long int i;
partnum=0;
for (i=0; i<prolength; i++)
Prolog[i]=0;
prolength=0;
strcpy(prestring, "");
currentpage=0;
file_flag=0;
}
Technical Details
Message-ID:
<5174@yarra.oz.au>Path:
arc1-ca.pugleaf.net!utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!uunet!munnari.oz.au!murtoa.cs.mu.oz.au!ditmela!yarra!chrisReferences:
<5110@yarra.oz.au>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!uunet!munnari.oz.au!murtoa.cs.mu.oz.au!ditmela!yarra!chris From: chris@yarra.oz.au (Chris Jankowski) Newsgroups: comp.lang.postscript Subject: Summary: saving trees - a tool needed Summary: 3 ways Keywords: mpage Message-ID: <5174@yarra.oz.au> Date: 8 Nov 89 05:47:09 GMT References: <5110@yarra.oz.au> Reply-To: chris@yarra.oz.au (Chris Jankowski) Organization: Pyramid Technology Corp Pty Ltd, Melbourne Lines: 651