1#! /bin/sh 2# -*- ksh -*- 3 4# psmandup --- produce a version of a PS file to print in manual Duplex. 5 6# Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana 7# Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana 8 9# This program is free software; you can redistribute it and/or modify 10# it under the terms of the GNU General Public License as published by 11# the Free Software Foundation; either version 2, or (at your option) 12# any later version. 13# 14# This program is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17# GNU General Public License for more details. 18# 19# You should have received a copy of the GNU General Public License 20# along with this program; if not, you can either send email to this 21# program's maintainer or write to: The Free Software Foundation, 22# Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA. 23 24# Commentary: 25 26# Author: Akim Demaille <demaille@inf.enst.fr> 27 28# In the interest of general portability, some common bourne shell 29# constructs were avoided because they weren't guaranteed to be available 30# in some earlier implementations. I've tried to make this program as 31# portable as possible. Welcome to unix, where the lowest common 32# denominator is rapidly diminishing. 33# 34# Among the more interesting lossages I noticed with some bourne shells 35# are: 36# * No shell functions. 37# * No `unset' builtin. 38# * `shift' cannot take a numeric argument, and signals an error if 39# there are no arguments to shift. 40 41# Todo: 42# Maybe rewrite in perl. It would help to handle (Begin|End)Document 43# which allows several Trailers etc. 44 45# Code: 46 47# Minimal path. It must be able to see the psutils. 48PATH=/usr/local/bin:$PATH 49export PATH 50 51# Get the name of the program 52program=`echo $0 | sed 's#.*/##g'` 53 54# Local vars 55debug= 56file= 57output= 58psfix=${PSFIX:-psfix} 59tmpdir=/tmp/$program.$$ 60verbose=echo 61 62 63# The version/usage strings 64version="psmandup 0.8 (a2ps 4.9.9k) 65 66Copyright (c) 1988, 89, 90, 91, 92, 93 Miguel Santana 67Copyright (c) 1995, 96, 97, 98 Akim Demaille, Miguel Santana 68This is free software; see the source for copying conditions. There is NO 69warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 70 71Written by <Akim.Demaille@inf.enst.fr> and <Miguel.Santana@st.com> 72News, updates and documentation: visit http://www.inf.enst.fr/a2ps/" 73 74usage="\ 75Usage: $program FILE 76Tries to produce a version of the PostScript FILE to print in manual 77Duplex. 78 79Options: 80 -h, --help display this help and exit 81 -v, --version display version information and exit 82 -q, --quiet don't print informational messages 83 -o, --output=FILE save result in FILE. If FILE is \`-', send to stdout 84 -f, --no-fix don't call psfix to fix PS problems in FILE 85 86Produced output is meant for PS level 2 printers which don't support 87Duplex printing, but support Manual Feed. Once the first set of pages 88is printed (odd pages), manual feed is asked: introduce the odd pages 89to print the even pages on the other side. 90 91Report bugs to <a2ps-bugs@inf.enst.fr>" 92 93help="Try \`$program --help' for more information." 94 95# The PostScript line to ask manual feed 96# We go and pick up setpagedevice because the psutils (here psselect) 97# define an ineffective setpagedevice. 98# I hope setpagedevice is always in systemdict... 99psmanualfeed='% Pagedevice definitions: 100countdictstack [{ 101%%BeginFeature: *ManualFeed True 102 (<<) cvx exec /ManualFeed true (>>) cvx exec 103 systemdict /setpagedevice get exec 104%%EndFeature 105} stopped 106cleartomark 107countdictstack exch sub dup 0 gt 108{ 109 { end } repeat 110}{ 111 pop 112} ifelse' 113 114# Don't leave really new lines in it 115psmanualfeed="`echo "$psmanualfeed" | tr '\n' ' 116'`" 117 118# Parse our command line options once, thoroughly. 119while test $# -gt 0 120do 121 arg="$1" 122 shift 123 124 case "$arg" in 125 -*=*) optarg=`echo "$arg" | sed 's/[-_a-zA-Z0-9]*=//'` ;; 126 *) optarg= ;; 127 esac 128 129 # If the previous option needs an argument, assign it. 130 if test -n "$prevopt"; then 131 optarg="$arg" 132 arg="$prevopt=" 133 prevopt= 134 fi 135 136 # Have we seen a non-optional argument yet? 137 case "$arg" in 138 --help|-h) 139 echo "$usage" 140 exit 0 141 ;; 142 143 --version|-v) 144 echo "$version" 145 exit 0 146 ;; 147 148 -s|-q|--quiet|--silent) verbose=: ;; 149 # Delay debugging so that options parsing does not appear 150 -D|--debug) debug=: ;; 151 152 --output|-o) prevopt="--output" ;; 153 --output=*) output=$optarg ;; 154 155 -n|--no-fix) psfix= ;; 156 157 -) # We are working with stdin 158 nonopt="$nonopt $arg" 159 ;; 160 161 -*) 162 case "$arg" in 163 --*=* ) arg=`echo "$arg" | sed -e 's/=.*//'` ;; 164 esac 165 exec 1>&2 166 echo "$program: Unknown or ambiguous option \`$arg'." 167 echo "$program: Try \`--help' for more information." 168 exit 1 169 ;; 170 171 *) 172 nonopt="$nonopt $arg" 173 ;; 174 esac 175done 176 177if test -n "$prevopt"; then 178 echo "$program: option \`$prevopt' requires an argument" 1>&2 179 echo "$help" 1>&2 180 exit 1 181fi 182 183case `echo "$nonopt" | wc -w | sed -e 's/[\t ]//g'` in 184 0) file=-;; 185 1) file=$nonopt;; 186 *) echo "$program: too many arguments" 1>&2 187 echo "$help" 1>&2 188 exit 1;; 189esac 190 191# Set -x now if debugging 192test $debug && set -x 193 194# Temp dir. Get ready not to leave junk (if not debugging) 195test $debug || trap "/bin/rm -rf $tmpdir" 0 1 2 3 13 14 15 196mkdir $tmpdir 197 198# If printing from stdin, save into a tmp file 199if test $file = '-'; then 200 file=$tmpdir/stdin.ps 201 cat > $file 202fi 203 204# Fix the file 205if test -n "$psfix"; then 206 $psfix $file -o $tmpdir/fixed.ps `test $verbose = ":" && echo "-q"` \ 207 || exit 1 208 file=$tmpdir/fixed.ps 209fi 210 211# Get the number of pages of the document 212pagenum=`grep '^%%Pages: ' $file | sed -e 's/%%Pages: \\([0-9]*\\).*$/\\1/g'` 213 214# Add padding to make sure to have an even number of pages 215# and fix the trailer of the file 216case $pagenum in 217 *0|*2|*4|*6|*8) 218 # No padding needed 219 ;; 220 221 *) 222 # One sheet needed 223 pagenum=`echo "$pagenum + 1" | bc` 224 # Put it before %%Trailer 225 sed -e "s/%%Trailer/%%Page: $pagenum 226showpage 227%%Trailer/g;\ 228 s/%%Pages: .*/%%Pages: $pagenum/g" $file | tr ' 229' '\n' \ 230 > $tmpdir/padded.ps 231 file=$tmpdir/padded.ps 232 ;; 233esac 234 235psselectarg="1" 236i=3 237# Build the string to give to psselect 238while test $i -le $pagenum; 239do 240 psselectarg="$psselectarg,$i" 241 i=`echo "$i + 2" | bc` 242done 243 244i=$pagenum 245while test $i != 0; 246do 247 psselectarg="$psselectarg,$i" 248 i=`echo "$i - 2" | bc` 249done 250 251# Get odd pages in order, and then 252# even pages in reversed order 253psselect -q $psselectarg $file > $tmpdir/ordered.ps || exit 1 254 255# Insert the manual feed request at the first page of the second half 256# This page has as page num, half of $PAGENUM (which is odd, so no 257# worry) 258midpagenum=`echo "($pagenum / 2) + 1" | bc` 259 260# Insert the manual feed request at the first page of the second half 261# This page has as page num, $MIDPAGENUM. 262# Make sure to skip human readable page number. 263if test "$output" && test "$output" != '-'; then 264 sed -e "s#^%%Page:\(.* $midpagenum[ \t]*\)\$#%%Page:\1 265$psmanualfeed#g" \ 266 $tmpdir/ordered.ps | tr ' 267' '\n' > $output || exit 1 268else 269 sed -e "s#^%%Page:\(.* $midpagenum[ \t]*\)\$#%%Page:\1 270$psmanualfeed#g" \ 271 $tmpdir/ordered.ps | tr ' 272' '\n' || exit 1 273fi 274 275# Don't remove files if debugging 276test $debug || /bin/rm -rf $tmpdir 277 278$verbose "Once the first half of the file printed, insert the sheets" 1>&2 279$verbose "stack into the manual feed tray to print the second half." 1>&2 280exit 0 281 282