[comp.sources.misc] v02i101: ditroff to DVI filter - ditdvi

ken@rochester.UUCP (Ken Yap) (04/21/88)

comp.sources.misc: Volume 2, Issue 101
Submitted-By: "Ken Yap" <ken@rochester.UUCP>
Archive-Name: ditdvi

I'm sick of this kid. Out the door it goes.

	Ken

#!/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
#	Makefile
#	cmbx10
#	cmmi10
#	cmr10
#	cmss10
#	cmssbx10
#	cmssi10
#	cmsy10
#	cmti10
#	cmtt10
#	ditdvi.1
#	ditdvi.c
#	ditdvi.h
#	dvi.c
#	dvi.h
#	fontfile.c
#	getspecials
#	reader.c
#	tfm2desc.1
#	tfm2desc.c
# This archive created: Tue Apr 19 19:06:41 1988
# By:	Ken Yap ()
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(4022 characters)'
if test -f 'README'
then
	echo shar: over-writing existing file "'README'"
fi
cat << \SHAR_EOF > 'README'
These are the sources for a ditroff (not troff) to TeX DVI converter.
I wrote this on a lark and to learn DVI format. Some reasons why you
may want this:

+ Your high resolution printer accepts DVI but you don't have a ditroff
filter for it.

+ You want to access the wide range of characters in TeX fonts.

+ You want to create weird and wonderful fonts for ditroff with METAFONT.

+ You have only a DVI previewer.

+ You want to standardize on one type of output.

+ You want to give the operator of a non-Unix machine a fit by printing
a Unix man page on the DVI printer.

+ (Put your own reason here.)

It works pretty well and I have printed tens of pages of documentation
with it.

You may do whatever you like with the source, except make money out of
it (because I gave it to you for free to begin with).  Do leave my name
in this documentation.

How it works:

Edit Makefile to specify where the TeX tfm files live and where ditroff
expects to find the binary tables.

The files cm* define the fonts of a virtual printer called dvi.  You
run the program tfm2desc to generate font tables in the files R, I, B,
etc. See the man page for tfm2desc and the Makefile entry for metrics
for flags to tfm2desc.  Make all, then run makedev (in your ditroff
distribution, not supplied here) or a PD version of that to make binary
font tables for ditroff.  Install these binary tables in a subdirectory
called devdvi near where ditroff expects to find other tables.

If you want to add fonts, make up more cm* description files and edit
Makefile to add the font names. You have to estimate the spacewidth
passed to tfm2desc. I use half of the width of a digit.  cmss isn't
really Helvetica, just sort of sans serif.

The resolution of this virtual printer is irrelevant so I've set it at
576 (8*72). You can change this in the Makefile.  You must choose a
unitwidth such that all the character widths are under 256, because
ditroff stores the widths in single bytes. The roundoff error will be
minimized if the widths are as large as possible.  Fortunately for
ditroff, the resolution of DVI files is much higher than anything
ditroff can comprehend. (1 / 2^16 of a point, if you are curious.)

Sizes 10 and below are translated to TeX fonts at their respective
design size. Above that, magnification is used. Hence the code to
translate size to magnification in reader.c. Most TeX fonts follow this
pattern of availability. Unfortunately the SIZES macro in the Makefile
isn't all you have to change if you want to add more sizes. You also
have to edit the switch statement in reader.c and make sure you have
the fonts in the right design size and magnification.

Note that if you don't have a font of the right size, you don't find
out until you try to print the DVI file, or convert it to your printer
language.

There is no room for the spaces or rule characters in the TeX character
set, so I've put spaces at 0200 and the rule at 0201. The constant 0201
is hacked into tfm2desc and ditdvi. Sorry.

I haven't tried out how well extended parens, brackets and braces are
drawn with eqn.

Drawing functions are not implemented. You can translate these to tpic
generated \specials. I'm too lazy.

Some special characters must be provided to ditroff or it will have a
fit or at least drop your characters silently.  These include hyphen
(hy), mathtimes (**), vertical bar (bv), the spaces and rule. The whole
sordid story can be read in "Adventures with Typesetter Independent
Troff" by Moore and Kahrs, TR 159, June 1985, Computer Science Dept.,
U. of Rochester.  It's fascinating how much knowledge of the special
fonts is still hardwired into ditroff.

There is one potential bug in fontfile.c. A pointer to a table of
shorts may be non-word aligned. Some machines don't like this.  You
need to do a block copy to malloc'ed memory. Again, I was lazy.

If you have old troff, my condolences. Have fun.

You can send me bug reports but I'm not too motivated to do much about
them.

	Ken Yap
	ken@cs.rochester.edu
	April 1988
SHAR_EOF
if test 4022 -ne "`wc -c 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 4022 characters)'
fi
echo shar: extracting "'Makefile'" '(1609 characters)'
if test -f 'Makefile'
then
	echo shar: over-writing existing file "'Makefile'"
fi
cat << \SHAR_EOF > 'Makefile'
CFLAGS		= -g -DRESOLUTION=$(RESOLUTION) -DFONTDIR=\"$(FONTDIR)\" -DTEXFONT=\"$(TEXFONT)\"

RESOLUTION	= 576
UNITWIDTH	= 24
FONTS		= R I B H HB HI C M S
SIZES		= 5 6 7 8 9 10 11 12 14 17 24 25 0

FONTDIR		= /u/ken/lib/ditdvi
TEXFONT		= /usr/lib/tex/fonts/

all:		tfm2desc ditdvi metrics descfile

ditdvi:		ditdvi.o reader.o dvi.o fontfile.o
		$(CC) $(LDFLAGS) $(CFLAGS) -o $@ ditdvi.o reader.o dvi.o fontfile.o

ditdvi.o:	ditdvi.c ditdvi.h

reader.o:	reader.c ditdvi.h

dvi.o:		dvi.c dvi.h

fontfile.o:	fontfile.c ditdvi.h

tfm2desc.o:	tfm2desc.c

tfm2desc:	tfm2desc.o
		$(CC) $(LDFLAGS) $(CFLAGS) -o $@ tfm2desc.o

metrics:	tfm2desc
		tfm2desc -d$(UNITWIDTH) -s48 cmr10 > R
		tfm2desc -d$(UNITWIDTH) -s55 cmbx10 > B
		tfm2desc -d$(UNITWIDTH) -s49 cmti10 > I
		tfm2desc -d$(UNITWIDTH) -s48 cmss10 > H
		tfm2desc -d$(UNITWIDTH) -s53 cmssbx10 > HB
		tfm2desc -d$(UNITWIDTH) -s49 cmssi10 > HI
		tfm2desc -d$(UNITWIDTH) -s101 cmtt10 m > C
		tfm2desc -d$(UNITWIDTH) -s48 cmmi10 s > M
		tfm2desc -d$(UNITWIDTH) -s48 cmsy10 s > S

#
#	mc is a local program that does multicolumn
#	you can figure out something with awk, I'm sure
#
descfile:
		echo '# ditroff device description for TeX' > DESC
		echo fonts `echo $(FONTS) | wc -w` $(FONTS) >> DESC
		echo sizes $(SIZES) >> DESC
		echo res $(RESOLUTION) >> DESC
		echo hor 1 >> DESC
		echo vert 1 >> DESC
		echo unitwidth $(UNITWIDTH) >> DESC
		echo paperwidth `expr $(RESOLUTION) \* 17 / 2` >> DESC
		echo paperlength `expr $(RESOLUTION) \* 11` >> DESC
		echo charset >> DESC
		getspecials | mc >> DESC

backup:
		cd ..; ctar Ditdvi | rsh can 'cd Src/Text/TeX; vtar'
SHAR_EOF
if test 1609 -ne "`wc -c 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 1609 characters)'
fi
echo shar: extracting "'cmbx10'" '(874 characters)'
if test -f 'cmbx10'
then
	echo shar: over-writing existing file "'cmbx10'"
fi
cat << \SHAR_EOF > 'cmbx10'
B
000	*G
001	*D
002	*H
003	*L
004	*C
005	*P
006	*S
007	*U
010	*F
011	*Q
012	*W
013	ff
014	fi
015	fl
016	Fi
017	Fl
020	ui
021	uj
022	\`
022	ga
023	\'
023	aa
024	hc
025	be
026	ma
027	ri
030	cd
031	ss
032	ae
033	oe
034	o/
035	AE
036	OE
037	O/
041	!
042	"
042	rq
043	#
044	$
045	%
046	&
047	'
050	(
051	)
052	*
053	+
054	,
055	-
055	\-
055	hy
056	.
057	/
060	0
061	1
062	2
063	3
064	4
065	5
066	6
067	7
070	8
071	9
072	:
073	;
074	!!
074	I!
075	=
076	I?
077	?
100	@
101	A
102	B
103	C
104	D
105	E
106	F
107	G
110	H
111	I
112	J
113	K
114	L
115	M
116	N
117	O
120	P
121	Q
122	R
123	S
124	T
125	U
126	V
127	W
130	X
131	Y
132	Z
133	[
134	lq
135	]
136	^
137	dt
140	`
141	a
142	b
143	c
144	d
145	e
146	f
147	g
150	h
151	i
152	j
153	k
154	l
155	m
156	n
157	o
160	p
161	q
162	r
163	s
164	t
165	u
166	v
167	w
170	x
171	y
172	z
173	en
174	em
175	''
176	~
177	..
177	um
200	\&
200	\|
200	\^
SHAR_EOF
if test 874 -ne "`wc -c 'cmbx10'`"
then
	echo shar: error transmitting "'cmbx10'" '(should have been 874 characters)'
