[net.sources] PostScript picture making programs for pleasure and business

greenber@swatsun (Peter Greenberg) (04/18/87)

Have FUN with your LaserWriter Plus or other PostScript creature!!!

I have written a few programs that play with PostScript in interesting
ways. I have wrapped these up as shell scripts that take arguments to 
determine what is printed. The README file will give the necessary details,
but before reading it, unpack and type these lines from your shell,
just for kicks. You will not sorry.

fontnames 
	-- You will get a page out of your PS creature giving names of each
font that is knows about printed in the font that it denotes. Boring, but
possibly useful.

mapfonts Times-Roman ZapfDingbats
	-- If you don't have these fonts, use the names of ones that you do
have. (LaserWriter Plus has them.) ZapfDingbats has no letters, Roman,
Greek, or otherwise. It was shown as the line of bizarre symbols when you
ran fontnames above. Your PS creature will hand you a page with a few
columns. Octal character codes will be matched to characters in each font.
Still boring, but a bit more useful.

fillchar ZapfChancery-MediumItalic PostScript 5 600 ZapfDingbats '\244' 0.85
	-- Again, change fonts and '\244' to some letter if you do not have
the fonts. I don't feel like explaining it. Do it and then show it to your
friends. Look up octal character 244 on the sheet from mapfonts to get a
clue.

scaleshow '\360' Symbol 600 7
	-- Most things have the Symbol font. Just do it to see what
happens. If you do not have a LaserWriter, you might want to try '\251'
instead.

I also threw in a bunch of useful and useless PostScript routines in a file
called template.ps

Peter Greenberg
Swarthmore College
Swarthmore, PA 19081
...!seismo!bpa!swatsun!greenber

------------------------SNIP SNIP SNIP------------------------------------
	
#! /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 the files:
#	README
#	README%
#	fillchar
#	fontnames
#	mapfont
#	scaleshow
#	template.ps
# This archive created: Sat Apr 18 17:27:53 1987
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'

README file

This posting contains 5 files.

template.ps is a file of neat little PostScript procedures that handle 
centering, flush right, and wrapping of text, and some other stuff.
Comments within say what is really going on.
	
The other four are small PostScript applications wrapped up in shell scripts.
They take zero or more command line arguments, and print some kind of pretty
picture. They currently use lpr as the spooler. If you do not have lpr, then
you should go through and change the variable called "spooler" which is set
near the top of the program.

You should be aware that the shell "wrappings" of these programs are not
robust. Error checking beyond number of parameters is not performed. They
are basically just nice ways of spooling PostScript programs.

If you do not have the Bourne shell, then clip out the shell stuff, and 
reconstruct some real PostScript program.

Note that if a font is not defined on your device, what PostScript does is 
device dependent. On the LaserWriter, it defaults the font to Courier. To
find out which fonts you have, run fontnames first (see below). Also note that
where a string is called for, PostScript strings without the parentheses are
taken. Therefore, you can use all the backslash escapes understood by 
PostScript. All the "Try this:" suggestions below assume you are using a 
LaserWriter Plus. Enter the stuff after the colon on these lines exactly as
shown.

This is what these things do:

fillchar InsideTextFontName InsideText Lines Size ShapeStrFontName ShapeStr
																	GrayLevel
	[Type the above all on one line!] Prints ShapeStr in font given by 
	ShapeStrFontName and size Size as an outline, then fills it
	with gray of level GrayLevel (1 = white, 0 = black), then writes InsideText
	repeatedly in font given by InsideTextFontName within the outline to fill 
	up Lines lines of text. The size that InsideText is printed in is figured
	out in PostScript. If ShapeStr is to long, PostScript might think that the
	path that it defines is too complicated to be a clipping path and it will
	bomb with a limit check error.

	Try this: fillchar ZapfChancery-MediumItalic PostScript 5 600 ZapfDingbats
'\244' 0.85

fontnames
	Prints the name of each font known to PostScript in that font. One font
	name is printed per line.
	
	Try this: fontnames
	
mapfont [font1 [font2]]
	Maps one font to another. Prints octal character code, character in font1,
	and character in font2 for each ASCII code between 0 and 255. If only one
	font is given, the mapping is from Courier to that font, if none are given
	than it is from Courier to Helvetica. 
		
	Try this: mapfont Times-Roman ZapfDingbats
	
