[comp.lang.postscript] mail labels

woody@chinacat.Unicom.COM (Woody Baker @ Eagle Signal) (12/18/90)

Some one mentioned that they would like a label program.  Here is a
simple hack that I did back in '86 or '87 to print labels.  It is
in Microsoft Basic, which I often use for quick, dirty throwaway code
like this.  I do find that the combination of Basic and Postscript
is rather powerful.  It is easy to debug.  Generaly, I'll debug and
test the postscript code, using dummy data.  Then I'll run a program
that wraps line numbers and LPRINT (send to printer) statements around
each line.  Then I'll write code to select fonts, or get data, and
replace the constant test data with variables, and print the
resulting stuff to the printer.  I have included a routine that will take
a text file, and convert it to lprint statements for basic as well.

This routine will have to have a routine supplied to read in the lines
of data from wherever, into s$(1)..s$(4).  You can also set the font
for each line, and the point sizes for each line on a line by line 
basis.  This produces 3 wide, by 11 deep labels.

Some notes about the program:
ph( )  is the array that holds the point sizes for the HEIGHT of each line
pw( )  is the array that holds the point sizes for the WIDTH for font.
px( )  is an array that holds an offset from the left of the label
py( )  is a computed array for line spacing based on ph and 1" labels
f ( )  is an array that holds a font number for each line.
flist$()  is an array of font names.  It is indexed by f() to pick fonts.

each label is 203 points wide.  CN is the column number.  It gets
multiplied by 203 to compute the x position for the label, then px(line)
gets added to it to compute the actual x coordinate for the moveto.  
LN gets multiplied by 72 ( it is the number of labels per page), and 
has 5 subtracted from it, to compensate for the dead band at the top of
the page.  This code runs faster in the printer if the  control D is
appended after showpage.  I suppose I should have rewritten this in
'C', and If I ever need it for my own use, I will.  At the time, I was
not heavily into 'C', and decided that Basic would be faster.