fi
echo shar: extracting "'cmmi10'" '(766 characters)'
if test -f 'cmmi10'
then
	echo shar: over-writing existing file "'cmmi10'"
fi
cat << \SHAR_EOF > 'cmmi10'
M
000	*G
001	*D
002	*H
003	*L
004	*C
005	*P
006	*S
007	*U
010	*F
011	*Q
012	*W
013	*a
014	*b
015	*g
016	*d
017	*e
020	*z
021	*y
022	*h
023	*i
024	*k
025	*l
026	*m
027	*n
030	*c
031	*p
032	*r
033	*s
034	*t
035	*u
036	*f
037	*x
040	*q
041	*w
042	Ve
043	Vh
044	Vp
045	Vr
046	ts
047	Vf
060	0
061	1
062	2
063	3
064	4
065	5
066	6
067	7
070	8
071	9
072	.
073	,
074	<
075	/
076	>
077	*
100	pd
101	A
102	B
103	C
104	D
105	E
106	F
107	G
110	H
111	I
112	J
113	K
114	L
115	M
116	N
117	O
120	P
121	Q
122	R
123	S
124	T
125	U
126	V
127	W
130	X
131	Y
132	Z
140	li
141	a
142	b
143	c
144	d
145	e
146	f
147	g
150	h
151	i
152	j
153	k
154	l
155	m
156	n
157	o
160	p
161	q
162	r
163	s
164	t
165	u
166	v
167	w
170	x
171	y
172	z
173	ui
174	uj
177	cp
200	\&
200	\|
200	\^
201	ru
201	_
201	\_
SHAR_EOF
if test 766 -ne "`wc -c 'cmmi10'`"
then
	echo shar: error transmitting "'cmmi10'" '(should have been 766 characters)'
fi
echo shar: extracting "'cmr10'" '(874 characters)'
if test -f 'cmr10'
then
	echo shar: over-writing existing file "'cmr10'"
fi
cat << \SHAR_EOF > 'cmr10'
R
000	*G
001	*D
002	*H
003	*L
004	*C
005	*P
006	*S
007	*U
010	*F
011	*Q
012	*W
013	ff
014	fi
015	fl
016	Fi
017	Fl
020	ui
021	uj
022	\`
022	ga
023	\'
023	aa
024	hc
025	be
026	ma
027	ri
030	cd
031	ss
032	ae
033	oe
034	o/
035	AE
036	OE
037	O/
041	!
042	"
042	rq
043	#
044	$
045	%
046	&
047	'
050	(
051	)
052	*
053	+
054	,
055	-
055	\-
055	hy
056	.
057	/
060	0
061	1
062	2
063	3
064	4
065	5
066	6
067	7
070	8
071	9
072	:
073	;
074	!!
074	I!
075	=
076	I?
077	?
100	@
101	A
102	B
103	C
104	D
105	E
106	F
107	G
110	H
111	I
112	J
113	K
114	L
115	M
116	N
117	O
120	P
121	Q
122	R
123	S
124	T
125	U
126	V
127	W
130	X
131	Y
132	Z
133	[
134	lq
135	]
136	^
137	dt
140	`
141	a
142	b
143	c
144	d
145	e
146	f
147	g
150	h
151	i
152	j
153	k
154	l
155	m
156	n
157	o
160	p
161	q
162	r
163	s
164	t
165	u
166	v
167	w
170	x
171	y
172	z
173	en
174	em
175	''
176	~
177	..
177	um
200	\&
200	\|
200	\^
SHAR_EOF
if test 874 -ne "`wc -c 'cmr10'`"
then
	echo shar: error transmitting "'cmr10'" '(should have been 874 characters)'
fi
echo shar: extracting "'cmss10'" '(874 characters)'
if test -f 'cmss10'
then
	echo shar: over-writing existing file "'cmss10'"
fi
cat << \SHAR_EOF > 'cmss10'
H
000	*G
001	*D
002	*H
003	*L
004	*C
005	*P
006	*S
007	*U
010	*F
011	*Q
012	*W
013	ff
014	fi
015	fl
016	Fi
017	Fl
020	ui
021	uj
022	\`
022	ga
023	\'
023	aa
024	hc
025	be
026	ma
027	ri
030	cd
031	ss
032	ae
033	oe
034	o/
035	AE
036	OE
037	O/
041	!
042	"
042	rq
043	#
044	$
045	%
046	&
047	'
050	(
051	)
052	*
053	+
054	,
055	-
055	\-
055	hy
056	.
057	/
060	0
061	1
062	2
063	3
064	4
065	5
066	6
067	7
070	8
071	9
072	:
073	;
074	!!
074	I!
075	=
076	I?
077	?
100	@
101	A
102	B
103	C
104	D
105	E
106	F
107	G
110	H
111	I
112	J
113	K
114	L
115	M
116	N
117	O
120	P
121	Q
122	R
123	S
124	T
125	U
126	V
127	W
130	X
131	Y
132	Z
133	[
134	lq
135	]
136	^
137	dt
140	`
141	a
142	b
143	c
144	d
145	e
146	f
147	g
150	h
151	i
152	j
153	k
154	l
155	m
156	n
157	o
160	p
161	q
162	r
163	s
164	t
165	u
166	v
167	w
170	x
171	y
172	z
173	en
174	em
175	''
176	~
177	..
177	um
200	\&
200	\|
200	\^
SHAR_EOF
if test 874 -ne "`wc -c 'cmss10'`"
then
	echo shar: error transmitting "'cmss10'" '(should have been 874 characters)'
fi
echo shar: extracting "'cmssbx10'" '(875 characters)'
if test -f 'cmssbx10'
then
	echo shar: over-writing existing file "'cmssbx10'"
fi
cat << \SHAR_EOF > 'cmssbx10'
HB
000	*G
001	*D
002	*H
003	*L
004	*C
005	*P
006	*S
007	*U
010	*F
011	*Q
012	*W
013	ff
014	fi
015	fl
016	Fi
017	Fl
020	ui
021	uj
022	\`
022	ga
023	\'
023	aa
024	hc
025	be
026	ma
027	ri
030	cd
031	ss
032	ae
033	oe
034	o/
035	AE
036	OE
037	O/
041	!
042	"
042	rq
043	#
044	$
045	%
046	&
047	'
050	(
051	)
052	*
053	+
054	,
055	-
055	\-
055	hy
056	.
057	/
060	0
061	1
062	2
063	3
064	4
065	5
066	6
067	7
070	8
071	9
072	:
073	;
074	!!
074	I!
075	=
076	I?
077	?
100	@
101	A
102	B
103	C
104	D
105	E
106	F
107	G
110	H
111	I
112	J
113	K
114	L
115	M
116	N
117	O
120	P
121	Q
122	R
123	S
124	T
125	U
126	V
127	W
130	X
131	Y
132	Z
133	[
134	lq
135	]
136	^
137	dt
140	`
141	a
142	b
143	c
144	d
145	e
146	f
147	g
150	h
151	i
152	j
153	k
154	l
155	m
156	n
157	o
160	p
161	q
162	r
163	s
164	t
165	u
166	v
167	w
170	x
171	y
172	z
173	en
174	em
175	''
176	~
177	..
177	um
200	\&
200	\|
200	\^
SHAR_EOF
if test 875 -ne "`wc -c 'cmssbx10'`"
then
	echo shar: error transmitting "'cmssbx10'" '(should have been 875 characters)'
fi
echo shar: extracting "'cmssi10'" '(897 characters)'
if test -f 'cmssi10'
then
	echo shar: over-writing existing file "'cmssi10'"
