chris@yarra.oz.au (Chris Jankowski) (11/08/89)
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; }
jgreely@oz.cis.ohio-state.edu (J Greely) (11/09/89)
>From: J Greely <jgreely@cis.ohio-state.edu> > print header, inserting '%%Pages: (atend)' as the second line. > If you don't do this, your output won't conform. As a side note, NeXT users should also delete all other '%%Pages:' comments in the header, since the version of Preview shipped with release 1.0 doesn't ignore subsequent '%%Pages:' lines. -=- J Greely (jgreely@cis.ohio-state.edu; osu-cis!jgreely)