scaleshow String Font Size LinesInScale
	Fills a shape given by String in font Font and size Size (that is, 
	the shapes of the characters if they were so pritned) with a grayscale with 	LinesInScale gradations. Light gray is on top, dark gray on the bottom.			PostScript limit check error is possible for large String.
						
	Try this: scaleshow '\360' Symbol 600 7
	
SHAR_EOF
fi # end of overwriting check
if test -f 'README%'
then
	echo shar: will not over-write existing file "'README%'"
else
cat << \SHAR_EOF > 'README%'

README file

This posting contains 5 files.

template.ps -- file of neat little PostScript procedures that handle 
	centering, flush right, and wrapping of text, and some other stuff.
	Comments within say what is really going on.
	
The other four are small PostScript applications wrapped up in shell scripts.
They take zero or more command line arguments, and print some kind of pretty
picture. They currently use lpr as the spooler. If you do not have lpr, then
you should go through and change the variable called "spooler" which is set
near the top of the program.

You should be aware that the shell "wrappings" of these programs are not
robust. Error checking beyond number of parameters is not performed. They
are basically just nice ways of spooling PostScript programs.

If you do not have the Bourne shell, then clip out the shell stuff, and 
reconstruct some real PostScript program.

Note that if a font is not defined on your device, what PostScript does is 
device dependent. On the LaserWriter, it defaults the font to Courier. To
find out which fonts you have, run fontnames first (see below). Also note that
where a string is called for, PostScript strings without the parentheses are
taken. Therefore, you can use all the backslash escapes understood by 
PostScript. All the "Try this:" suggestions below assume you are using a 
LaserWriter Plus. Enter the stuff after the colon on these lines exactly as
shown.

This is what these things do:

fillchar InsideTextFontName InsideText Lines Size ShapeStrFontName ShapeStr
																	GrayLevel
	[Type the above all on one line!] Prints ShapeStr in font given by 
	ShapeStrFontName and size Size as an outline, then fills it
	with gray of level GrayLevel (1 = white, 0 = black), then writes InsideText
	repeatedly in font given by InsideTextFontName within the outline to fill 
	up Lines lines of text. The size that InsideText is printed in is figured
	out in PostScript. If ShapeStr is to long, PostScript might think that the
	path that it defines is too complicated to be a clipping path and it will
	bomb with a limit check error.

	Try this: fillchar ZapfChancery-MediumItalic PostScript 5 600 ZapfDingbats
'\244' 0.85

fontnames
	Prints the name of each font known to PostScript in that font. One font
	name is printed per line.
	
	Try this: fontnames
	
mapfont [font1 [font2]]
	Maps one font to another. Prints octal character code, character in font1,
	and character in font2 for each ASCII code between 0 and 255. If only one
	font is given, the mapping is from Courier to that font, if none are given
	than it is from Courier to Helvetica. 
		
	Try this: mapfont Times-Roman ZapfDingbats
	
scaleshow String Font Size LinesInScale
	Fills a shape given by String in font Font and size Size (that is, 
	the shapes of the characters if they were so pritned) with a grayscale with 	LinesInScale gradations. Light gray is on top, dark gray on the bottom.			PostScript limit check error is possible for large String.
						
	Try this: scaleshow '\360' Symbol 600 7
	
SHAR_EOF
fi # end of overwriting check
if test -f 'fillchar'
then
	echo shar: will not over-write existing file "'fillchar'"
else
cat << \SHAR_EOF > 'fillchar'
#! /bin/sh

# This is a PostScript program wrapped as a shell script.

# copyright 1987 by Peter Greenberg. You may use, copy, or redistribute this
# work freely so long as this message and the copyright message are retained.

# comments/bug fixes to:
# Peter Greenberg
# Swarthmore College
# Swarthmore, PA 19081
# (215) 328-8610
# UUCP: ...!seismo!bpa!swatsun!greenber
# ARPA: swatsun!greenber@seismo.CSS.GOV

# CHANGE THESE LINES TO USE ANTOHER SPOOLER
spooler=/usr/ucb/lpr
spoolopts=-PPostScript

# Except for number of arguments (7), no checking done in shell. Specifically,
# arguments 3 and 4 must be integers, 7 must be real beween 0 and 1. If these
# conditions are not met, PostScript errors will result.

emit_header() {
cat <<End-Of-Header
%!
/InsideTextFontName /$1 def 
/InsideText ($2) def 
/Lines $3 def 
/Size $4 def 
/ShapeStrFontName /$5 def 
/ShapeStr ($6) def 
/GrayLevel $7 def
End-Of-Header
}