fi
cat << \SHAR_EOF > 'cmssi10'
HI
000	*G
001	*D
002	*H
003	*L
004	*C
005	*P
006	*S
007	*U
010	*F
011	*Q
012	*W
013	ff
014	fi
015	fl
016	Fi
017	Fl
020	ui
021	uj
022	\`
022	ga
023	\'
023	aa
024	hc
025	be
026	ma
027	ri
030	cd
031	ss
032	ae
033	oe
034	o/
035	AE
036	OE
037	O/
041	!
042	"
042	rq
043	#
044	po
044	ps
045	%
046	&
047	'
050	(
051	)
052	*
053	+
053	pl
054	,
055	-
055	\-
055	hy
056	.
057	/
060	0
061	1
062	2
063	3
064	4
065	5
066	6
067	7
070	8
071	9
072	:
073	;
074	!!
074	I!
075	=
075	eq
076	I?
077	?
100	@
101	A
102	B
103	C
104	D
105	E
106	F
107	G
110	H
111	I
112	J
113	K
114	L
115	M
116	N
117	O
120	P
121	Q
122	R
123	S
124	T
125	U
126	V
127	W
130	X
131	Y
132	Z
133	[
134	lq
135	]
136	^
137	dt
140	`
141	a
142	b
143	c
144	d
145	e
146	f
147	g
150	h
151	i
152	j
153	k
154	l
155	m
156	n
157	o
160	p
161	q
162	r
163	s
164	t
165	u
166	v
167	w
170	x
171	y
172	z
173	en
174	em
175	''
176	~
177	..
177	um
200	\&
200	\|
200	\^
SHAR_EOF
if test 897 -ne "`wc -c 'cmssi10'`"
then
	echo shar: error transmitting "'cmssi10'" '(should have been 897 characters)'
fi
echo shar: extracting "'cmsy10'" '(809 characters)'
if test -f 'cmsy10'
then
	echo shar: over-writing existing file "'cmsy10'"
fi
cat << \SHAR_EOF > 'cmsy10'
S
000	mi
001	m.
002	mu
003	**
004	di
005	dm
006	+-
007	-+
010	a+
011	a-
012	ax
013	a/
015	ci
016	mc
017	bu
021	==
022	ib
023	ip
024	<=
025	>=
030	ap
031	~~
032	sb
033	sp
034	<<
035	>>
036	l<
037	r>
040	<-
041	->
042	ua
043	da
044	<>
045	NE
046	SE
047	~=
050	<:
051	:>
051	im
055	NW
056	SW
057	pt
061	if
062	mo
063	cm
064	tr
066	sl
070	fa
071	te
072	no
073	es
074	R#
075	I#
076	to
077	bt
100	al
101	A
102	B
103	C
104	D
105	E
106	F
107	G
110	H
111	I
112	J
113	K
114	L
115	M
116	N
117	O
120	P
121	Q
122	R
123	S
124	T
125	U
126	V
127	W
130	X
131	Y
132	X
133	cu
134	ca
136	an
137	\/
137	lo
140	|-
140	st
141	-|
142	lf
143	rf
144	lc
145	rc
146	{
147	}
150	<
151	>
152	|
152	or
152	bv
153	||
156	\
160	sr
162	gr
163	is
170	sc
171	dg
172	dd
173	pp
174	cS
175	dS
176	hS
177	sS
200	\&
200	\|
200	\^
201	ru
201	_
201	\_
SHAR_EOF
if test 809 -ne "`wc -c 'cmsy10'`"
then
	echo shar: error transmitting "'cmsy10'" '(should have been 809 characters)'
fi
echo shar: extracting "'cmti10'" '(896 characters)'
if test -f 'cmti10'
then
	echo shar: over-writing existing file "'cmti10'"
fi
cat << \SHAR_EOF > 'cmti10'
I
000	*G
001	*D
002	*H
003	*L
004	*C
005	*P
006	*S
007	*U
010	*F
011	*Q
012	*W
013	ff
014	fi
015	fl
016	Fi
017	Fl
020	ui
021	uj
022	\`
022	ga
023	\'
023	aa
024	hc
025	be
026	ma
027	ri
030	cd
031	ss
032	ae
033	oe
034	o/
035	AE
036	OE
037	O/
041	!
042	"
042	rq
043	#
044	po
044	ps
045	%
046	&
047	'
050	(
051	)
052	*
053	+
053	pl
054	,
055	-
055	\-
055	hy
056	.
057	/
060	0
061	1
062	2
063	3
064	4
065	5
066	6
067	7
070	8
071	9
072	:
073	;
074	!!
074	I!
075	=
075	eq
076	I?
077	?
100	@
101	A
102	B
103	C
104	D
105	E
106	F
107	G
110	H
111	I
112	J
113	K
114	L
115	M
116	N
117	O
120	P
121	Q
122	R
123	S
124	T
125	U
126	V
127	W
130	X
131	Y
132	Z
133	[
134	lq
135	]
136	^
137	dt
140	`
141	a
142	b
143	c
144	d
145	e
146	f
147	g
150	h
151	i
152	j
153	k
154	l
155	m
156	n
157	o
160	p
161	q
162	r
163	s
164	t
165	u
166	v
167	w
170	x
171	y
172	z
173	en
174	em
175	''
176	~
177	..
177	um
200	\&
200	\|
200	\^
SHAR_EOF
if test 896 -ne "`wc -c 'cmti10'`"
then
	echo shar: error transmitting "'cmti10'" '(should have been 896 characters)'
fi
echo shar: extracting "'cmtt10'" '(860 characters)'
if test -f 'cmtt10'
then
	echo shar: over-writing existing file "'cmtt10'"
fi
cat << \SHAR_EOF > 'cmtt10'
C
000	*G
001	*D
002	*H
003	*L
004	*C
005	*P
006	*S
007	*U
010	*F
011	*Q
012	*W
013	ua
014	da
015	n'
016	!!
016	I!
017	I?
020	ui
021	uj
022	\`
022	ga
023	\'
023	aa
024	hc
025	be
026	ma
027	ri
030	cd
031	ss
032	ae
033	oe
034	o/
035	AE
036	OE
037	O/
040	__
041	!
042	"
043	#
044	$
045	%
046	&
047	'
050	(
051	)
052	*
053	+
054	,
055	-
055	\-
056	.
057	/
060	0
061	1
062	2
063	3
064	4
065	5
066	6
067	7
070	8
071	9
072	:
073	;
074	<
075	=
076	>
077	?
100	@
101	A
102	B
103	C
104	D
105	E
106	F
107	G
110	H
111	I
112	J
113	K
114	L
115	M
116	N
117	O
120	P
121	Q
122	R
123	S
124	T
125	U
126	V
127	W
130	X
131	Y
132	Z
133	[
134	\
135	]
136	^
137	_
140	`
141	a
142	b
143	c
144	d
145	e
146	f
147	g
150	h
151	i
152	j
153	k
154	l
155	m
156	n
157	o
160	p
161	q
162	r
163	s
164	t
165	u
166	v
167	w
170	x
171	y
172	z
173	{
174	|
175	}
176	~
177	..
177	um
200	\&
200	\|
200	\^
SHAR_EOF
if test 860 -ne "`wc -c 'cmtt10'`"
then
	echo shar: error transmitting "'cmtt10'" '(should have been 860 characters)'
fi
echo shar: extracting "'ditdvi.1'" '(636 characters)'
if test -f 'ditdvi.1'
then
	echo shar: over-writing existing file "'ditdvi.1'"
fi
cat << \SHAR_EOF > 'ditdvi.1'
.TH DITDVI 1 4/9/88
.CM 1
.SH "NAME"
ditdvi \- convert ditroff output to DVI
.SH "SYNOPSIS"
ditdvi [\fB\-o\fP] < file.di > file.dvi
.SH "DESCRIPTION"
\fIDitdvi\fP converts ditroff(1) output to DVI output.
The ditroff output should have been generated for a
virtual DVI printer.
.PP
The \fB\-o\fP flag turns on the standard 1 inch top and
left margins for the output. This option is for previewing
the DVI output with DVI previewers that crop margins.
.SH "FILES"
FONTDIR where the DESC file for the virtual printer lives
.SH "SEE ALSO"
ditroff(1), makedev(1), tfm2desc(1)
.SH "DIAGNOSTICS"
Hopefully self-explanatory. 
.SH "BUGS"
Lots.
SHAR_EOF
if test 636 -ne "`wc -c 'ditdvi.1'`"
then
	echo shar: error transmitting "'ditdvi.1'" '(should have been 636 characters)'
fi
echo shar: extracting "'ditdvi.c'" '(646 characters)'
if test -f 'ditdvi.c'
then
	echo shar: over-writing existing file "'ditdvi.c'"
fi
cat << \SHAR_EOF > 'ditdvi.c'
#include	<stdio.h>
#include	"ditdvi.h"

char		pageoffset	= 1;
char		*prog_name;

/*VARARGS1*/
fatal(s, arg1, arg2)
	char		*s;
	int		arg1, arg2;
{
	(void)fprintf(stderr, s, arg1, arg2);
	exit(1);
}

main(argc, argv)
	int		argc;
	char		*argv[];
{
	register int	c;
	char		*rindex();
	int		getopt();
	extern int	optind;
	extern char	*optarg;

	if ((prog_name = rindex(argv[0], '/')) == NULL)
		prog_name = argv[0];
	else
		++prog_name;
	while ((c = getopt(argc, argv, "o")) != EOF)
	{
		switch (c)
		{
		case 'o':
			pageoffset = 0;
			break;
		default:
			fatal("Usage: %s [-o] < f.di > f.dvi\n", prog_name);
			break;
		}
	}
	reader();
	exit(0);
}
SHAR_EOF
if test 646 -ne "`wc -c 'ditdvi.c'`"
then
	echo shar: error transmitting "'ditdvi.c'" '(should have been 646 characters)'
