denise@cwi.nl.UUCP (Denise L. Draper) (08/22/87)
pshalf takes PostScript input generates PostScript output with two input pages (rotated and approximately half size) to every output page. Also included is a fix to TranScript(tm) psdit. Enjoy, Denise Draper **DEI** denise@cwi.nl Centrum voor Wiskunde en Informatica ..!seismo!mcvax!denise -------------------------------------------------------------- #!/bin/sh # # This is a shar file. # Cut off everything above the /bin/sh line. # The rest of this file will extract: # # README Makefile pshalf.proto pshalf.ps pshalf.1.proto diffs.psdit squeeze.c # PATH=/bin:/usr/bin echo "extracting: README (1168 bytes)" if [ -s README ] then echo will not overwrite README 1>&2 else sed -e 's/^X//' > README <<'!End-Of-README!' X== X== pshalf -- produce PostScript pages two to a (paper) page X== X XTo make, set the variables in the Makefile, and make all. To install, Xmake install. I install the postscript file pshalf.ps as well as the Xshell script because it can be quite useful in its own right -- as a Xtemplate for other programs, if nothing else. X XAs noted in the manual page, pshalf will not work with output produced Xfrom standard Adobe psdit, because psdit does not obey the structuring Xconventions -- it does not produce conforming PostScript. (And naturally, Xpsroff was the first thing I tried to test pshalf with -- it took me a Xwhile to realize what was going on, arrgh!) The file diffs.psdit contains Xthe fixes to psdit and psdit.pro needed to make conforming output -- it Xreally was a fairly simple fix. X XThe included program squeeze is copywrited by Tomas Rokicki X(rokicki@sushi.stanford.edu). The rest is by me. I make no restrictions Xon its use or reuse or modifications, or whathaveyou, but I would appreciate Xit if 1) my name stayed attached, and 2) improvements, bug fixes, etc., Xare sent to me. X XDenise Draper denise@cwi.nl XCWI, Amsterdam ..!seismo!mcvax!denise !End-Of-README! fi echo -n extracted: ls -l README | awk '{ printf " %s (%d bytes)\n", $8, $4 }' echo "extracting: Makefile (796 bytes)" if [ -s Makefile ] then echo will not overwrite Makefile 1>&2 else sed -e 's/^X//' > Makefile <<'!End-Of-Makefile!' X# X# Makefile for pshalf X# X# home for pshalf XBINDIR=/usr/local X# X# home for pshalf.ps XPSDIR=/usr/local/lib/postscript X# XMANDIR=/usr/man/manl XMANEXT=l X Xall: pshalf pshalf.1 X Xpshalf: pshalf.ps pshalf.proto squeeze X squeeze < pshalf.ps | sed -e '1d' -e 's/\(.*\)/print "\1"/' > tmp X sed -e '/PROLOG/r tmp' -e '/PROLOG/d' < pshalf.proto > pshalf X rm tmp X chmod +x pshalf X Xpshalf.1: pshalf.1.proto Makefile X sed -e "s;PSDIR;$(PSDIR);" < pshalf.1.proto > pshalf.1 X Xsqueeze: squeeze.c X cc -O squeeze.c -o squeeze X Xinstall: all X install -c pshalf $(BINDIR) X install -c pshalf.ps $(PSDIR) X install -c pshalf.1 $(MANDIR)/pshalf.$(MANEXT) X Xshar: X shar README Makefile pshalf.proto pshalf.ps pshalf.1.proto \ X diffs.psdit squeeze.c > sharfile X Xclean: X rm -f sharfile pshalf pshalf.1 squeeze !End-Of-Makefile! fi echo -n extracted: ls -l Makefile | awk '{ printf " %s (%d bytes)\n", $8, $4 }' echo "extracting: pshalf.proto (1169 bytes)" if [ -s pshalf.proto ] then echo will not overwrite pshalf.proto 1>&2 else sed -e 's/^X//' > pshalf.proto <<'!End-Of-pshalf.proto!' X#!/bin/sh X# X# pshalf <files> X# X# Make Postscript output two pages to a page (rotated, approx 1/2 size). X# X# reads stdin or files, writes stdout. Takes miminally conforming PostScript X# input and produces minimally conforming PostScript output. X# X# Caveat: the output has mungled around with the showpage operator, which X# means that it cannot be used as input to any other program that must X# capture the showpage operator (for example psdraft, or pshalf itself). X# X# Written by Denise Draper denise@cwi.nl X# X Xawk ' XBEGIN { firsthalf = 1; outpages = 0 } X/^%%Pages:/ { next } X/^%%PageFonts:/ { next } X/^%%Page:/ { if( firsthalf ) { X if( outpages != 0 ) X print "HfDict begin ep end" X print "%%Page: ? " ++outpages X print "HfDict begin bp end" X } else { X print "HfDict begin hp end" X } X firsthalf = 1 - firsthalf X next X } X/^%%EndProlog/ { Xprint "% --Pshalf, by Denise Draper--" XPROLOG Xprint "% --End Pshalf--" Xprint "%%Pages: (atend)" Xprint "%%EndProlog" X next X } X/^%%Trailer/ { if( outpages != 0 ) X print "HfDict begin ep end" X print "%%Trailer" X print "%%Pages: " outpages X next X } X { print $0 } ' $@ !End-Of-pshalf.proto! fi echo -n extracted: ls -l pshalf.proto | awk '{ printf " %s (%d bytes)\n", $8, $4 }' echo "extracting: pshalf.ps (3125 bytes)" if [ -s pshalf.ps ] then echo will not overwrite pshalf.ps 1>&2 else sed -e 's/^X//' > pshalf.ps <<'!End-Of-pshalf.ps!' X%! X% pshalf - put postscript page descriptions, two to a page (rotated, X% and approx half size). X% X% Include this prolog (after any other prologs), and surround page X% descriptions with the calls: X% X% HfDict begin bp end X% ... 1st page description X% HfDict begin hp end X% ... 2nd page description X% HfDict begin ep end X% HfDict begin bp end X% ... 3rd page description X% etc. X% X% The 2nd half of the page may be skipped by leaving out hp, X% and the first half skipped by `Hfdict begin bp hp end' X% X% CAVEAT(S): This will (probably) not work if the input pages redefine X% showpage. The graphics should always work if the input pages are X% contained entirely between bp and ep pairs. If, however, there is a X% prolog outside of this, then any paths defined in the prolog remain X% in `prolog coordinates'. If a clipping path is defined in the prolog, X% it is ignored entirely. X% X% Written by Denise Draper denise@cwi.nl X X % Make our own dict, to minimize name X/HfDict 20 dict def % space conflict. XHfDict begin % (We must simply hope that the dict X % name itself provides no conflict.) X% X% Create the needed transformation matrices X Xgsave X X% If there is a prolog, there may be some global modification to the CTM. X% This is tricky since it is necessary that the order of modifications be X% theirmods(ourmods(default) or, in matrix notation, TOD X X/T % find T Xmatrix currentmatrix % TD Xmatrix defaultmatrix % D -1 Xmatrix invertmatrix % --> D Xmatrix concatmatrix % --> T Xdef X Xinitgraphics % set CTM to D Xclippath pathbbox % get coordinates of edges, to define O X/y2 exch def X/x2 exch def X/y1 exch def X/x1 exch def X X/X x2 x1 sub def % define x and y page lengths X/Y y2 y1 sub def X % Now modify D to create OD X90 rotate % (draw pictures to understand) X % I think this is the correct translate, but it doesn't work right X% y1 x1 sub x2 y1 add neg translate % (y1-x1), -(x2+y1) X % this one works Xy1 x1 sub x2 neg translate XX Y div Y X 2 mul div scale % X/Y, (Y/2)/X -- maybe should be square? Xmatrix currentmatrix /O1D exch def % matrix for 1st halfpage X XX 0 translate % (move over by (already scaled) page width) Xmatrix currentmatrix /O2D exch def % matrix for 2nd halfpage X Xgrestore %---- end matrix calculations X X/nclip { % Make a default clipping path X initclip newpath % (used in OD (e.g. halfpage) space) X x1 y1 moveto x1 y2 lineto % X x2 y2 lineto x2 y1 lineto % X closepath clip newpath } def % X X/bp { % BeginPage: starts a new real page X gsave % input page goes to first halfpage X O1D setmatrix nclip % X T concat % now we have TOD X} def % X X/hp { % HalfPage: go to 2nd halfpage X grestore gsave % X O2D setmatrix nclip % X T concat } def % X X/ep { % EndPage: print the real, composite page X showpage grestore % X} bind def % _bound_ to the _real_ showpage operator. X X% X% In userdict, replace the definition of showpage, so that any X% reference to showpage in the user's input doesn't have any effect. X% Xend % HfDict X/showpage /newpath load def X !End-Of-pshalf.ps! fi echo -n extracted: ls -l pshalf.ps | awk '{ printf " %s (%d bytes)\n", $8, $4 }' echo "extracting: pshalf.1.proto (1754 bytes)" if [ -s pshalf.1.proto ] then echo will not overwrite pshalf.1.proto 1>&2 else sed -e 's/^X//' > pshalf.1.proto <<'!End-Of-pshalf.1.proto!' X.TH PSHALF 1 "1987" X.ds PS P\s-2OST\s+2S\s-2CRIPT\s+2 X.SH NAME Xpshalf \- reduce size of \*(PS input X.SH SYNOPSIS X.B pshalf X[ X.I files X] X.SH DESCRIPTION X.I Pshalf Xtakes (minimally conforming) \*(PS input and produces X(minimally conforming) \*(PS output, with two Xinput pages mapped to each output page (each rotated and Xapproximately half size). XIf no X.I files Xare specified, the standard input is used. X.I Pshalf Xwill usually be used as a filter after some other command Xthat produces \*(PS output, for example: X.IP Xpsroff \-t \fI<other args>\fR | pshalf | lpr \-P\fI<\*(PSprinter>\fR X.IP Xenscript \-p \- \fI<other args>\fR | pshalf | lpr \-P\fI<\*(PSprinter>\fR X.PP X(with the \fB-r2\fR flag to enscript, this produces four-fold output, Xwhich is actually still quite legible.) X.SH CAVEAT X.I Pshalf Xchanges the X.I showpage Xprocedure in \*(PS. XAs a result X.I pshalf Xcannot be used with any other program that must also Xaffect the X.I showpage Xprocedure, for example X.IR psdraft (1), Xor X.I pshalf Xitself. X.PP X.I Pshalf Xdoes not work with the standard version of X.IR psroff (1), Xbecause that version (actually X.IR psdit ) Xdoes not obey the \*(PS structuring conventions. X(On our system, this bug in X.I Xpsdit Xhas been fixed.) X.SH FILES XPSDIR/pshalf.ps The verbose version of the \*(PS program X.SH "SEE ALSO" Xenscript(1), psroff(1), psgrind(1) X.SH AUTHOR XDenise Draper \(em denise@cwi.nl X.br XCentrum voor Wiskunde en Informatica, Amsterdam X.SH BUGS XIf the input \*(PS program establishes paths in its prolog, Xthese paths will remain in the original (unrotated, unshrunk) Xcoordinate system. The exception is the clipping path \(em Xany clipping path established in the prolog is simply ignored. X.SH NOTES X\*(PS is a trademark of Adobe Systems Incorporated. !End-Of-pshalf.1.proto! fi echo -n extracted: ls -l pshalf.1.proto | awk '{ printf " %s (%d bytes)\n", $8, $4 }' echo "extracting: diffs.psdit (2833 bytes)" if [ -s diffs.psdit ] then echo will not overwrite diffs.psdit 1>&2 else sed -e 's/^X//' > diffs.psdit <<'!End-Of-diffs.psdit!' X X------- psdit.c ------- X*** /tmp/d05706 Fri Aug 21 14:49:09 1987 X--- psdit.c Fri Aug 21 14:48:00 1987 X*************** X*** 861,870 **** X output = 1; X FlushShow(0); X if (!firstpage) { X! printf("\n%d p",n); X } X firstpage = FALSE; X! printf ("\n%%%%Page: %d %d\n", n, ++pageno, n); X for (i = 0; i <= nfonts; i++) { X if (fontdelta[i] != 0) { X sayload (i, fontname[i].name, (char *) 0); X--- 861,870 ---- X output = 1; X FlushShow(0); X if (!firstpage) { X! printf("\nep"); X } X firstpage = FALSE; X! printf ("\n%%%%Page: %d %d\nbp\n", n, ++pageno, n); X for (i = 0; i <= nfonts; i++) { X if (fontdelta[i] != 0) { X sayload (i, fontname[i].name, (char *) 0); X*************** X*** 955,961 **** X private t_trailer() X { X FlushShow(0); X! printf("\n%d p",pageno); X printf("\n%%%%Trailer\n"); X printf("xt\n"); X } X--- 955,962 ---- X private t_trailer() X { X FlushShow(0); X! if( !firstpage ) X! printf("\nep\n"); X printf("\n%%%%Trailer\n"); X printf("xt\n"); X } X X------- psdit.pro ------- X*** /tmp/d05598 Fri Aug 21 14:43:22 1987 X--- psdit.pro Thu Aug 20 18:17:56 1987 X*************** X*** 5,16 **** X X /$DITroff 140 dict def $DITroff begin X /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def X! /xi {0 72 11 mul translate 72 resolution div dup neg scale 0 0 moveto X! /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def F X! /pagesave save def}def X- /PB{save /psv exch def currentpoint translate X- resolution 72 div dup neg scale 0 0 moveto}def X- /PE{psv restore}def X /arctoobig 90 def /arctoosmall .05 def X /m1 matrix def /m2 matrix def /m3 matrix def /oldmat matrix def X /tan{dup sin exch cos div}def X--- 5,12 ---- X X /$DITroff 140 dict def $DITroff begin X /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def X! /xi {0 72 11 mul translate 72 resolution div dup neg scale X! /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def F }def X /arctoobig 90 def /arctoosmall .05 def X /m1 matrix def /m2 matrix def /m3 matrix def /oldmat matrix def X /tan{dup sin exch cos div}def X*************** X*** 45,51 **** X /MXY{moveto}def X /cb{pop}def % action on unknown char -- nothing for now X /n{}def/w{}def X! /p{pop showpage pagesave restore /pagesave save def}def X /abspoint{currentpoint exch pop add exch currentpoint pop add exch}def X /distance{dup mul exch dup mul add sqrt}def X /dstroke{currentpoint stroke moveto}def X--- 41,49 ---- X /MXY{moveto}def X /cb{pop}def % action on unknown char -- nothing for now X /n{}def/w{}def X! /bp{/psv save def 0 0 moveto} def X! /ep{showpage psv restore}def X! X /abspoint{currentpoint exch pop add exch currentpoint pop add exch}def X /distance{dup mul exch dup mul add sqrt}def X /dstroke{currentpoint stroke moveto}def !End-Of-diffs.psdit! fi echo -n extracted: ls -l diffs.psdit | awk '{ printf " %s (%d bytes)\n", $8, $4 }' echo "extracting: squeeze.c (3011 bytes)" if [ -s squeeze.c ] then echo will not overwrite squeeze.c 1>&2 else sed -e 's/^X//' > squeeze.c <<'!End-Of-squeeze.c!' X/* X * This is dvips, a freely redistributable PostScript driver X * for dvi files. It is (C) Copyright 1987 by Tomas Rokicki. X * You may modify and use this program to your heart's content, X * so long as you send modifications to Tomas Rokicki. It can X * be included in any distribution, commercial or otherwise, so X * long as the banner string defined in structures.h is not X * modified (except for the version number) and this banner is X * printed on program invocation, or can be printed on program X * invocation with the -? option. X */ X/* X * This routine squeezes a PostScript file down to it's X * minimum. We parse and then output it. X */ X#include "stdio.h" X#define LINELENGTH (70) Xstatic int linepos = 0 ; Xstatic int instring ; Xstatic int lastspecial = 1 ; X/* X * This next routine writes out a `special' character. In this case, X * we simply put it out, since any special character terminates the X * preceding token. X */ Xspecialout(c) Xchar c ; X{ X if (linepos + 1 > LINELENGTH) { X putchar('\n') ; X linepos = 0 ; X } X putchar(c) ; X linepos++ ; X lastspecial = 1 ; X} Xstrout(s) Xchar *s ; X{ X if (linepos + strlen(s) > LINELENGTH) { X putchar('\n') ; X linepos = 0 ; X } X linepos += strlen(s) ; X while (*s != 0) X putchar(*s++) ; X lastspecial = 1 ; X} Xcmdout(s, space) Xchar *s ; Xint space ; X{ X int l ; X X l = strlen(s) ; X if (linepos + l + 1 > LINELENGTH) { X putchar('\n') ; X linepos = 0 ; X lastspecial = 1 ; X } X if (! lastspecial && space) { X putchar(' ') ; X linepos++ ; X } X while (*s != 0) { X putchar(*s++) ; X } X linepos += l ; X lastspecial = 0 ; X} Xchar buf[1000] ; Xmain() { X int c, space ; X char *b ; X char seeking ; X X printf("%%!\n") ; X while (1) { X c = getchar() ; X if (c==EOF) X break ; X if (c=='%') { X while ((c=getchar())!='\n') ; X } X if (c <= ' ') X continue ; X space = 1 ; X switch (c) { Xcase '{' : Xcase '}' : Xcase '[' : Xcase ']' : X specialout(c) ; X break ; Xcase '<' : Xcase '(' : X if (c=='(') X seeking = ')' ; X else X seeking = '>' ; X b = buf ; X *b++ = c ; X do { X c = getchar() ; X *b++ = c ; X if (c=='\\') X *b++ = getchar() ; X } while (c != seeking) ; X *b++ = 0 ; X strout(buf) ; X break ; Xcase '/': X space = 0 ; X /*FALLTHROUGH*/ Xdefault: X b = buf ; X while ((c>='A'&&c<='Z')||(c>='a'&&c<='z')|| X (c>='0'&&c<='9')||(c=='/')||(c=='@')||(c=='-')|| X (c=='.')||(c=='#')||(c=='_')||(c=='$')||(c=='&')) { X *b++ = c ; X c = getchar() ; X } X if (b == buf) { X fprintf(stderr, "Oops! Missed a case: %c.\n", c) ; X exit(1) ; X } X *b++ = 0 ; X ungetc(c, stdin) ; X cmdout(buf,space) ; X } X } X if (linepos != 0) X putchar('\n') ; X exit(0) ; X} !End-Of-squeeze.c! fi echo -n extracted: ls -l squeeze.c | awk '{ printf " %s (%d bytes)\n", $8, $4 }' exit