[comp.sources.unix] v15i017: Ditroff to PostScript translator, Part05/05

rsalz@uunet.uu.net (Rich Salz) (05/27/88)

Submitted-by: Axel Mahler <axel%coma.UUCP@TUB.BITNET>
Posting-number: Volume 15, Issue 17
Archive-name: tpscript/part05

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 5)."
# Wrapped by rsalz@fig.bbn.com on Thu May 26 13:02:29 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f './pscript/genftable.ps' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./pscript/genftable.ps'\"
else
echo shar: Extracting \"'./pscript/genftable.ps'\" \(12794 characters\)
sed "s/^X//" >'./pscript/genftable.ps' <<'END_OF_FILE'
X%!
X% genftable - Postcript program to produce font tables for ditroff.
X%	      Tables are output on the standard output file - which
X%	      needs to be captured by the host computer.
X%
X%	      Note the routine "commondefs" which outputs local
X%	      defined (hand built) characters.
X%
X% Michael Rourke, University of N.S.W., Australia
X%
X
X/t 30 string def
X
X/ps
X% string ->
X{
X	print
X} def
X
X/pr
X% any -->
X{
X	t cvs ps
X} def
X
X/prsp
X{
X	(\t) ps
X} def
X
X/prnl
X{
X	(\n) ps
X} def
X
X/pro
X% int -->
X{
X	dup 0 eq
X	{ pr }
X	{ dup 8 idiv pro 8 mod pr }
X	ifelse
X} def
X
X/charsize
X% string --> bot top
X{
X	gsave
X	newpath 0 0 moveto false charpath flattenpath pathbbox
X	exch pop 3 -1 roll pop
X	grestore
X} def
X
X/strwidth
X% string --> width
X{
X	stringwidth pop round cvi
X} def
X
X/prsize
X% string -->
X{
X	dup strwidth pr prsp
X	dup charsize
X	top gt { 2 } { 0 } ifelse
X	exch bot lt { 1 or } if
X	pr prsp
X	0 get pro 
X} def
X
X/fontinfo
X% fontname troffinternal troffname
X{
X	(\ncat <<"!" > ) ps dup pr prnl
X	(# ) ps 2 index pr prnl
X	(name ) ps pr prnl
X	(internalname ) ps pr prnl
X	dup findfont 100 scalefont setfont
X	/fixedwidth false def
X	/Symbol eq
X	{
X		/actions symbol-encoding def
X		(special\n) ps
X	}
X	{
X		/actions standard-encoding def
X		currentfont /FontInfo get /isFixedPitch get
X		{
X			(# fixed width\n) ps
X			/fixedwidth true def
X		}
X		{
X			(ligatures fi fl ff ffi ffl 0\n) ps
X		}
X		ifelse
X	}
X	ifelse
X	% use "o" to get top and bottom on a normal char
X	(o) charsize /top exch def /bot exch def
X	% some non ascending chars slightly higher than "o"
X	% and some lower so adjust slightly
X	/top top 2 add def
X	/bot bot 4 sub def
X	/encoding currentfont /Encoding get def
X	/s 1 string def
X	0 1 255
X	{
X		s 0 2 index put
X		encoding exch get dup /.notdef ne
X		{
X			s 1 index actions exch get
X			% charname charstr
X			exec
X			flush
X		}
X		{
X			pop
X		}		
X		ifelse
X	} for
X	actions standard-encoding eq { commondefs } if
X	(!\n) ps flush
X} def
X
X/commondefs
X{
X	/fracsize (0) strwidth (\244) strwidth add def		% \244 = '/'
X	/Fisize (f) strwidth (\256) strwidth add 5 sub def	% \256 = 'fi'
X	/ffsize (f) strwidth 2 mul 5 sub def
X	/fl { flush } def
X	fixedwidth not
X	{
X		(ff) ps prsp ffsize pr (\t2\t0100\tff ligature - faked\n) ps fl
X		(Fi) ps prsp Fisize pr (\t2\t0100\tffi ligature - faked\n) ps fl
X		(Fl) ps prsp Fisize pr (\t2\t0100\tffl ligature - faked\n) ps fl
X	} if
X	(12) ps prsp fracsize pr (\t2\t0100\t1/2 - faked\n) ps fl
X	(13) ps prsp fracsize pr (\t2\t0100\t1/3 - faked\n) ps fl
X	(14) ps prsp fracsize pr (\t2\t0100\t1/4 - faked\n) ps fl
X	(18) ps prsp fracsize pr (\t2\t0100\t1/8 - faked\n) ps fl
X	(23) ps prsp fracsize pr (\t2\t0100\t2/3 - faked\n) ps fl
X	(34) ps prsp fracsize pr (\t2\t0100\t3/4 - faked\n) ps fl
X	(38) ps prsp fracsize pr (\t2\t0100\t3/8 - faked\n) ps fl
X	(58) ps prsp fracsize pr (\t2\t0100\t5/8 - faked\n) ps fl
X	(78) ps prsp fracsize pr (\t2\t0100\t7/8 - faked\n) ps fl
X	(sq\t100\t3\t0100\tsquare box - faked\n) ps fl
X} def
X
X/space
X% charname charstr -->
X{
X	(spacewidth ) ps
X	strwidth pr pop prnl
X	(charset\n) ps
X} def
X
X/norm
X% charname charstr -->
X{
X	dup pr prsp prsize pop prnl
X} def
X
X/normdup
X% charname charstr dupname -->
X{
X	3 1 roll norm
X	pr prsp (") ps prnl
X} def
X
X/gnorm
X% charname charstr -->
X{
X	(*) ps norm
X} def
X
X/map
X% charname charstr mapname -->
X{
X	pr prsp prsize prsp pr prnl
X} def
X
X/mapdup
X% charname charstr mapname dupname -->
X{
X	4 1 roll map
X	pr prsp (") ps prnl
X} def
X
X/mapdupdup
X% charname charstr mapname dupname dupname -->
X{
X	5 1 roll mapdup
X	pr prsp (") ps prnl
X} def
X
X/cmap
X% charname charstr mapname -->
X{
X	fixedwidth { 3 { pop } repeat } { map } ifelse
X} def
X
X/standard-encoding 149 dict def
standard-encoding begin
X	/space		{ space }		def
X	/exclam		{ norm }		def
X	/quotedbl	{ norm }		def
X	/numbersign	{ norm }		def
X	/dollar		{ norm }		def
X	/percent	{ norm }		def
X	/ampersand	{ norm }		def
X	/quoteright	{ norm }		def
X	/parenleft	{ norm }		def
X	/parenright	{ norm }		def
X	/asterisk	{ norm }		def
X	/plus		{ norm }		def
X	/comma		{ norm }		def
X	/hyphen		{ (hy) normdup }	def
X	/period		{ norm }		def
X	/slash		{ (sl) dup }		def
X	/zero		{ norm }		def
X	/one		{ norm }		def
X	/two		{ norm }		def
X	/three		{ norm }		def
X	/four		{ norm }		def
X	/five		{ norm }		def
X	/six		{ norm }		def
X	/seven		{ norm }		def
X	/eight		{ norm }		def
X	/nine		{ norm }		def
X	/colon		{ norm }		def
X	/semicolon	{ norm }		def
X	/less		{ norm }		def
X	/equal		{ norm }		def
X	/greater	{ norm }		def
X	/question	{ norm }		def
X	/at		{ norm }		def
X	/A		{ norm }		def
X	/B		{ norm }		def
X	/C		{ norm }		def
X	/D		{ norm }		def
X	/E		{ norm }		def
X	/F		{ norm }		def
X	/G		{ norm }		def
X	/H		{ norm }		def
X	/I		{ norm }		def
X	/J		{ norm }		def
X	/K		{ norm }		def
X	/L		{ norm }		def
X	/M		{ norm }		def
X	/N		{ norm }		def
X	/O		{ norm }		def
X	/P		{ norm }		def
X	/Q		{ norm }		def
X	/R		{ norm }		def
X	/S		{ norm }		def
X	/T		{ norm }		def
X	/U		{ norm }		def
X	/V		{ norm }		def
X	/W		{ norm }		def
X	/X		{ norm }		def
X	/Y		{ norm }		def
X	/Z		{ norm }		def
X	/bracketleft	{ norm }		def
X	/backslash	{ norm }		def
X	/bracketright	{ norm }		def
X	/asciicircum	{ (a^) map }		def
X	/underscore	{ (ru) normdup }	def
X	/quoteleft	{ norm }		def
X	/a		{ norm }		def
X	/b		{ norm }		def
X	/c		{ norm }		def
X	/d		{ norm }		def
X	/e		{ norm }		def
X	/f		{ norm }		def
X	/g		{ norm }		def
X	/h		{ norm }		def
X	/i		{ norm }		def
X	/j		{ norm }		def
X	/k		{ norm }		def
X	/l		{ norm }		def
X	/m		{ norm }		def
X	/n		{ norm }		def
X	/o		{ norm }		def
X	/p		{ norm }		def
X	/q		{ norm }		def
X	/r		{ norm }		def
X	/s		{ norm }		def
X	/t		{ norm }		def
X	/u		{ norm }		def
X	/v		{ norm }		def
X	/w		{ norm }		def
X	/x		{ norm }		def
X	/y		{ norm }		def
X	/z		{ norm }		def
X	/braceleft	{ norm }		def
X	/bar		{ norm }		def
X	/braceright	{ norm }		def
X	/asciitilde	{ (a~) map }		def
X	/exclamdown	{ (I!) map }		def
X	/cent		{ (ct) map }		def
X	/sterling	{ (po) map }		def
X	/fraction	{ }			def
X	/yen		{ ($J) map }		def
X	/florin		{ }			def
X	/section	{ (sc) map }		def
X	/currency	{ }			def
X	/quotesingle	{ (fm) (n') mapdup }	def
X	/quotedblleft	{ (lq) map }		def
X	/guillemotleft	{ (d<) map }		def
X	/guilsinglleft	{ (l<) map }		def
X	/guilsinglright	{ (r>) map }		def
X	/fi		{ (fi) cmap }		def
X	/fl		{ (fl) cmap }		def
X	/endash		{ (\\-) map }		def
X	/dagger		{ (dg) map }		def
X	/daggerdbl	{ (dd) map }		def
X	/periodcentered	{ }			def
X	/paragraph	{ (pp) map }		def
X	/bullet		{ (bu) map }		def
X	/quotesinglbase	{ } 			def
X	/quotedblbase	{ }			def
X	/quotedblright	{ (rq) map }		def
X	/guillemotright	{ (d>) map }		def
X	/ellipsis	{ }			def
X	/perthousand	{ (pm) cmap }		def
X	/questiondown	{ (I?) map }		def
X	/grave		{ (ga) (\\`) mapdup }	def
X	/acute		{ (aa) (\\') mapdup }	def
X	/circumflex	{ (^) map }		def
X	/tilde		{ (~) map }		def
X	/macron		{ (ma) map }		def
X	/breve		{ (be) map }		def
X	/dotaccent	{ (dt) map }		def
X	/dieresis	{ (..) (um) mapdup }	def
X	/ring		{ (ri) map }		def
X	/cedilla	{ (cd) map }		def
X	/hungarumlaut	{ ('') map }		def
X	/ogonek		{ (og) map }		def
X	/caron		{ (hc) map }		def
X	/emdash		{ (em) map }		def
X	/AE		{ (AE) cmap }		def
X	/ordfeminine	{ }			def
X	/Lslash		{ (PL) map }		def
X	/Oslash		{ (O/) map }		def
X	/OE		{ (OE) cmap }		def
X	/ordmasculine	{ }			def
X	/ae		{ (ae) cmap }		def
X	/dotlessi	{ (ui) map }		def
X	/lslash		{ (Pl) map }		def
X	/oslash		{ (o/) map }		def
X	/oe		{ (oe) cmap }		def
X	/germandbls	{ (ss) map }		def
end
X
X/symbol-encoding 189 dict def
symbol-encoding begin
X	/space		{ space }		def
X	/exclam		{ norm }		def
X	/universal	{ (fa) map }		def
X	/numbersign	{ norm }		def
X	/existential	{ (te) map }		def
X	/percent	{ norm }		def
X	/ampersand	{ norm }		def
X	/suchthat	{ (cm) map }		def
X	/parenleft	{ norm }		def
X	/parenright	{ norm }		def
X	/asteriskmath	{ (**) map }		def
X	/plus		{ (pl) map }		def
X	/comma		{ norm }		def
X	/minus		{ (mi) normdup }	def
X	/period		{ norm }		def
X	/slash		{ (sl) map }		def
X	/zero		{ norm }		def
X	/one		{ norm }		def
X	/two		{ norm }		def
X	/three		{ norm }		def
X	/four		{ norm }		def
X	/five		{ norm }		def
X	/six		{ norm }		def
X	/seven		{ norm }		def
X	/eight		{ norm }		def
X	/nine		{ norm }		def
X	/colon		{ norm }		def
X	/semicolon	{ norm }		def
X	/less		{ norm }		def
X	/equal		{ (eq) normdup }	def
X	/greater	{ norm }		def
X	/question	{ norm }		def
X	/congruent	{ (=~) map }		def
X	/Alpha		{ gnorm }		def
X	/Beta		{ gnorm }		def
X	/Chi		{ (*X) map }		def
X	/Delta		{ gnorm }		def
X	/Epsilon	{ gnorm }		def
X	/Phi		{ gnorm }		def
X	/Gamma		{ gnorm }		def
X	/Eta		{ (*Y) map }		def
X	/Iota		{ gnorm }		def
X	/theta1		{ }			def
X	/Kappa		{ gnorm }		def
X	/Lambda		{ gnorm }		def
X	/Mu		{ gnorm }		def
X	/Nu		{ gnorm }		def
X	/Omicron	{ gnorm }		def
X	/Pi		{ gnorm }		def
X	/Theta		{ (*H) map }		def
X	/Rho		{ gnorm }		def
X	/Sigma		{ gnorm }		def
X	/Tau		{ gnorm }		def
X	/Upsilon	{ gnorm }		def
X	/sigma1		{ (ts) map }		def
X	/Omega		{ (*W) map }		def
X	/Xi		{ (*C) map }		def
X	/Psi		{ (*Q) map }		def
X	/Zeta		{ gnorm }		def
X	/bracketleft	{ norm }		def
X	/therefore	{ (tf) map }		def
X	/bracketright	{ norm }		def
X	/perpendicular	{ (bt) map }		def
X	/underscore	{ (ul) map }		def
X	/radicalex	{ }			def
X	/alpha		{ gnorm }		def
X	/beta		{ gnorm }		def
X	/chi		{ (*x) map }		def
X	/delta		{ gnorm }		def
X	/epsilon	{ gnorm }		def
X	/phi		{ gnorm }		def
X	/gamma		{ gnorm }		def
X	/eta		{ (*y) map }		def
X	/iota		{ gnorm }		def
X	/phi1		{ }			def
X	/kappa		{ gnorm }		def
X	/lambda		{ gnorm }		def
X	/mu		{ gnorm }		def
X	/nu		{ gnorm }		def
X	/omicron	{ gnorm }		def
X	/pi		{ gnorm }		def
X	/theta		{ (*h) map }		def
X	/rho		{ gnorm }		def
X	/sigma		{ gnorm }		def
X	/tau		{ gnorm }		def
X	/upsilon	{ gnorm }		def
X	/omega1		{ }			def
X	/omega		{ (*w) map }		def
X	/xi		{ (*c) map }		def
X	/psi		{ (*q) map }		def
X	/zeta		{ gnorm }		def
X	/braceleft	{ norm }		def
X	/bar		{ (or) normdup }	def
X	/braceright	{ norm }		def
X	/similar	{ (ap) map }		def
X	/Upsilon1	{ }			def
X	/minute		{ (mt) map }		def
X	/lessequal	{ (<=) map }		def
X	/fraction	{ (/) map }		def
X	/infinity	{ (if) map }		def
X	/florin		{ }			def
X	/club		{ (Cc) map }		def
X	/diamond	{ (Cd) map }		def
X	/heart		{ (Ch) map }		def
X	/spade		{ (Cs) map }		def
X	/arrowboth	{ (<>) map }		def
X	/arrowleft	{ (<-) map }		def
X	/arrowup	{ (ua) map }		def
X	/arrowright	{ (->) map }		def
X	/arrowdown	{ (da) map }		def
X	/degree		{ (de) map }		def
X	/plusminus	{ (+-) map }		def
X	/second		{ (sd) map }		def
X	/greaterequal	{ (>=) map }		def
X	/multiply	{ (mu) map }		def
X	/proportional	{ (pt) map }		def
X	/partialdiff	{ (pd) map }		def
X	/bullet		{ }			def
X	/divide		{ (di) map }		def
X	/notequal	{ (!=) map }		def
X	/equivalence	{ (==) map }		def
X	/approxequal	{ (~=) map }		def
X	/ellipsis	{ }			def
X	/arrowvertex	{ }			def
X	/arrowhorizex	{ }			def
X	/carriagereturn	{ (cr) map }		def
X	/aleph		{ (al) map }		def
X	/Ifraktur	{ }			def
X	/Rfraktur	{ }			def
X	/weierstrass	{ }			def
X	/circlemultiply	{ (ax) map }		def
X	/circleplus	{ (a+) map }		def
X	/emptyset	{ (es) map }		def
X	/intersection	{ (ca) map }		def
X	/union		{ (cu) map }		def
X	/propersuperset	{ (sp) map }		def
X	/reflexsuperset	{ (ip) map }		def
X	/notsubset	{ (!s) map }		def
X	/propersubset	{ (sb) map }		def
X	/reflexsubset	{ (ib) map }		def
X	/element	{ (mo) map }		def
X	/notelement	{ (!m) (nm) mapdup }	def
X	/angle		{ (ag) map }		def
X	/gradient	{ (gr) map }		def
X	/registerserif	{ }			def
X	/copyrightserif	{ }			def
X	/trademarkserif	{ }			def
X	/product	{ }			def
X	/radical	{ (sr) map }		def
X	/dotmath	{ (m.) map }		def
X	/logicalnot	{ (no) map }		def
X	/logicaland	{ (an) (la) mapdup }	def
X	/logicalor	{ (lo) map }		def
X	/arrowdblboth	{ (io) map }		def
X	/arrowdblleft	{ (<:) (lh) mapdup }	def
X	/arrowdblup	{ (u=) map }		def
X	/arrowdblright	{ (:>) (rh) (im) mapdupdup } def
X	/arrowdbldown	{ (d=) map }		def
X	/lozenge	{ (dm) map }		def
X	/angleleft	{ (L<) map }		def
X	/registersans	{ (rg) map }		def
X	/copyrightsans	{ (co) map }		def
X	/trademarksans	{ (tm) map }		def
X	/summation	{ }			def
X	/parenlefttp	{ }			def
X	/parenleftex	{ }			def
X	/parenleftbt	{ }			def
X	/bracketlefttp	{ }			def
X	/bracketleftex	{ }			def
X	/bracketleftbt	{ }			def
X	/bracelefttp	{ }			def
X	/braceleftmid	{ }			def
X	/braceleftbt	{ }			def
X	/braceex	{ }			def
X	/apple		{ (AL) map }		def
X	/angleright	{ (R>) map }		def
X	/integral	{ (is) map }		def
X	/integraltp	{ }			def
X	/integralex	{ }			def
X	/integralbt	{ }			def
X	/parenrighttp	{ }			def
X	/parenrightex	{ }			def
X	/parenrightbt	{ }			def
X	/bracketrighttp	{ }			def
X	/bracketrightex	{ }			def
X	/bracketrightbt	{ }			def
X	/bracerighttp	{ }			def
X	/bracerightmid	{ }			def
X	/bracerightbt	{ }			def
end
X
X/Times-Roman		/Roman		/R	fontinfo
X/Helvetica		/Helvetica	/H	fontinfo
X/Courier		/Courier	/C	fontinfo
X/Symbol			/Symbol		/S	fontinfo
X/Times-Italic		/Italic		/I	fontinfo
X/Times-Bold		/Bold		/B	fontinfo
X/Times-BoldItalic	/BoldI		/BI	fontinfo
X/Helvetica-Bold		/HelveticaB	/HB	fontinfo
X/Helvetica-Oblique	/HelveticaO	/HO	fontinfo
X/Helvetica-BoldOblique	/HelveticaBO	/HX	fontinfo
X/Courier-Bold		/CourierB	/CB	fontinfo
X/Courier-Oblique	/CourierO	/CO	fontinfo
X/Courier-BoldOblique	/CourierBO	/CX	fontinfo
END_OF_FILE
if test 12794 -ne `wc -c <'./pscript/genftable.ps'`; then
    echo shar: \"'./pscript/genftable.ps'\" unpacked with wrong size!
fi
# end of './pscript/genftable.ps'
fi
if test -f './tpscript/tpscript.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./tpscript/tpscript.c'\"
else
echo shar: Extracting \"'./tpscript/tpscript.c'\" \(36974 characters\)
sed "s/^X//" >'./tpscript/tpscript.c' <<'END_OF_FILE'
static char *RCSid = "$Header: tpscript.c,v 1.6 87/07/15 19:51:55 andy Exp $";
X
X/*
X * $Log:	tpscript.c,v $
X * Revision 1.6  87/07/15  19:51:55  andy
X * The GEM related part of the PostScript prolog was enhanced.
X * 
X * Revision 1.5  87/04/27  17:35:44  andy
X * in line 205 was a comma missing. 
X * 
X * Revision 1.4  87/04/24  03:01:16  andy
X * *** empty log message ***
X * 
X * Revision 1.3  86/10/15  17:24:24  andy
X * Added Escape-Mechanism which calls another PostScript generating
X * Program as input filter.
X * This change was made to introduce graphics generated by gemdraw
X * in the tpscript output.
X * Escape Character is E --- see #ifdef GEMPRINT
X * 
X */
X
X/*
X *	tpscript.c
X *	Troff post-processor for postscript devices
X *
X *	Original program by Stephen Frede (stephenf@elecvax.oz)
X *		Dept. Comp. Sci., University of NSW, Sydney, Australia.
X *					...!seismo!munnari!elecvax!stephenf
X *
X *	Extensive modifications by Cameron Davidson (probe@mm730.uq.oz)
X *				University of Queensland, Brisbane, Australia
X *
X *	Other changes by Michael Rourke (michaelr@elecvax.oz) UNSW.
X */
X
X/* NOTES:
X *
X * Originally, changes to a new font would not take effect until
X * characters from that font were required to be printed, but this
X * means that commands passed through to postscript directly (via \!!)
X * may end up with the wrong font. So now font changes actually happen
X * when requested (or needed in the case of the special font).
X *
X */
X
X/*	The language that is accepted by this program is produced by the new
X *	device independent troff, and consists of the following statements,
X *
X *
X *	sn		set the point size to n
X *	fn		set the typesetter font to the one in position n
X *	cx		output the ASCII character x 
X *	Cxyz		output the code for the special character xyz. This
X *			command is terminated by white space.
X *	Hn		go to absolute horizontal position n
X *	Vn		go to absolute vertical position n ( down is positive )
X *	hn		go n units horizontally from current position
X *	vn		go n units vertically from current position
X *	nnc		move right nn units, then print the character c. This
X *			command expects exactly two digits followed by the
X *			character c.
X *			( this is an optimisation that shrinks output file
X *			size by about 35% and run-time by about 15% while
X *			preserving ascii-ness)
X *	w		paddable word space - no action needed
X *	nb a		end of line ( information only - no action needed )
X *			b = space before line, a = space after line
X *	pn		begin page n
X *	in		stipple as no. from 1 to n (BERK).
X *	P		spread ends -- output it (put in by rsort) (BERK).
X *	# ...\n		comment - ignore.
X *	! ...\n		pass through uninterpreted (LOCAL MOD).
X *	Dt ...\n	draw operation 't':
X *
X *		Dl dx dy		line from here to dx, dy
X *		Dc d		circle of diameter d, left side here
X *		De x y		ellipse of axes diameter x,y, left side here
X *		Da dx1 dy1 dx2 dy2	arc counter-clockwise, start here,
X *					centre is dx1, dy1 (relative to start),
X *					end is dx2, dy2 (relative to centre).
X *		D~ x y x y ...	wiggly line (spline) by x,y then x,y ...
X *		Dt d		set line thickness to d pixels (BERK).
X *		Ds d		set line style mask to d (BERK).
X *		Dg x y x y ...	gremlin (BERK).
X */
X#ifdef GEMPRINT 
X/*      E prg a1 a2 ... fork program "prg" with args a1 a2 ... .
X *                      continue after execution.
X */
X#endif
X/*	x ... \n	device control functions:
X *
X *		x i		initialize the typesetter
X *		x T s		name of device is s
X *		x r n h v	resolution is n units per inch. h is
X *				min horizontal motion, v is min vert.
X *				motion in machine units.
X *		x p		pause - can restart the typesetter
X *		x s		stop - done forever
X *		x t		generate trailer
X *		x f n s		load font position n with tables for 
X *				font s. Referring to font n now means
X *				font s.
X *		x H n		set character height to n
X *		x S n		set character slant to n
X *
X *		Subcommands like i are often spelled out as "init"
X *
X *	Commands marked "BERK" are berzerkeley extensions.
X *
X */
X
X#include	"tpscript.h"
X
X#define	FONTDIR	"/usr/lib/font"		/* where font directories live */
X
XFILE	*Debug = NULL;		/* debugging stream if non-null */
char	*fontdir = FONTDIR;	/* where the fonts live */
char	*ifile = 0;		/* current input file name */
int	lineno,			/* line no. in current input file */
X	npages = 0;			/* no. pages printed so far */
char	device[100],		/* device name, eg "alw" */
X	errbuf[100];		/* tmp buffer for error messages */
int	hpos = 0,		/* current horizontal position */
X	vpos = 0;		/* current vertical position (rel. TOP pg.) */
int	res,			/* resolution in THINGS/inch */
X	hor_res,		/* min horizontal movement (in THINGS) */
X	vert_res,		/* min vertical movement (in THINGS) */
X	respunits;
float	rotation = 0;		/* page orientation (degrees) */
int	currtfont = DEF_FONT,	/* current font number selected by troff */
X	papertype = 		/* paper type (different imageable regions) */
X#ifdef	ALW
X		PT_A4;
X#else
X		PT_DEFAULT;
X#endif
bool	manualfeed = FALSE;	/* normally auto-feed */
X
X/* due to an obscure bug in ditroff, sometimes no initial 'p' command
X * is generated, so we have to remember if any output has happened
X * to decide if a 'p' causes a page print or not.
X */
bool	firstpage = TRUE;	/* nothing yet printed anywhere */
X
X/* font parameters */
struct	fontparam 
X	tfp,		/* current troff font parameters */
X	pfp;		/* current postscript font parameters */
X
X
X/* table of font descriptions */
struct fontdesc 
X	*fontd = NOFONTDESC,
X	*spcfnt1 = NOFONTDESC,	/* special font */
X	*spcfnt2 = NOFONTDESC;	/* special font 2 */
X
X/* font mount table - array of pointers to font descriptions */
struct fontdesc	**fontmount;
X
X/* mapping between troff font names and builtin font names
X * This should go in the internal name part of the font description
X * itself, but there is only 10 bytes allocated (see dev.h).
X */
X
X#ifdef GERMAN
struct fontmap  fontmap[] = {
X 	{ "R", "Times-Roman-Germ" },
X 	{ "I", "Times-Italic-Germ" },
X 	{ "B", "Times-Bold-Germ" },
X 	{ "BI", "Times-BoldItalic-Germ" },
X 	{ "S", "Symbol" },
X 	{ "S2", "BracketFont" },	/* locally defined special font */
X 	{ "C", "Courier-Germ" },
X 	{ "CW", "Courier" },		/* synonym: constant width */
X 	{ "CB", "Courier-Bold-Germ" },
X 	{ "CO", "Courier-Oblique-Germ" },
X 	{ "CX", "Courier-BoldOblique-Germ" },
X 	{ "H", "Helvetica-Germ" },
X 	{ "HR", "Helvetica" },		/* two-char name for H */
X 	{ "HB", "Helvetica-Bold-Germ" },
X 	{ "HO", "Helvetica-Oblique-Germ" },
X 	{ "HX", "Helvetica-BoldOblique-Germ" },
X#ifdef XFONTS
X 	{ "BR", "Bookman-Light-Germ" },
X 	{ "BO", "Bookman-LightItalic-Germ" },
X 	{ "BB", "Bookman-Demi-Germ" },
X 	{ "BX", "Bookman-DemiItalic-Germ" },
X#endif
X 	{ (char *)0,	(char *)0 }
X};
X#else
struct fontmap  fontmap[] = {
X	{ "R", "Times-Roman" },
X	{ "I", "Times-Italic" },
X	{ "B", "Times-Bold" },
X	{ "BI", "Times-BoldItalic" },
X	{ "S", "Symbol" },
X	{ "S2", "BracketFont" },	/* locally defined special font */
X	{ "C", "Courier" },
X	{ "CW", "Courier" },		/* synonym: constant width */
X	{ "CB", "Courier-Bold" },
X	{ "CO", "Courier-Oblique" },
X	{ "CX", "Courier-BoldOblique" },
X	{ "H", "Helvetica" },
X	{ "HR", "Helvetica" },		/* two-char name for H */
X	{ "HB", "Helvetica-Bold" },
X	{ "HO", "Helvetica-Oblique" },
X	{ "HX", "Helvetica-BoldOblique" },
X#ifdef XFONTS
X 	{ "BR", "Bookman-Light" },
X 	{ "BO", "Bookman-LightItalic" },
X 	{ "BB", "Bookman-Demi" },
X 	{ "BX", "Bookman-DemiItalic" },
X#endif
X	{ (char *)0,	(char *)0 }
X};
X#endif
X
struct dev	dev;
X
short	*chartab = NULL;	/* char's index in charname array */
char	*charname = NULL;	/* special character names */
int	ncharname;		/* no. special character names */
int	nfonts = 0;		/* no. of fonts mounted */
int	nfontmount;		/* no. of font mount positions */
X
X	/*
X	 * this is the width that the printer will have moved following
X	 * the last printed character, if troff then says to move a
X	 * different amount we will shift the difference
X	 */
int	width_pending	= 0;
X
bool	word_started	= FALSE;	/* we are in middle of word string */
X
X
int		strcmp();
char		*emalloc();
struct fontdesc *findfont();
struct fontmap	*getfmap();
X
main(argc, argv)
int		argc;
register char	**argv;
X{
X	register FILE	*istr;
X	int		status = 0;
X	extern 	double	atof();
X#ifdef SPACING
X	float		spacing;
X#endif SPACING
X
X	strcpy(device, DEF_DEV); /* just in case we get a "Di" before a "DT" */
X	argv++;
X	while(*argv && **argv == '-')
X	{
X		char	c;
X
X		(*argv)++;	/* skip the '-' */
X		c = **argv;
X		(*argv)++;	/* skip the character */
X		switch(c)
X		{
X			case 'D':	/* debug */
X				Debug = stderr;
X				break;
X
X#ifdef SPACING
X			case 'h':
X				spacing = atof(*argv);
X				break;
X#endif SPACING
X			case 'r':	/* rotate */
X				if(**argv == '\0')
X					rotation = 90.0;
X				else
X					rotation = atof(*argv);
X				break;
X
X			case 'S':	/* manual feed */
X				manualfeed = TRUE;
X				break;
X
X			case 'L':	/* legal paper type */
X				papertype = PT_LEGAL;
X				break;
X
X			case 't':
X				postr = stdout;
X				break;
X
X			default:
X				break;
X		}
X		argv++;
X	}
X
X	if (postr == NULL)
X	{
X#ifdef	GRIS
X		postr = popen("exec sendfile -AC -aprinter -dbasser -ugris -e\"-R -qd\" -ntroff-alw", "w");
X		if (postr == NULL)
X			error(ERR_SNARK, "can't popen spooler");
X#else	GRIS
X		postr = stdout;
X#endif	GRIS
X	}
X
X	if(! *argv)
X	{
X		ifile = "stdin";
X		process(stdin);
X	}
X	else while(*argv)
X	{
X		if((istr=fopen(*argv, "r")) == NULL)
X		{
X			perror(*argv);
X			status++;
X		}
X		else
X		{
X			ifile = *argv;
X			process(istr);
X			fclose(istr);
X		}
X		argv++;
X	}
X	if (postr != stdout)
X		status += pclose(postr);
X	exit(status);
X	/* NOTREACHED */
X}
X
process(istr)
XFILE	*istr;
X{
X	int	ch;
X	char	str[50];
X	int	n;
X	register int	i;
X
X	lineno = 1;	/* start processing 1st input line */
X
X	while((ch=getc(istr)) != EOF)
X	{
X			/*
X			 * the first switch group can safely be scanned without
X			 * having to first ensure the horizontal position is
X			 * up to date.
X			 */
X		switch(ch)
X		{
X			/* noise */
X			case ' ':
X			case '\0':
X				continue;
X
X			case '\n':
X				lineno++;
X				continue;
X
X			case '0': case '1': case '2': case '3': case '4':
X			case '5': case '6': case '7': case '8': case '9':
X				ungetc(ch, istr);
X				fscanf(istr, "%2d", &n);
X
X				width_pending -= n;
X				hpos += n;
X
X				/* drop through to process the next char */
X
X			case 'c':	/* ascii character */
X
X					/*
X					 * if this char and preceeding were
X					 * not simply successive chars in the
X					 * same word then we need some
X					 * horizontal motion to reset position
X					 */
X				if ( width_pending != 0 )
X					hgoto( );
X
X				ch = getc(istr);
X
X				width_pending += GETWIDTH( tfp.fp_font,
X					(i = tfp.fp_font->f_fitab[ch - NUNPRINT] ));
X
X				if(ch != ' ')
X					putch(tfp.fp_font->f_codetab[i] & BMASK);
X				else
X					putch(' ');	/* no code for ' ' */
X				continue;
X
X			case 'C':	/* troff character */
X
X				if ( width_pending != 0 )
X					hgoto( );
X
X				fscanf(istr, "%s", str);
X				putspec(str);
X				continue;
X
X			case 'h':	/* relative horizontal movement */
X				fscanf(istr, "%d", &n);
X
X				/*
X				 * we continually accumulate horizontal
X				 * motions and all relative requests are
X				 * translated into absolute ones.
X				 * This avoids accumulation of character
X				 * width rounding errors
X				 * beyond a single word. (These errors arise
X				 * because troff requires widths to be
X				 * integral to the unit resolution whereas in
X				 * the printer they may be fractional).
X				 */
X
X				hpos += n;
X				if ( ( width_pending -= n ) != 0 )
X					hgoto( );	/* most likely end of word */
X
X				continue;
X
X			case 'w':
X				firstpage = FALSE;
X				CLOSEWORD();
X				continue;
X
X			case 'n':	/* newline */
X				fscanf(istr, "%*f %*f");
X				width_pending = 0;	/* doesn't matter now */
X				continue;
X
X			case 'f':	/* select font no. */
X				fscanf(istr, "%d", &n);
X				if(n > nfonts || n < 0 || fontmount[n] == NULL)
X				{
X					sprintf(errbuf, "ERROR: font %d not mounted",
X						n);
X					error(ERR_WARN, errbuf);
X				}
X				else
X				{
X					tfp.fp_font = fontmount[n];
X					currtfont = n;
X				}
X				continue;
X
X			case 's':	/* size in points */
X				fscanf(istr, "%d", &n);
X				if(n <= 0)
X				{
X					sprintf(errbuf, "Illegal point size %d\n", n);
X					error(ERR_WARN, errbuf);
X				}
X				else
X				{
X					tfp.fp_size = n;
X					tfp.fp_height = (float) n;
X				}
X				continue;
X
X			case 'H':	/* absolute horizontal position */
X
X				fscanf(istr, "%d", &hpos);
X				hgoto();
X				continue;
X
X			case 'V':	/* absolute vertical position */
X				fscanf(istr, "%d", &vpos);
X				vgoto();
X				continue;
X
X			case 'v':	/* relative vertical movement */
X				fscanf(istr, "%d", &n);
X				vmot(n);
X				continue;
X
X		}
X			/*
X			 * If the input char is in the second group
X			 * then we must make sure the printer is positioned
X			 * where troff thinks it is
X			 * and close any word currently being printed
X			 */
X		if ( width_pending != 0 )
X			hgoto( );
X		else
X			CLOSEWORD();
X
X		switch(ch)
X		{
X			case 'x':	/* device control function */
X				devcntrl(istr);
X				break;
X
X			case 'D':	/* draw */
X				draw(istr);
X				break;
X#ifdef GEMPRINT
X			case 'E':	/* call program */
X				call(istr);		  
X				break;
X#endif
X
X			case 'p':	/* new page */
X				fscanf(istr, "%d", &n);
X				page(n);
X				break;
X
X			case '#':	/* comment */
X				while((ch=getc(istr)) != '\n' && ch != EOF);
X				lineno++;
X				break;
X
X			case 't':	/* text */
X				text(istr);
X				break;
X
X# ifdef HASH
X			/*
X			 * debug - to be manually inserted in input stream if needed
X			 * if n >= 0 && n <= HASH_SIZE
X			 *	then will print entire hash contents
X			 * otherwise will dump just names in hash_tab[n] entry
X			 */
X			case 'Z':
X				fscanf(istr, "%d", &n);
X				dumphash( n );
X				break;
X				
X# endif
X
X			case '!':	/* pass through uninterpreted */
X				setfont(FALSE);	/* ensure current font is set */
X				putc('\n', postr);
X				while((ch=getc(istr)) != '\n' && ch != EOF)
X					putc(ch, postr);
X				break;
X
X			default:
X				sprintf(errbuf, "Unknown command '%c'", ch);
X				error(ERR_FATAL, errbuf);
X		}
X	}
X}
X
devcntrl(istr)
XFILE	*istr;
X{
X	char		str[50];
X	int		fontn,
X			ch;
X	float		f;
X
X	fscanf(istr, "%s", str);
X	switch(*str)
X	{
X		case 'i':	/* device initialisation */
X			initfonts(device);
X			devinit();
X			break;
X
X		case 'T':	/* we had better get this before an 'init' */
X			fscanf(istr, "%s", device);
X			break;
X
X		case 'r':	/* resolution */
X			fscanf(istr, "%d %d %d", &res, &hor_res, &vert_res);
X			respunits = res / PU_INCH;
X			break;
X
X		case 'f':	/* load font */
X			fscanf(istr, "%d %s", &fontn, str);
X			loadfont(str, fontn);
X			break;
X
X		case 's':	/* stop */
X			finish(0);
X			break;
X
X		case 'p':	/* pause */
X			break;
X
X		case 't':	/* trailer */
X			break;
X
X		case 'H':	/* character height (in points) */
X			fscanf(istr, "%f", &f);
X			if(f <= 0 || f > 1000)
X			{
X				sprintf(errbuf,
X					"Illegal character height %.1f", f);
X				error(ERR_WARN, errbuf);
X			}
X			else
X				tfp.fp_height = f;
X			break;
X
X		case 'S':
X			fscanf(istr, "%f", &f);
X			if(f < -80 || f > 80)
X			{
X				sprintf(errbuf, "Illegal character slant %.1f degrees", f);
X				error(ERR_WARN, errbuf);
X			}
X			else
X				tfp.fp_slant = f;
X			break;
X
X		default:
X			sprintf(errbuf, "Unknown device control '%s'", str);
X			error(ERR_WARN, errbuf);
X			break;
X	}
X	while((ch=getc(istr)) != '\n' && ch != EOF);	/* skip rest of input line */
X	lineno++;
X}
X
error(errtype, errmsg)
int	errtype;
char	*errmsg;
X{
X	switch(errtype)
X	{
X		case ERR_WARN:
X			fprintf(stderr, "Warning");
X			break;
X
X		case ERR_FATAL:
X			fprintf(stderr, "Error");
X			break;
X
X		case ERR_SNARK:
X			fprintf(stderr, "Snark");
X			break;
X	}
X	fprintf(stderr, "\t%s pscript input, line %d of '%s'\n",
X		errtype == ERR_SNARK ? "at" : "in",
X		lineno, ifile);
X	if(errmsg && *errmsg)
X		fprintf(stderr, "\t%s\n", errmsg);
X	if(errtype != ERR_WARN)
X		finish(1);
X}
X
finish(status)
int	status;
X{
X	page(-1);
X	pcommfinish(npages, "");
X	if(status != 0)
X		fprintf(stderr, "\t... aborted processing\n");
X	exit(status);
X}
X
X/*
X *	Output the postscript "prologue" that is the start of each program
X *	generated. This sets up definitions, sets the scale to be troff
X *	units, etc.
X *	By convention, single character variables are procedure names,
X *	while multi-character variables are local to procedures.
X */
X
char	*inittab[] = {
X	/* initialise current path to non-null */
X	"0 0 moveto",
X	/* fix to make "joined" lines better */
X	"2 setlinecap",
X	/* routine for RELATIVE HORIZONTAL RIGHT */
X	/* need no more
X	"/x { 0 rmoveto } def",
X	/* routine for RELATIVE VERTICAL DOWN */
X	"/y { neg 0 exch rmoveto } def",
X	/* routine for ABSOLUTE HORIZONTAL (rel left edge page) */
X	"/X { currentpoint exch pop moveto } def",
X	/* routine for ABSOLUTE VERTICAL (rel top of page) */
X	"/Y { pgtop exch sub currentpoint pop exch moveto } def",
X#ifdef	SPACING
X	"/s { currentpoint spacing 0 5 -1 roll ashow moveto } def",
X#else
X	"/s { show } def",
X#endif	SPACING
X	"/l { neg rlineto currentpoint stroke moveto } def",
X/* The following definitions are needed for PIC drawings. They aren't
X * neccessary if graphics comes in metafile. (27-11-86 -- axel@coma.uucp)
X */
X#ifndef GEMPRINT 
X	/* circle - arg is diameter.
X	 * Current point is left edge
X	 */
X	"/c {",
X	/* save radius and current position */
X	"2 div /rad exch def currentpoint /y0 exch def /x0 exch def",
X	/* draw circle */
X	"newpath x0 rad add y0 rad 0 360 arc stroke",
X	/* move to right edge of circle */
X	"x0 rad add rad add y0 moveto",
X	" } def",
X	/* Arc anticlockwise, currentpoint is start;
X	 * args are dx1, dy1 (centre relative to here)
X	 * and dx2, dy2 (end relative to centre).
X	 */
X	"/a {",
X	/* save all parameters */
X	"/y2 exch neg def /x2 exch def /y1 exch neg def /x1 exch def",
X	/* move to centre, push position for moveto after arc */
X	"x1 y1 rmoveto currentpoint",
X	/* push centre for args to arc */
X	"currentpoint",
X	/* calculate and push radius */
X	"x2 x2 mul y2 y2 mul add sqrt",
X	/* start angle */
X	"y1 neg x1 neg atan",
X	/* end angle */
X	"y2 x2 atan",
X	/* draw the arc, and move to end position */
X	"newpath arc stroke moveto x2 y2 rmoveto",
X	"} def",
X	/* ellipse - args are x diameter, y diameter;
X	 * current position is left edge
X	 */
X	"/e {",
X	/* save x and y radius */
X	"2 div /yrad exch def 2 div /xrad exch def",
X	/* save current position */
X	"currentpoint /y0 exch def /x0 exch def",
X	/* translate to centre of ellipse */
X	"x0 xrad add y0 translate",
X	/* scale coordinate system */
X	"xrad yrad scale",
X	/* draw the ellipse (unit circle in scaled system) */
X	"newpath 0 0 1 0 360 arc",
X	/* restore old scale + origin */
X	"savematrix setmatrix",
X	/* actually draw the ellipse (with unscaled linewidth) */
X	"stroke",
X	/* move to right of ellipse */
X	"x0 xrad add xrad add y0 moveto",
X	"} def",
X		/*
X		 * common procedure for spline curves
X		 */
X	"/spln {",
X		/* setup curve, remember where we are, fill in line,
X		** and reset current point
X		*/
X	"rcurveto currentpoint stroke moveto",
X	"} def",
X#else GEMPRINT
X"%%BeginProcSet: \"mfps-builtin-GEM-prologue\" \"(0.0)\" \"\"",
X"/Gem2PSdict 50 dict def",
X"Gem2PSdict begin",
X#ifdef GUMLAUT
X"/reencsmalldict 12 dict def",
X"/ReEncodeSmall",
X"{ reencsmalldict begin",
X"  /newcodesandnames exch def",
X"  /newfontname exch def",
X"  /basefontname exch def",
X"  /basefontdict basefontname findfont def",
X"  /newfont basefontdict maxlength dict def",
X"  basefontdict",
X"   { exch dup /FID ne",
X"    { dup /Encoding eq",
X"     { exch dup length array copy newfont 3 1 roll put }",
X"     { exch newfont 3 1 roll put }",
X"     ifelse",
X"    }",
X"    { pop pop }",
X"    ifelse",
X"   } forall",
X"  newfont /FontName newfontname put",
X"  newcodesandnames aload pop",
X"  newcodesandnames length 2 idiv",
X"   { newfont /Encoding get 3 1 roll put }",
X"   repeat",
X"  newfontname newfont definefont pop",
X"  end",
X"} def",
X"/germvec [",
X"8#204 /adieresis",
X"8#224 /odieresis",
X"8#201 /udieresis",
X"8#216 /Adieresis",
X"8#231 /Odieresis",
X"8#232 /Udieresis",
X"8#236 /germandbls",
X"] def",
X"/Times-Roman /Times-Roman-Germ germvec",
X"  ReEncodeSmall",
X"/Times-Italic /Times-Italic-Germ germvec",
X"  ReEncodeSmall",
X"/Times-Bold /Times-Bold-Germ germvec",
X"  ReEncodeSmall",
X"/Times-BoldItalic /Times-BoldItalic-Germ germvec",
X"  ReEncodeSmall",
X"/Helvetica /Helvetica-Germ germvec",
X"  ReEncodeSmall",
X"/Helvetica-Bold /Helvetica-Bold-Germ germvec",
X"  ReEncodeSmall",
X"/Helvetica-Oblique /Helvetica-Oblique-Germ germvec",
X"  ReEncodeSmall",
X"/Helvetica-BoldOblique /Helvetica-BoldOblique-Germ germvec",
X"  ReEncodeSmall",
X"/t { /Times-Roman-Germ findfont exch scalefont setfont } bind def",
X"/ti { /Times-Italic-Germ findfont exch scalefont setfont } bind def",
X"/tb { /Times-Bold-Germ findfont exch scalefont setfont } bind def",
X"/tx { /Times-BoldItalic-Germ findfont exch scalefont setfont } bind def",
X"/h { /Helvetica-Germ findfont exch scalefont setfont } bind def",
X"/hb { /Helvetica-Bold-Germ findfont exch scalefont setfont } bind def",
X"/ho { /Helvetica-Oblique-Germ findfont exch scalefont setfont } bind def",
X"/hbo { /Helvetica-BoldOblique-Germ findfont exch scalefont setfont }",
X" bind def",
X#else
X"/t { /Times-Roman findfont exch scalefont setfont } bind def",
X"/ti { /Times-Italic findfont exch scalefont setfont } bind def",
X"/tb { /Times-Bold findfont exch scalefont setfont } bind def",
X"/tx { /Times-BoldItalic findfont exch scalefont setfont } bind def",
X"/h { /Helvetica findfont exch scalefont setfont } bind def",
X"/hb { /Helvetica-Bold findfont exch scalefont setfont } bind def",
X"/ho { /Helvetica-Oblique findfont exch scalefont setfont } bind def",
X"/hbo { /Helvetica-BoldOblique findfont exch scalefont setfont } bind def",
X#endif GUMLAUT
X"/bitison",
X"{",
X"	/ybit exch def /xbit exch def",
X"	bstring ybit bwidth mul",
X"	xbit 8 idiv add get",
X"	1 7 xbit 8 mod sub bitshift",
X"	and 0 ne",
X"} bind def",
X"/setpattern",
X"{",
X"	/freq exch def",
X"	/bwidth exch def",
X"	/bpside exch def",
X"	/bstring exch def",
X"	/onbits 0 def /offbits 0 def",
X"	freq 0 {",
X"		/y exch def /x exch def",
X"		/xindex x 1 add 2 div bpside mul cvi def",
X"		/yindex y 1 add 2 div bpside mul cvi def",
X"		xindex yindex bitison",
X"		{ /onbits onbits 1 add def 1 }",
X"		{ /offbits offbits 1 add def 0 }",
X"		ifelse",
X"		} setscreen",
X"	{} settransfer",
X"	offbits offbits onbits add div setgray",
X"} bind def",
X"/mf {",
X"	statusdict begin /manualfeedtimeout 300 def ",
X"			 /manualfeed true def ",
X"		   end } bind def",
X"/af {",
X"	statusdict begin /waittimeout 5 def",
X"			 /manualfeed false def",
X"		   end } bind def",
X"/padj { transform round exch round exch itransform } bind def",
X"/ul { dup stringwidth pop 0 gsave 0.4 setlinewidth",
X"   currentpoint newpath moveto 0 -2 padj rmoveto padj rlineto",
X"   closepath stroke grestore } bind def",
X"/oshow { gsave currentpoint newpath moveto 0.2 setlinewidth false",
X"   charpath closepath stroke } bind def",
X"/wtext {",
X"  /str exch def /strwd exch def /nsp exch def /underl exch def",
X"  str stringwidth pop /pstrwd exch def",
X"  underl { gsave 0.4 setlinewidth currentpoint newpath",
X"  moveto 0 -2 padj rmoveto strwd 0 padj rlineto ",
X"  closepath stroke grestore } if",
X" nsp 0 ne",
X" { strwd pstrwd sub nsp div 0 8#040 str widthshow }",
X" { str show } ifelse",
X"} bind def",
X"/atext {",
X"  /str exch def /strwd exch def /underl exch def",
X"  str stringwidth pop /pstrwd exch def",
X"  underl { gsave 0.4 setlinewidth currentpoint newpath",
X"  moveto 0 -2 padj rmoveto strwd 0 padj rlineto",
X"  closepath stroke grestore } if",
X"  strwd pstrwd sub str length dup 1 gt { 1 sub } if div 0 str ashow",
X"} bind def",
X"/arrow {", 
X"        /leg exch def /taily exch def /tailx exch def",
X"        /tipy exch def /tipx exch def",
X"        gsave",
X"           1 setlinecap",
X"           newpath",
X"              tipx tipy translate",
X"              taily tipy sub /num exch def",
X"              tailx tipx sub /den exch def",
X"              num den eq den 0 eq and { /num 1 def } if",
X"              num den atan 16 sub rotate",
X"              leg 0 moveto 0 0 lineto",
X"              32 rotate",
X"              leg 0 lineto",
X"           closepath fill",
X"        grestore } bind def",
X"/pln { % xn yn xn-1 yn-1 .. x1 y1 n, draws a polyline with n-1 segments",
X"   /n exch def",
X"   /n n 1 sub def",
X"   padj moveto",
X"   1 1 n { pop padj lineto } for",
X"} bind def",
X"/pline {  % x1 y1 x2 y2, draws a line which is consistent with parallels",
X"   /y2 exch def /x2 exch def /y1 exch def /x1 exch def",
X"   x1 y1 padj moveto",
X"   x2 y2 padj rlineto",
X"} bind def",
X"/elip { % xscale yscale x y rad sang eang, draws an elliptical arc",
X"   /ea exch def /sa exch def /rad exch def",
X"   translate scale 0 0 rad sa ea arc",
X"   /sm 6 array def /im 6 array def /sm sm currentmatrix def",
X"   /im im defaultmatrix def sm 0 im 0 get put",
X"   sm 3 im 3 get put sm setmatrix",
X"} bind def",
X"/resetscale { /sm 6 array def /im 6 array def /sm sm currentmatrix def",
X"   /im im defaultmatrix def sm 0 im 0 get put",
X"   sm 3 im 3 get put sm setmatrix",
X"} bind def",
X#ifdef PSDEBUG
X/* Use: 'gsave ( labeltext ) X Y markpoint grestore' . Marks given point
X * with an 'x' and labels it with the supplied text. Intended for
X * Debugging 
X */
X"/markpoint { newpath moveto currentpoint 3 -1 roll",
X"   /Helvetica findfont 10 scalefont setfont dup stringwidth pop 2 add 0",
X"   rmoveto",
X"   show moveto 3 3 rmoveto -6 -6 rlineto 0 6 rmoveto 6 -6 rlineto",
X"   stroke } bind def",
X#endif
X"end",   /* end of Gem2PSdict initialization */
X"%%EndProcSet",
X#endif GEMPRINT
X#ifdef GERMAN
X 	/* routine to modify fonts */
X 	"/reencsmalldict 12 dict def",
X 	  "/ReEncodeSmall",
X 	    "{ reencsmalldict begin",
X 	    "  /newcodesandnames exch def",
X 	    "  /newfontname exch def",
X 	    "  /basefontname exch def",
X 	    "  /basefontdict basefontname findfont def",
X 	    "  /newfont basefontdict maxlength dict def",
X 	    "  basefontdict",
X 	    "   { exch dup /FID ne",
X 	    "    { dup /Encoding eq",
X 	    "     { exch dup length array copy newfont 3 1 roll put }",
X 	    "     { exch newfont 3 1 roll put }",
X 	    "     ifelse",
X 	    "    }",
X 	    "    { pop pop }",
X 	    "    ifelse",
X 	    "   } forall",
X 	    "  newfont /FontName newfontname put",
X 	    "  newcodesandnames aload pop",
X 	    "  newcodesandnames length 2 idiv",
X 	    "   { newfont /Encoding get 3 1 roll put }",
X 	    "   repeat",
X 	    "  newfontname newfont definefont pop",
X 	    "  end",
X 	    "} def",
X 	    /* Vector for additional german characters */
X 	    "/germvec [",
X 	    "8#321 /adieresis",
X 	    "8#322 /odieresis",
X 	    "8#323 /udieresis",
X 	    "8#324 /Adieresis",
X 	    "8#325 /Odieresis",
X	    "8#326 /Udieresis",
X 	    "] def",
X 	/* Define German fonts */
X 	"/Times-Roman /Times-Roman-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Times-Italic /Times-Italic-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Times-Bold /Times-Bold-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Times-BoldItalic /Times-BoldItalic-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Helvetica /Helvetica-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Helvetica-Bold /Helvetica-Bold-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Helvetica-Oblique /Helvetica-Oblique-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Helvetica-BoldOblique /Helvetica-BoldOblique-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Courier /Courier-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Courier-Bold /Courier-Bold-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Courier-Oblique /Courier-Oblique-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Courier-BoldOblique /Courier-BoldOblique-Germ germvec",
X 	"  ReEncodeSmall",
X#ifdef XFONTS
X 	"/Bookman-Light /Bookman-Light-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Bookman-LightItalic /Bookman-LightItalic-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Bookman-Demi /Bookman-Demi-Germ germvec",
X 	"  ReEncodeSmall",
X 	"/Bookman-DemiItalic /Bookman-DemiItalic-Germ germvec",
X 	"  ReEncodeSmall",
X#endif XFONTS
X#endif GERMAN
X	/* routine to select a font */
X	"/ft { /fonttype exch def /xsiz exch def /ysiz exch def /sl exch def",
X	" fonttype [ xsiz pt 0 sl sin sl cos div ysiz pt mul ysiz pt 0 0 ]",
X	" makefont setfont",
X#ifndef GEMPRINT
X	/* point size also affects linewidth (see Pic user manual, p. 17) */
X	" xsiz 1.7 div setlinewidth } def",
X#else
X	/* this seems to be of no use, if pictures are derived from a
X	 * GEM-Metafile (axel@coma, 3-Nov-86) */
X	"} def",
X#endif
X	(char *) 0 };
X
X
devinit()
X{
X	register char	**ptab;
X	register int	i;
X
X	/* postscript basic units are "1/PU_INCH" inches.
X	 * Normally PU_INCH=72, making postscript units points (1/72 inch)
X	 * Scale postscript to accept whatever resolution we are given
X	 * Typically res=300 for a 300 dot/inch laser printer
X	 */
X	pcomminit(PU_INCH / (float) res, rotation, papertype, manualfeed, 0,
X		(char *)0, "troff->tpscript");
X	ptab = inittab;
X	while(*ptab)
X		fprintf(postr, "%s\n", *ptab++);
X	/* conversion back to points for font sizes etc. */
X	fprintf(postr, "/pt { %d mul } def\n", respunits);
X
X#if	defined(UQMINMET) && !defined(ALW)
X			/* to compensate for "setmargins" */
X	fprintf( postr, "\n-90 230 translate\n" );
X#endif
X	/* All graphics transformations have been done. Save the
X	 * transformation matrix
X	 */
X	fprintf(postr, "/savematrix matrix currentmatrix def\n");
X#ifdef SPACING
X	/* set increased character spacing (if any) */
X	fprintf(postr, "/spacing %.1f pt def\n", spacing);
X#endif SPACING
X
X	s2init();	/* initialise special font 2 */
X
X	/* set up font abbreviations */
X	for(i=1; i<nfonts+1; i++)
X		fprintf(postr, "/f.%s /%s findfont def\n",
X			fontd[i].f_extname, fontd[i].f_intname);
X	/* select default current font */
X	tfp.fp_size = DEF_SIZE;
X	tfp.fp_height = (float) DEF_SIZE;
X	tfp.fp_slant = 0;
X	tfp.fp_font = &fontd[DEF_FONT];
X	pfp.fp_font = (struct fontdesc *) NULL;
X	setfont(FALSE);
X
X	/* save state */
X	endinit();
X}
X
X
X/*
X *	Called when some use of characters or line-drawing
X *	is about to be made, to ensure that the correct font and
X *	line thickness is selected in postscript.
X */
setfont(force)
bool	force;
X{
X
X	if(tfp.fp_size == pfp.fp_size &&
X		tfp.fp_height == pfp.fp_height &&
X		tfp.fp_slant == pfp.fp_slant &&
X		tfp.fp_font == pfp.fp_font &&
X		! force)
X		return;
X	CLOSEWORD();
X	fprintf(postr, "\n%.1f %.0f %d f.%s ft",
X		tfp.fp_slant,
X		tfp.fp_height, tfp.fp_size,
X		tfp.fp_font->f_extname);
X	pfp = tfp;
X}
X
draw(istr)
XFILE	*istr;
X{
X	int	ch;
X	int	x, y,
X		x1, y1,
X		d;
X
X	setfont( FALSE );	/* in case of size change affecting line thickness */
X
X	switch(ch=getc(istr))
X	{
X		case 'l':
X			fscanf(istr, "%d %d", &x, &y);
X			fprintf(postr, "\n%d %d l", x, y);
X			break;
X
X		case 'c':
X			fscanf(istr, "%d", &d);
X			fprintf(postr, "\n%d c", d);
X			break;
X
X		case 'e':
X			fscanf(istr, "%d %d", &x, &y);
X			fprintf(postr, "\n%d %d e", x, y);
X			break;
X
X		case 'a':
X			fscanf(istr, "%d %d %d %d", &x, &y, &x1, &y1);
X			fprintf(postr, "\n%d %d %d %d a", x, y, x1, y1);
X			break;
X
X		case '~':
X			draw_spline( istr );
X			break;
X
X		default:
X			sprintf(errbuf, "Illegal draw function '%c'", ch);
X			error(ERR_WARN, errbuf);
X			break;
X	}
X	while((ch=getc(istr)) != '\n' && ch != EOF);
X	lineno++;
X}
X
X
text(istr)
XFILE	*istr;
X{
X	register int	ch;
X
X	fprintf(postr, "\n(");
X	while((ch=getc(istr)) != '\n' && ch != EOF)
X		pch(ch);
X	fprintf(postr, ")s");
X}
X
page(n)
register int	n;
X{
X	hpos = 0; vpos = 0;
X	/* for each page except the first, print the previous one */
X	if(firstpage)
X		firstpage = FALSE;
X	else
X	{
X		fprintf(postr, "\npage");
X		setfont(TRUE);
X		resetspcl();		/* it forgets definitions on next page */
X	}
X	if(n >= 0)		/* beginning of a new page */
X		fprintf(postr, "\n%%%%Page: %d %d\n", n, ++npages);
X}
X
hgoto()
X{
X	CLOSEWORD();
X	width_pending = 0;	/* doesn't matter now */
X	fprintf(postr, "\n%d X", hpos);
X}
X
vgoto( )
X{
X	CLOSEWORD();
X	fprintf(postr, "\n%d Y", vpos);
X}
X
vmot(n)
int	n;	/* +'ve is DOWN */
X{
X	CLOSEWORD();
X	fprintf(postr, "\n%d y", n);
X	vpos += n;
X}
X
X/*
X *	Read the DESC file for the current device. This includes
X *	information about all the common fonts. The format is:
X *
X *		struct dev	(see dev.h)
X *		point size table	(dev.nsizes * sizeof(short))
X *		char index table	(chtab; dev.nchtab * sizeof(short))
X *		char name table		(chname; dev.lchname)
X *
X *	followed by dev.nfonts occurrences of	
X *		struct font	(see dev.h)
X *		width tables		(font.nwfont)
X *		kern tables		(font.nwfont)
X *		code tables		(font.nwfont)
X *		font index table	(dev.nchtab + NASCPRINT)
X */
X
initfonts(devname)
char	*devname;
X{
X	register int			i;
X	register struct fontdesc	*fd;
X	FILE				*fstr;
X	char				path[100];
X
X	sprintf(path, "%s/dev%s/DESC.out", fontdir, devname);
X	if((fstr=fopen(path, "r")) == NULL)
X	{
X		sprintf(errbuf, "Can't open '%s' (%s)",
X			path, sys_errlist[errno]);
X		error(ERR_FATAL, errbuf);
X	}
X	if(efread((char *)&dev, sizeof(dev), 1, fstr) != 1)
X	{
X		sprintf(errbuf, "%s: bad format (read dev failed)", path);
X		error(ERR_SNARK, errbuf);
X	}
X
X	nfonts = dev.nfonts;
X	/* nfontmount should be at least nfonts+2 */
X	nfontmount = nfonts + 20;
X	ncharname = dev.nchtab;
X	fontd = (struct fontdesc *)
X			emalloc((unsigned)(nfonts+2) * sizeof(struct fontdesc));
X	fontmount = (struct fontdesc **)
X			emalloc((unsigned)nfontmount * sizeof(struct fontdesc *));
X
X	/* skip point size table */
X	efseek(fstr, (int)((dev.nsizes + 1)*sizeof(short)));
X
X	chartab = (short *) emalloc((unsigned)ncharname * sizeof(short));
X	efread((char *)chartab, sizeof(* chartab), ncharname, fstr);
X
X	charname = emalloc((unsigned)dev.lchname);
X	efread(charname, sizeof(* charname), dev.lchname, fstr);
X
X	hash_init();
X
X	for(i=1; i <= nfonts; i++)
X	{
X		register int			nw;
X		struct font			f;
X		struct fontmap			*fm;
X
X		/* read struct font header */
X		efread((char *)&f, sizeof(f), 1, fstr);
X
X		nw = (int)(f.nwfont & BMASK);	/* NO sign extension */
X		fd = &fontd[i];
X		fd->f_nent = nw;
X
X		fd->f_widthtab = emalloc((unsigned)nw);
X		fd->f_codetab = emalloc((unsigned)nw);
X		fd->f_fitab = emalloc((unsigned)(ncharname+NASCPRINT));
X		/* remember if font is special */
X		if(f.specfont == 1)
X		{
X			if(spcfnt1 == NOFONTDESC )
X				spcfnt1 = fd;
X			else if ( spcfnt2 == NOFONTDESC )
X				spcfnt2 = fd;
X			else
X			{
X				sprintf( errbuf,
X					"Too many special fonts, %s ignored",
X					fd->f_extname );
X				error(ERR_WARN, errbuf );
X			}
X		}
X
X		fm = getfmap(f.namefont);
X		if(fm)
X		{
X			fd->f_intname = fm->fm_intname;
X			fd->f_extname = fm->fm_extname;
X			fd->f_mounted = TRUE;
X		}
X		else
X			fprintf(stderr, "font name '%s' not known\n",
X				f.namefont);
X
X		efread(fd->f_widthtab, sizeof(char), nw, fstr);
X		efseek(fstr, 1*nw);	/* skip kern tables */
X		efread(fd->f_codetab, sizeof(char), nw, fstr);
X		efread(fd->f_fitab, sizeof(char), ncharname+NASCPRINT, fstr);
X	}
X
X	fclose(fstr);
X
X	for(i=0; i < nfontmount; i++)
X		fontmount[i] = NOFONTDESC;
X
X	/* zeroth font desc entry reserved for "extra" fonts */
X	fd = &fontd[0];
X	fd->f_intname = "";	/* not NULL */
X	fd->f_extname = "";	/* not NULL */
X	fd->f_codetab = emalloc((unsigned)MAXCHARS);
X	fd->f_fitab = emalloc((unsigned)(ncharname+NASCPRINT));
X	fd->f_nent = MAXCHARS;
X
X	/* sentinel fontdesc entry */
X	fd = &fontd[nfonts+1];
X	fd->f_intname = (char *)NULL;
X	fd->f_extname = (char *)NULL;
X	fd->f_nent = 0;
X	fd->f_codetab = (char *)NULL;
X	fd->f_fitab = (char *)NULL;
X}
X
loadfont(extname, fpos)
char	*extname;	/* troff font name */
int	fpos;		/* font position */
X{
X	register struct fontdesc	*font;
X
X	if(fpos > nfontmount || fpos < 0)
X	{
X		sprintf(errbuf, "Illegal font mount position %d\n", fpos);
X		error(ERR_WARN, errbuf);
X		return;
X	}
X	if ( (font = findfont(extname)) == (struct fontdesc *) NULL )
X	{
X		sprintf(errbuf, "No such font '%s'\n", extname);
X		error(ERR_WARN, errbuf);
X		return;
X	}
X	fontmount[fpos] = font;
X}
X
struct fontmap *
getfmap(extname)
char	*extname;
X{
X	struct fontmap	*fm;
X
X	fm = fontmap;
X	while(fm->fm_intname && strcmp(fm->fm_extname, extname) != 0)
X		fm++;
X	if(fm->fm_intname)
X		return(fm);
X	else
X		return((struct fontmap *)NULL);
X}
X
X#ifndef	UQMINMET
X
struct fontdesc *
findfont(extname)
char	*extname;
X{
X	struct fontdesc	*fd;
X
X	fd = fontd;
X	while(fd->f_intname && strcmp(fd->f_extname, extname) != 0)
X		fd++;
X	if(fd->f_intname)
X		return(fd);
X	else
X		return((struct fontdesc *)NULL);
X}
X
X#else	UQMINMET
X		/*
X		 * find font including from possible synonym
X		 * - use internal name instead of troff name.
X		 * troff names need not uniquely correspond to a given
X		 * internal name
X		 */
struct fontdesc *
findfont(extname)
char	*extname;
X{
X	struct fontmap	*fm;
X	struct fontdesc	*fd;
X
X	if ( (fm = getfmap( extname )) == (struct fontmap *)NULL )
X		return((struct fontdesc *)NULL);
X	fd = fontd;
X	while(fd->f_intname && strcmp(fd->f_intname, fm->fm_intname) != 0)
X		fd++;
X	if(fd->f_intname)
X		return(fd);
X	else
X		return((struct fontdesc *)NULL);
X}
X#endif UQMINMET
X
char *
emalloc(size)
unsigned size;
X{
X	char		*malloc();
X	register char	*s;
X
X	s = malloc(size);
X	if(s == NULL)
X	{
X		fprintf(stderr, "Ran out of memory allocating %u bytes\n",
X			size);
X		finish(1);
X	}
X	return(s);
X}
X
efread(buf, size, nel, istr)
char	*buf;
int	size,
X	nel;
XFILE	*istr;
X{
X	register int n;
X
X	if((n=fread(buf, size, nel, istr)) != nel)
X		fprintf(stderr, "Bad format font file\n");
X	return(n);
X}
X
efseek(istr, offset)
XFILE	*istr;
int	offset;
X{
X	if(fseek(istr, (long)offset, 1) != 0)
X		fprintf(stderr, "Snark: Bad seek on font file\n");
X}
X
X
putch(ch)
int	ch;
X{
X	setfont(FALSE);	/* ensure correct font */
X
X	if ( word_started == FALSE ) {
X		word_started = TRUE;
X		putc('(', postr);
X	}
X	pch(ch);
X}
END_OF_FILE
if test 36974 -ne `wc -c <'./tpscript/tpscript.c'`; then
    echo shar: \"'./tpscript/tpscript.c'\" unpacked with wrong size!
fi
# end of './tpscript/tpscript.c'
fi
echo shar: End of archive 5 \(of 5\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.