fi
echo shar: extracting "'ditdvi.h'" '(2724 characters)'
if test -f 'ditdvi.h'
then
	echo shar: over-writing existing file "'ditdvi.h'"
fi
cat << \SHAR_EOF > 'ditdvi.h'
#ifndef		FONTDIR
#define		FONTDIR		"/usr/lib/ditroff"
#endif

#define		DEF_DEV		"dvi"
#define		NFONTS		100
#define		NSIZES		20

#define		RULE_CHAR	0201		/* put here by tfm2desc */

char		*strcpy(), *sprintf();

typedef		unsigned char	uchar;

extern char	pageoffset;
extern char	*prog_name;

/*
**	characteristics of a typesetter
*/

typedef struct tdev {
      unsigned  short filesize;	/* number of bytes in file, */
				/* excluding dev part */
	short	res;		/* basic resolution in goobies/inch */
	short	hor;		/* goobies horizontally */
	short	vert;
	short	unitwidth;	/* size at which widths are given, in effect */
	short	nfonts;		/* number of fonts physically available */
	short	nsizes;		/* number of sizes it has */
	short	sizescale;	/* scaling for fractional point sizes */
	short	paperwidth;	/* max line length in units */
	short	paperlength;	/* max paper length in units */
	short	nchtab;		/* number of funny names in chtab */
	short	lchname;	/* length of chname table */
	short	spare1;		/* in case of expansion */
	short	spare2;
	} tdev;

typedef struct tfont {		/* characteristics of a font */
	uchar	nwfont;		/* number of width entries for this font */
	char	specfont;	/* 1 == special font */
	char	ligfont;	/* 1 == ligatures exist on this font */
	char	spare1;		/* unused for now */
	char	namefont[10];	/* name of this font (e.g., "R" */
	char	intname[10];	/* internal name on device, in ascii */
	} tfont;

/* ligatures, ORed into ligfont */

#define	LFF	01
#define	LFI	02
#define	LFL	04
#define	LFFI	010
#define	LFFL	020

typedef struct lookup {
	char		*chname;
	short		ordinal;
	} lookup;

typedef struct settings {
	char		s_ts_name[20];		/* name of typesetter */
	char		*s_font_name;		/* current font name */
	int		s_font_num;		/* current font number */
	int		s_point_size;		/* current point size */
	int		s_point_index;		/* index into pstab and raster */
	int		s_page_num;		/* current page number */
	int		s_H, s_V;		/* H and V ints */
	int		s_resolution, s_horizontal,
			s_vertical;		/* of typesetter */
	} settings;

typedef	struct fontdes {
	tfont		*tfontp;		/* font entry */
	uchar		*widtab;		/* width table */
	uchar		*kerntab;		/* kerning table */
	uchar		*codetab;		/* code table */
	uchar		*fitab;			/* font index table */
	int		texfont[NSIZES];	/* number of font in DVI file */
	} fontdes;

/* define some macros for convenient reference to fields */
#define	n_width		tfontp->nwfont		/* first thing in font entry */
#define	font_name	tfontp->namefont	/* array of char */
#define	int_name	tfontp->intname		/* array of char */

extern tdev	dev;
extern int	halfwidth;
extern short	*pstab;
extern lookup	*specialtab;
extern settings	engine;				/* where we are at now */
extern fontdes	fonts[NFONTS];
SHAR_EOF
if test 2724 -ne "`wc -c 'ditdvi.h'`"
then
	echo shar: error transmitting "'ditdvi.h'" '(should have been 2724 characters)'
fi
echo shar: extracting "'dvi.c'" '(3825 characters)'
if test -f 'dvi.c'
then
	echo shar: over-writing existing file "'dvi.c'"
fi
cat << \SHAR_EOF > 'dvi.c'
#include	<stdio.h>
#include	"dvi.h"

/*
**	Code generation routines for DVI
**	See dvitype.web in TeX sources for description of DVI format.
*/

int		filepos = 0;
static int	postpos;

static put1(c)
	int		c;
{
	putchar(c);
	++filepos;
}

static put2(c)
	int		c;
{
	put1((c >> 8) & 0xff);
	put1(c & 0xff);
}

static put3(c)
	int		c;
{
	put1((c >> 16) & 0xff);
	put1((c >> 8) & 0xff);
	put1(c & 0xff);
}

static put4(c)
	int		c;
{
	put1((c >> 24) & 0xff);
	put1((c >> 16) & 0xff);
	put1((c >> 8) & 0xff);
	put1(c & 0xff);
}

set_char(c)
	int		c;
{
	if (0 <= c && c < 128)
		put1(SET_CHAR + c);
	else if (128 <= c && c < 256)
	{
		put1(SET1);
		put1(c);
	}
	else if (256 <= c && c < 65536)
	{
		put1(SET2);
		put2(c);
	}
	else if (65536 <= c && c < (1 << 24))
	{
		put1(SET3);
		put3(c);
	}
	else
	{
		put1(SET4);
		put4(c);
	}
}

set_rule(a, b)
	int		a, b;
{
	put1(SET_RULE);
	put4(a);
	put4(b);
}

put_char(c)
	int		c;
{
	if (0 <= c && c < 256)
	{
		put1(PUT1);
		put1(c);
	}
	else if (256 <= c && c < 65536)
	{
		put1(PUT2);
		put2(c);
	}
	else if (65536 <= c && c < (1 << 24))
	{
		put1(PUT3);
		put3(c);
	}
	else
	{
		put1(PUT4);
		put4(c);
	}
}

put_rule(a, b)
	int		a, b;
{
	put1(PUT_RULE);
	put4(a);
	put4(b);
}

int bop(counts, backptr)
	int		counts[];
	int		backptr;
{
	register int	i, prev;

	prev = filepos;
	put1(BOP);
	for (i = 0; i < 10; ++i)
		put4(counts[i]);
	put4(backptr);
	return (prev);			/* return position of this bop */
}

eop()
{
	put1(EOP);
}

push()
{
	put1(PUSH);
}

pop()
{
	put1(POP);
}

right(x)
	int		x;
{
	if (-128 <= x && x < 128)
	{
		put1(RIGHT1);
		put1(x & 0xff);
	}
	else if (-32768 <= x && x < 32768)
	{
		put1(RIGHT2);
		put2(x & 0xffff);
	}
	else if (-(1 << 23) <= x && x < (1 >> 23))
	{
		put1(RIGHT3);
		put3(x & 0xffffff);
	}
	else
	{
		put1(RIGHT4);
		put4(x);
	}
}

down(y)
	int		y;
{
	if (-128 <= y && y < 128)
	{
		put1(DOWN1);
		put1(y & 0xff);
	}
	else if (-32768 <= y && y < 32768)
	{
		put1(DOWN2);
		put2(y & 0xffff);
	}
	else if (-(1 << 23) <= y && y < (1 >> 23))
	{
		put1(DOWN3);
		put3(y & 0xffffff);
	}
	else
	{
		put1(DOWN4);
		put4(y);
	}
}

fnt_num(n)
	int		n;
{
	if (0 <= n && n < 64)
		put1(FNT_NUM + n);
	else if (64 <= n && n <= 256)
	{
		put1(FNT1);
		put1(n);
	}
	else if (256 <= n && n <= 65536)
	{
		put1(FNT2);
		put2(n);
	}
	else if (65536 <= n && n <= (1 >> 24))
	{
		put1(FNT3);
		put3(n);
	}
	else
	{
		put1(FNT4);
		put4(n);
	}
}

xxx(s)
	char		*s;
{
	register int	len = strlen(s);

	if (0 <= len && len < 256)
	{
		put1(XXX1);
		put1(len);
	}
/*
	use only XXX1 and XXX4
	else if (256 <= len && len < 65536)
	{
		put1(XXX2);
		put2(len);
	}
	else if (65536 <= len && len < (1 << 24))
	{
		put1(XXX3);
		put3(len);
*/
	else
	{
		put1(XXX4);
		put4(len);
	}
	while (*s != '\0')
		put1(*s++);
}

fnt_def(k, c, s, d, a, l)
	int		k, c, s, d;
	char		*a, *l;
{
	register int	la = strlen(a), ll = strlen(l);

	if (0 <= k && k < 256)
	{
		put1(FNT_DEF1);
		put1(k);
	}
	else if (256 <= k && k < 65536)
	{
		put1(FNT_DEF2);
		put2(k);
	}
	else if (65536 <= k && k < (1 >> 24))
	{
		put1(FNT_DEF3);
		put3(k);
	}
	else
	{
		put1(FNT_DEF4);
		put4(k);
	}
	put4(c);
	put4(s);
	put4(d);
	put1(la);
	put1(ll);
	while (*a != '\0')
		put1(*a++);
	while (*l != '\0')
		put1(*l++);
}

pre(num, den, mag, k)
	int		num, den, mag;
	char		*k;
{
	register int	len = strlen(k);

	put1(PRE);
	put1(DVI_VERSION);
	put4(num);
	put4(den);
	put4(mag);
	put1(len);
	while (*k != '\0')
		put1(*k++);
}