emit_main_stuff() {
cat <<End-Of-Main-Stuff
% This program prints some string repeatedly within the path defined by some
% other string.

/FillWithText { % 
	/grayness exch def 	% background color     
	/c exch def		% string defining clipping path
	/cfont exch def		% font of string defining clipping path
	/size exch def		% size of outline string shape
	/lines exch def		% number of lines within shape
	/str exch def		% string to be repeated within shape
	/sfont exch def		% font of str

	gsave
	
	size srand		% we will need random numbers later
	cfont findfont size scalefont setfont
	c true charpath		% set up clipping path	
	gsave stroke grestore	% stroke and fill with background color
	gsave grayness setgray fill grestore
	pathbbox		% get bounding box
		/ury exch def
		/urx exch def
		/lly exch def
		% strings should start left of box
		str stringwidth pop sub /llx exch def
	/lineht ury lly sub lines div def
	/cury ury lineht sub def
	clip			% do the clipping
	sfont findfont lineht scalefont setfont
	% nested loop to print text in box
	{ 
		llx rand str stringwidth pop cvi mod add cury moveto

		{ str show ( ) stringwidth pop 2 div 0 rmoveto 
			currentpoint pop urx ge {exit} if } loop
		/cury cury lineht sub def
		cury lly le {exit} if
	} loop				

	grestore
} def

40 40  moveto
InsideTextFontName InsideText Lines Size ShapeStrFontName ShapeStr GrayLevel 
FillWithText

showpage
End-Of-Main-Stuff
}

case $# in
	7) ;;
	*) echo usage: ; echo $0 InsideTextFontName InsideText Lines Size ShapeStrFontName ShapeStr GrayLevel ; exit 1 ;;
esac

(emit_header $@ ; emit_main_stuff) | $spooler $spoolopts
exit 0
SHAR_EOF
chmod +x 'fillchar'
fi # end of overwriting check
if test -f 'fontnames'
then
	echo shar: will not over-write existing file "'fontnames'"
else
cat << \SHAR_EOF > 'fontnames'
#! /bin/sh
# PostScript program wrapped up in a Bourne Shellscript.
# copyright 1987 by Peter Greenberg. 

# This stuff can be used, copied modified, and incorporated into other works 
# so long as this message and the copyright message are retained.

# comments/bug fixes to:
# Peter Greenberg
# Swarthmore College
# Swarthmore, PA 19081
# (215) 328-8610
# UUCP: ...!seismo!bpa!swatsun!greenber
# ARPA: swatsun!greenber@seismo.CSS.GOV

spooler=/usr/ucb/lpr
spoolopts=-PPostScript

emit_main_stuff() {
cat <<End-Of-Main-Stuff
%!
% Just a little hack to show the name of each font printed in that font.
% Of course, non-alphabetic fonts will look strange. Will print the name
% of each font that PostScript knows about, one to a line.

% This program takes a while to run on an LW+.

/Font %fontname scale
 {
 	/scale exch def
 	findfont
 	scale scalefont
 	setfont
 } def

/Size 15 def

/Lineheight Size 3 add def

/Leftmargin 30 def

/Topmargin 770 def

 
/Showinfont % string fontname
 {
 	Leftmargin currentpoint exch pop Lineheight sub moveto
 	Size Font
 	show
 } def
 
Leftmargin Topmargin moveto

FontDirectory {
	pop dup 256 string cvs exch Showinfont
} forall

showpage

End-Of-Main-Stuff
}

emit_main_stuff | $spooler $spoolopts
exit 0
SHAR_EOF
chmod +x 'fontnames'
fi # end of overwriting check
if test -f 'mapfont'
then
	echo shar: will not over-write existing file "'mapfont'"
else
cat << \SHAR_EOF > 'mapfont'
#! /bin/sh

# This is a PostScript program wrapped as a shell script.

# copyright 1987 by Peter Greenberg. You may use, copy, or redistribute this
# work freely so long as this message and the copyright message are retained.

# comments/bug fixes to:
# Peter Greenberg
# Swarthmore College
# Swarthmore, PA 19081
# (215) 328-8610
# UUCP: ...!seismo!bpa!swatsun!greenber
# ARPA: swatsun!greenber@seismo.CSS.GOV

# USAGE:
# mapfont [mapfrom [mapto]]
# defaults: mapfrom=Courier ; mapto=Helvetica

# CHANGE THESE LINES TO USE ANTOHER SPOOLER
spooler=/usr/ucb/lpr
spoolopts=-PPostScript

