sarantos@notecnirp.Princeton.EDU (Sarantos Kapidakis) (03/24/89)
Here is my program label2ps, for printing labels in a postscript printer. In addition, any sequence of postscript commands can be executed on every label, drawing any figure. There are several options, for adjusting it to the user needs and label sheet. Nearly all the work is done in postscript Also, I include a "labelsort" program, for completeness, and manual pages. sarantos ------------------------------ CUT HERE ------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # label2ps # label2ps.1 # labelsort # labelsort.1 # This archive created: Thu Mar 23 18:43:03 1989 # By: Sarantos Kapidakis (Princeton University CS Dept) export PATH; PATH=/bin:/usr/bin:$PATH if test -f 'label2ps' then echo shar: "will not over-write existing file 'label2ps'" else cat << \SHAR_EOF > 'label2ps' #!/bin/csh -f set groups mode=centered nx=0 ny=0 feed deffile proc set font=Times-Roman size=10 lines=0 rep=0 repx=1 copies=1 set wxo=18 wyo=39 wxe=594 wye=753 wx=180 wy=66 bx=18 by=6 set myargv=(`printenv LABEL2PS` $*:q) set i=0 while($i < $#myargv) @ i++ switch ($myargv[$i]:q) case -t: unset P breaksw case -P*: set P=$myargv[$i] breaksw case -W: if ($i + 4 > $#myargv) then echo ${0}: option $myargv[$i] requires 4 numeric arguments exit(2) endif @ i++; set wxo=$myargv[$i]:q @ i++; set wyo=$myargv[$i]:q @ i++; set wxe=$myargv[$i]:q @ i++; set wye=$myargv[$i]:q breaksw case -X: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set wxo=$myargv[$i]:q breaksw case -Y: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set wyo=$myargv[$i]:q breaksw case -x: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set wxe=$myargv[$i]:q breaksw case -y: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set wye=$myargv[$i]:q breaksw case -h: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set wy=$myargv[$i]:q breaksw case -w: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set wx=$myargv[$i]:q breaksw case -m: set feed=feed breaksw case -g: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires string argument exit(2) endif @ i++; set groups=$myargv[$i]:q breaksw case -d: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires string argument exit(2) endif @ i++; set deffile=($deffile $myargv[$i]) breaksw case -ny: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set ny=$myargv[$i]:q breaksw case -nx: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set nx=$myargv[$i]:q breaksw case -by: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set by=$myargv[$i]:q breaksw case -bx: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set bx=$myargv[$i]:q breaksw case -T: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; @ wxo -= $myargv[$i]:q ; @ wxe -= $myargv[$i]:q @ i++; @ wyo -= $myargv[$i]:q ; @ wye -= $myargv[$i]:q breaksw case -j: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set j=$myargv[$i]:q @ wxo += $j ; @ wyo += $j ; @ wxe -= $j ; @ wye -= $j @ j *= 2 ; @ wx -= $j ; @ wy -= $j ; @ bx += $j ; @ by += $j breaksw case -c*: if ($myargv[$i]:q == '-c') then if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires argument exit(2) endif @ i++; set colmode='-c'$myargv[$i]:q else set colmode=$myargv[$i]:q endif switch ($colmode:q) case -c2s: set wxo=27 wyo=72 wxe=585 wye=720 wx=256 wy=72 bx=46 by=24 breaksw case -c3s: set wxo=27 wyo=48 wxe=585 wye=744 wx=162 wy=48 bx=36 by=24 breaksw case -c2: case -c2l: set wxo=18 wyo=63 wxe=594 wye=729 wx=274 wy=90 bx=28 by=6 breaksw case -c3: case -c3l: set wxo=18 wyo=39 wxe=594 wye=753 wx=180 wy=66 bx=18 by=6 breaksw default: echo ${0}: ${colmode}: 'illegal form mode' exit(2) endsw breaksw case -p: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires argument exit(2) endif @ i++; set proc=$myargv[$i]:q breaksw case -#: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set copies=$myargv[$i]:q breaksw case -N: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set rep=$myargv[$i]:q breaksw case -l: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set lines=$myargv[$i]:q breaksw case -f: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires string argument exit(2) endif @ i++; set font=$myargv[$i]:q breaksw case -s: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set size=$myargv[$i]:q breaksw case -i: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires string argument exit(2) endif @ i++; set mode=$myargv[$i]:q if ("$mode" != normal && "$mode" != left && "$mode" != right && "$mode" != indent && "$mode" != centered) then echo ${0}: invalid argument to option -i: $myargv[$i] echo possible arguments: normal left right indent centered exit(2) endif breaksw case -n: if ($i + 1 > $#myargv) then echo ${0}: option $myargv[$i] requires numeric argument exit(2) endif @ i++; set repx=$myargv[$i]:q breaksw case -H: cat << 'EOF' -t: Put the output to the standard output(Default action). -P*: Send the output to the corresponding printer. -W xmin ymin xmax ymax: Set the device coordinate bounds. -X xmin: Set the device coordinate xmin only. -Y ymin: Set the device coordinate ymin only. -x xmax: Set the device coordinate xmax only. -y ymax: Set the device coordinate ymax only. -h height: Set the height of the label. -w width: Set the width of the label. -m: Don't print the labels yet, wait for manual paper feed. -g group: Print only the labels that in the '#' line contain any letter from the ``groups'' string. -d deffile: At the end of the initialization, insert the contents of file deffile. -bx dist: Specify the spacing between labels (horizontally). -by dist: Specify the spacing between labels (vertically). -ny rows: Set the number of rows to be printed. -nx cols: Set the number of columns to be printed. -T xdist ydist: Move everything by so many units in each direction. -j dist: Ignore (don't use) dist units in each direction on the area of the label. -c column_mode: Set the form of the label sheet, Available names for column_mode are: "2 3 2s 3s 2l 3l" -p proc: Specify the postscript commands to execute on every label. -# rep: Print each page rep times, before proceeding to the next page. -N rep: Set the number of times to repeat printing the labels. -l lines: Specify the maximum number of lines on each label. 0 means no maximum. -f font: Specify the font to be used for printing. -s size: Specify the size of the font to be used for printing. -i mode: Specify the line indentation mode: normal, left, right, indent & centered. -n rep: Specify the number of times to print each label. -H: Print this list (help) and exit. 'EOF' exit(0) case -*: echo ${0}: ${myargv[$i]}: 'illegal option' exit(2) default: @ i-- break endsw end @ j = $i + 1 if ($?P) then if ($P == -P) set P=-P`printenv PSPRINTER` if ($P == -P) set P $0 $myargv[-$i]:q -t $myargv[$j-]:q | lpr $P exit endif set name=`printenv NAME` if ("$name" != '') then if ("`printenv ORGANIZATION`" != '') \ set name="$name, `printenv ORGANIZATION`" set name='('"$name"')' endif cat << EOF %!PS-Adobe-1.0 %%Creator: $USER $name %%Title: `hostname`:$cwd $0 $*:q %%CreationDate: `date` %%Pages: (atend) %%DocumentFonts: $font %%BoundingBox: $wxo $wyo $wxe $wye %%EndComments 1 setlinecap 1 setlinejoin 0 setlinewidth /worldlimits {/ymax exch def /xmax exch def /ymin exch def /xmin exch def /yrange ymax ymin sub def /xrange xmax xmin sub def } def /fatal { dup print xmin ymin moveto show showpage quit } def /feed {statusdict begin /manualfeed true def /manualfeedtimeout 300 def end} def /box { 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath } def /c_show { 1 index stringwidth pop sub 2 div 0 rmoveto show } def /r_show { 1 index stringwidth pop sub 0 rmoveto show } def /smallshow { gsave currentfont wx 2 index stringwidth pop div scalefont setfont show grestore } def /noleadingblanks {( ) {anchorsearch not {exit} if} loop} def /blankslength {dup noleadingblanks dup length 3 -1 roll length exch sub} def /advancelines {ysize mul ypos exch sub /ypos exch def xpos ypos moveto} def /advanceline {dup type /stringtype eq {1} if advancelines} def /oneline {advanceline dup stringwidth pop wx gt} def /normalline {oneline {smallshow} {show} ifelse} def /leftline {noleadingblanks oneline {smallshow} {show} ifelse} def /rightline {noleadingblanks oneline {smallshow} {wx r_show} ifelse} def /centeredline {noleadingblanks oneline {smallshow} {wx c_show} ifelse} def /indentline {oneline {smallshow} {blankslength size mul 0 rmoveto show} ifelse} def $wxo $wyo $wxe $wye worldlimits /wx $wx def % width of each label /wy $wy def % height of each label /by $by def % y distance between labels /bx $bx def % x distance between labels /nx $nx def % number of columns (0 means maximum that can fit in the page) /ny $ny def % number of rows (0 means maximum that can fit in the page) /#copies $copies def % each page is copied so many times /rx $repx def % repeat each label (to adjacent labels) factor /ry $rep def % repeat the whole output factor /font /$font def % font to be used in the label /size $size def % size of letters in the label /lines $lines def % number of lines in the label /userproc { $proc } def % the user procedure, to draw at each label /line /${mode}line load def % the line mode /initlabel { nx 0 eq {/nx xrange bx add wx bx add idiv dup 0 eq {pop 1} if def } if ny 0 eq {/ny yrange by add wy by add idiv dup 0 eq {pop 1} if def } if lines 0 gt { /ysize wy size sub lines 1 sub dup 0 gt {div} {pop pop size} ifelse def ysize size lt {(too many lines specified, decreace size) fatal} if} if font findfont size scalefont setfont /nxy nx ny mul def /nn 0 def } def % lines_array -> lines_array x y /xylabel { nn nxy eq {showpage /nn 0 def} if xmin wx bx add nn nx mod mul add ymin wy by add ny nn nx idiv sub mul by sub add /userproc load length 0 ne {gsave 2 copy wy sub translate userproc grestore} if /nn nn 1 add def } def % lines_array -> linesarray x y_vertical_centered /cxylabel {xylabel wy 3 index length 1 sub ysize mul size add sub 2 div sub} def /formlabel { dup length lines 0 gt {lines gt {(too many lines on label, increace lines) fatal} if} { /ysize exch wy size sub exch 1 sub dup 0 gt {div} {pop pop size} ifelse size 1.2 mul 2 copy gt {exch} if pop def } ifelse rx {cxylabel size sub ysize add /ypos exch def /xpos exch def dup {line} forall} repeat pop } def /pictloop { nxy { xylabel pop pop } repeat } def /pictpage { nn 0 eq {pictloop} if } def $feed initlabel EOF if ("$deffile" != '') cat $deffile echo '%%EndProlog' echo '%%Page: label 1' if ($rep != '0') echo '[' set cmd if ($rep == '0') set cmd='formlabel ' awk 'BEGIN{i=length(gr="'$groups:q'"); while(i > 0) g[substr(gr, i--, 1)]=1}\ /^#/{if (q) {print "["a" ] '$cmd:q'"; a=""} if (gr=="") q=1; else { \ i=length; while(i > 0 && (q=g[substr($0, i--, 1)]) == 0);} next} \ q==1{a = a " (" $0 ")"} \ END{if (q) print "["a" ] '$cmd:q'"}' \ $myargv[$j-] if ($rep != '0') echo '] ry {dup {formlabel} forall} repeat pop' if ("$proc" != '') echo 'pictpage' cat << EOF showpage %%Trailer %%Pages: 1 EOF exit(0) SHAR_EOF chmod +x 'label2ps' fi if test -f 'label2ps.1' then echo shar: "will not over-write existing file 'label2ps.1'" else cat << \SHAR_EOF > 'label2ps.1' .TH LABEL2PS 1 "February 3, 1989" local tools .\" $Header$ .SH NAME label2ps \- convert labels to postscript .SH SYNTAX .B label2ps [ .BI \-P * ][ .B \-m ][ .BI \-g\ group ][ .BI \-c\ colmode ][ .BI \-#\ rep ][ .BI \-i\ mode ] [ .I other_options ] [ .B \-H ] [ .I files ] .SH DESCRIPTION .I label2ps converts labels, with format as in .B labels command, to postscript. .PP .I label2ps can select some of the labels for printing, can use different fonts, size of letters, line indentation mode, different label papers, and can handle very long lines, too. The idea is that you print the labels into plain paper, until the output is what you want, changing some of the options each time. .PP .I label2ps has 3 ways for repeating labels. One is to repeat every label, before proceeding to the next label, the other is to repeat every page, before printing the next page, and the last one is to repeat printing everything, after printing them, without changing pages between different rounds of printing. This last way, needs to remember all the labels, and may not be able to handle very long lists of labels. .PP All options, except .B \-P , need their argument to be separated with space(s) from them. .PP The available options are: .TP .B \-t Put the postscript output to the standard output (default). .TP .BI \-P * Send the postscript output to the corresponding printer. If no printer is given (adjacent to the .B \-P option), the environment variable .B PSPRINTER is used to decide which printer, and if this is not defined, the default printer is used. .TP .BI \-W\ "xmin ymin xmax ymax" Set the device coordinate bounds. This is useful for papers of non standard size. .TP .BI \-X\ xmin Set the device coordinate xmin only. .TP .BI \-Y\ ymin Set the device coordinate ymin only. .TP .BI \-x\ xmax Set the device coordinate xmax only. .TP .BI \-y\ ymax Set the device coordinate ymax only. .TP .B \-m Don't print the labels yet, wait for manual paper feed. Timed out is set to 5 minutes. .TP .BI \-g\ group Print only the labels that in their .B # line (first line) contain any letter from the .I groups string. .TP .BI \-d\ deffile At the end of the initialization, insert the contents of file .I deffile , containing postscript definitions (possibly font construction specifications). It is called at the end of the prologue, so it can overwrite any settings. .TP .BI \-bx\ dist Specify the horizontal spacing between labels. .TP .BI \-by\ dist Specify the vertical spacing between labels. .TP .BI \-ny\ rows Set the number of rows to be printed. Print only in these rows. The size of the labels does not change in this way, see .B \-c for that. .TP .BI \-nx\ cols Set the number of columns to be printed. Print only in these columns. The size of the labels does not change in this way, see .B \-c for that. .TP .BI \-T\ "xdist ydist" Move everything on the paper by .I xdist units on the x-axis and .I ydist units on the y-axis. Useful for printing labels on not well adjusted printers. .TP .BI \-j\ dist Ignore (don't use, consider it junk) .I dist units in each of the four sides of the label. Useful for printing labels on not well adjusted printers. .TP .BI \-c\ column_mode Set the form of the label sheet, changing many of the other options, for known label sheet formats. Usually the names come from the number of columns. Available names for .I column_mode are: .B "2 3 2s 3s 2l 3l" , where the suffix .B "s" means shorter than the maximum (for not well adjusted printers), and .B "l" means long, the maximum (which is the default). More modes will be added for new types of papers, to avoid typing the numbers every time. It may be the most useful option. .TP .BI \-p\ proc Specify any postscript commands to be executed on every label. Usually it will be a postscript procedure, defined in the included files (see .B \-d ). It is executed once for each label printed, before the text of the label, and if no labels are given, the function result will fill exactly one page of labels (which can be duplicated using the .BI \-# option). Only one procedure (or inline sequence of commands) can be defined this way, but the procedure itself can create other special effects, like producing different picture on odd or even invocations. The procedure is executed at the lower left corner of each label area, without scaling or clipping, and should be bounded by the box: .B "0 0 /wx /wy" . The procedure is welcome to produce any side effects (like pictures overlapping with other labels), or even to change even procedure definitions. Similarly, the postscript code inserted using the .B \-d option, can change procedure definitions, or program parameters. But the final result is then the user's responsibility. .IP For example, the option .BI \-p " \' 0 0 moveto wx wy box stroke \'" will draw the border of each label, for testing the label fitting on the paper. .TP .BI \-#\ rep Print each page .I rep times, before proceeding to the next page. Compare with option .BI \-n " and " \-N . .TP .BI \-N\ rep Set the number of times to repeat printing the labels. The whole process will be repeated .I rep times. Compare with option .BI \-n " and " \-# . .TP .BI \-l\ lines Specify the maximum number of lines on each label. The default is 0, which means no maximum, but has the disadvantage that spacing is not the same on all labels. .TP .BI \-f\ font Specify the font to be used for printing. The default is .B Times-Roman. .TP .BI \-s\ size Specify the size of the font to be used for printing. The default is 10. .TP .BI \-i\ mode Specify the line indentation mode: .B normal (each line is printed as it is), .B left (each line is printed left justified), .B right , (each line is printed right justified), .B indent , (spaces at the beginning of the line are given extra width), and .B centered (each line is printed centered), which is the default .TP .BI \-n\ rep Specify the number of times to print each label. All these prints will be adjacent to each other. Compare with option .BI \-N " and " \-# . .TP .B \-H Print a helping list and exit. .SH ENVIRONMENT If .B LABEL2PS is defined, it contains initial arguments to the .I label2ps program, and if .B PSPRINTER is defined, it is used as the default printer (option .B \-P without (adjacent) argument). Also .B USER , .B NAME and .B ORGANIZATION , if defined, are used, and inserted in comments. .SH BUGS Very long label listings (more than 1000 labels ?) may exceed postscript limitations, when using \-N . .SH AUTHOR Sarantos Kapidakis .SH "SEE ALSO" pslabels(1), labels(1), labelsort(1), zipsort(1) SHAR_EOF fi if test -f 'labelsort' then echo shar: "will not over-write existing file 'labelsort'" else cat << \SHAR_EOF > 'labelsort' #!/bin/csh -f # Sort labels, according to the last field of the first label line # (the one after the ``#'' line). # (The fields of the line are space/tab separated). # If that field includes no trailing dots, only the part after the # last of these dots will be used in comparisons. # The input text should not include the character ``:'', # otherwise replace it everywhere in this file with another character. awk '/^#/{if (NR>1) print m; m = $0; next} \ m!=""{e=length($NF); i=1 ; \ while(e > 0 && substr($NF, e, 1) == ".") e--; \ while((j=index(substr($NF, i, e-i), ".")) != 0) i+=j; \ printf "%s %s:%s", substr($NF, i), $0, m; m=""} \ {printf ":%s", $0} \ END{printf "\n"}' $* | \ sort -df | \ awk -F: '{i=1; while(i++ < NF) print $i}' exit(0) # The older version follows, it does not handle dots. # old # awk '/^#/{if (NR>1) print "\n"; m = m $0; next} \ # old # m!=""{printf "%s %s:%s", $NF, $0, m; m=""} \ # old # {printf ":%s", $0} \ # old # END{printf "\n"}' $* | \ # old # sort -df | \ # old # awk -F: '{i=1; while(i++ < NF) print $i}' SHAR_EOF chmod +x 'labelsort' fi if test -f 'labelsort.1' then echo shar: "will not over-write existing file 'labelsort.1'" else cat << \SHAR_EOF > 'labelsort.1' .TH LABELSORT 1 "February 15, 1989" local tools .\" $Header$ .SH NAME labelsort \- sort labels according to the last name .SH SYNTAX .B labelsort [ .I files ] .SH DESCRIPTION .I labelsort takes as input labels, and produces as output the same labels, but sorted. The label format is as in the .B labels command. .I labelsort sorts labels according to the last field of the first label line (the one after the ``#'' line). The fields of the line are space/tab separated. .PP If that field includes no trailing dots, only the part after the last of these dots will be used in comparisons. .PP The input text should not include the character ``:'', otherwise replace it everywhere in this file with another character. .PP There are no options. .SH AUTHOR Sarantos Kapidakis .SH "SEE ALSO" labels(1), zipsort(1), label2ps(1) SHAR_EOF fi exit 0 # End of shell archive