post(back, num, den, mag, height, width, stack, pages)
{
	postpos = filepos;
	put1(POST);
	put4(back);
	put4(num);
	put4(den);
	put4(mag);
	put4(height);
	put4(width);
	put2(stack);
	put2(pages);
}

post_post()
{
	register int	i;

	put1(POST_POST);
	put4(postpos);
	put1(DVI_VERSION);
	for (i = 0; i < 4; ++i)
		put1(SIGNATURE);
	while ((filepos & 0x3) != 0)
		put1(SIGNATURE);
}
SHAR_EOF
if test 3825 -ne "`wc -c 'dvi.c'`"
then
	echo shar: error transmitting "'dvi.c'" '(should have been 3825 characters)'
fi
echo shar: extracting "'dvi.h'" '(1103 characters)'
if test -f 'dvi.h'
then
	echo shar: over-writing existing file "'dvi.h'"
fi
cat << \SHAR_EOF > 'dvi.h'
#define	DVI_VERSION	2

#define	SET_CHAR	0
#define	SET1		128
#define	SET2		129
#define	SET3		130
#define	SET4		131
#define	SET_RULE	132
#define	PUT1		133
#define	PUT2		134
#define	PUT3		135
#define	PUT4		136
#define	PUT_RULE	137
#define	NOP		138
#define	BOP		139
#define	EOP		140
#define	PUSH		141
#define	POP		142
#define	RIGHT1		143
#define	RIGHT2		144
#define	RIGHT3		145
#define	RIGHT4		146
#define	W0		147
#define	W1		148
#define	W2		149
#define	W3		150
#define	W4		151
#define	X0		152
#define	X1		153
#define	X2		154
#define	X3		155
#define	X4		156
#define	DOWN1		157
#define	DOWN2		158
#define	DOWN3		159
#define	DOWN4		160
#define	Y0		161
#define	Y1		162
#define	Y2		163
#define	Y3		164
#define	Z0		166
#define	Z1		167
#define	Z2		168
#define	Z3		169
#define	Z4		170
#define	FNT_NUM		171
#define	FNT1		235
#define	FNT2		236
#define	FNT3		237
#define	FNT4		238
#define	XXX1		239
#define	XXX2		240
#define	XXX3		241
#define	XXX4		242
#define	FNT_DEF1	243
#define	FNT_DEF2	244
#define	FNT_DEF3	245
#define	FNT_DEF4	246
#define	PRE		247
#define	POST		248
#define	POST_POST	249

#define	SIGNATURE	223
SHAR_EOF
if test 1103 -ne "`wc -c 'dvi.h'`"
then
	echo shar: error transmitting "'dvi.h'" '(should have been 1103 characters)'
fi
echo shar: extracting "'fontfile.c'" '(4416 characters)'
if test -f 'fontfile.c'
then
	echo shar: over-writing existing file "'fontfile.c'"
fi
cat << \SHAR_EOF > 'fontfile.c'
#include	<stdio.h>
#include	"ditdvi.h"

/*
**	Routines to read ditroff DESC file.
*/

tdev	dev;
int	halfwidth;
short	*pstab;
lookup	*specialtab;
fontdes	fonts[NFONTS];

static char *smalloc(n)
	int		n;
/*
**	Get memory, or die
*/
{
	register char	*p;
	char		*malloc();

	if ((p = malloc(n)) == NULL)
		fatal("No more memory\n");
	return (p);
}

int readfontdir()
/*
**	Read in the information from the DESC file, storing it in
**	the font info array.
*/
{
	register int	i;
	register char	*filedata, *chname;
	register short	*chtab;
	register FILE	*f;
	char		fname[100];
	char		*sprintf();

	(void)sprintf(fname, "%s/dev%s/DESC.out", FONTDIR, engine.s_ts_name);
	if ((f = fopen(fname, "r")) == NULL)
	{
		perror(fname);
		return (0);
	}
	if (fread((char *)&dev, sizeof(char), sizeof(tdev), f) != sizeof(tdev))
		return (0);
	halfwidth = dev.unitwidth / 2;
	if (dev.nfonts >= NFONTS)
		fatal("Font capacity of %d fonts exceeded, reconfigure\n", NFONTS - 1);
	if (dev.nsizes >= NSIZES)
		fatal("Pointsize capacity of %d sizes exceeded, reconfigure\n", NSIZES);

	for (i = 0; i < NFONTS; ++i)		/* zero descriptors */
	{
		register fontdes	*f;
		register int		j;

		f = &fonts[i];
		f->tfontp = (tfont *)0;
		f->codetab = f->fitab = (uchar *)0;
		for (j = 0; j < NSIZES; ++j)
			f->texfont[j] = -1;	/* initially unloaded */
	}

	filedata = smalloc(dev.filesize);
	if (fread(filedata, sizeof(char), dev.filesize, f) != dev.filesize)
		fatal("Short read on %s\n", fname);
	(void)fclose(f);
	pstab = (short *)filedata;
	filedata += (dev.nsizes + 1) * sizeof(short);
	chtab = (short *)filedata;
	filedata += dev.nchtab * sizeof(short);
	chname = filedata;
	filedata += dev.lchname;
	makespecialtab(dev.nchtab, chname, chtab);
#ifdef	DEBUG_FONTS
	dumptables();
#endif	DEBUG_FONTS
	for (i = 1; i <= dev.nfonts; i++)
	{
		register int		nw;

		fonts[i].tfontp = (tfont *)filedata;
		nw = fonts[i].n_width;
		filedata += sizeof(tfont);
		fonts[i].widtab = (uchar *)filedata;
		filedata += nw;
		fonts[i].kerntab = (uchar *)filedata;
		filedata += nw;
		fonts[i].codetab = (uchar *)filedata;
		filedata += nw;
		fonts[i].fitab = (uchar *)filedata;
		filedata += dev.nchtab + (128 - 32);
	}
#ifdef	DEBUG_FONTS
	dumpfonts();
#endif	DEBUG_FONTS
	return (1);
}

static int speccmp(l1, l2)
	lookup		*l1, *l2;
{
	return (strcmp(l1->chname, l2->chname));
}

makespecialtab(nspecials, strings, offsets)
	int		nspecials;
	char		*strings;
	short		offsets[];
{
	register int	i;

	specialtab = (lookup *)smalloc(nspecials * sizeof(lookup));
	for (i = 0; i < nspecials; ++i)
	{
		specialtab[i].ordinal = i;
		specialtab[i].chname = strings + offsets[i];
	}
	qsort((char *)specialtab, nspecials, sizeof(lookup), speccmp);
#ifdef	DEBUG_FONTS
	for (i = 0; i < nspecials; ++i)
		printf("%s %d\n", specialtab[i].chname, specialtab[i].ordinal);
#endif	DEBUG_FONTS
}

#ifdef	DEBUG_FONTS
static dumptables()
/*
**	Print font size tables
*/
{
	register int		i;

	printf("Point size table\n");
	for (i = 0; i <= dev.nsizes; ++i)
	{
		printf("%3d", pstab[i]);
		if (i % 20 == 19)
			putchar('\n');
		else
			putchar(' ');
	}
	putchar('\n');
	printf("Special chars\n");
	for (i = 0; i < dev.nchtab; ++i)
	{
		printf("%s", &chname[chtab[i]]);
		if (i % 20 == 19)
			putchar('\n');
		else
			putchar(' ');
	}
	putchar('\n');
}

static dumpfonts()
/*
**	Print out a human readable representation of fonts for
**	debugging purposes.
*/
{
	register int		i;

	for (i = 1; i < NFONTS; ++i)
	{
		if (fonts[i].tfontp != NULL)
			dumponefont(i);
	}
}

static dumponefont(n)
	int			n;
/*
**	Say all we know about this font
*/
{
	register tfont		*tf;
	register uchar		*t;
	register int		i, nw;

	tf = fonts[n].tfontp;
	printf("%s (%s), %d entries,%s%s\n",
		tf->namefont, tf->intname, (int)tf->nwfont,
		tf->specfont ? " special" : " ",
		tf->ligfont ? " ligatures" : " ");
	nw = tf->nwfont;
	t = fonts[n].widtab;
	printf("Width table\n");
	for (i = 0; i < nw; ++i)
	{
		printf("%3d", t[i]);
		if (i % 20 == 19)
			putchar('\n');
		else
			putchar(' ');
	}
	putchar('\n');
	t = fonts[n].codetab;
	printf("Code table\n");
	for (i = 0; i < nw; ++i)
	{
		printf("%3d", t[i]);
		if (i % 20 == 19)
			putchar('\n');
		else
			putchar(' ');
	}
	putchar('\n');
	t = fonts[n].fitab;
	printf("Font index table\n");
	for (i = 0; i < dev.nchtab; ++i)
	{
		printf("%3d", t[i]);
		if (i % 20 == 19)
			putchar('\n');
		else
			putchar(' ');
	}
	putchar('\n');
}
#endif	DEBUG_FONTS
SHAR_EOF
if test 4416 -ne "`wc -c 'fontfile.c'`"
then
	echo shar: error transmitting "'fontfile.c'" '(should have been 4416 characters)'