2 REM   This is a quick and dirty hack done some number of years ago to
3 REM   produce 3 wide by 11 deep mailing labels.  This code builds a
4 REM   postscript program from lines of data supplied to it.  You have to
5 REM   supply a routine to read in the lines of data from a data file.
6 REM   routine at 34800 is a subroutine that can be called to allow you
7 REM   to set the points and fonts on a line by line basis.  This file
8 REM   has hard coded HELVETICA at 12 points, except for line 2 which is
9 REM   14 points.  This code is rather noxious, but it works.
10 DIM FLIST$(40):F=1:CLS:REM dimension the font list array
20 Q$=CHR$(34):QN$=Q$+",":REM Q$ and Qn$ are set to " and ",
30 READ A$:IF A$<>"zz" THEN FLIST$(I)=A$:I=I+1:GOTO 30:REM read font names
40 I=I-1:Y=INT(I/2): REM Y is the number of fonts/2
45 GOSUB 34800:REM   example call to select fonts can be removed
50 REM dummy data strings for demo purposes
100 S$(1)="This is line 1":S$(2)="This is line 2":S$(3)="This is line 3"
101 S$(4)="This is line 4"
109 NL=4: REM number of lines per label
110 FOR I = 1 TO 10:PW(I)=12:PH(I)=12: NEXT I:REM set point width and hite
115 REM set line 2 to 14 points, and all lines (there are up to 10)
116 REM to font number 4, helvetica
120 PW(2)=14:PH(2)=14: REM for grins, make line 2 14 points tall
125 FOR I = 1 TO 10
126   F(I)=4:  REM set Helvetica for each line
127 NEXT I
150 FOR I = 1 TO 10:PX(I)=40:NEXT I:REM  offset lines 40 points into the label
158 REM  This line sets the y position for each line based on the point hite.
159 REM  each lable is 72 points tall
160 H=72:FOR I= 1 TO 10: H=H-PH(I):PY(I)=H:NEXT I:REM compute line spacing
197 REM
198 REM ln=lable#
199 REM cn = column number.
200 FOR J = 0 TO 10: FOR K = 0 TO 2:
201  LN=J:CN=K:
203     REM  change line 205 to call a subroutine to load s$(1)..s$(4) with
204     REM  each labels information.
205  S$(1)="lable"+CHR$(J+64)+"-"+CHR$(K+64): REM dummy line
210 GOSUB 10000: REM emit postscript code.
250 NEXT K: NEXT J
260 LPRINT"showpage"+chr$(4)
994 REM
995 REM subroutine at 34800 to allows input of font info and returns:
996 REM nu=font number, np=width in points and nph=height in points
997 REM s$=what to print
998 REM
999 END: REM for safety.
1020 REM
1021 REM body of postscript code goes in here starting at 10020
1022 REM
10000 LX=LN*72-5:LY=CN*203:REM 72-5 lowers the labels on the page
10010 LPRINT "gsave";LY,LX;" translate"
10020 FOR I= 1 TO NL
10030 LPRINT "/"+FLIST$(F(I))+" findfont [";PH(I);" 0 0 ";PW(I);"0 0 ] makefont setfont"
10040 LPRINT PX(I),PY(I);" moveto ("+S$(I)+") show"
10050 NEXT I:LPRINT"grestore"
11000 RETURN
30000 RETURN
30300 DATA "Times-Roman","Times-Bold","Times-Italic","Times-BoldItalic"
30600 DATA "Helvetica  ","Helvetica-Bold","Helvetica-Italic","Helvetica-BoldItalic"
30900 DATA "Courier    ","Courier-Bold","Courier-Italic","Courier-BoldItalic"
31200 DATA "Symbol     "
31500 DATA "Palatino-Roman","Palatino-Bold","Palatino-Italic","Palatino-BoldItalic"
31800 DATA "NewCenturySchlbk-Roman","NewCenturySchlbk-Bold","NewCenturySchlbk-Italic"
32100 DATA "NewCenturySchlbk-BoldItalic"
32400 DATA "Helvetica-Narrow","Helvetica-NarrowBold","Helvetica-NarrowOblique"
32700 DATA "Helvetica-NarrowBoldOblique"
33000 DATA "AvantGarde-Book","AvantGarde-Demi","AvantGarde-BookOblique","AvantGarde-DemiOblique"
33300 DATA "Bookman-Light","Bookman-Demi","Bookman-LightItalic","Bookman-DemiItalic"
33600 DATA "ZapfChancery-MediumItalic"
33900 DATA "ZapfDingbats","This is no font!"
34200 DATA "zz"
34500 REM select font
34800 CLS:PRINT"Defined Fonts are:":PRINT:PRINT
35100 FOR Z=0 TO Y:PRINT Z;"=";FLIST$(Z),Z+Y+1;"=";FLIST$(Z+Y+1):NEXT Z
35400 INPUT"Enter Font Number";NU
35700 IF NU>34 THEN 34800
36000 CLS:RETURN
36300 REM
36600 INPUT"Enter pointsize and other parameters (Y/N) ";RP$:IF RP$="n" OR RP$="N" THEN 38400
36900 PRINT"Default hight is ";NPH;" default width is ";NP;:INPUT"  Change it (y/n)";RP$
37200 IF RP$="n" OR RP$="N" THEN 38100
37500 INPUT"Enter hight and width in points";NPH,NP
38100 PRINT "Default type style is ";FLIST$(NU);" change it (y/n)";:INPUT RP$:IF RP$="y" OR RP$="Y" THEN GOSUB 34800
38400 RETURN
______________________________________________