emit_header() {
cat <<End-Of-Header
%!
/Font1 /$1 def
/Font2 /$2 def
End-Of-Header
}

emit_main_stuff() {
cat <<End-Of-Main-Stuff
% This program maps one PostScript font to another. For each character
% code in a specific range, this program will print (to the actual page)
% the character code in octal, the character in Font1, then the character
% in Font2. The reason for this is to show which characters are associated
% with which ASCII codes in each font. It is especially useful to see what
% non-alphabetical fonts like Symbol and ZapfDingbats have to offer. 
% The output is in neat columns, determined by taking into account the
% left and right margins and top and bottom margins and the pitch of the 
% characters. Presently these are set to produce a nice looking 8.5 x 11 inch
% page but this can be fiddled with.

% Unfortunately, this program takes about 3 minutes to execute on an LW+.

/ArrayToStr
{
	/Array exch def
	/Length Array length def
	/Str Length string def
	
	0 1 Length 1 sub { Str exch dup Array exch get put } for
	Str
} bind def

/IntToChar %char is a one character string
{
	/Int exch def
	/Str 1 string def
	Str 0 Int put
	Str
} def

/FontSet 
{
	findfont Size scalefont setfont
} bind def
 
/IntToOctString { %integer. Only handles 3-digit octal (0..511)
	/DecInt exch def	
	/OctStr 3 string def
	OctStr 0 DecInt 64 idiv 48 add put
	/DecInt DecInt 64 mod def
	OctStr 1 DecInt 8 idiv 48 add put
	/DecInt DecInt 8 mod def 
	OctStr 2 DecInt 48 add put
	OctStr
} bind def

/inch { 72 mul } def

/Top 9.5 inch def
/Bottom 0.5 inch def
/Left 0.5 inch def
/Right 7 inch def
/Size 12 def
/Lineheight Size 5 add def
/FirstChar 0 def
/LastChar 255 def
/SpaceStr (: ) def

/CharsPerCol Top Bottom sub Lineheight div cvi def
/ColPerPage  LastChar FirstChar sub CharsPerCol div cvi def
/ColWidth Right Left sub ColPerPage div cvi def

 Left Top 0.5 inch add moveto
Font1 FontSet
(Mapping from ) show Font1 80 string cvs show ( to ) show Font2 80 string cvs 
	show
/PresentCol Left def
/PresentRow Top def
FirstChar 1 LastChar {
	/ThisChar exch def
	PresentCol PresentRow moveto
	Font1 FontSet
	ThisChar dup IntToOctString show ( ) show 
	IntToChar dup show SpaceStr show
	Font2 FontSet show
	/PresentRow PresentRow Lineheight sub def
	PresentRow Bottom lt { 
		/PresentRow Top def 
		/PresentCol PresentCol ColWidth add def
	} if
} bind for 
showpage
End-Of-Main-Stuff
}

case $# in
	0) FONT1=Courier ; FONT2=Helvetica ;;
	1) FONT1=Courier ; FONT2=$1 ;;
	*) FONT1=$1 ; FONT2=$2 ;;
esac

(emit_header $FONT1 $FONT2 ; emit_main_stuff) | $spooler $spoolopts

exit 0
SHAR_EOF
chmod +x 'mapfont'
fi # end of overwriting check
if test -f 'scaleshow'
then
	echo shar: will not over-write existing file "'scaleshow'"
else
cat << \SHAR_EOF > 'scaleshow'
#! /bin/sh

# This is a PostScript program wrapped as a shell script.

# copyright 1987 by Peter Greenberg. You may use, copy, or redistribute this
# work freely so long as this message and the copyright message are retained.

# comments/bug fixes to:
# Peter Greenberg
# Swarthmore College
# Swarthmore, PA 19081
# (215) 328-8610
# UUCP: ...!seismo!bpa!swatsun!greenber
# ARPA: swatsun!greenber@seismo.CSS.GOV

# Usage: scaleshow ShapeString ShapeFont Size Lines 
# The program will bomb out with an appropriate error message if ther are not
# exactly four arguments. Otherwise no checking is done. Size must be a
# real and Lines and integer. If they are not, a PostScript error will result.

# CHANGE THESE LINES TO USE ANTOHER SPOOLER
spooler=/usr/ucb/lpr
spoolopts=-PPostScript

emit_header() {
cat <<End-Of-Header
%!
/String ($1) def
/ShapeFont /$2 def
/Size $3 def
/Lines $4 def
End-Of-Header
}