fi
echo shar: extracting "'getspecials'" '(191 characters)'
if test -f 'getspecials'
then
	echo shar: over-writing existing file "'getspecials'"
fi
cat << \SHAR_EOF > 'getspecials'
#! /bin/sh
#
#	This shell script extracts all the two character sequences for
#	inclusion in the DESC file
#
cat cm*10 \
	| sed -e '/	.$/d' -e '/^.$/d' -e '/^..$/d' -e 's/.*	//' \
	| sort -u
SHAR_EOF
if test 191 -ne "`wc -c 'getspecials'`"
then
	echo shar: error transmitting "'getspecials'" '(should have been 191 characters)'
fi
chmod +x 'getspecials'
echo shar: extracting "'reader.c'" '(10736 characters)'
if test -f 'reader.c'
then
	echo shar: over-writing existing file "'reader.c'"
fi
cat << \SHAR_EOF > 'reader.c'
#include	<stdio.h>
#include	<ctype.h>
#include	"ditdvi.h"

/*
**	The heart of the converter, read ditroff, spit out DVI.
*/

#undef		DEBUG_INPUT
#undef		USE_PUT

/* same values as TeX82 uses */
#define		FIX		(1<<16)
#define		CPIN		7227		/* centipoints in an inch */
#define		NUM		25400000
#define		DEN		(CPIN*FIX)
#define		UNITY		1000

/* paper dimensions */
#define		HEIGHT		(11*72*FIX)	/* height in scaled pts */
#define		WIDTH		(17*36*FIX)	/* width in scaled pts */

/* goobies to scaled points */
#define		gtosp(g)	((g)*scale)

#define		vmove(n)	down(gtosp(n)), engine.s_V += (n)

settings	engine	= {
	DEF_DEV, "R",			/* s_ts_name, s_font_name */
	0, 0,				/* s_font_num, s_point_size */
	0,				/* s_point_index */
	0,				/* s_page_num */
	0, 0,				/* s_H, s_V */
	0, 0, 0,			/* resolution, horizontal, vertical */
};

int	counters[10]	= { 0 };
int	scale		= 0;
int	last_move	= 0;
char	fontchanged	= 0;

int	mag		= UNITY;
int	back		= -1;		/* back pointer for bop */
char	bopsent		= 0;

int	fontind		= 0;

struct fonttab {
	int		font;
	int		size;
	} fonttab[NFONTS];

static int getnum()
{
	register int	i, c;

	while (isspace(c = getchar()))
		;
	(void)ungetc(c, stdin);
	for (i = 0; isdigit(c = getchar()); )
		i = i * 10 + c - '0';
	(void)ungetc(c, stdin);
	return (i);
}

static int getint()
{
	register int	i;
	register char	c, flag = 0;

	while (isspace(c = getchar()))
		;
	if (c == '-')
		flag = 1;
	else
		(void)ungetc(c, stdin);
	for (i = 0; isdigit(c = getchar()); )
		i = i * 10 + c - '0';
	(void)ungetc(c, stdin);
	return (flag ? -i : i);
}

static resolve_name(font, size, name, newmag)
	char		*name;
	int		font, size;
	double		*newmag;
{
	char		*index();

	*newmag = 1.0;
	(void)strcpy(name, fonts[font].int_name);
	if (size <= 10)
	{
		/* stop at first digit */
		for ( ; *name != '\0'; ++name)
			if (isdigit(*name))
				break;
		/* overlay the size spec */
		(void)sprintf(name, "%d", size);
	}
	else switch (size)
	{
		case 11:
			*newmag = 1.095445;
			break;
		case 12:
			*newmag = 1.2;
			break;
		case 14:
			*newmag = 1.44;
			break;
		case 17:
			*newmag = 1.728;
			break;
		case 24:
		case 25:
			*newmag = 2.48832;
			break;
		default:
			(void)fprintf(stderr, "Can't handle point size %d\n",
				size);
			break;
	}
}

static loadfont(font, sizeindex)
	int		font, sizeindex;
{
	register int	size	= pstab[sizeindex];
	double		newmag;
	char		fontfile[256];

	fontchanged = 0;
	/* defined yet? */
	if (fonts[font].texfont[sizeindex] < 0)
	{
		resolve_name(font, size, fontfile, &newmag);
		fnt_def(fontind, 0, (int)(newmag * (double)(size * (1<<16))),
			size * (1<<16), "", fontfile);
		fonttab[fontind].font = font;
		fonttab[fontind].size = size;
		fonts[font].texfont[sizeindex] = fontind++;
	}
	fnt_num(fonts[font].texfont[sizeindex]);
}

static outchar(ch)
	int		ch;
{
	register int	c, i, index, code, width;
	register fontdes	*f;
	register int	savedfont = -1;

#ifdef	DEBUG_OUTPUT
	(void)fprintf(stderr, "<%c>\n", ch);
#endif	DEBUG_OUTPUT
	c = ch - 32;
	f = &fonts[engine.s_font_num];
	index = f->fitab[c];				/* char to index */
	if (index != 0)
	{
		code = f->codetab[index];
		width = f->widtab[index];
	}
	else						/* a special then */
	{
		for (i = 1; i <= dev.nfonts; ++i)
		{
			f = &fonts[i];
			if (!f->tfontp->specfont)
				continue;
			if (f->fitab == 0)		/* font not available */
				continue;
			if ((index = f->fitab[c]) != 0)
			{
				savedfont = engine.s_font_num;
				engine.s_font_num = i;
				fontchanged = 1;
				code = f->codetab[index];
				width = f->widtab[index];
				break;
			}
		}
	}
	if (index != 0)
	{
		if (fontchanged)
			loadfont(engine.s_font_num, engine.s_point_index);
/*
**	Rule height is roughly 1/18th of point size
*/
#ifdef	USE_PUT
		if (code != RULE_CHAR)
			put_char(code);
		else
			put_rule(gtosp(engine.s_resolution *
			engine.s_point_size / (72 * 18)), gtosp(width));
#else
		if (code != RULE_CHAR)
			set_char(code);
		else
			set_rule(gtosp(engine.s_resolution *
			engine.s_point_size / (72 * 18)), gtosp(width));
		last_move += (width * engine.s_point_size + halfwidth) / dev.unitwidth;
#endif
		if (savedfont >= 0)
		{
			engine.s_font_num = savedfont;
			fontchanged = 1;
		}
	}
	else if (ch != ' ')		/* kludge, space glyph not in fonts */
		(void)fprintf(stderr, "Font %s, glyph %d not found\n",
			fonts[engine.s_font_num].font_name, ch);
}

static outstring(s)
	char		*s;
{
	register int	low, mid, high;
	register char	*t, *m;

#ifdef	DEBUG_OUTPUT
	(void)fprintf(stderr, "<%s>\n", s);
#endif	DEBUG_OUTPUT
	low = 0;
	high = dev.nchtab - 1;
	while (low <= high)
	{
		mid = (low + high) / 2;
		t = s;
		m = specialtab[mid].chname;
		while (*t == *m && *t != '\0')
			++t, ++m;
		if (*t > *m)
			low = mid + 1;
		else if (*t < *m)
			high = mid - 1;
		else				/* equal, found it */
		{
			outchar(specialtab[mid].ordinal + 128);
			break;
		}
	}
}

static hmove(n)
	int		n;
{
	engine.s_H += n;
	if (n == last_move)
	{
		last_move = 0;
		return;
	}
	n -= last_move;
	last_move = 0;
	right(gtosp(n));
}

static hgoto(n)
	int		n;
{
#ifdef	USE_PUT
	engine.s_H += last_move;
	last_move = 0;
	if (n == engine.s_H)
		return;
	hmove(n - engine.s_H);
#else
	pop();
	push();
	down(gtosp(engine.s_V));
	right(gtosp(n));
	engine.s_H = n;
	last_move = 0;
#endif
}

static vgoto(n)
	int		n;
{
	if (n == engine.s_V)
		return;
	vmove(n - engine.s_V);
}

static specialchar()
{
	register char	c, *p;
	char		special[10];

	for (p = special; isprint(c = getchar()); )
		*p++ = c;
	*p = '\0';
	outstring(special);
}

static finishpage()
{
	/* finish previous page */
	if (bopsent)
	{
		pop();
		eop();
		++engine.s_page_num;
	}
	bopsent = 0;
}

static newpage(n)
{
	finishpage();
	last_move = engine.s_H = engine.s_V = 0;
	counters[0] = n;
	back = bop(counters, back);
	/* DVI output origin is at (1in,1in), need to cancel */
	if (pageoffset)
	{
		down(-CPIN * FIX / 100);	/* up 1 in */
		right(-CPIN * FIX / 100);	/* left 1 in */
	}
	push();
	bopsent = 1;
}