1 REM program to take a postscript text file and convert it to
2 REM a series of LPRINTS for basic.  This lets you substitue
3 REM parameters in real time with basic etc.
5 N=10000: REM START WITH LINE 10000
20 INPUT "Enter name of file to convert";N$
30 INPUT "Enter name of output file    ";N2$
40 OPEN N$ FOR INPUT AS #1
50 OPEN N2$ FOR OUTPUT AS #2
60 ON ERROR GOTO 1000
70 LINE INPUT #1,L$:REM get line with commas etc until cr! (255 bytes max)
80 N=N+20:NN$=STR$(N):REM INC LINECOUNTER AND CONVERT TO STRING
90 O$=NN$+"  LPRINT "+CHR$(34)+L$+CHR$(34)
100 PRINT #2,O$:GOTO 70
1000 PRINT ERR,ERL:CLOSE#1:CLOSE#2:END
2000 REM this is for GWBASIC or BASICA or BASIC for the
2010 REM MS-DOS TYPE machines.  After running this program
2020 REM load the output file with a normal load, and save it as a normal
2030 REM basic file.  Then when you load the converted program
2040 REM you can then run it and it will print the postscript code
2050 REM to the printer.  You can then mix basic code within the
2060 REM lprints or before it to allow inputting of info before
2070 REM printing.  I used it to convert a program in postscript
2080 REM that prints business cards to accept names and addresses
2090 REM from the user, plug the strings into the postscript code
2100 REM and print the resulting postscript to create custom
2200 REM business cards.

Cheers
Woody

bukys@cs.rochester.edu (Liudvikas Bukys) (12/18/90)

Here is a little shell&awk script which takes in label information, separated by
blank lines, and outputs labels suitable for printing on the 3-across 11-down
sheets commonly available these days.

Liudvikas Bukys
<bukys@cs.rochester.edu>

#!/bin/sh

###############################################################################
#
# label2ps -- convert label data to postscript, in 11 x 3 format
#
# to use this program:
#
# (1) Load the printer with label-paper, FACE DOWN
#
# (2) Type
#
#	label2ps  labelfile1 labelfile2 labelfile3 ...  >  labels.ps
#	lpr labels.ps
#
# (3) If some of the pages turned out bad, you can extract and print
#     a subset of pages.  For example, if you want pages 3,4,5, and 9
#     again, you can do this:
#
#	psrev -s 3-5,9 labels.ps  |  lpr
#
###############################################################################

for f in "${@-'-'}"
do
	cat "$f"
	echo ""
done | sed -e 's/[\\()]/\\&/g' | awk '
BEGIN	{
	print	"%!PS-Adobe-1.0"
	print	"%%Pages: (atend)"
	print	"%%DocumentFonts: Helvetica Helvetica-BoldOblique"
	print	"%%BoundingBox: 0 0 612 792"
	print	"%%EndComments"
	print	"/Helvetica findfont 9 scalefont setfont"
	print	"/INIT	{"
	print	"	/N 0 def"
	print	"	} def"
	print	"/NEXT	{"
	print   "%	N 32 ge { (page ?) PAGE } if"
	print	"	0 792 moveto"
	print	"	18 -22 rmoveto"
	print	"	N 11 idiv 204 mul  N 11 mod -72 mul  rmoveto"
	print	"	/N N 1 add def"
	print	"	} def"
	print	"/LINE	{"
	print	"	gsave show grestore"
	print	"	0 -10 rmoveto"
	print	"	} def"
	print	"/PAGE	{"
	print	"	gsave"
	print	"	/Helvetica-BoldOblique findfont 8 scalefont setfont"
	print	"	426 30 moveto"
	print	"	LINE"
	print	"	0 -10 rmoveto"
	print	"	('"`whoami`  `date`"') LINE"
	print	"	grestore"
	print	"	showpage"
	print	"	INIT"
	print	"	} def"
	print	"INIT"
	print	"%%EndProlog"
	print	"%%Page: 1 1"
	labels = 0
	pages = 1
	}
	{
	if ($0 == "")
		line = 0
	else	{
		if (line++ == 0)
			{
			if (labels%32 == 0 && labels != 0)
				{
				print "(" "page " pages ") PAGE"
				pages++
				print "%%Page: " pages " " pages
				}
			print "NEXT"
			labels++
			}
		print "(" $0 ") LINE"
		}
	}
END	{
	print "NEXT"
	print "(TOTAL OF " labels " LABELS PRINTED) LINE"
	print "(" "page " pages ") PAGE"
	print "%%Trailer"
	print "%%Pages: " pages
	}'