emit_main_stuff() {
cat <<End-Of-Main-Stuff
/SetFont 
{
	findfont Size scalefont setfont
} def

/CenterShow {
	/Str exch def
	/Ycoord currentpoint exch pop def 
	Right Left sub Str stringwidth pop sub 
	2 div Left add Ycoord moveto
	Str show
} def

/CenterShowPlace { %string     returns proper x-coord for center show
	/Str exch def
	Right Left sub Str stringwidth pop sub 
	2 div Left add 
} def
	
/DrawBox { % boxllx boxlly boxurx boxury
	/boxury exch def
	/boxurx exch def
	/boxlly exch def
	/boxllx exch def
	boxllx boxlly moveto
	boxllx boxury lineto
	boxurx boxury lineto
	boxurx boxlly lineto
	closepath
	boxurx boxury moveto
} def
	
/HorrizontalScaleShow { % numscales string
	gsave
	true charpath closepath flattenpath clip pathbbox
	/ury exch def
	/urx exch def
	/lly exch def
	/llx exch def
	newpath
	1 exch div /Grade exch def
	/Height ury lly sub def
	/Incr Grade Height mul def
	/Oldury lly def
	
	0 Grade 1 {
		setgray
		llx Oldury urx Oldury Incr add dup
		/Oldury exch def
		DrawBox
		fill
	} for
	grestore
} def	
	
/inch { 72 mul } def

/Right 7 inch def
/Left 1 inch def
/Top 9.5 inch def
/Bottom 0.5 inch def


0 Top Bottom sub 2 div Bottom add moveto
ShapeFont SetFont
Lines String dup CenterShowPlace 3 inch moveto
HorrizontalScaleShow

showpage
End-Of-Main-Stuff
}

case $# in
	4) ;;
	*) echo Usage: ; echo $0 ShapeString ShapeFont Size Lines; exit 1 ;;
esac

(emit_header $@ ; emit_main_stuff) | $spooler $spoolopts
exit 0
SHAR_EOF
chmod +x 'scaleshow'
fi # end of overwriting check
if test -f 'template.ps'
then
	echo shar: will not over-write existing file "'template.ps'"
else
cat << \SHAR_EOF > 'template.ps'
%!
% TEMPLATE: This does nothing yet. It is a bunch of useful routines that you
% may want to incorporate into your PostScript programs. They probably work.

% copyright 1987 by Peter Greenberg. You can copy, use, and redistribute this
% work so long as the copyright message and this message are retained.

/ArrayToStr % array -> string
% Takes array of integers and makes a string containing the integers ASCII
% characters
{
	/Array exch def
	/Length Array length def
	/Str Length string def
	
	0 1 Length 1 sub { Str exch dup Array exch get put } for
	Str
} def

/IntToChar % string -> int
% Returns character code of first character in string
{
	/Int exch def
	/Str 1 string def
	Str 0 Int put
	Str
} def

/SetFont %  -> 
% sets currentfont to Font in size Size, which are preset variables. 
{
	findfont Size scalefont setfont
} def

/CenterShow { % string -> 
% Shows string in middle of page. Y coordinate is not changed. Assumes 
% definition of Left and Right.
	/Str exch def
	/Ycoord currentpoint exch pop def 
	Right Left sub Str stringwidth pop sub 
	2 div Left add Ycoord moveto
	Str show
} def

/FlushRightShow { % string ->
% Shows string flush to right hand side of the page. 
% Y coordinate is not changed. Assumes definition of Left and Right.
	/Str exch def
	currentpoint /Ycoord exch def pop
	Right Str stringwidth pop sub Ycoord moveto
	Str show
} def

/MirrorShow % string ->
% Like ordinary show, but string is shown in mirror image.
{
        gsave
        dup /Str exch def
        stringwidth /Ydisp exch def /Xdisp exch def
        currentpoint /Y exch def /X exch def
        X Xdisp add Y Ydisp add translate 0 0 moveto
        [ -1 0 0 1 0 0 ] concat
        Str show
        grestore
        Xdisp Ydisp rmoveto
} def

/ConcatStr % string1 string2 -> newstring
% Concatenates string1 and string2, returns newstring of combined length.
{
	/Str2 exch def
	/Str1 exch def
	/NewStr Str1 length Str2 length add string def
	NewStr Str1 length Str2 putinterval
	NewStr 0 Str1 putinterval
	NewStr
} def