static nextword()
{
	register int	c;

	while (!isspace(getchar()))
		;
	while (isspace(c = getchar()))
		;
	(void)ungetc(c, stdin);
}

static getstring(s, len)
	char		*s;
	int		len;
{
	register char	c;

	--len;				/* for the '\0' terminator */
	while (len > 0 && !isspace(c = getchar()))
		*s++ = c;
	*s = '\0';
}

/*
**	If you expect to load fonts above ditroff's limit of 10
**	you may need this routine.
*/
static fontposition(i, s)
	int		i;
	char		*s;
{
}

static postamble()
{
	register int	i;
	double		newmag;
	char		fontfile[256];

	finishpage();		/* ship off pending page */
	/* we use one level of stack */
	post(back, NUM, DEN, mag, HEIGHT, WIDTH, 1, engine.s_page_num);
	for (i = 0; i < fontind; ++i)
	{
		register struct fonttab	*ft = &fonttab[i];

		resolve_name(ft->font, ft->size, fontfile, &newmag);
		fnt_def(i, 0, (int)(newmag * (double)(ft->size * (1<<16))),
			ft->size * (1<<16), "", fontfile);
	}
	post_post();
}

static setfontsize(n)
	int		n;
{
	register int	i;

	for (i = 0; i < dev.nsizes; ++i)
		if (pstab[i] == n)
			break;
	if (i >= dev.nsizes)
	{
		(void)fprintf(stderr, "%d is not a legal point size\n", n);
		return;
	}
	engine.s_point_size = n;
	engine.s_point_index = i;
}

static int devcntl()
{
	register char	c;
	register int	i;
	char		comment[256];
	char		fontname[256];

	while (isspace(c = getchar()))
		;
	switch (c)
	{
	case 'i':			/* initialize */
		nextword();
		(void)sprintf(comment, "Generated by %s from ditroff output for %s at resolution %d",
			prog_name, engine.s_ts_name, engine.s_resolution);
		if (!readfontdir())
			fatal("Can't read DESC file\n");
		pre(NUM, DEN, mag, comment);
		break;
	case 'T':			/* typesetter name */
		nextword();
		getstring(engine.s_ts_name, sizeof(engine.s_ts_name));
		break;
	case 'r':			/* resolution */
		nextword();
		engine.s_resolution = getnum();
		if (engine.s_resolution <= 0)
			fatal("Resolution should be positve, is %d\n",
				engine.s_resolution);
		scale = 72 * (1<<16) / engine.s_resolution;
		engine.s_horizontal = getnum();
		engine.s_vertical = getnum();
		break;
	case 'p':			/* pause */
		break;
	case 's':			/* stop */
		nextword();
		postamble();
		return(1);
	case 't':			/* trailer */
		nextword();
		break;
	case 'f':			/* associate font with number */
		nextword();
		i = getnum();
		nextword();
		getstring(fontname, sizeof(fontname));
		fontposition(i, fontname);
		break;
	case 'H':			/* set character height */
		break;
	case 'S':			/* set slant */
		break;
	default:
		fatal("Unknown device control %c\n", c);
		break;
	}
	return (0);
}

static graphics()
/*
**	Conversion to tpic output left as an exercise for hacker.
**	Should generate xxx commands in DVI.
*/
{
	register char	c;
	register int	p1, p2, p3;

	switch (c = getchar())
	{
	case 'l':
		break;
	case 'c':
		break;
	case 'e':
		break;
	case 'a':
		break;
	case '~':
		break;
	default:
		fatal("Unknown drawing function %c\n", c);
		break;
	}
	/* eat up the rest of the line */
	while (getchar() != '\n')
		;
}

reader()
/*
**	Switch to appropriate routine depending on character read in
*/
{
	register int	c;

	while ((c = getchar()) != EOF)
	{
#ifdef	DEBUG_INPUT
		(void)fprintf(stderr, "%c", c);
#endif	DEBUG_INPUT
/*
**	The code generated by pcc for switch statements is sufficiently
**	inefficient to take out the most common cases. (Loop to match, gag!)
*/
		if (c == 'h')
		/* this is used often enough to justify making it inline
		instead of calling getnum */
		{
			register int	hmotion;

			for (hmotion = 0; isdigit(c = getchar()); )
				hmotion = hmotion * 10 + c - '0';
			(void)ungetc(c, stdin);
			hmove(hmotion);
		}
		else if (c == 'c')
			outchar(getchar());
		else if (isdigit(c))
		{
			register int	hmotion;
			register char	c1;

			if (!isdigit(c1 = getchar()))
			{
				fatal("Non-digit in nn\n");
				return;
			}
			hmotion = (c - '0') * 10 + c1 - '0';
			hmove(hmotion);
			outchar(getchar());
		}
		/* for the less common cases we can afford some inefficiency */
		else switch (c)
		{
		case 'H':
			hgoto(getnum());
			break;
		case 'v':
			vmove(getnum());
			break;
		case 'V':
			vgoto(getint());
			break;
		case 'C':
			specialchar();
			break;
		case 's':
			setfontsize(getnum());
			fontchanged = 1;
			break;
		case 'f':
			engine.s_font_num = getnum();
			engine.s_font_name = fonts[engine.s_font_num].font_name;
			fontchanged = 1;
			break;
		case 'p':
			newpage(getnum());
			break;
		case 'n':
			(void)getnum();		/* no action required */
			(void)getnum();
			break;
		case 'w':
			break;			/* no action required */
		case 'x':
			if (devcntl())		/* stop? */
				return;
			break;
		case 'D':
			graphics();
			break;
		case '\0':			/* discard whitespace and noise */
		case ' ':
		case '\n':
			break;
		default:
			fatal("Unrecognized ditroff command: %c\n", c);
			break;
		}
	}
}
SHAR_EOF
if test 10736 -ne "`wc -c 'reader.c'`"
then
	echo shar: error transmitting "'reader.c'" '(should have been 10736 characters)'
fi
echo shar: extracting "'tfm2desc.1'" '(2653 characters)'
if test -f 'tfm2desc.1'
then
	echo shar: over-writing existing file "'tfm2desc.1'"
fi
cat << \SHAR_EOF > 'tfm2desc.1'
.TH TFM2DESC 1 4/9/88
.CM 1
.SH "NAME"
tfm2desc \- generate ditroff font description file from TeX tfm file
.SH "SYNOPSIS"
tfm2desc [\fB\-ddesignsize\fP] [\fB\-sspacewidth\fP] \fItfmprefix\fP [type]
.SH "DESCRIPTION"
\fITfm2desc\fP is a program to generate typesetter description
files from tfm files.
The typesetter being described is a virtual one, since the DESC
file will be used with \fIditroff\fP and \fIditdvi\fP.
.PP
The file argument is the name of a file in the current directory
with the following data: The first line is the name of the \fIditroff\fP
font, e.g.
R.
Each succeeding lines describes one character.
The line contains the octal code and the one- or
two character sequence for the glyph, separated by a tab.
Adjacent duplicate octal codes can be used to specify characters
with one or more synonyms and will generate ``ditto'' lines in
the output file.
.PP
\fItfm2desc\fP reads the tfm file named TEXFONT/tfmprefix.tfm.
TEXFONT is a #define'd string in the source you can change.
The metrics go to standard output. These should go to a file
of the same name as the first line of the input file.
The output should then be processed by \fImakedev\fP.
.PP
The \fB\-d\fP flag specifies an alternate design size instead of
that in the tfm file.
All widths will be scaled accordingly.
This allows you to make the widths as large as possible but they should be
less than 256 (the limit imposed by \fIditroff\fP).
Large width entries minimize the roundoff error in the widths.
The design size will be written on the unitwidth line in the output file.
.PP
The \fB\-s\fP flag specifies the spacewidth line in the output file.
.PP
\fItype\fP is an optional single letter which is either m or s, meaning
monospaced or special (\fIditroff\fP terminology).
No ligature entries will be generated for these fonts.
The special line will be put in the output file for special fonts.
.PP
The #define'd constant RESOLUTION should match that in the DESC file.
Since the printer is imaginary, the choice is arbitrary, subject
to constraints imposed on the unitwidth and width entries.
As distributed, 576 units per inch is used.
.SH "FILES"
/usr/lib/tex/fonts directory where the tfm files live
.SH "SEE ALSO"
ditroff(1), makedev(1), ditdvi(1)
.SH "DIAGNOSTICS"
Hopefully self-explanatory.
.SH "BUGS"
Contains hacks to deal with the 1/6 and 1/12 em spacing characters
and the baseline rule.
These should be placed in positions 128 and
above because all the lower 128 positions are occupied in TeX fonts.
\fIDitdvi\fP knows about this hack.
.SH "ACKNOWLEDGEMENT"
This program borrows ideas and some code from \fItfm2difont\fP,
written by Scott Simpson.
SHAR_EOF
if test 2653 -ne "`wc -c 'tfm2desc.1'`"
then
	echo shar: error transmitting "'tfm2desc.1'" '(should have been 2653 characters)'
fi
echo shar: extracting "'tfm2desc.c'" '(6358 characters)'
if test -f 'tfm2desc.c'
then
	echo shar: over-writing existing file "'tfm2desc.c'"
fi
cat << \SHAR_EOF > 'tfm2desc.c'
#include	<stdio.h>

/*
**	Get character widths out of tfm files. See man page.
*/

/* where the TeX tfm files live */
#ifndef		TEXFONT
#define		TEXFONT		"/usr/lib/tex/fonts/"
#endif

#define		FIX		(1<<20)
#define		UNKNOWN		(-1)
#define		PPI		72

#ifndef		RESOLUTION
#define		RESOLUTION	(PPI*8)
#endif

#define		HEADERSIZE	24

int		designsize	= 0;
int		spacewidth	= -1;

usage()
{
	(void)fprintf(stderr, "Usage: tfm2desc [-d<ds>] [-s<sw>] fontmap [m|s]\n");
	exit(1);
}

main(argc,argv)
	int		argc;
	char		*argv[];
{
	register int	c;
	register char	type = ' ';
	char		tfmname[256];
	char		extname[10];
	FILE		*tfmfile;
	extern int	optind;
	extern char	*optarg;
	int		getopt(), atoi();

	while ((c = getopt(argc, argv, "d:s:")) != EOF)
	{
		switch (c)
		{
		case 'd':
			designsize = atoi(optarg);
			if (designsize <= 0)
				(void)fprintf(stderr, "Bad designsize: %d, will use designsize in tfm file\n", designsize);
			break;
		case 's':
			spacewidth = atoi(optarg);
			break;
		default:
			exit(1);
			break;
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < 1)
		usage();
	if (freopen(argv[0], "r", stdin) == NULL)
	{
		perror(argv[0]);
		exit(1);
	}
	(void)sprintf(tfmname, "%s%s.tfm", TEXFONT, argv[0]);
	if ((tfmfile = fopen(tfmname, "r")) == NULL)
	{
		perror(argv[0]);
		exit(1);
	}
	(void)fgets(extname, sizeof(extname), stdin);
	if (extname[1] == '\n')
		extname[1] = '\0';
	if (extname[2] == '\n')
		extname[2] = '\0';
	if (argc >= 2)
		type = argv[1][0];
	convert(extname, argv[0], tfmfile, type);
	exit(0);
}

#define	get1(buffer, offset)	(buffer[offset])

int get2(buffer, offset)
	unsigned char	*buffer;
	int		offset;
{
	return ((buffer[offset] << 8) | buffer[offset + 1]);
}

int get4(buffer, offset)
	unsigned char	*buffer;
	int	offset;
{
	register int	i, n;

	n = 0;
	for (i = 0; i < 4; ++i)
		n = (n << 8) | buffer[offset + i];
	return (n);
}

/*
**	Convert from FIXES to pixels. The roundoff error of this
**	routine is a max of (72*designsize)/2^20, which is negligible
**	for ordinary pointsizes.
*/
fixestopixels(fix, designsize)
	int		fix;
	int		designsize;
{
	register unsigned long	l;

	l = fix * RESOLUTION / PPI;
	l = (l * designsize + FIX / 2) / FIX;
	return (l);
}

/*
**	The main routine which converts a tfm file to a troff width table file
*/
convert(extname, intname, tfmfile, type)
	char		*extname, *intname;
	FILE		*tfmfile;
	char		type;
{
	register int	i, j, ch;
	register unsigned char	*tfmbuf;
	register int	aheight;
	int		lh, bc, ec, nw, nh;
	char		line[256];
	char		name[3];
	char		*malloc();

/*
**	Read the whole tfm file in one gulp
*/
	i = getc(tfmfile) & 0xff;
	i = (i << 8) | (getc(tfmfile) & 0xff);
	i *= 4;
	if ((tfmbuf = (unsigned char *)malloc(i)) == NULL)
	{
		(void)fprintf(stderr, "Out of memory\n");
		exit(1);
	}
	i -= 2;
	if ((j = fread(tfmbuf + 2, sizeof(char), i, tfmfile)) != i)
	{
		(void)fprintf(stderr, "Short read on %s, want %d, got %d\n",
			intname, i, j);
		exit(1);
	}

	(void)printf("name %s\ninternalname %s\n", extname, intname);
	if (type == 's')
		(void)printf("special\n");
	else if (type != 's' && type != 'm')	/* not special or mono-spaced */
		(void)printf("ligatures ff fi fl ffi ffl 0\n");
	if (type != 's')
	{
		if ((aheight = getaheight(tfmbuf)) == UNKNOWN)
		{
			(void)fprintf(stderr, "No letter 'a' in %s.tfm\n", intname);
			(void)fprintf(stderr, "\tSetting height to zero\n");
			aheight = 0;
		}
	}

	if (spacewidth >= 0)
		(void)printf("spacewidth %d\n", spacewidth);

	lh = get2(tfmbuf, 2) * 4;
	bc = get2(tfmbuf, 4);
	ec = get2(tfmbuf, 6);
	nw = get2(tfmbuf, 8) * 4;
	nh = get2(tfmbuf, 10) * 4;
	if (designsize <= 0)
		designsize = get4(tfmbuf, HEADERSIZE + 4) / FIX;

	(void)printf("charset\n");
	ch = -1;
	while (fgets(line, sizeof(line), stdin) != NULL)
	{
		register int	widthindex, heightanddepth, width;
		int		height, depth, kerning;
		int		temp;

		if (sscanf(line, "%o\t%2s\n", &temp, name) != 2)
		{
			(void)fprintf(stderr, "Bad spec file: %s", line);
			exit(1);
		}
		/* space is a terminator */
		if (name[0] == '\0')
		{
			name[0] = ' ';
			name[1] = '\0';
		}
		if (temp >= 128)
		{
			specials(name, temp, spacewidth);
			continue;
		}
		if (temp == ch)
		{
			(void)printf("%s\t\"\n", name);
			continue;
		}
		ch = temp;
		widthindex = get1(tfmbuf, HEADERSIZE + lh + (ch-bc)*4);
		heightanddepth = get1(tfmbuf, HEADERSIZE + lh + (ch-bc)*4 + 1);
		if (widthindex == 0)
			continue;
		width = get4(tfmbuf, HEADERSIZE + lh + (ec-bc+1)*4 + widthindex*4);
		width = fixestopixels(width, designsize);
		height = get4(tfmbuf, HEADERSIZE + lh + (ec-bc+1)*4 + nw +
				(heightanddepth>>4)*4);
		height = fixestopixels(height, designsize);
		depth = get4(tfmbuf, HEADERSIZE + lh + (ec-bc+1)*4 + nw + nh +
			(heightanddepth & 0xf)*4);
		depth = fixestopixels(depth, designsize);
		kerning = 0;
		if (height > aheight)
			kerning |= 2;
		if (depth > 0)
			kerning |= 1;
		if (width >= 256)
			(void)fprintf(stderr, "Warning: width of %d for %s is too wide for ditroff to handle\n",
				width, name);
		(void)printf("%s\t%d\t%d\t0%o\n", name, width, kerning, ch);
	}
}

/* Returns the height of the letter 'a' in the font passed as a parameter.
 * The height is returned in pixels since troff likes to use pixels as its
 * unit. If the letter 'a' is not found, UNKNOWN is returned.
 */
int getaheight(buffer)
	unsigned char	*buffer;
{
	register int	lh, bc, ec, nw, designsize;
	register int	widthindex, heightanddepth, height;

	lh = get2(buffer, 2) * 4;
	bc = get2(buffer, 4);
	ec = get2(buffer, 6);
	nw = get2(buffer, 8) * 4;
	if (bc > 'a' || ec < 'a')
		return (UNKNOWN);
	designsize = get4(buffer, HEADERSIZE + 4) / FIX;	/* Convert from FIXes */
	widthindex = get1(buffer, HEADERSIZE + lh + ('a'-bc)*4);
	heightanddepth = get1(buffer, HEADERSIZE + lh + ('a'-bc)*4 + 1);
	if (widthindex == 0)
		return (UNKNOWN);
	height = get4(buffer, HEADERSIZE + lh + (ec-bc+1)*4 + nw +
		(heightanddepth >> 4)*4);
	return (fixestopixels(height, designsize));
}

specials(name, ch, width)
	char		*name;
	int		ch, width;
{
	if (strcmp(name, "\\&") == 0)
		width = 0;
	/* assume em space is twice space width */
	else if (strcmp(name, "\\^") == 0)
		width = (width + 3) / 6;		/* 1/12 em space */
	else if (strcmp(name, "\\|") == 0)
		width = (width + 1) / 3;		/* 1/6 em space */
	/* make ru same as spacewidth */
	(void)printf("%s\t%d\t0\t0%o\n", name, width, ch);
}
SHAR_EOF
if test 6358 -ne "`wc -c 'tfm2desc.c'`"
then
	echo shar: error transmitting "'tfm2desc.c'" '(should have been 6358 characters)'
fi
#	End of shell archive
exit 0