/NextLine { % ->
% Goes to nextline as given by preset Lineheight.
	Left 
	currentpoint exch pop Lineheight sub dup Bottom lt 
	  { 
	  	pop copypage erasepage Top
	  }
	if
	moveto
} def

% The following procedures all help in wrapping text. See comment on
% last procedure.

/SP 32 def

/WhitespaceSearch {
	/Str exch def
	/StrLen Str length def

	/i 0 def
	{
	   i StrLen lt
	     {
		Str i get 32 gt 
		 {
	 	 	/i i 1 add def
	 	 }
	 	 {
	 	 	exit
	 	 }
	        ifelse
	     }
	     {
	   	exit
	     }
 	  ifelse
	} loop	
	
	i StrLen lt
	  {	
		/j i def
		{
			j StrLen lt 
			  {
			  	Str j get 32 le 
		 	  	  {
			  		/j j 1 add def
			  	  }
		 	 	  {
		  			exit
		 	 	  }
				ifelse
			  }
			  {
			  	exit
			  }
			ifelse
		} loop
		
		j StrLen lt 
		  {
			Str j StrLen j sub getinterval % Put Post on Stack
		  }
		  { () % put an empty string on the stack
		  }
		ifelse 
		Str i j i sub getinterval % Put Whitespace on Stack
		Str 0 i getinterval % Put Pre on stack
		true	
	  }
	  {	
	  	Str
	  	false
	  }
	ifelse
   	
} def
 	   	

/WrapShow % string     returns true if newline inserted after word
{
	/Str exch def 
				
	Str stringwidth pop dup /StrW exch def
	Right Left sub gt 
	  {
		NextLine
		Str show %just get out
		NextLine true
	  }
	  {	
	  	StrW currentpoint pop add dup /Xcoord exch def
		WrapZone gt % Xcoord would extend past Wrapzone
		  {	
			Xcoord Right le
			  { Str show NextLine true } % word ends in WrapZone
			  { NextLine Str show false } 
			  			% word extends past Rt. Margin
			ifelse
		  }
		  { Str show false }
		ifelse
	  }
	ifelse
} def

/Tabulate {
	currentpoint exch Tab div ceiling Tab mul Left add exch moveto
} def

/ShowWhitespace % bool string (whitespace)
{
	% a true will be on the stack if a newline had been inserted before
	% whitespace
	/WhiteSp exch def
	/NewLineBefore exch def
	WhiteSp 0 get 
	dup dup
	32 eq NewLineBefore not and { ( ) show } if
	9 eq { Tabulate } if
	10 eq NewLineBefore not and { NextLine } if
	WhiteSp 1 WhiteSp length 1 sub getinterval {
	    	dup dup 
	    	32 eq { ( ) show } if
	   	9 eq { Tabulate } if
	    	10 eq { NextLine }  if
	} forall
	  
	
} def   
	
/WrapText % string (perhaps very long) ->
% Shows the string from current point. Wraps text according to preset 
% Lineheight, Left, Right, Top, Bottom. Puts in page breaks, line breaks, etc.
% Does not justify text. Takes newlines literally and prints them, so this
% is not quite like a ?roff fill routine, and it may be a bit flaky, but it is
% cool nonetheless.
{
	/Str exch def
	 
	   Str WhitespaceSearch % loop until all words are eaten
	      { 
	        /TextWord exch def /WhiteSpace exch def /Rest exch def
	        TextWord WrapShow % returns true if newline inserted after word
	        WhiteSpace ShowWhitespace
	        Rest WrapText
	      } 
	      { 
	      	WrapShow
	         %no spaces so this is the last word
	      } 
	   ifelse
} def



/inch { 72 mul } def

/Top 10.5 inch def
/Bottom 0.5 inch def
/Left 1 inch def
/Right 8 inch def
/WrapZone 7 inch def
/Size 10 def
/Lineheight Size 5 add def
/Font1 /Courier def
/Font2 /ZapfDingbats def  % all symbols, no real letters
/Font3  /AvantGarde-Book def
/LineChr (-) def % boxes in ZapfDingbats
/Tab 1 inch def

% PUT PROGRAM HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0

-- 
Peter Greenberg, Swarthmore College, Swarthmore, PA 19081 
AT&T:(215) 328-8384 or 8610
UUCP: ...{{seismo | inhp4}!bpa | {sun | rutgers}!liberty}!swatsun!greenber
ARPA: swatsun!greenber@bpa.BELL-ATL.COM