summaryrefslogtreecommitdiff
path: root/obsolete/dviware
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /obsolete/dviware
Initial commit
Diffstat (limited to 'obsolete/dviware')
-rw-r--r--obsolete/dviware/dvi2xx/2up.sty428
-rw-r--r--obsolete/dviware/dvi2xx/MakeTeXPK109
-rw-r--r--obsolete/dviware/dvi2xx/Makefile132
-rw-r--r--obsolete/dviware/dvi2xx/README86
-rw-r--r--obsolete/dviware/dvi2xx/README.0.51alpha932
-rw-r--r--obsolete/dviware/dvi2xx/README.dell-unix86
-rw-r--r--obsolete/dviware/dvi2xx/README.pcl43
-rw-r--r--obsolete/dviware/dvi2xx/README.vms727
-rw-r--r--obsolete/dviware/dvi2xx/commands.h65
-rw-r--r--obsolete/dviware/dvi2xx/config.h255
-rw-r--r--obsolete/dviware/dvi2xx/dvi2xx.05164
-rw-r--r--obsolete/dviware/dvi2xx/dvi2xx.c4634
-rw-r--r--obsolete/dviware/dvi2xx/dvi2xx.history643
-rw-r--r--obsolete/dviware/dvi2xx/dvi2xx.make182
-rw-r--r--obsolete/dviware/dvi2xx/dvi2xx.man321
-rw-r--r--obsolete/dviware/dvi2xx/dvi2xx.txt330
-rw-r--r--obsolete/dviware/dvi2xx/findfile.c324
-rw-r--r--obsolete/dviware/dvi2xx/graybox.sty48
-rw-r--r--obsolete/dviware/dvi2xx/lj3-filter116
-rw-r--r--obsolete/dviware/dvi2xx/printcap.sample9
-rw-r--r--obsolete/dviware/dvi2xx/sample2.tex179
-rw-r--r--obsolete/dviware/dvi2xx/testpage.tex78
-rw-r--r--obsolete/dviware/dvi2xx/tfm.c255
-rw-r--r--obsolete/dviware/dvi2xx/xmalloc.c41
l---------obsolete/dviware/dvicopy/README1
-rw-r--r--obsolete/dviware/dvicopy/dvicopy.web4480
-rw-r--r--obsolete/dviware/dvicopy/read.me11
-rw-r--r--obsolete/dviware/dvipdfmx/README5
-rw-r--r--obsolete/dviware/dvipdfmx/dvipdfmx.txt502
-rw-r--r--obsolete/dviware/dvips/README7
-rw-r--r--obsolete/dviware/tkdvi/ChangeLog-0.1-0.270
-rw-r--r--obsolete/dviware/tkdvi/ChangeLog-0.2-0.3198
-rw-r--r--obsolete/dviware/tkdvi/README167
-rw-r--r--obsolete/dviware/tkdvi/tkdvi-0.1-conf.patch863
-rw-r--r--obsolete/dviware/tkdvi/tkdvi-0.3.1-gamma.patch261
-rw-r--r--obsolete/dviware/tkdvi/tkdvi-et99.pdfbin0 -> 127793 bytes
-rw-r--r--obsolete/dviware/tkdvi/tkdvi-etcl2K.pdfbin0 -> 235988 bytes
-rw-r--r--obsolete/dviware/tkdvi/tkdvi_0.2-1.diff.gzbin0 -> 4636 bytes
-rw-r--r--obsolete/dviware/tkdvi/tkdvi_0.2-1.dsc22
39 files changed, 15774 insertions, 0 deletions
diff --git a/obsolete/dviware/dvi2xx/2up.sty b/obsolete/dviware/dvi2xx/2up.sty
new file mode 100644
index 0000000000..adb81628b9
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/2up.sty
@@ -0,0 +1,428 @@
+%Article: 10393 of comp.text.tex
+%From: tvz@zandtwerk.Princeton.EDU (Timothy Van Zandt)
+%Newsgroups: comp.text.tex
+%Subject: Here is a 2up.sty for LaTeX.
+%Message-ID: <14650@princeton.Princeton.EDU>
+%Date: 27 Sep 91 19:27:46 GMT
+%Organization: Princeton University, Princeton NJ
+%
+%I seem to remember recent inquiries here or in comp.lang.postscript about
+%printing TeX documents two-up. This can be achieved using a PostScript
+%filter and/or a dvidvi converter.
+%
+%Here is another solution. It is a document style option for LaTeX which
+%makes a few modifications to LaTeX's output routine. It does not require
+%a PostScript output device.
+%
+%
+%---------------------------BEGIN 2up.sty -----------------------------
+\def\fileversion{v0.9}
+\def\filedate{91/09/26}
+%%
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \%% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+%% Document style option `2up', for use with LaTeX v2.09
+%% By Timothy Van Zandt, tvz@Princeton.EDU
+%%
+%% It is recommended that this documentation be kept with the style file.
+%%
+%% *******************************************************************
+%% ** DESCRIPTION **
+%% *******************************************************************
+%%
+%% This is style prints a document two-up. It does this by making a few
+%% simple changes to LaTeX's output routine. It does not involve a dvidvi
+%% converter or PostScript code. It produces a standard dvi file.
+%%
+%% As long as you have or can generate the needed font bitmaps (e.g., pk
+%% files), fonts will not be scaled and output quality will be high.
+%% Non-standard font sizes are needed if the document is reduced.
+%% This is often necessary so that the two pages fit on the sheet of paper.
+%%
+%% If you have used `true' dimensions in your document, you cannot reduce
+%% it and you may find it impossible to fit the two pages on a single one.
+%% `true' dimensions are a no-no if you want to change the magnification
+%% of a document.
+%%
+%% Otherwise, this style option should be compatible with any LaTeX styles
+%% or options that do not change LaTeX's \@outputpage and \enddocument,
+%% macros and that do not modify the commands and parameters that these
+%% use in a non-standard way.
+%%
+%% In this documentation, the "source" layout is the layout of your document
+%% the way it is usually printed. The "target" layout is the layout when it
+%% is printed two-up.
+%%
+%%
+%% *******************************************************************
+%% ** PARAMETERS **
+%% *******************************************************************
+%%
+%% After inputing this file, you must set the following parameters
+%% *** ONCE AND ONLY ONCE, AND IN THIS ORDER. ***
+%%
+%%
+%% 1. Target magnification. Use the command
+%%
+%% \targetmag{<num>}
+%%
+%% where
+%%
+%% a. <num> is integer nearest to 1000 times the magnification, or
+%% b. <num> is \magstep<n> for a magnification of 1.2^n (n=0,...,5), or
+%% c. <num> is \magstepminus<n> for a magnification of 1.2^{-n} (n=0,...,5).
+%%
+%% To minimize the number of non-standard font magnifications, use (b) or (c),
+%% and choose the magnification closest to 1 such that the source pages
+%% fit properly in the target output.
+%%
+%%
+%% 2. Source magnification. Use the command
+%%
+%% \sourcemag{<num>}
+%%
+%% where <num> is as in (1), but for the source output.
+%%
+%%
+%% 3. Target paper width and height. Use:
+%%
+%% \targetpaperwidth{<width>true<unit>}
+%% \targetpaperheight{<height>true<unit>}
+%%
+%% where <unit> is cm, in, pt, etc., and <width> and <height> are the
+%% true width and height of the paper, when looking at the target output
+%% right side up.
+%%
+%%
+%% 4. Source paper width and height. Use:
+%%
+%% \sourcepaperwidth{<width><unit>}
+%% \sourcepaperheight{<height><unit>}
+%%
+%% where <unit>, <width> and <height> are as in (2), but for the source
+%% output.
+%%
+%%
+%% 5. Target layout. Use
+%%
+%% \targetlayout{<layout>}
+%%
+%% where <layout> is "topbottom" if the two source pages are to be printed
+%% one on top of the other, or "sidebyside" if the two source pages are
+%% to be printed side by side. With the sidebyside layout and LaTeX's twoside
+%% option, odd pages always appear on the right and even pages appear on the
+%% left; blank pages are inserted if necessary.
+%%
+%%
+%%
+%% MAKE NO OTHER CHANGES TO YOUR DOCUMENT EXCEPT THE FOLLOWING:
+%%
+%% -- You have to see to it that the target output is printed with the
+%% correct orientation.
+%%
+%% -- You can use \emptytwouppage to insert a completely blank half page in
+%% the target, and \cleartwouppage to eject a complete target page. Ordinarily
+%% you do not need to use these commands.
+%%
+%%
+%% *******************************************************************
+%% ** DEFAULTS **
+%% *******************************************************************
+%%
+%% The following commands set the parameters for some common sources and
+%% targets. The definitions of these commands are also useful examples.
+%%
+%%
+%% I. \twouparticle.
+%%
+%% Source: A portrait document on 8.5x11 inch paper with the standard margins
+%% used in the article document style and without marginal notes.
+%%
+%% Target: A landscape document on the same size paper, with the source
+%% pages printed side by side.
+%%
+%% Definition:
+%%
+%% \targetmag{\magstepminus1}
+%% \sourcemag{\magstep0}
+%% \targetpaperwidth{11truein}
+%% \targetpaperheight{8.5truein}
+%% \sourcepaperwidth{8.5in}
+%% \sourcepaperheight{11in}
+%% \targetlayout{sidebyside}
+%%
+%% If you use narrower side margins than the default ones in the article
+%% document style, or if you use marginal notes, then you will need to
+%% to reduce the magnication to \magstepminus2 or lower or use
+%% \twouplegaltarget, defined below.
+%%
+%%
+%% II. \twouplegaltarget.
+%%
+%% Source: A portrait document on 8.5x11 inch paper with just about any
+%% margins and perhaps with marginal notes.
+%%
+%% Target: A landscape document on legal size paper (8.5x14 inches),
+%% with the source pages printed side by side.
+%%
+%% Definition:
+%%
+%% \targetmag{\magstepminus1}
+%% \sourcemag{\magstep0}
+%% \targetpaperwidth{14truein}
+%% \targetpaperheight{8.5truein}
+%% \sourcepaperwidth{8.5in}
+%% \sourcepaperheight{11in}
+%% \targetlayout{sidebyside}
+%%
+%%
+%% III. \twouplandscape.
+%%
+%% Source: A landscape document on 8.5x11 inch paper with just about any
+%% margins.
+%%
+%% Target: A portrait document on the same size paper, with the source pages
+%% stacked vertically.
+%%
+%% Definition:
+%%
+%% \targetmag{\magstepminus2}
+%% \sourcemag{\magstep0}
+%% \targetpaperwidth{8.5truein}
+%% \targetpaperheight{11truein}
+%% \sourcepaperwidth{11in}
+%% \sourcepaperheight{8.5in}
+%% \targetlayout{topbottom}
+%%
+%%
+%% *******************************************************************
+%% ** IMPLEMENTATION **
+%% *******************************************************************
+%%
+%%
+\typeout{Document style option: `2up' \fileversion \space\space <tvz>}
+%%
+%% Parameter registers:
+\newcount\@sourcemag
+\newdimen\@targetpaperwidth
+\newdimen\@targetpaperheight
+\newdimen\@sourcepagewidth
+\newdimen\@sourcepageheight
+\newif\if@sidebyside
+\@sidebysidetrue
+%%
+%% Registers used by output routing.
+\newif\if@firstpage
+\@firstpagetrue
+\newbox\@leftpage
+\newbox\@rightpage
+%%
+\def\targetmag#1{\mag #1}
+\def\sourcemag#1{\@sourcemag #1}
+\def\targetpaperwidth#1{\@targetpaperwidth #1}
+\def\targetpaperheight#1{\@targetpaperheight #1}
+%%
+%% \@sourcepagewidth and |\@sourcepageheight should be the unmagnified
+%% dimensions of the source page when measured without TeX's 1 inch margins.
+\def\sourcepaperwidth#1{%
+ \@sourcepagewidth #1
+ \advance\@sourcepagewidth by -2in
+ \divide\@sourcepagewidth by \@sourcemag
+ \multiply\@sourcepagewidth by 1000\relax}
+\def\sourcepaperheight#1{%
+ \@sourcepageheight #1
+ \advance\@sourcepageheight by -2in
+ \divide\@sourcepageheight by \@sourcemag
+ \multiply\@sourcepageheight by 1000\relax}
+\def\targetlayout#1{%
+ \def\@tempa{sidebyside}%
+ \def\@tempb{topbottom}%
+ \def\@tempc{#1}
+ \ifx\@tempa\@tempc
+ \@sidebysidetrue
+ \else
+ \ifx\@tempb\@tempc
+ \@sidebysidefalse
+ \else
+ \@latexerr{Valid target layouts are "sidebyside" and "topbottom"}\@eha
+ \fi
+ \fi}
+%%
+\def\magstepminus#1{%
+ \ifcase#1 \@m\or 833\or 694\or 579\or 482\or 401\fi\relax}
+\def\twouparticle{%
+ \targetmag{\magstepminus1}%
+ \sourcemag{\magstep0}%
+ \targetpaperwidth{11truein}%
+ \targetpaperheight{8.5truein}%
+ \sourcepaperwidth{8.5in}%
+ \sourcepaperheight{11in}%
+ \targetlayout{sidebyside}}
+\def\twouplegaltarget{%
+ \targetmag{\magstepminus1}%
+ \sourcemag{\magstep0}%
+ \targetpaperwidth{14truein}%
+ \targetpaperheight{8.5truein}%
+ \sourcepaperwidth{8.5in}%
+ \sourcepaperheight{11in}%
+ \targetlayout{sidebyside}}
+\def\twouplandscape{%
+ \targetmag{\magstepminus2}%
+ \sourcemag{\magstep0}%
+ \targetpaperwidth{8.5truein}%
+ \targetpaperheight{11truein}%
+ \sourcepaperwidth{11in}%
+ \sourcepaperheight{8.5in}%
+ \targetlayout{topbottom}}
+%%
+%% LaTeX's output page routine is modified so that it saves each page and
+%% prints out every two. Each page is centered in a half-page
+\def\@outputpage{%
+ \if@firstpage
+ \global\@firstpagefalse
+ \def\next{%
+ \@makepagebox\@leftpage
+ \stepcounter{page}}%
+ \if@sidebyside
+ \if@twoside
+ \ifodd\count\z@
+ \def\next{%
+ \@makeemptypage\@leftpage
+ \@outputpage}%
+ \fi
+ \fi
+ \fi
+ \else
+ \global\@firstpagetrue
+ \def\next{%
+ \@makepagebox\@rightpage
+ \@shiptwouppage
+ \stepcounter{page}}
+ \if@sidebyside
+ \if@twoside
+ \ifodd\count\z@
+ \else
+ \def\next{%
+ \@makeemptypage\@rightpage
+ \@shiptwouppage
+ \@outputpage}%
+ \fi
+ \fi
+ \fi
+ \fi
+ \next}
+%%
+%% This is the \shipout routine.
+\def\@shiptwouppage{
+ \if@sidebyside
+ \shipout\vbox{%
+ \vskip -1truein
+ \hbox{\hskip -1truein\box\@leftpage\box\@rightpage}}
+ \else
+ \shipout\hbox{%
+ \hskip -1truein
+ \vbox{\offinterlineskip\vskip -1truein \box\@leftpage\box\@rightpage}}
+ \fi}
+%%
+%% \@makepagebox is just like \@outputpage in \LaTeX's standard output
+%% routine, except that it saves the page in a box instead of shipping it out.
+\def\@makepagebox#1{%
+ \begingroup\catcode`\ =10
+ \let\-\@dischyph \let\'\@acci \let\`\@accii \let\=\@acciii
+ \if@specialpage
+ \global\@specialpagefalse\@nameuse{ps@\@specialstyle}%
+ \fi
+ \if@twoside
+ \ifodd\count\z@
+ \let\@thehead\@oddhead \let\@thefoot\@oddfoot
+ \let\@themargin\evensidemargin
+ \else
+ \let\@thehead\@evenhead \let\@thefoot\@evenfoot
+ \let\@themargin\oddsidemargin
+ \fi
+ \else
+ \fi
+ \setbox#1=\vbox to \@sourcepageheight{%
+ \normalsize \baselineskip\z@ \lineskip\z@
+ \let\par\@@par
+ \vskip \topmargin
+ \hbox to \@sourcepagewidth{%
+ \hskip \@themargin
+ \vbox{%
+ \setbox\@tempboxa=\vbox to\headheight{%
+ \vfil
+ \hbox to\textwidth{%
+ \let\label\@gobble \let\index\@gobble \@thehead}}%
+ \dp\@tempboxa\z@
+ \box\@tempboxa
+ \vskip \headsep
+ \box\@outputbox
+ \baselineskip\footskip
+ \hbox to\textwidth{%
+ \let\label\@gobble \let\index\@gobble \@thefoot}}
+ \hss}
+ \vss}%
+ \if@sidebyside
+ \global\setbox#1=\vbox to \@targetpaperheight{%
+ \vss
+ \hbox to .5\@targetpaperwidth{\hss\box#1\hss}
+ \vss}
+ \else
+ \global\setbox#1=\vbox to .5\@targetpaperheight{%
+ \vss
+ \hbox to \@targetpaperwidth{\hss\box#1\hss}
+ \vss}
+ \fi
+ \global\@colht\textheight
+ \endgroup
+ \let\firstmark\botmark}
+%%
+%% This is used to generate an empty page.
+\def\@makeemptypage#1{%
+ \if@sidebyside
+ \global\setbox#1=\vbox to \@targetpaperheight{\vss
+ \hbox to .5\@targetpaperwidth{\hss}}
+ \else
+ \global\setbox#1=\vbox to .5\@targetpaperheight{\vss
+ \hbox to .5\@targetpaperwidth{\hss\box#1\hss}}
+ \fi}
+%%
+%% Eject a page, even when there is only one source page on it.
+\def\cleartwouppage{%
+ \clearpage
+ \if@firstpage
+ \else
+ \twoupemptypage
+ \fi}
+%%
+\def\twoupemptypage{%
+ \clearpage
+ {\let\@makepagebox\@makeemptypage
+ \@outputpage}
+ \addtocounter{page}{-1}}
+%%
+%% This is LaTeX's standard \enddocument, except that we change \clearpage
+%% to \cleartwouppage.
+\def\enddocument{\@checkend{document}\cleartwouppage\begingroup
+ \if@filesw \immediate\closeout\@mainaux
+ \def\global\@namedef##1##2{}\def\newlabel{\@testdef r}%
+ \def\bibcite{\@testdef b}\@tempswafalse \makeatletter\input \jobname.aux
+ \if@tempswa \@warning{Label(s) may have changed. Rerun to get
+ cross-references right}\fi\fi\endgroup\deadcycles\z@\@@end}
+%%
+\endinput
+
diff --git a/obsolete/dviware/dvi2xx/MakeTeXPK b/obsolete/dviware/dvi2xx/MakeTeXPK
new file mode 100644
index 0000000000..485372a9ce
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/MakeTeXPK
@@ -0,0 +1,109 @@
+#!/bin/sh
+#
+# This script file makes a new TeX PK font, because one wasn't
+# found. Parameters are:
+#
+# name dpi bdpi magnification [mode]
+#
+# `name' is the name of the font, such as `cmr10'. `dpi' is
+# the resolution the font is needed at. `bdpi' is the base
+# resolution, useful for figuring out the mode to make the font
+# in. `magnification' is a string to pass to MF as the
+# magnification. `mode', if supplied, is the mode to use.
+#
+# Note that this file must execute Metafont, and then gftopk,
+# and place the result in the correct location for the PostScript
+# driver to find it subsequently. If this doesn't work, it will
+# be evident because MF will be invoked over and over again.
+#
+# Of course, it needs to be set up for your site.
+#
+# TEMPDIR needs to be unique for each process because of the possibility
+# of simultaneous processes running this script.
+
+DESTDIR=/usr/local/lib/tex/pk/pk300
+MFINPUTS=`pwd`:/usr/local/lib/mf/inputs
+export MFINPUTS
+TEMPDIR=/usr/tmp/mtpk.$$
+# MF=mf
+MF=cmmf
+#################### END OF Configuration
+
+NAME=$1
+DPI=$2
+BDPI=$3
+MAG=$4
+MODE=$5
+
+umask 0
+
+if test "$MODE" = ""
+then
+ if test $BDPI = 300
+ then
+ MODE=imagen
+ elif test $BDPI = 400
+ then
+ MODE=nexthi
+ elif test $BDPI = 100
+ then
+ MODE=nextscreen
+ elif test $BDPI = 635
+ then
+ MODE=linolo
+ elif test $BDPI = 1270
+ then
+ MODE=linohi
+ elif test $BDPI = 2540
+ then
+ MODE=linosuper
+ else
+ echo "I don't know the mode for $BDPI"
+ echo "Have your system admin update MakeTeXPK"
+ exit 1
+ fi
+fi
+
+# Something like the following is useful at some sites.
+# DESTDIR=/usr/local/lib/tex/fonts/pk.$MODE
+GFNAME=./$NAME.$DPI'gf'
+PKNAME=./$NAME.$DPI'pk'
+
+# Clean up on normal or abnormal exit
+trap "cd /; rm -rf $TEMPDIR $DESTDIR/pktmp.$$" 0 1 2 15
+
+mkdir $TEMPDIR
+cd $TEMPDIR
+
+if test -r $DESTDIR/$PKNAME
+then
+ echo "$DESTDIR/$PKNAME already exists!"
+ exit 0
+fi
+
+# check also in the standard place
+
+if test -r /usr/lib/tex/fonts/pk/$PKNAME
+then
+ echo /usr/lib/tex/fonts/pk/$PKNAME already exists!
+ exit 0
+fi
+
+echo $MF "\mode:=$MODE; mag:=$MAG; scrollmode; input $NAME" \\\</dev/null
+$MF "\mode:=$MODE; mag:=$MAG; scrollmode; input $NAME" </dev/null
+if test ! -r $GFNAME
+then
+ echo "Metafont failed for some reason on $GFNAME"
+ exit 1
+fi
+
+gftopk $GFNAME $PKNAME
+
+# Install the PK file carefully, since others may be doing the same
+# as us simultaneously.
+
+mv $PKNAME $DESTDIR/pktmp.$$
+cd $DESTDIR
+mv pktmp.$$ $PKNAME
+
+exit 0
diff --git a/obsolete/dviware/dvi2xx/Makefile b/obsolete/dviware/dvi2xx/Makefile
new file mode 100644
index 0000000000..cbd741e33a
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/Makefile
@@ -0,0 +1,132 @@
+# makefile for the dvi-to-(3812 || lj + || lj II || lj IIp ) filter.
+#
+CFLAGS=-O -s -Dunix
+BINDIR=/usr/local/bin
+MANDIR=/usr/man
+MANSEC=1
+CC=cc
+
+# under Ultrix 4.1 use:
+# CFLAGS=-O1 -s -Dunix
+
+# for DEC alpha machines use
+# LFLAGS=-lbsd
+# CC=gcc
+# CFLAGS=-Dunix -ansi -pedantic -Dalpha
+
+# for gcc you might wish to set the following flags
+CC=gcc
+CFLAGS=-Dunix -ansi -pedantic -O2
+# under Linux you might want to use the following configuration
+CFLAGS=-Dunix -ansi -pedantic -O2 -m486
+
+# of DO_SUBDIRS is specifies the fontpath is searched recursively
+# for each subpart (applies to raster info and tfm files); the
+# default search depth is bounded to 10
+DO_SUBDIRS =
+# DO_SUBDIRS = -DDO_SUBDIRECTORIES
+DO_SUBDIRS = -DDO_SUBDIRECTORIES -DMAX_SUBDIR_SEARCH_DEPTH=2
+
+# FONTAREA specifies the search path for locating raster information.
+# if you are unhappy with dvi2xx's guess work, specify the path
+# here, otherwise let it unspecified
+FONTAREA =
+# under Linux add the following path is used in most installations
+FONTAREA = -DFONTAREA=\"/usr/TeX/lib/tex/fonts\"
+
+# DEFAULT_TFM_PATH is the default search path for locating .tfm
+# files. .tfm-files are only read by dvilj4. The pre configured
+# search path ("/usr/local/lib/tex/fonts") is used when this
+# variable is left empty
+DEFAULT_TFM_PATH =
+# under Linux add the following path is used in most installations
+DEFAULT_TFM_PATH = -DDEFAULT_TFM_PATH=\"/usr/TeX/lib/tex/fonts\"
+
+
+FLAGS = $(CFLAGS) $(FONTAREA) $(DEFAULT_TFM_PATH) $(DO_SUBDIRS)
+
+OBJS=findlj.o find3812.o
+HFILES=commands.h config.h
+PROGRAMS=dvilj2p dvilj2 dvilj4 dvi3812 dvilj dviljp
+
+all: $(PROGRAMS) dvi2xx.txt
+
+dvi3812: dvi2xx.c find3812.o $(HFILES)
+ $(CC) ${FLAGS} -DIBM3812 -o $@ dvi2xx.c find3812.o ${LFLAGS}
+
+dvilj2p: dvi2xx.c findlj.o $(HFILES)
+ $(CC) ${FLAGS} -DLJ2P -o $@ dvi2xx.c findlj.o ${LFLAGS}
+
+dvilj2: dvi2xx.c findlj.o $(HFILES)
+ $(CC) ${FLAGS} -DLJ2 -o $@ dvi2xx.c findlj.o ${LFLAGS}
+
+dvilj4: dvilj4.o findlj4.o tfm.o xmalloc.o $(HFILES)
+ $(CC) -o $@ dvilj4.o findlj4.o tfm.o xmalloc.o ${LFLAGS}
+
+dvilj4.o: dvi2xx.c $(HFILES)
+ $(CC) ${FLAGS} -DLJ4 -c dvi2xx.c
+ mv dvi2xx.o dvilj4.o
+
+tfm.o: tfm.c
+ $(CC) ${FLAGS} -DLJ -c tfm.c
+
+dvilj: dvi2xx.c findlj.o $(HFILES)
+ $(CC) ${FLAGS} -DLJ -DSEVENBIT -o $@ dvi2xx.c findlj.o ${LFLAGS}
+
+dviljp: dvi2xx.c findlj.o $(HFILES)
+ $(CC) ${FLAGS} -DLJ2P -DSEVENBIT -o $@ dvi2xx.c findlj.o ${LFLAGS}
+
+findlj.o: findfile.c config.h
+ $(CC) ${FLAGS} -DLJ -c findfile.c
+ mv findfile.o $@
+
+findlj4.o: findfile.c config.h
+ $(CC) ${FLAGS} -DLJ4 -c findfile.c
+ mv findfile.o $@
+
+find3812.o: findfile.c config.h
+ $(CC) ${FLAGS} -DIBM3812 -c findfile.c
+ mv findfile.o $@
+
+clean:
+ rm -f core $(OBJS) $(PROGRAMS)
+
+DISTFILES = \
+ ./dvi2xx.c ./commands.h ./config.h ./findfile.c ./Makefile \
+ ./tfm.c ./xmalloc.c \
+ ./testpage.tex ./dvi2xx.history ./dvi2xx.man ./dvi2xx.txt \
+ ./graybox.sty ./dvi2xx.make ./dvi2xx.051 ./README \
+ ./MakeTeXPK ./lj3-filter ./printcap.sample ./README.vms \
+ ./sample2.tex ./2up.sty ./README.dell-unix ./README.pcl \
+ ./README.0.51alpha9
+
+shar: $(DISTFILES)
+ shar ${DISTFILES} > dvi2xx.shar
+
+
+tar:
+ pdtar zcvf dvi2xx.tar.Z ${DISTFILES}
+ shar dvi2xx.tar.Z > dvi2xx.shar
+
+testfiles:
+ ./dvilj2 -eftable.lj2 ftable
+ ./dvilj2p -eftable.lj2p ftable
+ ./dvi3812 ftab2
+
+
+install:
+ @for f in $(PROGRAMS); do \
+ echo installing $$f in $(BINDIR); \
+ install -c $$f $(BINDIR); \
+ done
+ cp dvi2xx.man dvi2xx.$(MANSEC)
+ install dvi2xx.$(MANSEC) $(MANDIR)/man$(MANSEC)
+
+dvi2xx.txt: dvi2xx.man
+ -nroff -man dvi2xx.man | col -b > dvi2xx.txt
+
+
+
+
+
+
diff --git a/obsolete/dviware/dvi2xx/README b/obsolete/dviware/dvi2xx/README
new file mode 100644
index 0000000000..40264f43de
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/README
@@ -0,0 +1,86 @@
+The dvi2xx family consists of the following programs:
+
+ Dvilj2 converts TeX-output .dvi files into HP PCL (i.e. HP
+ Printer Control Language) commands suitable for printing on a HP
+ LaserJet+, HP LaserJet II and fully compatible printers.
+
+ Dvilj2p converts TeX-output .dvi files into HP PCL commands suit-
+ able for printing on a HP LaserJet IIp, HP LaserJet III or HP
+ Laserjet 2000 and fully compatible printers. This version uses a
+ newer PCL command set and provides landscape printing.
+
+ Dviljp and dvilj are similar to dvilj2p and dvilj2 but they sup-
+ port only 128 character fonts. They may be used for Laserjet
+ clones which do not support 256 character fonts.
+
+ Dvi3812 converts TeX-output .dvi files into PMP files, the native
+ command language of the IBM 3812 page printer.
+
+binary versions are available for:
+ - aix 3.1 rs6000
+ - hpux 7.0 risc
+ - msdos
+ - os/2
+ - ultrix 4.2 risc
+ - SunOS 4.1
+
+
+
+=================================================================
+Configuration:
+-----------------------------------------------------------------
+Compilation of the program:
+ under Unix: Makefile
+ in MS-DOS: cut out relevant part of dvi2xx.make
+ under VMS: see README.vms
+
+ config.h
+ most important:
+ FONTAREA:
+ fontpath leading to font directories; can be
+ overuled at runtiime by setting the
+ environment variable TEXPXL or the command
+ line option -a
+ default: "/usr/local/lib/tex/pk300"
+ (VMS default: "tex$pkdir:")
+
+ MAKETEXPK:
+ Name of the program which is called to generate a pk
+ file in a missing magnification
+ default: "MakeTeXPK"
+-----------------------------------------------------------------
+execution under MS-DOS:
+ CONFIG.SYS:
+ files=20
+ buffers=30
+-----------------------------------------------------------------
+MakeTeXPK:
+ DESTDIR:
+ Name of the directory where the neewly generated fonts
+ should be placed finally
+ default: /usr/local/lib/tex/pk/pk300
+
+ MF:
+ Name of the MetaFont program
+ default: cmmf
+
+ MFINPUTS:
+ search path for metafont input files for MetaFont
+ default: `pwd`:/usr/local/lib/mf/inputs
+
+ TEMPDIR:
+
+ directory for where the MetaFont compilation takes
+ place, and where intermediate files are put in, and
+ which is removed after the MakeTeXPK run.
+ default: /usr/tmp/mtpk.$$
+
+ be sure that you install MakeTeXPK in a way that it is allowed
+ to write to DESTDIR.
+
+-----------------------------------------------------------------
+lj3-filter:
+ location of perl (headerline) /usr/local/bin/perl
+ location of the tmp file (variable $tmpfile)
+ name of dvi-filter and its options (variable $dvifilter)
+
diff --git a/obsolete/dviware/dvi2xx/README.0.51alpha9 b/obsolete/dviware/dvi2xx/README.0.51alpha9
new file mode 100644
index 0000000000..9b5aac61d6
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/README.0.51alpha9
@@ -0,0 +1,32 @@
+New features of version 0.51alpha9:
+
+ - support for LJ4 builtin fonts
+ (thanks to Karl Berry <karl@cs.umb.edu>)
+
+ - support for Amiga
+ (thanks to Stefan Sticht <sticht@edith.deg.sub.org>)
+
+ - recursive file directroy search, when -DDO_SUBDIRECTORIES
+ is specified at compile time
+ (thanks to Rik Faith <faith@cs.unc.edu>)
+ recursive search is performed for each subpart of the
+ path (under unix: colon-separated)
+
+ - cleanup for findfile.c
+
+ - faster file execution under Unix (due to findfile.c changes)
+
+ - new command line option "-M" to avoid automatic invocation
+ of MakeTexOK when missing fonts are encountered
+ (thanks to Karl Berry <karl@cs.umb.edu>)
+
+ - LJ4 is now treated as a superset of LJ2P
+ (landscape mode and duplex mode can be specified)
+
+ - For dvilj4 econo-mode can be activated by specifying
+ "-E" as command line option
+
+ - cosmetic code cleanup (most systems that had to link with
+ "-lucb" should be able to link without it now, etc).
+
+
diff --git a/obsolete/dviware/dvi2xx/README.dell-unix b/obsolete/dviware/dvi2xx/README.dell-unix
new file mode 100644
index 0000000000..7b1357d4ac
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/README.dell-unix
@@ -0,0 +1,86 @@
+Subject: Re: SYSV4 and DVI Laserjet IIIp printer driver
+Date: Sun, 5 Jan 92 15:09:10 MET
+
+PROBLEM:
+Fred Appelman <fred@cv.ruu.nl> wrote:
+
++> I am looking for a TeX printer driver that runs under System V release 4
++> (Dell Unix) that can drive my Laserjet IIIp printer. I have already tried
++> various packages, but have been unsucessfull so far. The printer has
++> 1 Mb of printer memory.
++>
++> I have tried the following:
++> dvi2lj (Version 0.50) -- Compiles fine. When I print I do get a result,
++> but several of the letters are printed at the
++> wrong position.
+
+My reply:
++I am really wondering, what is going on to happen under Dell Unix.
++As i am the author of the driver mentioned above, i KNOW that on a lot
++of various platforms and operating systems your problem never occured.
++I have no DELL unix around, but at least with interactive unix, the driver
++works like a charm.
++
++The most frequent problem with the driver in the UNIX world is, that
++the printer setup is somewhat messed up. people spoiled with postscript
++do not pay attention that the printer setup (such as line-print filter, tty
++settings) is 8 bit transparent. The easiest way to figure out whether
++this is happening is to print a tex document containing just the
++text "aeiou" whith cmr10 (no magn). the with of the i in the font is 10
++pixels, which is encoded in pcl as 0x0a, which many printer drivers like
++to translate in <cr><lf>. As a consequence the output after "i" is messed
++up.
+
+
+SOLUTION (Fred Appelman):
+
+Thank you for your help. The problem was exactly as you described. The
+printer output was not 8 bit transparent. Your suggested test procedure
+was brilliant. By directly copying the data to the device file, I had
+no problems, so I was pretty sure that the problem was somewhere in the
+driver. I have found the error:
+
+This is a part of the original code:
+ : ${TERM:=unknown}
+ if [ ${TERM} = hplaser ]; then
+ jetfile=1
+ else
+ TERM=hplaser
+ export TERM
+ jetfile=
+ fi
+ tput lines 1>/dev/null 2>&1 || TPUT=:
+After the fix:
+ : ${TERM:=unknown}
+ if [ ${TERM} = hplaser ]; then
+ jetfile=1
+ else
+ TERM=hplaser
+ export TERM
+ jetfile=1
+ fi
+ tput lines 1>/dev/null 2>&1 || TPUT=:
+
+
+So a description of the fix:
+ 1. Log in as root
+ 2. Edit the file /usr/lib/lp/model/hplaser
+ 3. Change line 486 from
+ jetfile=
+ into
+ jetfile=1
+ 4. Remove the printerdefintion:
+ lpadmin -xlj (or whatever name you have choosen)
+ 5. Reinstall the printer
+ lpadmin -p lj -mhplaser -T "hplaser" -v /dev/lp
+ Note1: The name of the printer (lj) or the device
+ (/dev/lp) can vary.
+ Note2: This fix was necessary on Dell UNIX SYSVR4 relase 2.0
+ Newer releases may not need this fix.
+
+
+
+
+
+
+
diff --git a/obsolete/dviware/dvi2xx/README.pcl b/obsolete/dviware/dvi2xx/README.pcl
new file mode 100644
index 0000000000..7553344fe9
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/README.pcl
@@ -0,0 +1,43 @@
+Including PCL-Graphics in TeX documents:
+
+The changes I made were for the HPLJ2P set of commands. I am not sure if they
+would still work for the III series printers.
+
+Basically the program strips commands related to setting fonts, pagelength,etc.
+It also strips all ascii text. The commands that are passed on to the printer
+are the following :
+ The commands setting the cursor position - these are modified to take
+ into account the current postion of the cursor
+ The commands setting the printing resolution
+ The raster graphics commands
+ The rectangle drawing commands
+
+The program has been tested with output from
+ DrawPerfect/WordPerfect
+ QuattroPro
+ Ansel
+ Mathcad
+
+The way that we use the facility is as follows
+
+\begin{picture}{X,Y} %Xand Y are the physical dimensions of the picture
+\put(0,0){/special{hpfile=filename}}
+\end{picture}
+
+This enables latex to know the size of the picture and so place it correctly.
+The picture environment can also be included inside a figure.
+
+If you are unclear about something please feel free to contact me. I hope this
+modification is of use to other people as well.
+
+Cheers
+Fred
+
+Frederick Hoare
+email: fred@dip1.ee.uct.ac.za
+Department of Electrical and Electronic Engineering
+University of Cape Town, South Africa
+
+
+
+
diff --git a/obsolete/dviware/dvi2xx/README.vms b/obsolete/dviware/dvi2xx/README.vms
new file mode 100644
index 0000000000..38b248871d
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/README.vms
@@ -0,0 +1,727 @@
+From HAAN@IRIMCF.TUDELFT.NL Thu Oct 17 16:56:16 1991
+Received: from IRIMCF.TUDELFT.NL (IRIMCF) by TUDRVA.TUDelft.NL (PMDF #12232) id
+ <01GBUYPA7S68AKTSPZ@TUDRVA.TUDelft.NL>; Thu, 17 Oct 1991 16:56 +0100
+Date: Thu, 17 Oct 91 16:53 MET
+From: H.deHaan@IRIVAX.TUDELFT.NL
+Subject: VMS-port of dvi2xx
+Sender: Henk de Haan <HAAN@IRIMCF.TUDELFT.NL>
+To: NEUMANN@DEC4.WU-WIEN.AC.AT
+Message-Id: <01GBUYPA7S68AKTSPZ@TUDRVA.TUDelft.NL>
+X-Vms-To: NEUMANN@DEC4.WU-WIEN.AC.AT
+Comments: Sent using PMDF-822 V3.0, routing is done by TUDRVA
+Status: OR
+
+ Dear Gustaf,
+
+ Thanks for writing the DVI print program for the HP-Laserjet family.
+Because our group recently bought a HP Laserjet 3 printer (for our VAX/VMS
+system), we needed a LaTeX driver for it. The only drivers I could locate
+(and that would run on VAX/VMS) are the Beebe drivers, but they are rather
+slow and they don't support any \special commands. For this reason I've
+ported your program to VAX/VMS.
+
+ I'm sending you my changes to your programs (in respect to the DVI2XX,
+version 0.50 distribution). All my changes are propely included in #ifdef ...
+#endif constructions. I'm also including an extra file (called VAXVMS.C), which
+is copied from the DVIPS distribution, and which was originally written by
+Nelson Beebe.
+
+ The other changes are:
+
+ config.h - definition of FONTAREA and signed_char
+
+ findfile.c - path of types.h and stat.h
+ - VMS specific versions for the font search paths
+
+ dvi2xx.c - definition of the functions in VAXVMS.C
+ - writing of output file in a binary format with fixed
+ record lengths (512 bytes), this implied that:
+ - fwrite didn't work anymore, so another version
+ of EMITB had to be made (using putc).
+ - the last record had to be padded with zeros
+ - usage of VAX/VMS specific error codes
+ - definition of 12 for MAXOPEN (because MAXOPEN is
+ standard defined as 8).
+ - VAX/VMS doesn't allow the "%hd" format specifier to
+ be used in output statements, so this was changed
+ to the "%d" format.
+
+ The program is tested on a MicroVAX-II running VMS 5.3-1 and is compiled
+using the VAXC compiler (version 2.3). The compile sequence used is:
+
+ $ CC /DEFINE=(LJ2P,DEBUG) DVI2XX
+ $ CC FINDFILE
+ $ CC VAXVMS
+ $ LINK /EXEC=DVILJ2P DVI2XX,FINDFILE,VAXVMS,SYS$INPUT:/OPT
+ SYS$SHARE:VAXCRTL.EXE/SHARE
+ ^Z
+
+The program can be defined with:
+
+ $ DVILJ2P :== $disk:[directory]DVILJ2P
+
+And can be run with:
+
+ $ DVILJ2P [options] dvi-filename
+
+The uppercase options (such as -D) have to be put between quotation marks,
+because the VAX/VMS operating systems converts the command string to lower
+case (so: $ DVILJ2P "-D1" dvi-filename).
+
+Only the LJ2P version is compiled and tested. I'm printing the output file
+with the command:
+
+ $ PRINT/QUEUE=queue-name /PASSALL file.LJ
+
+
+ The only suggestion for some improvements to the program, are in respect
+to the \special commands. It would be nice if your program could interpret the
+\tpic specials.
+
+ With kind regards, Henk de Haan
+
+ /-------------------------------+---------------------------------\
+ / Henk de Haan | Phone: +31 15 781398 \
+ / Delft University of Technology | FAX: +31 15 786422 \
+ / ISO | E-mail: H.deHaan@IRI.TUDelft.NL \
+ / p/a IRI | Bitnet: HAAN@HDETUD5 \
+< Mekelweg 15 | DECnet: IRIMCF::HAAN >
+ \ 2629 JB Delft | JANET: HH01@UK.AC.RL.DE /
+ \ The Netherlands | HEPnet: 19477::HH01 /
+ \_________________________________|___________________________________/
+ \ Phrase: The only way to cold fusion is Muon Catalyzed Fusion (?) /
+ \-----------------------------------------------------------------/
+
+From banko%uiphya.dnet@garcon.cso.uiuc.edu Tue Jun 9 22:03:04 1992
+Received: from UIPHYA.DECnet MAIL11D_V3 by garcon.cso.uiuc.edu with SMTP id AA06269
+ (5.65d+/IDA-1.4.4 for <neumann@dec4.wu-wien.ac.at>); Tue, 9 Jun 1992 14:53:56 -0500
+Date: Tue, 9 Jun 1992 14:53:52 -0500
+Message-Id: <199206091953.AA06269@garcon.cso.uiuc.edu>
+From: banko%uiphya.dnet@garcon.cso.uiuc.edu (Bradley T. Banko)
+To: neumann@dec4.wu-wien.ac.at
+Cc: h.dehaan@iri.tudelft.nl
+Subject: dvi2xx on VMS success... Thanks.
+Status: OR
+
+Dear Gustaf & Henk,
+
+With a little hacking, we have had success getting dvi2xx to work on our
+Vaxstation 3100s running VMS 5.5. I am enclosing 3 small files below which
+describe the changes we had to make. (readme.vms, compile.com & vaxvms.c)
+
+Getting a copy of vaxvms.c was our first problem, and then finding the
+"SEVENBIT" define in dvi2xx.c was the final major victory.
+
+Thanks for your help!
+
+Brad Banko
+b-banko@uiuc.edu
+
+=======================================================================
+readme.vms
+=======================================================================
+
+6/9/92 Brad Banko, b-banko@uiuc.edu
+
+The key "defines" are in "config.h" (DEBUG, USEPXL, vms & LJ).
+The "main" function type was redefined to be "int". Vax C wouldn't
+compile it with "void main".
+
+A compile/link command file is: "compile.com".
+
+The key changes are:
+
+ 1) define logical name TEXPXL to refer to the tex fonts
+ directory (not device) :== tex_disk:[tex.fonts]
+ (instead of tex$pkdir: == tex_disk:[tex.fonts.])
+
+ 2) "#define SEVENBIT" for our older HP Laserjet+.
+
+=========================================================================
+>From HAAN@IRIMCF.TUDELFT.NL Thu Oct 17 16:56:16 1991
+Received: from IRIMCF.TUDELFT.NL (IRIMCF) by TUDRVA.TUDelft.NL (PMDF #12232) id
+ <01GBUYPA7S68AKTSPZ@TUDRVA.TUDelft.NL>; Thu, 17 Oct 1991 16:56 +0100
+Date: Thu, 17 Oct 91 16:53 MET
+From: H.deHaan@IRIVAX.TUDELFT.NL
+Subject: VMS-port of dvi2xx
+Sender: Henk de Haan <HAAN@IRIMCF.TUDELFT.NL>
+To: NEUMANN@DEC4.WU-WIEN.AC.AT
+Message-Id: <01GBUYPA7S68AKTSPZ@TUDRVA.TUDelft.NL>
+X-Vms-To: NEUMANN@DEC4.WU-WIEN.AC.AT
+Comments: Sent using PMDF-822 V3.0, routing is done by TUDRVA
+Status: OR
+
+ Dear Gustaf,
+
+ Thanks for writing the DVI print program for the HP-Laserjet family.
+Because our group recently bought a HP Laserjet 3 printer (for our VAX/VMS
+system), we needed a LaTeX driver for it. The only drivers I could locate
+(and that would run on VAX/VMS) are the Beebe drivers, but they are rather
+slow and they don't support any \special commands. For this reason I've
+ported your program to VAX/VMS.
+
+ I'm sending you my changes to your programs (in respect to the DVI2XX,
+version 0.50 distribution). All my changes are propely included in #ifdef ...
+#endif constructions. I'm also including an extra file (called VAXVMS.C), which
+is copied from the DVIPS distribution, and which was originally written by
+Nelson Beebe.
+
+ The other changes are:
+
+ config.h - definition of FONTAREA and signed_char
+
+ findfile.c - path of types.h and stat.h
+ - VMS specific versions for the font search paths
+
+ dvi2xx.c - definition of the functions in VAXVMS.C
+ - writing of output file in a binary format with fixed
+ record lengths (512 bytes), this implied that:
+ - fwrite didn't work anymore, so another version
+ of EMITB had to be made (using putc).
+ - the last record had to be padded with zeros
+ - usage of VAX/VMS specific error codes
+ - definition of 12 for MAXOPEN (because MAXOPEN is
+ standard defined as 8).
+ - VAX/VMS doesn't allow the "%hd" format specifier to
+ be used in output statements, so this was changed
+ to the "%d" format.
+
+ The program is tested on a MicroVAX-II running VMS 5.3-1 and is compiled
+using the VAXC compiler (version 2.3). The compile sequence used is:
+
+ $ CC /DEFINE=(LJ2P,DEBUG) DVI2XX
+ $ CC FINDFILE
+ $ CC VAXVMS
+ $ LINK /EXEC=DVILJ2P DVI2XX,FINDFILE,VAXVMS,SYS$INPUT:/OPT
+ SYS$SHARE:VAXCRTL.EXE/SHARE
+ ^Z
+
+The program can be defined with:
+
+ $ DVILJ2P :== $disk:[directory]DVILJ2P
+
+And can be run with:
+
+ $ DVILJ2P [options] dvi-filename
+
+The uppercase options (such as -D) have to be put between quotation marks,
+because the VAX/VMS operating systems converts the command string to lower
+case (so: $ DVILJ2P "-D1" dvi-filename).
+
+Only the LJ2P version is compiled and tested. I'm printing the output file
+with the command:
+
+ $ PRINT/QUEUE=queue-name /PASSALL file.LJ
+
+ The only suggestion for some improvements to the program, are in respect
+to the \special commands. It would be nice if your program could interpret the
+\tpic specials.
+
+ With kind regards, Henk de Haan
+
+ /-------------------------------+---------------------------------\
+ / Henk de Haan | Phone: +31 15 781398 \
+ / Delft University of Technology | FAX: +31 15 786422 \
+ / ISO | E-mail: H.deHaan@IRI.TUDelft.NL \
+ / p/a IRI | Bitnet: HAAN@HDETUD5 \
+< Mekelweg 15 | DECnet: IRIMCF::HAAN >
+ \ 2629 JB Delft | JANET: HH01@UK.AC.RL.DE /
+ \ The Netherlands | HEPnet: 19477::HH01 /
+ \_________________________________|___________________________________/
+ \ Phrase: The only way to cold fusion is Muon Catalyzed Fusion (?) /
+ \-----------------------------------------------------------------/
+
+============================================================================
+compile.com
+============================================================================
+$!
+$! The program is tested on a MicroVAX-II running VMS 5.3-1 and is compiled
+$! using the VAXC compiler (version 2.3). The compile sequence used is:
+$!
+$! original package from Gustaf Neumann's archive at:
+$! ftp.wu-wien.ac.at
+$!
+$! modified and run on Vax VMS 5.5 Vaxstation 3100 with Laserjet+
+$! see README.VMS for more info, Brad Banko, 6/9/92
+$! b-banko@uiuc.edu
+$!
+$ set verify
+$ dvilj :== "$ uiphyb$dka300:[banko.dvi2xx]dvilj.exe"
+$ define texpxl tex_disk:[tex.fonts]
+$ CC /define=sevenbit DVI2XX
+$ CC FINDFILE
+$ CC VAXVMS
+$ LINK /EXEC=DVILJ DVI2XX,FINDFILE,VAXVMS,SYS$INPUT:/OPT
+SYS$SHARE:VAXCRTL.EXE/SHARE
+
+===========================================================================
+a vaxvms.c (no changes, from uxc.cso.uiuc.edu, just fyi)
+===========================================================================
+/***********************************************************************
+This file provides alternative functions for several VMS VMS C library
+routines which either unacceptable, or incorrect, implementations. They
+have been developed and tested under VMS Version 4.4, but indications
+are that they apply to earlier versions, back to 3.2 at least. They
+should be retested with each new release of VMS C.
+
+Contents:
+ EXIT
+ FSEEK
+ FTELL
+ GETCHAR
+ GETENV
+ READ
+ UNGETC
+ getlogin
+ qsort
+ system
+ tell
+ unlink
+
+The VAX VMS file system record structure has unfortunate consequences
+for random access files.
+
+By default, text files written by most system utilities, and languages
+other than C, have a variable length record format, in which a 16-bit
+character count is aligned on an even-byte boundary in the disk block
+b(always 512 bytes in VMS, independent of record and file formats),
+followed by <count> bytes of data. Binary files, such as .EXE, .OBJ,
+and TeX .DVI and font files, all use a 512-byte fixed record format
+which has no explicit length field. No file byte count is stored;
+instead, the block count, and the offset of the last data byte in the
+last block are recorded in the file header (do ``DUMP/HEADER filespec''
+to see it). For binary files with fixed-length records, the last block
+is normally assumed to be full, and consequently, file transfer of
+binary data from other machines via Kermit, FTP, or DCL COPY from ANSI
+tapes, generally fails because the input file length is not a multiple
+of 512.
+
+This record organization may be contrasted with the STREAM, STREAM_LF,
+and STREAM_CR organizations supported from Version 4.0; in these, disk
+blocks contain a continuous byte stream in which nothing, or LF, or CR,
+is recognized as a record terminator. These formats are similar to the
+Unix and TOPS-20 file system formats which also use continuous byte
+streams.
+
+For C, this means that a program operating on a file in record format
+cannot count input characters and expect that count to be the same value
+as the offset parameter passed to fseek(), which numerous C programs
+assume to be the case. The draft ANSI C standard, and Harbison and
+Steele's ``C Reference Manual'', emphasize that only values returned by
+ftell() should be used as arguments to fseek(), allowing the program to
+return to a position previously read or written. UNFORTUNATELY, VMS C
+ftell() DOES NOT RETURN A CORRECT OFFSET VALUE FOR RECORD FILES.
+Instead, for record files, it returns the byte offset of the start of
+the current record, no matter where in that record the current position
+may be. This misbehavior is completely unnecessary, since the
+replacements below perform correctly, and are written entirely in C.
+
+Another problem is that ungetc(char c, FILE* fp) is unreliable. VMS C
+implements characters as signed 8-bit integers (so do many other C
+implementations). fgetc(FILE* fp) returns an int, not a char, whose
+value is EOF (-1) in the event of end-of-file; however, this value will
+also be returned for a character 0xFF, so it is essential to use
+feof(FILE *fp) to test for a true end-of-file condition when EOF is
+returned. ungetc() checks the sign of its argument c, and if it is
+negative (which it will be for 128 of the 256 signed bytes), REFUSES TO
+PUT IT BACK IN THE INPUT STREAM, on the assumption that c is really EOF.
+This too can be fixed; ungetc() should only do nothing if feof()
+indicates a true end-of-file condition. The overhead of this is
+trivial, since feof() is actually implemented as a macro which does
+nothing more than a logical AND and compare-with-zero.
+
+getchar() waits for a <CR> to be typed when stdin is a terminal; the
+replacement vms_getchar() remedies this.
+
+Undoubtedly other deficiencies in VMS C will reveal themselves.
+
+VMS read() returns only a single disk block on each call. Its
+replacment, vms_read(), will return the requested number of bytes, if
+possible.
+
+There are also a few Unix standard functions which are unimplemented.
+qsort() is not provided. getlogin() and unlink() have VMS equivalents
+provided below. tell() is considered obsolete, since its functionality
+is available from lseek(), but it is still seen in a few programs, so is
+provided below. getenv() fails if the name contains a colon; its
+replacement allows the colon.
+
+In the interest of minimal source perturbation, replacements for VMS
+functions are given the same names, but prefixed "vms_". For
+readability, the original names are preserved, but are converted to
+upper-case:
+
+ #define FTELL vms_ftell
+ #define FSEEK vms_fseek
+ #define GETCHAR vms_getchar
+ #define GETENV vms_getenv
+ #define UNGETC vms_ungetc
+
+These are only defined to work correctly for fixed length 512-byte
+records, and no check is made that the file has that organization (it is
+possible, but not without expensive calls to fstat(), or access to
+internal library structures).
+
+[02-Apr-87] -- Nelson H.F. Beebe, University of Utah Center for
+ Scientific Computing
+***********************************************************************/
+
+#define EXIT vms_exit
+#define FTELL vms_ftell
+#define FSEEK vms_fseek
+#define GETENV vms_getenv
+#define GETCHAR vms_getchar
+#define READ vms_read
+#define UNGETC vms_ungetc
+
+#include <stdio.h>
+#include <types.h>
+#include <ctype.h>
+#include <stat.h>
+#include <descrip.h>
+#include <iodef.h> /* need for vms_getchar() */
+#include <ssdef.h>
+
+/**********************************************************************/
+/*-->EXIT*/
+
+void
+vms_exit(code)
+int code;
+{
+ switch (code)
+ {
+ case 0:
+ exit(1); /* success */
+ break;
+
+ default:
+ exit(2); /* error */
+ break;
+ }
+}
+
+/**********************************************************************/
+/*-->FSEEK*/
+
+/* VMS fseek() and ftell() on fixed-length record files work correctly
+only at block boundaries. This replacement code patches in the offset
+within the block. Directions from current position and from
+end-of-file are converted to absolute positions, and then the code for
+that case is invoked. */
+
+long
+FSEEK(fp,n,dir)
+FILE *fp;
+long n;
+long dir;
+{
+ long k,m,pos,val,oldpos;
+ struct stat buffer;
+
+ for (;;) /* loops only once or twice */
+ {
+ switch (dir)
+ {
+ case 0: /* from BOF */
+ oldpos = FTELL(fp); /* get current byte offset in file */
+ k = n & 511; /* offset in 512-byte block */
+ m = n >> 9; /* relative block number in file */
+ if (((*fp)->_cnt) && ((oldpos >> 9) == m)) /* still in same block */
+ {
+ val = 0; /* success */
+ (*fp)->_ptr = ((*fp)->_base) + k; /* reset pointers to requested byte */
+ (*fp)->_cnt = 512 - k;
+ }
+ else
+ {
+ val = fseek(fp,m << 9,0); /* move to start of requested 512-byte block */
+ if (val == 0) /* success */
+ {
+ (*fp)->_cnt = 0; /* indicate empty buffer */
+ (void)fgetc(fp); /* force refill of buffer */
+ (*fp)->_ptr = ((*fp)->_base) + k; /* reset pointers to requested byte */
+ (*fp)->_cnt = 512 - k;
+ }
+ }
+ return(val);
+
+ case 1: /* from current pos */
+ pos = FTELL(fp);
+ if (pos == EOF) /* then error */
+ return (EOF);
+ n += pos;
+ dir = 0;
+ break; /* go do case 0 */
+
+ case 2: /* from EOF */
+ val = fstat(fileno(fp),&buffer);
+ if (val == EOF) /* then error */
+ return (EOF);
+ n += buffer.st_size - 1; /* convert filesize to offset and */
+ /* add to requested offset */
+ dir = 0;
+ break; /* go do case 0 */
+
+ default: /* illegal direction parameter */
+ return (EOF);
+ }
+ }
+}
+
+/**********************************************************************/
+/*-->FTELL*/
+
+/* With fixed-length record files, ftell() returns the offset of the
+start of block. To get the true position, this must be biased by
+the offset within the block. */
+
+long
+FTELL(fp)
+FILE *fp;
+{
+ char c;
+ long pos;
+ long val;
+ if ((*fp)->_cnt == 0) /* buffer empty--force refill */
+ {
+ c = fgetc(fp);
+ val = UNGETC(c,fp);
+ if (val != c)
+ return (EOF); /* should never happen */
+ }
+ pos = ftell(fp); /* this returns multiple of 512 (start of block) */
+ if (pos >= 0) /* then success--patch in offset in block */
+ pos += ((*fp)->_ptr) - ((*fp)->_base);
+ return (pos);
+}
+
+/**********************************************************************/
+/*-->GETCHAR*/
+
+static int tt_channel = -1; /* terminal channel for image QIO's */
+
+#define FAILED(status) (~(status) & 1) /* failure if LSB is 0 */
+
+int
+GETCHAR()
+{
+ int ret_char; /* character returned */
+ int status; /* system service status */
+ static $DESCRIPTOR(sys_in,"TT:");
+
+ if (tt_channel == -1) /* then first call--assign channel */
+ {
+ status = sys$assign(&sys_in,&tt_channel,0,0);
+ if (FAILED(status))
+ lib$stop(status);
+ }
+ ret_char = 0;
+ status = sys$qiow(0,tt_channel,IO$_TTYREADALL | IO$M_NOECHO,0,0,0,
+ &ret_char,1,0,0,0,0);
+ if (FAILED(status))
+ lib$stop(status);
+
+ return (ret_char);
+}
+
+/**********************************************************************/
+/*-->READ*/
+int
+READ(file_desc,buffer,nbytes)
+register int file_desc;
+register char *buffer;
+register int nbytes;
+{
+ register int ngot;
+ register int left;
+
+ for ((left = nbytes, ngot = 0); left > 0; /* NOOP */)
+ {
+ ngot = read(file_desc,buffer,left);
+ if (ngot < 0)
+ return (-1); /* error occurred */
+ buffer += ngot;
+ left -= ngot;
+ }
+ return(nbytes-left);
+}
+
+/**********************************************************************/
+/*-->UNGETC*/
+long
+UNGETC(c,fp) /* VMS ungetc() is a no-op if c < 0 (which is half the time!) */
+char c;
+FILE *fp;
+{
+
+ if ((c == EOF) && feof(fp))
+ return (EOF); /* do nothing at true end-of-file */
+ else if ((*fp)->_cnt >= 512)/* buffer full--no fgetc() done in this block!*/
+ return (EOF); /* must be user error if this happens */
+ else /* put the character back in the buffer */
+ {
+ (*fp)->_cnt++; /* increase count of characters left */
+ (*fp)->_ptr--; /* backup pointer to next available char */
+ *((*fp)->_ptr) = c; /* save the character */
+ return (c); /* and return it */
+ }
+}
+
+/**********************************************************************/
+/*-->getenv*/
+char*
+GETENV(name)
+char* name;
+{
+ char* p;
+ char* result;
+ char ucname[256];
+
+ p = ucname;
+ while (*name) /* VMS logical names must be upper-case */
+ {
+ *p++ = islower(*name) ? toupper(*name) : *name;
+ ++name;
+ }
+ *p = '\0';
+
+ p = strchr(ucname,':'); /* colon in name? */
+ if (p == (char *)NULL) /* no colon in name */
+ result = getenv(ucname);
+ else /* try with and without colon */
+ {
+ result = getenv(ucname);
+ if (result == (char *)NULL)
+ {
+ *p = '\0';
+ result = getenv(ucname);
+ *p = ':';
+ }
+ }
+ return (result);
+}
+
+/**********************************************************************/
+/*-->getlogin*/
+char*
+getlogin()
+{
+ return ((char *)getenv("USER")); /* use equivalent VMS routine */
+}
+
+/**********************************************************************/
+/*-->qsort*/
+
+/***********************************************************************
+TeXindex uses the standard Unix library function qsort() for
+record sorting. Unfortunately, qsort() is not a stable sorting
+algorithm, so input order is not necessarily preserved for equal
+sort keys. This is important, because the sorting is
+case-independent, while the actual entries may not be. For
+example, the input
+
+\entry{i}{22}{{\CODE{i}}}
+\entry{i}{42}{{\CODE{i}}}
+\entry{I}{41}{{\CODE{I}}}
+\entry{I}{42}{{\CODE{I}}}
+
+produces
+
+\initial {I}
+\entry {{\CODE{i}}}{22}
+\entry {{\CODE{I}}}{41--42}
+\entry {{\CODE{i}}}{42}
+
+instead of the correct
+
+\initial {I}
+\entry {{\CODE{i}}}{22, 42}
+\entry {{\CODE{I}}}{41--42}
+
+We therefore provide this stable shellsort replacement for
+qsort() based on the code given on p. 116 of Kernighan and
+Ritchie, ``The C Programming Language'', Prentice-Hall (1978).
+This has order N**1.5 average performance, which is usually
+slower than qsort(). In the interests of simplicity, we make no
+attempt to handle short sequences by alternative methods.
+
+[07-Nov-86]
+***********************************************************************/
+
+#if VMS_QSORT
+#define BASE(i) &base[(i)*width]
+
+void
+qsort(base, nel, width, compar)
+ char base[]; /* start of data in memory */
+ int nel; /* number of elements to be sorted */
+ int width; /* size (in bytes) of each element */
+ int (*compar)(); /* comparison function */
+{
+ int gap;
+ int i;
+ int j;
+
+ register int k; /* inner exchange loop parameters */
+ register char* p;
+ register char* q;
+ register char c;
+
+ for (gap = nel/2; gap > 0; gap /= 2)
+ {
+ for (i = gap; i < nel; i++)
+ {
+ for (j = i-gap; j >= 0; j -= gap)
+ {
+ p = BASE(j);
+ q = BASE(j+gap);
+ if ((*compar)(p,q) <= 0)
+ break; /* exit j loop */
+ else
+ {
+ for (k = 0; k < width; (++p, ++q, ++k))
+ {
+ c = *q;
+ *q = *p;
+ *p = c;
+ }
+ }
+ }
+ }
+ }
+}
+#endif
+/**********************************************************************
+*-->system*
+int
+system(s)
+char *s;
+{
+ struct dsc$descriptor t;
+
+ t.dsc$w_length = strlen(s);
+ t.dsc$a_pointer = s;
+ t.dsc$b_class = DSC$K_CLASS_S;
+ t.dsc$b_dtype = DSC$K_DTYPE_T;
+ return (LIB$SPAWN(&t) == SS$_NORMAL) ? 0 : 127;
+}
+
+**********************************************************************/
+/*-->tell*/
+long
+tell(handle)
+int handle;
+{
+ return (lseek(handle,0L,1));
+}
+
+/**********************************************************************/
+/*-->unlink*/
+int
+unlink(filename)
+char *filename;
+{
+ return (delete(filename)); /* use equivalent VMS routine */
+}
+
diff --git a/obsolete/dviware/dvi2xx/commands.h b/obsolete/dviware/dvi2xx/commands.h
new file mode 100644
index 0000000000..3de8eeeebe
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/commands.h
@@ -0,0 +1,65 @@
+/* DVI COMMANDS */
+#define SETC_000 0 /* typeset character 0 and move right */
+#define SETC_127 127 /* typeset character 127 and move right */
+#define SET1 128 /* typeset a character and move right */
+#define SET2 129 /* ??? */
+#define SET3 130 /* ??? */
+#define SET4 131 /* ??? */
+#define SET_RULE 132 /* typeset a rule and move right */
+#define PUT1 133 /* typeset a character */
+#define PUT2 134 /* ??? */
+#define PUT3 135 /* ??? */
+#define PUT4 136 /* ??? */
+#define PUT_RULE 137 /* typeset a rule */
+#define NOP 138 /* no operation */
+#define BOP 139 /* beginning of page */
+#define EOP 140 /* ending of page */
+#define PUSH 141 /* save the current positions */
+#define POP 142 /* restore previous positions */
+#define RIGHT1 143 /* move right */
+#define RIGHT2 144 /* ??? */
+#define RIGHT3 145 /* ??? */
+#define RIGHT4 146 /* ??? */
+#define W0 147 /* move right by |w| */
+#define W1 148 /* move right and set |w| */
+#define W2 149 /* ??? */
+#define W3 150 /* ??? */
+#define W4 151 /* ??? */
+#define X0 152 /* move right by |x| */
+#define X1 153 /* move right and set |x| */
+#define X2 154 /* ??? */
+#define X3 155 /* ??? */
+#define X4 156 /* ??? */
+#define DOWN1 157 /* move down */
+#define DOWN2 158 /* ??? */
+#define DOWN3 159 /* ??? */
+#define DOWN4 160 /* ??? */
+#define Y0 161 /* move down by |y| */
+#define Y1 162 /* move down and set |y| */
+#define Y2 163 /* ??? */
+#define Y3 164 /* ??? */
+#define Y4 165 /* ??? */
+#define Z0 166 /* move down by |z| */
+#define Z1 167 /* move down and set |z| */
+#define Z2 168 /* ??? */
+#define Z3 169 /* ??? */
+#define Z4 170 /* ??? */
+#define FONT_00 171 /* set current font to 0 */
+#define FONT_63 234 /* set current font to 0 */
+#define FNT1 235 /* set current font */
+#define FNT2 236 /* Same as FNT1, except that arg is 2 bytes */
+#define FNT3 237 /* Same as FNT1, except that arg is 3 bytes */
+#define FNT4 238 /* Same as FNT1, except that arg is 4 bytes */
+#define XXX1 239 /* extension to \.DVI primitives */
+#define XXX2 240 /* Like XXX1, but 0<=k<65536 */
+#define XXX3 241 /* Like XXX1, but 0<=k<@t$2^{24}$@> */
+#define XXX4 242 /* potentially long extension to \.DVI
+ primitives */
+#define FNT_DEF1 243 /* define the meaning of a font number */
+#define FNT_DEF2 244 /* ??? */
+#define FNT_DEF3 245 /* ??? */
+#define FNT_DEF4 246 /* ??? */
+#define PRE 247 /* preamble */
+#define POST 248 /* postamble beginning */
+#define POST_POST 249 /* postamble ending */
+ /* undefined_commands 250,251,252,253,254,255 */
diff --git a/obsolete/dviware/dvi2xx/config.h b/obsolete/dviware/dvi2xx/config.h
new file mode 100644
index 0000000000..f643620824
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/config.h
@@ -0,0 +1,255 @@
+#define USEPXL
+
+/*
+ * default font path
+ * can be overridden by environment variable TEXPXL
+ * or -a command line option
+ * popular choice:
+ * #define FONTAREA "/usr/local/lib/tex/fonts/pk"
+ */
+#ifndef FONTAREA
+#ifdef vms
+#define FONTAREA "tex$pkdir:"
+#else
+#ifdef _AMIGA
+#define FONTAREA "TeX:pk"
+#else
+#define FONTAREA "/usr/local/lib/tex/pk300"
+#endif
+#endif
+#endif
+
+/* if DO_SUBDIRECTORIES is specified, search to this depth */
+#ifndef MAX_SUBDIR_SEARCH_DEPTH
+#define MAX_SUBDIR_SEARCH_DEPTH 10
+#endif
+
+/*
+ * if your LaserJet II P or LaserJet III or LaserJet 2000
+ * complains about not enough memory, you might try to reduce
+ * the value below or uncomment to use the default settings
+ */
+#ifdef LJ2P
+#define MAX_FONTS_PER_PAGE 255 /* maximum number of fonts per page */
+#endif
+
+
+/* Timing is not very portable.... if you have troubles, use
+ * -DNO_TIMING in the Makefile
+ */
+
+#ifdef u3b2
+#define NO_TIMING
+#endif
+#ifdef _AMIGA
+#define NO_TIMING
+#endif
+
+#ifndef NO_TIMING
+#define TIMING
+#endif
+
+/*
+ * per default use MakeTexPK in unix environments unless it is not wanted
+ */
+#ifdef unix
+#ifndef MAKETEXPK
+/* name of the program which is called to generate missing pk files
+ */
+#define MAKETEXPK "MakeTeXPK"
+#endif
+#endif
+
+#ifdef _AMIGA
+#ifndef MAKETEXPK
+/* name of the program which is called to generate missing pk files
+ */
+#define MAKETEXPK "MakeTeXPK"
+#endif
+#endif
+
+
+
+#ifdef NO_MAKETEXPK
+#undef MAKETEXPK
+#endif
+
+/*
+ * assure that LJ2P is defined when LJ4 is defined;
+ * compile with support for LJ4's resident fonts
+ */
+#ifdef LJ4
+#define LJ2P
+#define LJ_RESIDENT_FONTS
+#endif
+
+/*
+ * assure that LJ2 is defined when LJ2P is defined
+ */
+#ifdef LJ2P
+#ifndef LJ2
+#define LJ2
+#endif
+#endif
+
+/*
+ * assure that LJ is defined when LJ2 of LJ4 is defined
+ */
+#if defined(LJ2)
+#ifndef LJ
+#define LJ
+#endif
+#endif
+
+/*
+ * assure that IBM3812 is not defined when LJ is defined
+ */
+#ifdef LJ
+#ifdef IBM3812
+#undef IBM3812
+#endif
+#endif
+
+#ifdef LJ_RESIDENT_FONTS
+#ifndef DEFAULT_TFM_PATH
+#define DEFAULT_TFM_PATH "/usr/local/lib/tex/fonts"
+#endif
+#endif
+
+
+#define TRUE (bool) 1
+#define FALSE (bool) 0
+#define UNKNOWN -1
+
+#define STRSIZE 255 /* stringsize for file specifications */
+
+typedef char bool;
+
+#ifdef hpux
+typedef char signed_char;
+#else
+#ifdef vms
+typedef char signed_char;
+#else
+#ifdef u3b2
+typedef short signed_char;
+#else
+/* this is the default !! */
+typedef signed char signed_char;
+#endif
+#endif
+#endif
+
+#if !defined(u3b2) && !defined(alpha)
+#define ARITHMETIC_RIGHT_SHIFT
+#endif
+
+#ifdef alpha
+#define long int
+#endif
+
+bool findfile();
+
+
+/*
+ * maximal number of characters in font file
+ * #define LASTFNTCHAR 127 7-bit classic version
+ * #define LASTFNTCHAR 255 8-bit fonts
+ */
+
+#ifdef SEVENBIT
+#define LASTFNTCHAR 127
+#else
+#define LASTFNTCHAR 255
+#endif
+
+
+
+/* this information is needed in findfile.c and dvi2xx.c, NO CUSTOMIZATION */
+#ifdef LJ
+#ifdef LJ4
+#define RESOLUTION 600
+/*#define MFMODE "hplf"*/ /* mode definition for metafont */
+#define MFMODE "CanonCX" /* mode definition for metafont */
+#else
+#define RESOLUTION 300
+#define MFMODE "imagen" /* mode definition for metafont */
+#endif
+#endif
+
+#ifdef IBM3812
+#define RESOLUTION 240
+#define MFMODE "IBMThreeEightOneTwo" /* mode definition for metafont */
+#endif
+
+
+#ifdef unix
+#define OS "Unix"
+#define READ_BINARY "r"
+#define WRITE_BINARY "w"
+#define labs(x) abs(x)
+#endif
+#ifdef MSDOS
+#define OS "MS-DOS"
+#define READ_BINARY "rb"
+#define WRITE_BINARY "wb"
+#define MSC5
+#endif
+#ifdef OS2
+#define OS "OS/2"
+#define READ_BINARY "rb"
+#define WRITE_BINARY "wb"
+#define MSC5
+#endif
+
+#ifdef vms
+#define OS "VMS"
+#include <ssdef.h>
+#include <stsdef.h>
+#define ftell vms_ftell /* use some external routines, because */
+#define fseek vms_fseek /* of some bugs in the VMS run time */
+#define getchar vms_getchar /* library */
+#define getenv vms_getenv
+#define ungetc vms_ungetc
+#define getname vms_getname
+#define READ_BINARY "rb"
+#define WRITE_BINARY "wb","rfm=fix","bls=512","mrs=512" /* fixed records */
+#define labs(x) abs(x)
+#endif
+
+#ifdef _AMIGA
+#define OS "Amiga"
+#define READ_BINARY "r"
+#define WRITE_BINARY "w"
+#ifdef __SASC
+#define sys_errlist __sys_errlist
+#include <stdlib.h>
+#endif
+#endif
+
+
+/* Information returned by tfm_read_info. */
+typedef struct {
+ /* These string lengths are imposed by the TFM format. Either of these
+ values may be the empty string. */
+ char coding_scheme[40];
+ char family[20];
+
+ /* The second fontdimen. */
+ unsigned interword;
+
+ /* These values are what will work to select the font in PCL. If this
+ TFM file doesn't have the `KN' extensions (distinguishable by the
+ family == "HPAUTOTFM"). */
+#define SPACING_FIXED 0
+#define SPACING_PROPORTIONAL 1
+ unsigned spacing;
+ int weight;
+ unsigned style;
+ unsigned typeface_id;
+
+ /* TFM files can always have 256 characters, even if we're using the
+ old pixel format that only supports 128. The values are fix-words
+ scaled by the design size; i.e., straight from the TFM file. */
+ long widths[256];
+} tfm_info_type;
diff --git a/obsolete/dviware/dvi2xx/dvi2xx.051 b/obsolete/dviware/dvi2xx/dvi2xx.051
new file mode 100644
index 0000000000..77383891ed
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/dvi2xx.051
@@ -0,0 +1,64 @@
+Dear user of the dvi2xx driver for the ibm3812 and the lj-family!
+The new release (0.51) features in the following points:
+
+The following items are changed since 0.50:
+ - MakeTeXPK support:
+ If a pk-file is not found on the fontpath the script
+ MakeTeXPK (included in the distribution) is executed to
+ generate the pk file in the requited magnification.
+ - a bug fix for clipping 1 pixel to much on the paper edge
+ (thanks to TeX spieler@linac.ikp.physik.th-darmstadt.de
+ (Christian Spieler)
+ - better handling of large bitmap glyphs (reduced memory
+ assumption esp. in dvilj2p)
+ - vms support (thanks to Henk de Haan <HAAN@IRIMCF.TUDELFT.NL>)
+ - various cleanups in the code
+ - better handling of negative page numbers
+ - support for 3b2 machines (strange c compiler)
+ - support for LaserJet duplex printers such as the HP LaserJet
+ IIId (option -d1 or -d2).
+ - support for direct inclusinion of pcl graphics
+ (thanks to Fred Hoare <fred@dip1.ee.uct.ac.za>, README.pcl)
+ - support for LJ4 (600 dpi)
+ (unknown spender)
+ - support for DEC alpha machines (configured via Makefile)
+ - a bugfix for certain older LaserJet clones, where some
+ garbage was printed on top of the first page
+ (Thanks to Rik Faith <faith@cs.unc.edu>)
+
+included in the distribution
+ - a sample bsd-stype printcap entry for SunOS (thanks to Ted
+ Cox) and a sample lj3-filter written in Perl (evolved from
+ Stefan Essers contribution in comp.lang.perl)
+ - 2up.sty (from tvz@zandtwerk.Princeton.EDU (Timothy Van Zandt))
+ which allows to print LaTeX documents in two-up style (two
+ logical pages are printed on one landscape sheet).
+ Useful in connection with dvilj2p (for LaserJet 2000, LaserJet
+ IIP, LaserJet III and LaserJet IIIP) in connection with
+ MakeTeXPK.
+ - a README file for Dell Unix (Thanks to Fred Appelman
+ <fred@cv.ruu.nl>
+
+The new distribution may be obtained
+
+ - via anonymous ftp from
+
+ ftp.wu-wien.ac.at:pub/src/Typeset/dvi2xx/dvi2xx.051a8.shar
+
+ (source and msdos .exe-files, os2 .exe files, binaries for DecStations
+ under ultrix 4.1, rs6000 under aix 3.1 and hp9000/835 under hpux 7.0
+ will follow with the final 0.51 distribution)
+
+ The ip-address of ftp.wu-wien.ac.at is 137.208.3.4
+
+ - from Simtel20 (soon); at least pc-binaries and sources
+
+ - via sending a short note indicating wether you want to receive the new
+ distribution (source and/or PC-binaries).
+
+-gustaf neumann
+-----------------------------------------------------------------------------
+Gustaf Neumann neumann@dec4.wu-wien.ac.at, neumann@awiwuw11.bitnet
+Vienna University of Economics and Business Administration
+Augasse 2-6, A-1090 Vienna, Austria
+Tel: +43 (222) 31-336 4533 ~Fax 347-555
diff --git a/obsolete/dviware/dvi2xx/dvi2xx.c b/obsolete/dviware/dvi2xx/dvi2xx.c
new file mode 100644
index 0000000000..8c0959bce9
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/dvi2xx.c
@@ -0,0 +1,4634 @@
+#define VERSION "0.51alpha9"
+/**********************************************************************
+ **************************** Intro *********************************
+ **********************************************************************
+ * This program translates TeX's DVI-Code into device dependent
+ * code of either the
+ *
+ * - HP-LASERJET+ and compatibles (PCL), or the
+ * - IBM 3812 pageprinter
+ *
+ * depending on the preprocessor switches specified before compilation.
+ * The program is written to run on a PC XT/AT/PS2 under MS-DOS. It can
+ * be compiled nicely with MSC Rel. 3.0-5.1 with option -AL (large memory
+ * model). Take care that in the CONFIG.SYS file the FILES parameter
+ * is set to 20; otherwise reduce MAXOPEN. 640K are recommended.
+ * I use link option /stack:9000 to increase runtime stack.
+ * It also works without modifications under Unix System V.
+ **********************************************************************
+ * Adapted for the PC: Gustaf Neumann
+ * +1002 stuff University of Economics
+ * +3812 support Augasse 2-6
+ * +Output buffering A-1090 Vienna, AUSTRIA
+ * +lpt binary support Tel. *43-222-340525/533
+ * +pk-89 stuff 773
+ * +pixelpaths
+ * +alternative directory structure
+ * +code compiles also under Unix V (HP/UX)
+ * (thx Michael Haberler)
+ * +huge characters (a character bigger than 32K)
+ * formats PXL1001 and PXL 1002
+ * (use: raster graphics)
+ * +reduction of the produced code
+ * +new options -X -Y -c -g
+ * +changed options -r (LJ now default from first to last)
+ * -x,-y (accept floats)
+ * +new option -z for LJ: print testpage containing
+ * pagecounter after printjob
+ * +try to overcome font limit on LJ (max 16 fonts/page) and
+ * (max 32 fonts/document):
+ * additional fonts are drawn as bitmap-
+ * graphics.
+ * +allows to set character close to the paperedge on LJ
+ * +gf-supprt (by Joe Kelsey joe@Pacer.com)
+ * gf.c and gf.h from mitdevices/dvi2ps
+ * +clipping of rules
+ * +OS/2 defines from Rutger Berns, apprmb@hheouh50.bitnet
+ *
+ * BITNET/EARN: NEUMANN at AWIWUW11
+ **********************************************************************
+ * fixes in LJ-mode: rule-drawing,
+ * characters with 127<=height<=200
+ * reset printer at beginning and end of each job
+ * better positioning of rules
+ * 30.1.89 (0.48) bug fixed for files containing >32 fonts (thanks A. Brosig),
+ * different font assignment heuristic
+ * fixes in 3812-mode: 14.juli 87 positioning of rastered characters
+ * better positioning of rules
+ * general fixes
+ * 1.1.88 page origin set to 1in/1in (hopefully everywhere)
+ * 22.7.88 reset y-position for each page-eject
+ * 15.1.89 fixing bug is space allocation for EmitFileName
+ * (thanks to Bernhard Simon)
+ * 15.3.91 (0.49) landscape support for lj ii p, lj iii and lj 2000
+ * fixing rule drawing problems for IBM3812 in landcape mode,
+ * 256 character clean (lj family and IBM3812)
+ * 5.5.91 (0.50) -DSEVENBIT added for older LJ-emulations
+ * -D1, -D2, -D-, -D1-, -D2- options added due to suggestions
+ * from Tomasz Wolniewicz
+ **********************************************************************
+ * Preprocessor switches:
+ * #define DEBUG for massive printing of trace information
+ * when -d cmdline option specified
+ * #define IBM3812 produce output for the IBM3812 pageprinter
+ * #define LJ produce output for the HP Laserjet+ or LJ II
+ * #define LJ2P produce output for the HP Laserjet LJ IIP, LJ III
+ * or LaserJet 2000
+ * #define LJ_LARGE_FONT_MEMORY large FONT Memory for LJ printer family
+ * #define DRAWGLYPH draws PK-Glyphs on stderr
+ * #define USEPXL use PXL and PK fonts rather than gf fonts
+ */
+/**********************************************************************
+ ************************ Global Definitions ************************
+ **********************************************************************/
+/* #define IBM3812 */
+/* #define LJ */
+/* #define DRAWGLYPH */
+
+#include "config.h"
+
+
+#include "commands.h"
+#include <string.h>
+#include <signal.h>
+#include <stdio.h>
+#include <ctype.h>
+#ifdef vms
+#include <file.h>
+#else
+#include <fcntl.h>
+#endif
+#ifdef MSDOS
+#include <dos.h> /* only for binaryopen on device */
+#endif
+#ifdef unix
+#include <limits.h>
+#endif
+
+#define DVIFORMAT 2
+#define UNKNOWN -1
+#define FIRSTFNTCHAR 0
+
+#ifdef OPEN_MAX /* ... in a friendly unix system */
+#ifndef vms
+#define MAXOPEN_OS (OPEN_MAX - 8)
+#else
+#define MAXOPEN_OS 12 /* OPEN_MAX seems to be 8 on VMS systems */
+#endif
+#else
+#define MAXOPEN_OS 12 /* limit on number of open font files */
+#endif
+
+#ifdef LJ_RESIDENT_FONTS
+/* we have to read tfm files as well */
+#define MAXOPEN (MAXOPEN_OS - 1)
+#else
+#define MAXOPEN MAXOPEN_OS
+#endif
+
+#define NFNTCHARS LASTFNTCHAR+1
+#define STACK_SIZE 100 /* DVI-stack size */
+#define NONEXISTANT -1 /* offset for PXL files not found */
+#define NO_FILE ((FILE *)-1)
+#define NEW(A) ((A *) malloc(sizeof(A)))
+#define EQ(a,b) (strcmp(a,b)==0)
+#define MM_TO_PXL(x) (int)(((x)*RESOLUTION*10)/254)
+#define PT_TO_PXL(x) (int)((long)((x)*RESOLUTION*100l)/7224)
+#define PT_TO_DVI(x) (long)((x)*65536l)
+#define BOPENCMD fopen
+#define BINOPEN(f) BOPENCMD(f,READ_BINARY)
+/* SMALL_SIZE characters are loaded into font storage of the printer */
+/* LARGE_SIZE characters are rastered */
+/* HUGE_SIZE characters are not loaded into the memory of the host */
+#define SMALL_SIZE (unsigned char) 0
+#define LARGE_SIZE (unsigned char) 1
+#define HUGE_SIZE (unsigned char) 2
+#define HUGE_CHAR_PATTERN 32767l
+#define BYTES_PER_PIXEL_LINE 500 /* max number of bytes per pixel line */
+
+
+#define PK_POST 245
+#define PK_PRE 247
+#define PK_ID 89
+
+/* to speedup the program a little: redefinition of PixRound and PutWord */
+/*#define PIXROUND(x,c) ((((double)x+(double)(c>>1))/(double)c)+0.5)*/
+#define PIXROUND(x,c) (((x)+c)/c)
+#define PUTWORD(w) EMITC((char)(w>>8)&0xff); EMITC((char)w&0xff)
+/*************************************************************************/
+#define EMIT fprintf /* output a formatted string */
+#ifndef vms
+#define EMITB(len,b) fwrite(b,1,len,outfp) /* output binary data of len */
+#else
+ /* VMS doesn't like to use fwrite on a file with fixed record sizes,
+ so use number of putc calls */
+#define EMITB(len,b) for (kk = 0;kk < len; kk++) putc(*(b+kk),outfp);
+#endif
+#define EMITWORD(w) PUTWORD((w)) /* output a 2 byte word of data */
+
+#define MoveOver(b) h += (long) b
+#define MoveDown(a) v += (long) a
+#define qfprintf if (!G_quiet) fprintf
+#define qprintf if (!G_quiet) printf
+#define LARGER(a,b) (((a)>(b)) ? (a) : (b))
+
+#ifdef IBM3812
+#define PRINTER "IBM 3812 pageprinter"
+#define EMITC(c) PMPoutC(c) /* output a single character */
+#define PMPcont(l) PMPout(-1,(long)l) /* next l bytes continuous */
+#define PMPflush PMPout(0l,"") /* flush PMP-buffer */
+#define EMITL(l,d) PMPout((int)l,d) /* EMIT-logical: via PMP-buffer */
+#define hconvRESOLUTION 240
+#define vconvRESOLUTION 240
+#define CHAR_WIDTH_LARGE 100 /* limit for loading into printer font */
+#define CHAR_HEIGTH_LARGE 127 /* limit for loading into printer font */
+#define OUTBUFSIZE 20000 /* size of output buffer for PMP cmds */
+ /* has to be less max(signed int) */
+#define MAXFONTSTORAGE 130000l /* font storage in the 3812 pageprinter */
+#define EMITFILE_EXTENSION ".pmp" /* default extension of emit file */
+#define XDEFAULTOFF RESOLUTION /* y default offset on page 1 inch */
+#define YDEFAULTOFF RESOLUTION /* y default offset on page 1 inch */
+#define CHARSTRINGMAX 80 /* bufferlength for SetString */
+#define MAX_PAGE_WIDTH 2040
+#define MAX_PAGE_HEIGHT 3360
+/**********************************************************************/
+/************** Positioning for the 3812 ****************************/
+/**********************************************************************/
+#define VERT_HALF(n) ((short)((n+1)>>1)-1)
+#define HOR_HALF(n) ((short)(n>>1))
+#define MoveHor(n) if ((n)!=0) { PMPcont(3); PMPout(1,"\342"); EMITWORD((n)); }
+#define MoveVert(n) if ((n)!=0) { PMPcont(3); PMPout(1,"\343"); EMITWORD((n)); }
+#endif
+
+#ifdef LJ
+#ifdef LJ4
+#define PRINTER "HP Laserjet IV"
+#else
+#ifdef LJ2P
+#define PRINTER "HP LaserJet IIP"
+#else
+#ifdef LJ2
+#define PRINTER "HP LaserJet II"
+#else
+#define PRINTER "HP LaserJet"
+#endif
+#endif
+#endif
+#define hconvRESOLUTION RESOLUTION
+#define vconvRESOLUTION RESOLUTION
+#ifdef LJ2
+/* the printer limit of the LJ2P is actually 16384x16384,
+ * but to exploit it, one would need lots of memory in the printer
+ */
+#define CHAR_WIDTH_LARGE 200 /* limit for loading into printer font */
+#define CHAR_HEIGTH_LARGE 255 /* y_offset reaches the same size! */
+#else /* such as LaserJet+, Laserjet II */
+#define CHAR_WIDTH_LARGE 100 /* limit for loading into printer font */
+#define CHAR_HEIGTH_LARGE 127 /* y_offset reaches the same size! */
+#endif
+#define EMITFILE_EXTENSION ".lj" /* default extension of emit file */
+#ifndef MAX_FONTS_PER_PAGE
+#define MAX_FONTS_PER_PAGE 16 /* maximum number of fonts per page */
+#endif
+#define HANDLE_MAX_FONTS 255 /* max nr of fonts handled (rasterfont) */
+#define FONTS_DOWNLOADABLE 32 /* max nr of fonts that can be downloaded */
+#define MAXFONTSTORAGE (395l*1024l) /* standard user memory */
+#define EMITC(c) putc(c,outfp) /* output a single character */
+#define EMITL(l,d) EMITB(l,d) /* EMIT-logical = EMITB */
+#define XDEFAULTOFF RESOLUTION-54 /*x default offset on page 1 inch (LJ2)*/
+#define YDEFAULTOFF RESOLUTION+9 /* y default offset on page 1 inch */
+#define max(x,y) if ((y)>(x)) x = y
+#ifndef vms
+#define INT_ASCII(b,i) if (i == 0) b[0] = '\0'; else sprintf((char *)b,"%hd",i)
+#else
+#define INT_ASCII(b,i) if (i == 0) b[0] = '\0'; else sprintf((char *)b,"%d",i)
+#endif
+#endif
+
+#ifdef SEVENBIT
+#define VIS 33
+#define VIS2 (VIS+32)
+unsigned char
+VisChar(c)
+unsigned char c;
+{
+ c &= 0xff;
+ if (c < VIS)
+ return ((unsigned char)(160 + c));
+ if (c < 128)
+ return (c);
+ if (c < (255 - VIS2))
+ return ((unsigned char)(VIS2 + c));
+ return (255);
+}
+#else
+#define VisChar(c) (unsigned char)(c)
+#endif
+
+
+/**********************************************************************/
+/*********************** external definitions ***********************/
+/**********************************************************************/
+
+#ifndef _AMIGA
+#ifndef unix
+long access();
+FILE *BOPENCMD();
+void exit();
+int fclose();
+int fprintf();
+int fseek();
+char *index();
+int printf();
+int sscanf();
+int strcmp();
+char *strcpy();
+#ifdef MSC5
+unsigned int strlen();
+#endif
+void free();
+void setbuf();
+#endif
+
+#ifdef MSDOS
+int intdos();
+#else
+char *malloc();
+char *getenv();
+int atoi();
+#endif
+#endif
+
+
+#ifndef USEPXL
+/* interface to gf.c */
+extern FILE *gfin;
+extern int checksum;
+extern long tfm_wd[], char_pointer[];
+extern char char_exists[];
+extern int num_cols, num_rows, num_bytes, x_offset, y_offset;
+extern unsigned char bits[];
+extern int gf_font_max_m, gf_font_max_n, gf_font_min_n;
+extern int gettochar();
+extern void readbits();
+extern void readpost();
+extern void seekpost();
+extern int seekchar();
+#endif
+
+
+/**********************************************************************/
+/************************* Global Procedures ************************/
+/**********************************************************************/
+/* Note: Global procedures are declared here in alphabetical order, with
+ those which do not return values typed "void". Their bodies occur in
+ alphabetical order following the main() procedure. The names are
+ kept unique in the first 6 characters for portability. */
+double ActualFactor();
+void AllDone();
+#ifdef MSDOS
+void AssureBinary(); /* DOS and Microsoft C dependent !!! */
+#endif
+void CopyFile();
+void CopyHPFile();
+void DecodeArgs();
+void DoBop();
+long DoConv();
+void DoSpecial();
+void EmitChar();
+void Fatal();
+void FindPostAmblePtr();
+void FormFeed();
+void GetBytes();
+void GetFontDef();
+char *GetKeyStr();
+bool GetKeyVal();
+bool IsSame();
+void lcase();
+void LoadAChar();
+long NoSignExtend();
+/* see cautionary note in code, re arithmetic vs logical shifts */
+void OpenFontFile();
+long PixRound();
+void PkRaster();
+void PutWord();
+void RasterLine();
+void RasterChar();
+void ReadFontDef();
+void ReadPostAmble();
+void SetChar();
+void SetFntNum();
+void SetPosn();
+void SetRule();
+void SetString();
+long SignExtend();
+/* see cautionary note in code, re arithmetic vs logical shifts */
+void SkipFontDef();
+void Warning();
+unsigned char skip_specials() ;
+
+#ifdef IBM3812
+void PMPout();
+void PMPoutC();
+#endif
+
+/**********************************************************************/
+/*********************** Font Data Structures ***********************/
+/**********************************************************************/
+
+struct char_entry { /* character entry */
+#ifdef USEPXL
+ unsigned short width, height; /* width and height in pixels */
+ short xOffset, yOffset, yyOffset; /* x offset and y offset in pixels*/
+#endif
+ struct {
+ bool isloaded;
+ union {
+ long fileOffset;
+ long *pixptr;
+ } address;
+ } where;
+ long tfmw; /* TFM width */
+ long cw; /* character width in pixels */
+ unsigned char flag_byte; /* for PK-files */
+ unsigned char charsize;
+};
+struct font_entry { /* font entry */
+ long k, c, s, d;
+ int a, l;
+ char n[STRSIZE]; /* FNT_DEF command parameters */
+ long font_mag; /* computed from FNT_DEF s and d parameters */
+ /*char psname[STRSIZE];*/ /* PostScript name of the font */
+ char name[STRSIZE]; /* full name of PXL file */
+ FILE * font_file_id; /* file identifier (NO_FILE if none) */
+#ifdef USEPXL
+ long magnification; /* magnification read from PXL file */
+ long designsize; /* design size read from PXL file */
+#endif
+ struct char_entry ch[NFNTCHARS]; /* character information */
+ struct font_entry *next;
+ unsigned short ncdl; /* #of different chars actually downloaded */
+ unsigned short plusid; /* Font id in Printer */
+ bool used_on_this_page;
+#ifdef LJ_RESIDENT_FONTS
+ bool resident_p; /* is font resident in printer? */
+ char symbol_set[40]; /* symbol set value (resident fonts) */
+ unsigned short resid; /* typeface id (resident fonts) */
+ unsigned spacing; /* 0=monospace, 1=variable (resident fonts) */
+ unsigned style; /* upright/italic/... (resident fonts) */
+ int weight; /* regular/bold/... (resident fonts) */
+ double pitch; /* chars per inch (monospaced resident fonts)*/
+#endif
+ enum PxlId {
+ id1001, id1002, pk89 } id;
+#ifdef LJ
+ unsigned short max_width, max_height, max_yoff;
+#endif
+};
+
+
+struct pixel_list {
+ FILE *pixel_file_id; /* file identifier */
+ int use_count; /* count of "opens" */
+};
+/**********************************************************************/
+/************************* Global Variables *************************/
+/**********************************************************************/
+long FirstPage = -1000000; /* first page to print (uses count0) */
+long LastPage = 1000000; /* last page to print */
+long PrintPages = 1000000; /* nr of pages to print */
+bool FirstPageSpecified = FALSE;
+bool LastPageSpecified = FALSE;
+char G_progname[STRSIZE]; /* program name */
+char filename[STRSIZE]; /* DVI file name */
+char rootname[STRSIZE]; /* DVI filename without extension */
+char *PXLpath = FONTAREA; /* PXL path name for search */
+char *HeaderFileName = ""; /* file name & path of Headerfile */
+char *EmitFileName = ""; /* file name & path for output */
+#ifdef IBM3812
+bool FirstAlternate = FALSE; /* first page from alternate casette ? */
+#endif
+bool Reverse = FALSE; /* process DVI pages in reverse order? */
+bool Landscape = FALSE; /* print document in ladscape mode */
+bool ResetPrinter = TRUE; /* reset printer at the begin of the job*/
+bool DoublePage = FALSE; /* print on both sides of a paper */
+bool PrintSecondPart = TRUE; /* print First Part when DoublePage */
+bool PrintFirstPart = TRUE; /* print Second Part when DoublePage */
+bool PrintEmptyPages = TRUE; /* print Empty pages in DoublePage mode*/
+short PageParity = 1;
+#ifdef MAKETEXPK
+bool makeTexPK = TRUE;
+#endif
+
+#ifdef LJ
+#ifdef LJ2P
+int DuplexMode = 0;
+#endif
+#ifdef LJ4
+bool econoMode = FALSE;
+#endif
+bool PrintTestPage = FALSE; /* print testpage with pagecounter after job */
+unsigned short pagesize = 0; /* page size value */
+unsigned short pgsiz_dots = 0; /* page size in dots (for rule-clipping)*/
+#endif
+
+
+#ifndef vms
+short G_errenc = 0; /* has an error been encountered? */
+#else
+long G_errenc = SS$_NORMAL; /* has an error been encountered? */
+#endif
+bool G_header = FALSE; /* copy header file to output? */
+bool G_quiet = FALSE; /* for quiet operation */
+bool G_noverbatim = TRUE; /* inform user about pxl-files used */
+bool G_nowarn = FALSE; /* don't print out warnings */
+short x_origin = XDEFAULTOFF; /* x-origin in dots */
+short y_origin = YDEFAULTOFF; /* y-origin in dots */
+short x_goffset; /* global x-offset in dots */
+short y_goffset; /* global y-offset in dots */
+unsigned short ncopies = 1; /* number of copies to print */
+long hconv, vconv; /* converts DVI units to pixels */
+long den; /* denominator specified in preamble */
+long num; /* numerator specified in preamble */
+long h; /* current horizontal position */
+long hh = 0; /* current h on device */
+long v; /* current vertical position */
+long vv = 0; /* current v on device */
+long mag; /* magnification specified in preamble */
+long usermag = 0; /* user specified magnification */
+int ndone = 0; /* number of pages converted */
+int nopen = 0; /* number of open PXL files */
+#ifdef vms
+int kk; /* loop variable for EMITB */
+#endif
+FILE *outfp = NULL; /* output file */
+FILE *pxlfp; /* PXL file pointer */
+FILE *dvifp = NULL; /* DVI file pointer */
+struct font_entry *prevfont = NULL; /* font_entry pointer previous font*/
+struct font_entry *fontptr; /* font_entry pointer */
+struct font_entry *hfontptr = NULL; /* font_entry pointer */
+struct font_entry *pfontptr = NULL; /* previous font_entry pointer */
+struct pixel_list pixel_files[MAXOPEN+1]; /* list of open PXL files */
+long postambleptr; /* Pointer to the postamble */
+long ppagep; /* previous page pointer */
+static int last_ry = UNKNOWN; /* last y-position on page */
+static int last_rx = UNKNOWN; /* last x-position on page */
+long StartPrintPages; /* notpad for double paged output */
+int WouldPrint = 0;
+bool ZeroPage = FALSE; /* Document starts with a Zero Page */
+bool EvenPage = FALSE; /* Document starts with an even Page */
+long LastPtobePrinted = 0;
+int G_ncdl = 0;
+
+long allocated_storage = 0; /* size of mallocated storage (statistics) */
+long power[32] ;
+long gpower[33] ;
+
+
+#ifdef DEBUG
+int Debug = 0;
+#endif
+
+#ifdef LJ
+int fonts_used_on_this_page = MAX_FONTS_PER_PAGE+1;
+char rasterfont[HANDLE_MAX_FONTS];
+ /* raster if fonts/page>MAX_FONTS_PER_PAGE*/
+#ifdef LJ_RESIDENT_FONTS
+unsigned resident_count = 0;
+char *TFMpath = DEFAULT_TFM_PATH;
+#endif
+#endif
+
+long used_fontstorage = 0;
+
+#ifdef IBM3812
+char PMPformat[20];
+char CharString[CHARSTRINGMAX];
+unsigned int CharStringPos = 0;
+#define CharStringOut \
+ if (CharStringPos>0) { \
+ PMPcont(CharStringPos+1);\
+ PMPoutC((unsigned char)CharStringPos);\
+ PMPout(CharStringPos, CharString); \
+ CharStringPos=0; }
+#endif
+
+#ifdef TIMING
+/************************timing stuff*********************/
+#ifdef BSD_TIME_CALLS
+#ifndef vms
+#include <sys/timeb.h>
+#else
+#include <timeb.h>
+#endif
+struct timeb timebuffer;
+double start_time;
+#else
+#include <sys/time.h>
+struct timeval Tp;
+double start_time;
+#endif
+#endif
+
+
+
+/**********************************************************************/
+/******************************* main *******************************/
+/**********************************************************************/
+void
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ struct stack_entry { /* stack entry */
+ long h, v, w, x, y, z; /* what's on stack */
+ };
+ short command; /* current command */
+ long count[10]; /* the 10 counters at begining of each page*/
+ long cpagep = 0; /* current page pointer */
+ bool Emitting = FALSE; /* outputting typsetting instructions? */
+ int i; /* command parameter; loop index */
+ int k; /* temporary parameter */
+ char n[STRSIZE]; /* command parameter */
+ int PassNo = 0; /* which pass over the DVI page are we on? */
+ bool SkipMode = FALSE; /* in skip mode flag */
+ int sp = 0; /* stack pointer */
+ struct stack_entry stack[STACK_SIZE]; /* stack */
+ char SpecialStr[STRSIZE]; /* "\special" strings */
+ long val, val2; /* temporarys to hold command information */
+ long w = 0; /* current horizontal spacing */
+ long x = 0; /* current horizontal spacing */
+ long y = 0; /* current vertical spacing */
+ long z = 0; /* current vertical spacing */
+
+
+#ifdef vms
+ extern noshare int errno;
+ extern noshare char *sys_errlist[];
+#else
+ extern char *sys_errlist[];
+ extern int errno;
+#endif
+
+ setbuf(stderr, NULL);
+ (void) strcpy(G_progname, argv[0]);
+ DecodeArgs( argc, argv );
+
+ power [ 0 ] = 1 ;
+ for ( i = 1 ; i <= 31 ; i ++)
+ power [ i ] = power [ i - 1 ] << 1 ;
+ gpower[0] = 0l ;
+ for ( i = 1 ; i <= 32 ; i ++)
+ gpower[i] = gpower[i - 1] + power[i - 1] ;
+
+ if ((i = (int) NoSignExtend(dvifp, 1)) != PRE) {
+ Fatal(
+ "%s: PRE doesn't occur first--are you sure this is a DVI file?\n\n",
+ G_progname);
+ }
+ i = (int) SignExtend(dvifp, 1);
+ if (i != DVIFORMAT) {
+ Fatal( "%s: DVI format = %d, can only process DVI format %d files\n\n",
+ G_progname, i, DVIFORMAT);
+ }
+
+ if (*EmitFileName == '-')
+ outfp = stdout;
+ else
+ if ((outfp = fopen(EmitFileName, WRITE_BINARY)) == NULL)
+ Fatal("opening output file: fopen(%s) : %s",
+ EmitFileName,sys_errlist[errno]);
+
+#ifdef MSDOS
+ AssureBinary(outfp);
+#endif
+
+#ifdef TIMING
+#ifdef BSD_TIME_CALLS
+ ftime(&timebuffer);
+ start_time = timebuffer.time + (float)(timebuffer.millitm) / 1000.0;
+#else
+ gettimeofday(&Tp, NULL);
+ start_time = Tp.tv_sec + ((float)(Tp.tv_usec))/ 1000000.0;
+#endif
+#endif
+
+ /* it is important that these be the very first things output !!! */
+ if ( G_header )
+ CopyFile( HeaderFileName );
+
+ /*****************************/
+ /*for( i0=0; i0<nif; i0++ ) */ /* copy all included files */
+ /* CopyFile( Ifile[i0] ); */
+ /*****************************/
+
+#ifdef IBM3812
+ PMPout(3, "\307\310\366"); /* unload all fonts and macros */
+ EMITWORD(MAX_PAGE_WIDTH);
+ EMITWORD(MAX_PAGE_HEIGHT);
+ if (Landscape)
+ PMPout(2, "\322\1");
+#endif
+#ifdef LJ
+ if (ResetPrinter)
+ EMIT(outfp, "\033E");
+#ifdef LJ4
+ EMIT(outfp, "\033%%-12345X@PJL SET RESOLUTION=600\012");
+ EMIT(outfp, "@PJL SET PAGEPROTECT=OFF\012");
+ EMIT(outfp, "@PJL SET ENTER LANGUAGE=PCL\012");
+ EMIT(outfp, "\033&u600D\033*t600R");
+ if (econoMode)
+ EMIT(outfp, "\033*v1T");
+#endif
+#ifdef LJ2P
+ if (DuplexMode)
+ EMIT(outfp, "\033&l%dH", DuplexMode);
+#endif
+ if (Landscape)
+ EMIT(outfp, "\033&l1O\033*rF");
+ if (pagesize>0)
+#ifndef vms
+ EMIT(outfp, "\033&l%hdaE\033&aL", pagesize);
+#else
+ EMIT(outfp, "\033&l%daE\033&aL", pagesize);
+#endif
+ else
+ EMIT(outfp, "\033&lE\033&aL");
+
+ if (ncopies>1)
+#ifndef vms
+ EMIT(outfp, "\033&l%hdX", ncopies);
+#else
+ EMIT(outfp, "\033&l%dX", ncopies);
+#endif
+#endif
+ if (DoublePage) {
+ StartPrintPages = PrintPages;
+#ifdef IBM3812
+ Reverse = (bool)!Reverse; /* perverse and strange */
+#endif
+
+ }
+ if (Reverse) {
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr, "reverse\n");
+#endif
+ ReadPostAmble(TRUE);
+ fseek(dvifp, ppagep, 0);
+ } else {
+ ReadPostAmble(TRUE);
+ fseek(dvifp, 14l, 0);
+ k = (int) NoSignExtend(dvifp, 1);
+ GetBytes(dvifp, n, k);
+ }
+ PassNo = 0;
+
+ while (TRUE) {
+ command = (short) NoSignExtend(dvifp, 1) ;
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"CMD:\t%d\n", command);
+#endif
+ switch (command) {
+ case SET1:
+ case SET2:
+ case SET3:
+ case SET4:
+ val = NoSignExtend(dvifp, (int) command - SET1 + 1);
+ if (!SkipMode)
+ SetChar(val, command, PassNo, TRUE,FALSE);
+ break;
+ case SET_RULE:
+ val = NoSignExtend(dvifp, 4);
+ val2 = NoSignExtend(dvifp, 4);
+ if (Emitting)
+ SetRule(val, val2, 1);
+ break;
+ case PUT1:
+ case PUT2:
+ case PUT3:
+ case PUT4:
+ val = NoSignExtend(dvifp, (int) command - PUT1 + 1);
+ if (!SkipMode)
+ SetChar(val, command, PassNo, TRUE,FALSE);
+ break;
+ case PUT_RULE:
+ val = NoSignExtend(dvifp, 4);
+ val2 = NoSignExtend(dvifp, 4);
+ if (Emitting)
+ SetRule(val, val2, 0);
+ break;
+ case NOP:
+ break;
+ case BOP:
+ cpagep = ftell(dvifp) - 1;
+ for (i = 0; i <= 9; i++)
+ count[i] = NoSignExtend(dvifp, 4);
+ ppagep = NoSignExtend(dvifp, 4);
+ h = v = w = x = y = z = 0;
+ hh = vv = 0;
+ sp = 0;
+ fontptr = NULL;
+ prevfont = NULL;
+ DoBop();
+/*
+fprintf(stderr,"skimode %d, count %d, F %d, L %d\n",
+ (int)SkipMode,(int)count[0],(int)FirstPageSpecified,(int)LastPageSpecified);
+*/
+ SkipMode = (bool) ((FirstPageSpecified && count[0] < FirstPage) ||
+ (LastPageSpecified && count[0] > LastPage ));
+/*
+fprintf(stderr,"skimode %d, count %d, F %d, L %d\n",
+ (int)SkipMode,(int)count[0],(int)FirstPageSpecified,(int)LastPageSpecified);
+*/
+
+ if (DoublePage && !SkipMode) {
+ if (PassNo == 0) {
+ LastPtobePrinted=count[0];
+ if (!Reverse && (WouldPrint == 0)) {
+ if (count[0] == 0l) {
+ ZeroPage = TRUE;
+ EvenPage = FALSE;
+ }
+ else {
+ EvenPage = (bool) ( (count[0]<0? labs(count[0])+1: count[0]) %2 == 0);
+
+ if (PrintEmptyPages && EvenPage && PageParity==1) {
+ WouldPrint ++;
+ if (PrintFirstPart) {
+ qfprintf(stderr,"[EvenPage] ");
+ FormFeed();
+ }
+ }
+ }
+ }
+ WouldPrint ++;
+/*
+ fprintf(stderr, "doublepage %d, page parity = %d, 1=%d 2=%d, Reverse %d, WouldPrint %d, fpZ %d\n",
+ (int)DoublePage, (int)PageParity,(int)PrintFirstPart,(int)PrintSecondPart,
+ (int)Reverse, (int)WouldPrint, (int)ZeroPage);
+*/
+ }
+ if (!PrintFirstPart && PageParity==1) {
+ if (count[0]==0l) {
+ ZeroPage = TRUE;
+ EvenPage = FALSE;
+ }
+ SkipMode = TRUE;
+ }
+ else {
+/*
+fprintf(stderr,"FirstPart\n count %d, mod %d, pp %d\n",(int)count[0],(int)count[0]%2,PageParity);
+*/
+ SkipMode = (bool)(PageParity != (short)(
+ (count[0]<0? labs(count[0])+1: count[0])%2));
+ if (count[0]==0l) SkipMode=(bool)!SkipMode;
+ }
+
+ }
+ Emitting = (bool)((PassNo != 0) && !SkipMode);
+/*
+fprintf(stderr,"Emitting= %d, PassNo=%d, SkipMode = %d\n",(int)Emitting,(int)PassNo,(int)SkipMode);
+*/
+ if ( !SkipMode ) {
+ if ( PassNo == 0)
+ qfprintf(stderr, "[%ld", count[0]);
+ }
+ break;
+ case EOP:
+ if ( !SkipMode ) {
+ if ( PassNo == 0 ) {
+ /* start second pass on current page */
+ fseek(dvifp, cpagep, 0);
+ PassNo = 1;
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"\nStarting second pass\n");
+#endif
+
+ } else {
+ /* end of second pass, and of page processing */
+
+ last_ry = UNKNOWN;
+ FormFeed();
+ ++ndone;
+
+ qfprintf(stderr, "] ");
+ if ( (ndone % 10) == 0 )
+ qfprintf(stderr, "\n");
+
+ if (DoublePage) --PrintPages;
+ if (--PrintPages < 1) AllDone(TRUE);
+ PassNo = 0;
+ }
+ } else
+ PassNo = 0;
+
+ if ( PassNo == 0 && Reverse ) {
+ if ( ppagep > 0 )
+ fseek(dvifp, ppagep, 0);
+ else {
+ if (DoublePage && !SkipMode)
+ ZeroPage = (bool)(count[0]==0l);
+
+ if (ZeroPage)
+ EvenPage = FALSE;
+ else
+ EvenPage = (bool) ((int)LastPtobePrinted%2 == 0);
+
+ AllDone(FALSE);
+ }
+ }
+ break;
+ case PUSH:
+ if (sp >= STACK_SIZE)
+ Fatal("stack overflow");
+ stack[sp].h = h;
+ stack[sp].v = v;
+ stack[sp].w = w;
+ stack[sp].x = x;
+ stack[sp].y = y;
+ stack[sp].z = z;
+ sp++;
+ break;
+ case POP:
+ --sp;
+ if (sp < 0)
+ Fatal("stack underflow");
+ h = stack[sp].h;
+ v = stack[sp].v;
+ w = stack[sp].w;
+ x = stack[sp].x;
+ y = stack[sp].y;
+ z = stack[sp].z;
+ break;
+ case RIGHT1:
+ case RIGHT2:
+ case RIGHT3:
+ case RIGHT4:
+ val = SignExtend(dvifp, (int) command - RIGHT1 + 1);
+ if (Emitting)
+ MoveOver(val);
+ break;
+ case W0:
+ if (Emitting)
+ MoveOver(w);
+ break;
+ case W1:
+ case W2:
+ case W3:
+ case W4:
+ w = SignExtend(dvifp, (int)command - W1 + 1);
+ if (Emitting)
+ MoveOver(w);
+ break;
+ case X0:
+ if (Emitting)
+ MoveOver(x);
+ break;
+ case X1:
+ case X2:
+ case X3:
+ case X4:
+ x = SignExtend(dvifp, (int)command - X1 + 1);
+ if (Emitting)
+ MoveOver(x);
+ break;
+ case DOWN1:
+ case DOWN2:
+ case DOWN3:
+ case DOWN4:
+ val = SignExtend(dvifp, (int)command - DOWN1 + 1);
+ if (Emitting)
+ MoveDown(val);
+ break;
+ case Y0:
+ if (Emitting)
+ MoveDown(y);
+ break;
+ case Y1:
+ case Y2:
+ case Y3:
+ case Y4:
+ y = SignExtend(dvifp, (int)command - Y1 + 1);
+ if (Emitting)
+ MoveDown(y);
+ break;
+ case Z0:
+ if (Emitting)
+ MoveDown(z);
+ break;
+ case Z1:
+ case Z2:
+ case Z3:
+ case Z4:
+ z = SignExtend(dvifp, (int)command - Z1 + 1);
+ if (Emitting)
+ MoveDown(z);
+ break;
+ case FNT1:
+ case FNT2:
+ case FNT3:
+ case FNT4:
+ if (!SkipMode) {
+ SetFntNum(NoSignExtend(dvifp, (int)command -FNT1 +1),Emitting);
+ }
+ break;
+ case XXX1:
+ case XXX2:
+ case XXX3:
+ case XXX4:
+ k = (int) NoSignExtend(dvifp, (int)command - XXX1 + 1);
+ GetBytes(dvifp, SpecialStr, k);
+ if (Emitting)
+ DoSpecial(SpecialStr, k);
+ break;
+ case FNT_DEF1:
+ case FNT_DEF2:
+ case FNT_DEF3:
+ case FNT_DEF4:
+ k = (int) NoSignExtend(dvifp, (int)command - FNT_DEF1 + 1);
+ SkipFontDef(); /* SkipFontDef(k); */
+ break;
+ case PRE:
+ Fatal("PRE occurs within file");
+ break;
+ case POST:
+ AllDone(FALSE);
+ PassNo = 0;
+ break;
+ case POST_POST:
+ Fatal("POST_POST with no preceding POST");
+ break;
+ default:
+ if (command >= FONT_00 && command <= FONT_63) {
+ if (!SkipMode)
+ SetFntNum((long) command - FONT_00, Emitting);
+ } else if (command >= SETC_000 && command <= SETC_127) {
+ if (!SkipMode) {
+ SetString(command, PassNo);
+ }
+ } else
+ Fatal("%d is an undefined command", command);
+ break;
+ }
+ } /* while TRUE */
+}
+
+
+/*-->ActualFactor*/
+/**********************************************************************/
+/************************** ActualFactor ****************************/
+/**********************************************************************/
+double /* compute the actual size factor given the approximation */
+ActualFactor(unmodsize)
+long unmodsize; /* actually factor * 1000 */
+{
+ double realsize; /* the actual magnification factor */
+ realsize = (double)unmodsize / 1000.0;
+ if (abs((int)(unmodsize - 1095l))<2)
+ realsize = 1.095445115; /*stephalf*/
+ else if (abs((int)(unmodsize - 1315l))<2)
+ realsize = 1.31453414; /*stepihalf*/
+ else if (abs((int)(unmodsize - 1577l))<2)
+ realsize = 1.57744097; /*stepiihalf*/
+ else if (abs((int)(unmodsize - 1893l))<2)
+ realsize = 1.89292916; /*stepiiihalf*/
+ else if (abs((int)(unmodsize - 2074l))<2)
+ realsize = 2.0736; /*stepiv*/
+ else if (abs((int)(unmodsize - 2488l))<2)
+ realsize = 2.48832; /*stepv*/
+ else if (abs((int)(unmodsize - 2986l))<2)
+ realsize = 2.985984; /*stepvi*/
+ /* the remaining magnification steps are represented with sufficient
+ accuracy already */
+ return(realsize);
+}
+
+
+/*-->AllDone*/
+/**********************************************************************/
+/****************************** AllDone ******************************/
+/**********************************************************************/
+void
+AllDone(PFlag)
+bool PFlag;
+{
+ double time;
+
+ if (DoublePage && (PageParity==1)) { /* Shall we go around again?*/
+ int k;
+ char n[STRSIZE];
+
+ if (PrintEmptyPages && EvenPage && Reverse && PrintFirstPart) {
+ WouldPrint ++;
+ qfprintf(stderr,"[EvenPage] ");
+ FormFeed();
+ }
+#ifdef LJ
+ Reverse = (bool)!Reverse;
+#endif
+ if (Reverse) {
+ if (!PFlag) {
+ fseek (dvifp, postambleptr, 0);
+ (void) NoSignExtend(dvifp, 1);
+ ppagep = NoSignExtend(dvifp, 4);
+ }
+ fseek(dvifp, ppagep, 0);
+ } else {
+ fseek(dvifp, 14l, 0);
+ k = (int) NoSignExtend(dvifp, 1);
+ GetBytes(dvifp, n, k);
+ }
+
+ if (PrintSecondPart) {
+ if (PrintFirstPart) {
+ qfprintf(stderr,"\n----------------------starting second pass\n");
+#ifdef LJ
+ EMIT(outfp, "\033&l2H"); /* Manual Feed */
+#endif
+#ifdef IBM3812
+ PMPout(6,"\326\001\305\300\326\252");
+ /* set display; ring bell; stop; clear display */
+ PMPflush;
+#endif
+ }
+
+ if (PrintEmptyPages && Reverse) {
+ if (ZeroPage) WouldPrint++;
+ if ((WouldPrint%2) == 1) {
+ qfprintf(stderr,"[Padding] ");
+ FormFeed();
+ }
+ }
+ WouldPrint = 0;
+ if (PrintEmptyPages && !Reverse && ZeroPage) {
+ WouldPrint++;
+ qfprintf(stderr,"[ZeroPage] ");
+ FormFeed();
+ }
+ PageParity = 0;
+ PrintPages = StartPrintPages;
+ return;
+ }
+ }
+
+ if (EvenPage && DoublePage && !Reverse) WouldPrint++;
+
+ if (PrintEmptyPages && DoublePage && PrintSecondPart) {
+ if (Reverse) {
+ if (ZeroPage) {
+ WouldPrint ++;
+ qfprintf(stderr,"[ZeroPage] ");
+ FormFeed();
+ }
+ }
+ else if ((WouldPrint%2) != 0) {
+ qfprintf(stderr,"[Padding] ");
+ FormFeed();
+ }
+ }
+
+#ifdef IBM3812
+ PMPout(10, "\373\010PMP.init"); /* re-init printer */
+ PMPflush;
+
+ if (used_fontstorage > MAXFONTSTORAGE) {
+ Warning("\n\7used font_storage of %s: %ld Bytes (of %ld)\7",
+ PRINTER, used_fontstorage, MAXFONTSTORAGE);
+ Warning("Try to format file in separate runs!");
+ } else
+ qfprintf(stderr,
+ "\nAll done, used font_storage of %s: %ld Bytes (of %ld)",
+ PRINTER, used_fontstorage, MAXFONTSTORAGE);
+#endif
+#ifdef LJ
+ qfprintf(stderr, "\nAll done, used font_storage of %s: %ld Bytes",
+ PRINTER, used_fontstorage);
+#ifdef LJ_RESIDENT_FONTS
+ qfprintf(stderr, " + %d resident font%s", resident_count,
+ resident_count == 1 ? "" : "s");
+#endif
+ EMIT(outfp, "\033E");
+#ifdef LJ4
+ EMIT(outfp, "\033%%-12345X"); /* what does it? */
+#endif
+ if (PrintTestPage) EMIT(outfp, "\033z");
+#ifdef vms
+ /* last record is not flushed to file, unless it is completely filled */
+ for (kk = (int)((*outfp)->_cnt); kk > 0; --kk) putc('\0',outfp);
+ fflush(outfp);
+#endif
+#endif
+
+ if (!G_quiet) {
+ fprintf(stderr,"\nDynamically allocated storage: %ld Bytes \n",
+ allocated_storage);
+ fprintf(stderr,"%d characters downloaded as soft fonts\n", G_ncdl);
+
+#ifdef TIMING
+#ifdef BSD_TIME_CALLS
+ ftime(&timebuffer);
+ time = (timebuffer.time + (float)(timebuffer.millitm)/1000.0)
+ - start_time;
+#else
+ gettimeofday(&Tp, NULL);
+ time = (Tp.tv_sec + (float)(Tp.tv_usec)/1000000.0) - start_time;
+#endif
+
+ if (ndone > 0) {
+ fprintf(stderr,
+ "Time of complete run: %.2f seconds, %d page(s), %.2f seconds/page",
+ time, ndone, time / ndone);
+ fprintf(stderr," (%.2f ppm)\n",(ndone * 60) / time);
+ }
+ fprintf(stderr,"\n");
+#endif
+ }
+
+ exit(G_errenc);
+}
+
+
+/*-->CopyFile*/ /* copy a file straight through to output */
+/*********************************************************************/
+/***************************** CopyFile ******************************/
+/*********************************************************************/
+void
+CopyFile( str )
+char *str;
+{
+ FILE * spfp;
+ char t;
+ if ( (spfp = BINOPEN(str)) == NULL ) {
+ Warning("Unable to open file %s", str );
+ return;
+ }
+ qfprintf(stderr," [%s", str);
+ for (t = (char)getc(spfp); !feof(spfp); t = (char)getc(spfp))
+ putc(t, outfp);
+ fclose(spfp);
+ qfprintf(stderr,"]");
+}
+
+
+/*-->CopyHPFile*/ /* copy a HP file to output removing unwanted control codes*/
+/*********************************************************************/
+/***************************** CopyHPFile ******************************/
+/*********************************************************************/
+void
+CopyHPFile( str )
+char *str;
+{
+ FILE * spfp;
+ char t,numstr[20];
+ int count,rx,ry,miny,minx,num;
+
+ if ( (spfp = BINOPEN(str)) == NULL ) {
+ Warning("Unable to open file %s", str );
+ return;
+ }
+ minx=32767; /* Set to a high value initially */
+ miny=32767;
+
+/* Pass through the input PCL file twice. The first time find the smallest */
+/* x- and y-offsets so that they can be subtracted out when sending */
+/* positioning commands later. The second pass strips the unwanted commands */
+/* from the input file and outputs the rest */
+
+ qfprintf(stderr," [%s", str);
+ for (t = (char)getc(spfp); !feof(spfp); t = (char)getc(spfp))
+ {
+ if (t==0x1B) /* Find the escape character */
+ {
+ t=(char) getc(spfp);
+ if (t==0x2A) /* This indiactes the start of a graphics command */
+ {
+
+ t=(char) getc(spfp);
+ switch(t)
+ {
+ case(0x70):
+ /* These are the graphics positioning commands */
+ /* Find the smallest x and y offsets */
+ num=0;
+ count=0;
+ for (t=(char) getc(spfp);t<0x40;t=(char) getc(spfp))
+ numstr[count++]=t;
+ numstr[count]=0;
+ num= atoi (numstr);
+
+ /* Take into account the possible different ordering */
+ /* of the commands (x first, y first) */
+
+ if ((t==0x59)||(t==0x79))
+ {
+ if (numstr[0]!='+'&&numstr[0]!='-'&&numstr[0]!='-')
+ if (num<miny) miny=num;
+ if (t==0x79)
+ {
+ num=0;
+ count=0;
+ for (t=(char) getc(spfp);t<0x40;t=(char) getc(spfp))
+ numstr[count++]=t;
+ numstr[count]=0;
+ num=atoi (numstr);
+ if(numstr[0]!='+'&&numstr[0]!='-'&&numstr[0]!='-')
+ if (num<minx) minx=num;
+ }
+ }
+ if ((t==0x58)||(t==0x78))
+ {
+ if (numstr[0]!='+'&&numstr[0]!='-'&&numstr[0]!='-')
+ if (num<minx) minx=num;
+ if (t==0x78)
+ {
+ num=0;
+ count=0;
+ for (t=(char) getc(spfp);t<0x40;t=(char) getc(spfp))
+ numstr[count++]=t;
+ numstr[count]=0;
+ num= atoi (numstr);
+ if (numstr[0]!='+'&&numstr[0]!='-'&&numstr[0]!='-')
+ if (num<miny) miny=num;
+ }
+ }
+ break;
+ /* Ignore all other commands for the moment - just read them */
+ case(0x74):
+ for (t=(char) getc(spfp);t != 0x52; t=(char) getc(spfp));
+ break;
+
+ case(0x72):
+ for (t=(char) getc(spfp);((t< 0x40)||(t>0x60)); t=(char) getc(spfp));
+ break;
+
+ case(0x62):
+ num=0;
+ count=0;
+ /* Read in the correct number of bytes of raster graphics */
+ /* so that we don't get commands and raster graphics confused */
+
+ for (t=(char) getc(spfp);((t<0x40)||(t>=0x60));t=(char) getc(spfp))
+ numstr[count++]=t;
+ numstr[count]=0;
+ if (t==0x4D)
+ for(t=numstr[count=0];t!=0;t=numstr[++count]);
+ if (t==0x57)
+ {
+ for(t=numstr[count=0];t!=0;t=numstr[++count]);
+ for(count= atoi(numstr);count>0;count--)
+ t=(char) getc(spfp);
+ }
+ break;
+
+ case(0x63):
+ for (t=(char) getc(spfp);((t< 0x40)||(t>0x60)); t=(char) getc(spfp));
+ break;
+
+ default:
+ break;
+
+
+ }
+ }
+ }
+ }
+ fclose(spfp);
+ qfprintf(stderr,"]");
+
+ if ( (spfp = BINOPEN(str)) == NULL ) {
+ Warning("Unable to open file %s", str );
+ return;
+ }
+ qfprintf(stderr," [%s", str);
+
+/* Pass through the input file again but this time output the */
+/* retained PCL commands */
+
+ for (t = (char)getc(spfp); !feof(spfp); t = (char)getc(spfp))
+ {
+ if (t==0x1B)
+ {
+ t=(char) getc(spfp);
+ if (t==0x2A)
+ {
+ t=(char) getc(spfp);
+ switch(t)
+ {
+ case(0x70):
+ num=0;
+ count=0;
+ for (t=(char) getc(spfp);t<0x40;t=(char) getc(spfp))
+ numstr[count++]=t;
+ numstr[count]=0;
+ num= atoi (numstr);
+ if ((t==0x59)||(t==0x79))
+ {
+ if (numstr[0]!='+'&&numstr[0]!='-')
+ {
+ /* Subtract the minimum offset found in first pass */
+ /* and add in the current vertical offset */
+ ry=num-miny+(int)PIXROUND(v,vconv)+y_goffset;
+ /* Output the new positioning command */
+ EMIT(outfp,"\033*p%dY",ry);
+ }
+
+ else if (num>=0) EMIT(outfp,"\033*p%c%dY",numstr[0],num);
+ else EMIT(outfp,"\033*p%dY",num);
+
+ if (t==0x79)
+ {
+ num=0;
+ count=0;
+ for (t=(char) getc(spfp);t<0x40;t=(char) getc(spfp))
+ numstr[count++]=t; /* reconstructed code */
+ numstr[count]=0;
+ num=atoi (numstr);
+ if(numstr[0]!='+'&&numstr[0]!='-')
+ {
+ /*Add in correct horizontal offset */
+ rx=num-minx+(int)PIXROUND(h,hconv)+x_goffset;
+ EMIT(outfp,"\033*p%dX",rx);
+ }
+ else if (num>=0) EMIT(outfp,"\033*p%c%dX",numstr[0],num);
+ else EMIT(outfp,"\033*p%dX",num);
+ }
+ }
+
+ if ((t==0x58)||(t==0x78))
+ {
+ if(numstr[0]!='+'&&numstr[0]!='-')
+ {
+ /*Add in the correct horizontal offset*/
+ rx=num-minx+(int)PIXROUND(h,hconv)+x_goffset;
+ EMIT(outfp,"\033*p%dX",rx);
+ }
+ else if (num>=0) EMIT(outfp,"\033*p%c%dX",numstr[0],num);
+ else EMIT(outfp,"\033*p%dX",num);
+
+ if (t==0x78)
+ {
+ num=0;
+ count=0;
+ for (t=(char) getc(spfp);t<0x40;t=(char) getc(spfp))
+ numstr[count++]=t;
+ numstr[count]=0;
+ num= atoi (numstr);
+ if(numstr[0]!='+'&&numstr[0]!='-')
+ {
+ /*Add in correct vertical offset*/
+ ry=num-miny+(int)PIXROUND(v,vconv)+y_goffset;
+ EMIT(outfp,"\033*p%dY",ry);
+ }
+ else if (num >=0) EMIT(outfp,"\033*p%c%dY",numstr[0],num);
+ else EMIT(outfp,"\033*p%dY",num);
+ }
+ }
+ break;
+
+ case(0x74):
+ /* Set the Raster resolution */
+ EMIT(outfp,"\033*t");
+ for (t=(char) getc(spfp);t != 0x52; t=(char) getc(spfp))
+ putc(t,outfp);
+ putc(t,outfp);
+ break;
+
+ case(0x72):
+ /* Raster Graphics commands such as start */
+ EMIT(outfp,"\033*r");
+ for (t=(char) getc(spfp);((t< 0x40)||(t>0x60)); t=(char) getc(spfp))
+ putc(t,outfp);
+ putc(t,outfp);
+ break;
+
+ case(0x62):
+ /* Transfer the correct number of bytes of raster graphics */
+ EMIT(outfp,"\033*b");
+ num=0;
+ count=0;
+ for (t=(char) getc(spfp);((t<0x40)||(t>=0x60));t=(char) getc(spfp))
+ numstr[count++]=t;
+ numstr[count]=0;
+ if (t==0x4D)
+ {
+ for(t=numstr[count=0];t!=0;t=numstr[++count])
+ putc(t,outfp);
+ EMIT(outfp,"M");
+ }
+ if (t==0x57)
+ {
+ for(t=numstr[count=0];t!=0;t=numstr[++count])
+ putc(t,outfp);
+ EMIT(outfp,"W");
+ for(count= atoi(numstr);count>0;count--)
+ {
+ t=(char) getc(spfp);
+ putc(t,outfp);
+ }
+ }
+ break;
+
+ case(0x63):
+ /* Rectangular draw commands */
+ EMIT(outfp,"\033*c");
+ for (t=(char) getc(spfp);((t< 0x40)||(t>0x60)); t=(char) getc(spfp))
+ putc(t,outfp);
+ putc(t,outfp);
+ break;
+
+ default:
+ break;
+
+
+ }
+ }
+ }
+ }
+ fclose(spfp);
+ qfprintf(stderr,"]");
+}
+
+
+
+/*-->DecodeArgs*/
+/*********************************************************************/
+/***************************** DecodeArgs ****************************/
+/*********************************************************************/
+void
+DecodeArgs( argc, argv )
+int argc;
+char *argv[];
+{
+ int argind; /* argument index for flags */
+ char curarea[STRSIZE]; /* current file area */
+ char curname[STRSIZE]; /* current file name */
+ char *tcp, *tcp1; /* temporary character pointers */
+ char *this_arg;
+ double x_offset=0.0, y_offset=0.0;
+
+ if ((tcp = getenv("TEXPXL")) != NULL)
+ PXLpath = tcp;
+
+#ifdef LJ_RESIDENT_FONTS
+ if ((tcp = getenv("TEXFONTS")) != NULL)
+ TFMpath = tcp;
+#endif
+
+ argind = 1;
+ while (argind < argc) {
+ tcp = argv[argind];
+ if (*tcp == '-') {
+ ++tcp;
+ switch (*tcp) {
+ case 'a': /* a selects different pxl font area */
+ PXLpath = ++tcp;
+ break;
+#ifdef IBM3812
+ case 'b': /* first page from alternate casette */
+ FirstAlternate = TRUE;
+ break;
+#endif
+ case 'c': /* number of copies to print */
+ if ( sscanf(tcp + 1, "%hd", &ncopies) != 1 )
+ Fatal("Argument of -c is not a valid integer\n");
+ if (ncopies<1) {
+ Warning("argument of -c < 1; set to 1!");
+ ncopies=1;
+ }
+ break;
+#ifdef DEBUG
+ case '-': /* d selects Debug output */
+ Debug = TRUE;
+ break;
+#endif
+#ifdef LJ2P
+ case 'd': /* d selects DUPLEX mode */
+ tcp++;
+ if (*tcp == '1' ) DuplexMode = 1;
+ else if (*tcp == '2') DuplexMode = 2;
+ else {
+ Warning("Invalid DUPLEX mode, assuming DUPLEX=1, Long-Edge Binding");
+ DuplexMode = 1;
+ }
+ break;
+#endif
+ case 'D': /* D selects DoublePage */
+ DoublePage = TRUE;
+ tcp++;
+ if (*tcp == '1' || *tcp == '2') {
+ if (*tcp == '2') PrintFirstPart = FALSE;
+ else PrintSecondPart = FALSE;
+ tcp++;
+ }
+ if (*tcp == '-') PrintEmptyPages = FALSE;
+ break;
+#ifdef LJ4
+ case 'E': /* do not reset printer (go) */
+ econoMode = TRUE;
+ break;
+#endif
+ case 'e': /* emit file is specified */
+ EmitFileName = ++tcp;
+#ifdef MSDOS
+ /* delete trailing ':' (causing hangup) */
+ if (EmitFileName[strlen(EmitFileName)-1] == ':')
+ EmitFileName[strlen(EmitFileName)-1] = '\0';
+#endif
+#ifdef OS2 /* repeated to avoid problems with stupid c preprocessors */
+ /* delete trailing ':' (causing hangup) */
+ if (EmitFileName[strlen(EmitFileName)-1] == ':')
+ EmitFileName[strlen(EmitFileName)-1] = '\0';
+#endif
+ break;
+ case 'f': /* next arg is starting pagenumber */
+ if ( sscanf(tcp + 1, "%ld", &FirstPage) != 1 )
+ Fatal("Argument is not a valid integer\n");
+ FirstPageSpecified = TRUE;
+ break;
+#ifdef LJ
+ case 'g': /* do not reset printer (go) */
+ ResetPrinter = FALSE;
+ break;
+#endif
+ case 'h': /* copy header file through to output */
+ HeaderFileName = ++tcp;
+ G_header = TRUE;
+ break;
+#if defined(LJ2P) || defined(IBM3812)
+ case 'l': /* landscape */
+ Landscape = TRUE;
+ break;
+#endif
+#ifdef MAKETEXPK
+ case 'M':
+ /* -M, -M1 => don't make font; -M0 => do. */
+ makeTexPK = *(tcp + 1) == '0';
+ break;
+#endif
+ case 'x': /* specify x-offset */
+ this_arg = 0;
+ if (!(*++tcp)) {
+ this_arg = (++argind >= argc ? 0 : argv[argind]);
+ } else {
+ this_arg = tcp;
+ }
+ if (!this_arg
+ || sscanf(this_arg,"%lf", &x_offset) != 1)
+ Fatal("Argument of -x is not a valid floating point number\n");
+ break;
+ case 'y': /* specify y-offset */
+ this_arg = 0;
+ if (!(*++tcp)) {
+ this_arg = (++argind >= argc ? 0 : argv[argind]);
+ } else {
+ this_arg = tcp;
+ }
+ if (!this_arg || sscanf(this_arg, "%lf", &y_offset) != 1)
+ Fatal("Argument of -y is not a valid floating point number\n");
+ break;
+ case 'X': /* specify X-origin in dots */
+ this_arg = 0;
+ if (!(*++tcp)) {
+ this_arg = (++argind >= argc ? 0 : argv[argind]);
+ } else {
+ this_arg = tcp;
+ }
+ if (!this_arg || sscanf(this_arg,"%hd", &x_origin) != 1)
+ Fatal("Argument of -X is not a valid integer\n");
+ break;
+ case 'Y': /* specify Y-origin in dots */
+ this_arg = 0;
+ if (!(*++tcp)) {
+ this_arg = (++argind >= argc ? 0 : argv[argind]);
+ } else {
+ this_arg = tcp;
+ }
+ if (!this_arg ||
+ sscanf(this_arg, "%hd", &y_origin) != 1)
+ Fatal("Argument of -Y is not a valid integer\n");
+ break;
+ case 'm': /* specify magnification to use */
+ switch ( (*++tcp) ) {
+ case '#':
+ /* next arg is a magnification to use */
+ if ( sscanf(tcp + 1, "%ld", &usermag) != 1 )
+ Fatal("Argument of mag is not a valid integer\n");
+ break;
+ case '0':
+ usermag = 1000;
+ break;
+ case 'h':
+ case 'H':
+ usermag = 1095;
+ break;
+ case '1':
+ usermag = 1200;
+ break;
+ case 'q':
+ usermag = 1250;
+ break;
+ case '2':
+ usermag = 1440;
+ break;
+ case '3':
+ usermag = 1728;
+ break;
+ case '4':
+ usermag = 2074;
+ break;
+ case '5':
+ usermag = 2488;
+ break;
+ default:
+ Fatal("%c is a bad mag step\n", *tcp);
+ }
+ break;
+#ifdef SUPERCOMMENT
+ case 'o': /* PostScript command to send */
+ if ( ++argind >= argc )
+ Fatal("No argument following -o\n", 0);
+ PScmd[nps++] = argv[argind];
+ break;
+#endif
+ case 'p': /* print n pages */
+ if ( sscanf(tcp + 1, "%ld", &PrintPages) != 1 )
+ Fatal("Argument is not a valid integer\n");
+ if (PrintPages < 1)
+ Fatal("Argument of -p must be greater than 0\n");
+ break;
+ case 'q': /* quiet operation */
+ G_quiet = TRUE;
+ break;
+ case 'r': /* switch order to process pages */
+ Reverse = (bool)(!Reverse);
+ break;
+#ifdef LJ
+ case 's': /* specify X-origin in dots */
+ this_arg = 0;
+ if (!(*++tcp)) this_arg = (++argind >= argc ? 0 : argv[argind]);
+ else this_arg = tcp;
+ if (!this_arg || sscanf(this_arg,"%hd", &pagesize) != 1)
+ Fatal("Argument of -s is not a valid integer\n");
+ switch (pagesize) {
+ case 1: pgsiz_dots = 3150; break; /* executive */
+ case 2: pgsiz_dots = 3300; break; /* letter */
+ case 3: pgsiz_dots = 4200; break; /* legal */
+ case 26: pgsiz_dots = 3507; break; /* a4 */
+ case 80: pgsiz_dots = 2250; break; /* monarc */
+ case 81: pgsiz_dots = 2850; break; /* com10 */
+ case 90: pgsiz_dots = 2598; break; /* int dl */
+ case 91: pgsiz_dots = 2704; break; /* int c5 */
+ default: Fatal(
+#ifndef vms
+ "%hd is a bad value for pagesize (1,2,3,26,80,81,90,91)",
+#else
+ "%d is a bad value for pagesize (1,2,3,26,80,81,90,91)",
+#endif
+ pagesize);
+ }
+ break;
+#endif
+ case 't': /* ending pagenumber */
+ if ( sscanf(tcp + 1, "%ld", &LastPage) != 1 )
+ Fatal("Argument is not a valid integer\n");
+ LastPageSpecified = TRUE;
+ break;
+ case 'v': /* verbatim mode (print pxl-file names) */
+ G_noverbatim = FALSE;
+ break;
+ case 'w': /* don't print out warnings */
+ G_nowarn = TRUE;
+ break;
+#ifdef LJ
+ case 'z':
+ PrintTestPage = (bool)(!PrintTestPage);
+ break;
+#endif
+ default:
+ fprintf(stderr, "%c is not a legal flag\n", *tcp);
+ }
+ } else {
+
+ (void) strcpy(filename, tcp);
+ tcp = strrchr(argv[argind], '/');
+ /* split into directory + file name */
+ if (tcp == NULL) {
+ curarea[0] = '\0';
+ tcp = argv[argind];
+ } else {
+ (void) strcpy(curarea, argv[argind]);
+ curarea[tcp-argv[argind]+1] = '\0';
+ tcp += 1;
+ }
+
+ (void) strcpy(curname, tcp);
+ /* split into file name + extension */
+ tcp1 = strchr(tcp, '.');
+ if (tcp1 == NULL) {
+ (void) strcpy(rootname, curname);
+ strcat(curname, ".dvi");
+ } else {
+ *tcp1 = '\0';
+ (void) strcpy(rootname, curname);
+ *tcp1 = '.';
+ }
+
+ (void) strcpy(filename, curarea);
+ (void) strcat(filename, curname);
+
+ if ((dvifp = BINOPEN(filename)) == NULL) {
+ Fatal("%s: can't find DVI file \"%s\"\n\n",
+ G_progname, filename);
+ }
+ }
+ argind++;
+ }
+
+ x_goffset = (short) MM_TO_PXL(x_offset) + x_origin;
+ y_goffset = (short) MM_TO_PXL(y_offset) + y_origin;
+
+ if (dvifp == NULL) {
+ fprintf(stderr,"\nThis is the DVI to %s converter version %s",
+ PRINTER, VERSION);
+#ifdef SEVENBIT
+ fprintf(stderr,", 7bit");
+#endif
+ fprintf(stderr," (%s)\n", OS);
+ fprintf(stderr,"usage: %s [OPTIONS] dvifile\n", G_progname);
+
+ fprintf(stderr,"OPTIONS are:\n");
+#ifdef DEBUG
+ fprintf(stderr,"\t-- ..... turns debug output on\n");
+#endif
+ fprintf(stderr,
+ "\t-aX ..... X= searchpath leading to pixel-files (.pk or .pxl)\n");
+#ifdef IBM3812
+ fprintf(stderr,
+ "\t-b ..... take paper for first page from alternate casette\n");
+#endif
+ fprintf(stderr,"\t-cX ..... X= number of copies\n");
+#ifdef LJ2P
+ fprintf(stderr,"\t-dX ..... duplex, X=1: long-edge, 2: short-edge binding\n");
+#endif
+ fprintf(stderr,"\t-D ..... turns doublepage output on; ");
+ fprintf(stderr,"-D1 odd pages only, -D2 even\n");
+#ifdef LJ4
+ fprintf(stderr,"\t-E ..... print in econo-mode\n");
+#endif
+ fprintf(stderr,"\t-eX ..... X= output file\n");
+ fprintf(stderr,"\t-fX ..... print from begin of page number X\n");
+#ifdef LJ
+ fprintf(stderr,
+ "\t-g ..... do not reset printer at begin of job (go)\n");
+#endif
+ fprintf(stderr,"\t-hX ..... X= name of headerfile\n");
+#ifdef LJ2P
+ fprintf(stderr,"\t-l ..... landscape mode\n");
+#endif
+#ifdef MAKETEXPK
+ fprintf(stderr,"\t-MX ..... Don't generate missing PK files\n");
+#endif
+ fprintf(stderr,"\t-mX ..... magnification X=0;h;1;2;3;4;5;#xxxx\n");
+ fprintf(stderr,"\t-pX ..... print X pages\n");
+ fprintf(stderr,"\t-q ..... quiet operation\n");
+ fprintf(stderr,"\t-r ..... process pages in reverse order\n");
+#ifdef LJ
+ fprintf(stderr,"\t-sX ..... set paper size to X (see documentation)\n");
+#endif
+ fprintf(stderr,"\t-tX ..... print to end of page number X\n");
+ fprintf(stderr,"\t-w ..... don't print out warnings\n");
+ fprintf(stderr,"\t-v ..... tell user which pixel-files are used\n");
+ fprintf(stderr,"\t-xX ..... X= x-offset on printout in mm\n");
+ fprintf(stderr,"\t-yX ..... X= y-offset on printout in mm\n");
+ fprintf(stderr,"\t-XO ..... O= x page origin in dots (default=%d)\n",
+ XDEFAULTOFF );
+ fprintf(stderr,"\t-YO ..... O= y page origin in dots (default=%d)\n",
+ YDEFAULTOFF );
+#ifdef LJ
+ fprintf(stderr,
+ "\t-z ..... print test page with pagecounter after job\n");
+#endif
+ exit(1);
+ }
+ if (EQ(EmitFileName, "")) {
+ if ((EmitFileName = malloc( STRSIZE )) != NULL)
+ allocated_storage += STRSIZE;
+ else
+ Fatal("Can't allocate storage of %d bytes\n",STRSIZE);
+ (void) strcpy(EmitFileName, curname);
+ tcp1 = strchr(EmitFileName, '.');
+ *tcp1 = '\0';
+ strcat(EmitFileName, EMITFILE_EXTENSION);
+ }
+}
+
+
+/*-->DoConv*/
+/*********************************************************************/
+/******************************** DoConv ***************************/
+/*********************************************************************/
+long
+DoConv(num, den, convResolution)
+long num, den;
+int convResolution;
+{
+ /*register*/ double conv;
+ conv = ((double)num / (double)den) *
+ ((double)mag / 1000.0) *
+ ((double)convResolution/254000.0);
+
+ return((long) ((1.0/conv)+0.5));
+}
+
+
+/*-->DoSpecial*/
+/*********************************************************************/
+/***************************** DoSpecial ***************************/
+/*********************************************************************/
+typedef enum { None, String, Integer /*, Number, Dimension*/ }
+
+
+ValTyp;
+typedef struct {
+ char *Key; /* the keyword string */
+ char *Val; /* the value string */
+ ValTyp vt; /* the value type */
+ union { /* the decoded value */
+ int i;
+ float n;
+ } v;
+} KeyWord;
+typedef struct {
+ char *Entry;
+ ValTyp Typ;
+} KeyDesc;
+#define PSFILE 0
+#define ORIENTATION 1
+#define RESETPOINTS 2
+#define DEFPOINT 3
+#define FILL 4
+#define GRAY 5
+#define PATTERN 6
+#define HPFILE 7
+KeyDesc KeyTab[] = {
+ { "file", String },
+ { "orientation", Integer},
+ { "resetpoints", String},
+ { "defpoint", String},
+ { "fill", String},
+ { "gray", Integer},
+ { "pattern", Integer},
+ { "hpfile", String}
+ /*,
+ {"hsize", Dimension},
+ {"vsize", Dimension},
+ {"hoffset", Dimension},
+ {"voffset", Dimension},
+ {"hscale", Number},
+ {"vscale", Number}*/
+
+
+};
+
+
+#define NKEYS (sizeof(KeyTab)/sizeof(KeyTab[0]))
+void
+DoSpecial( str, n )
+/* interpret a \special command, made up of keyword=value pairs */
+char *str;
+int n;
+{
+ char spbuf[STRSIZE], xs[STRSIZE], ys[STRSIZE];
+ char *sf = NULL;
+ float x,y;
+ long x_pos, y_pos;
+ KeyWord k;
+ int i, j, j1;
+ static int GrayScale=10, Pattern=1;
+ static bool GrayFill=TRUE;
+ static long p_x[80], p_y[80];
+ str[n] = '\0';
+ spbuf[0] = '\0';
+
+ SetPosn(h, v);
+ while ( (str = GetKeyStr(str, &k)) != NULL ) {
+ /* get all keyword-value pairs */
+ /* for compatibility, single words are taken as file names */
+ if ( k.vt == None && access(k.Key, 0) == 0) {
+ if ( sf )
+ Warning("More than one \\special file name given. %s ignored", sf);
+ (void) strcpy(spbuf, k.Key);
+ sf = spbuf;
+/*
+ for (j = 1; ((sf[j]=='/' ? sf[j]='\\':sf[j]) != '\0'); j++);
+*/
+ } else if ( GetKeyVal( &k, KeyTab, NKEYS, &i ) && i != -1 )
+ switch (i) {
+ case PSFILE:
+ case HPFILE:
+ if ( sf )
+ Warning("More than one \\special file name given. %s ignored",
+ sf);
+ (void) strcpy(spbuf, k.Val);
+ sf = spbuf;
+/*
+ for (j=1; ((sf[j]=='/' ? sf[j]='\\':sf[j]) != '\0'); j++) ;
+*/
+ break;
+ case ORIENTATION:
+#ifdef IBM3812
+ if ((k.v.i >= 0) && (k.v.i < 4)) {
+ last_ry = UNKNOWN;
+ sprintf(PMPformat, "\322%c", (unsigned char)k.v.i);
+ PMPout(2, PMPformat);
+ if (k.v.i == 1) Landscape = TRUE;
+ else if (k.v.i == 0) Landscape = FALSE;
+#endif
+#ifdef LJ
+ if ((k.v.i >= 0) && (k.v.i < 2)) {
+ last_ry = UNKNOWN;
+ EMIT(outfp, "\033&l%dO\033*rF", (unsigned char)k.v.i);
+#endif
+ } else
+ Warning( "Invalid orientation (%d)given; ignored.", k.v.i);
+ break;
+ case RESETPOINTS:
+ (void) strcpy(spbuf, k.Val);
+
+ sf = NULL;
+ break;
+
+ case DEFPOINT:
+ (void) strcpy(spbuf, k.Val);
+ i=sscanf(spbuf,"%d(%[^,],%s)",&j,xs,ys);
+ if (i>0) {
+ x_pos=h; y_pos=v;
+ if (i>1) {
+ if (sscanf(xs,"%fpt",&x)>0) {
+ fprintf(stderr,"x = %f\n",x);
+ x_pos = PT_TO_DVI(x);
+ }
+ }
+ if (i>2) {
+ if (sscanf(ys,"%fpt",&y)>0) {
+ fprintf(stderr,"y = %f\n",y);
+ y_pos = PT_TO_DVI(y);
+ }
+ }
+ p_x[j]=x_pos;
+ p_y[j]=y_pos;
+ } else
+ Warning("invalid point definition\n");
+
+ sf = NULL;
+ break;
+
+ case FILL:
+ (void) strcpy(spbuf, k.Val);
+ i=sscanf(spbuf,"%d/%d %s",&j,&j1,xs);
+ if (i>1) {
+#ifdef LJ
+ SetPosn(p_x[j], p_y[j]);
+ x_pos = (long)PIXROUND(p_x[j1]-p_x[j], hconv);
+ y_pos = (long)PIXROUND(p_y[j1]-p_y[j], vconv);
+ if (labs(x_pos)<labs(y_pos)) x_pos=x_pos+3;
+ else y_pos=y_pos+3;
+ if (GrayFill) {
+ EMIT(outfp, "\033*c%lda%ldb%dg2P", x_pos, y_pos, GrayScale);
+ } else {
+ EMIT(outfp, "\033*c%lda%ldb%dg3P", x_pos, y_pos, Pattern);
+ }
+ last_ry = UNKNOWN;
+#endif
+ }
+ break;
+ case GRAY:
+ if ((k.v.i >= 0) && (k.v.i < 101)) {
+ GrayScale = k.v.i;
+ GrayFill = TRUE;
+ } else
+ Warning( "Invalid gray scale (%d) given; ignored.", k.v.i);
+ break;
+ case PATTERN:
+ if ((k.v.i >= 0) && (k.v.i < 7)) {
+ Pattern = k.v.i;
+ GrayFill = FALSE;
+ } else
+ Warning( "Invalid pattern (%d) given; ignored.", k.v.i);
+ break;
+
+ default:
+ Warning("Can't handle %s=%s command; ignored.", k.Key, k.Val);
+ break;
+ }
+ else
+ Warning("Invalid keyword or value in \\special - <%s> ignored", k.Key);
+ }
+ if ( sf ) {
+ last_ry = UNKNOWN;
+#ifdef IBM3812
+ PMPflush;
+#endif
+ if (i==HPFILE)
+ CopyHPFile( sf );
+ else
+ CopyFile( sf );
+ }
+}
+
+
+/*-->EmitChar*/
+/**********************************************************************/
+/**************************** EmitChar ******************************/
+/**********************************************************************/
+void /* output a character bitmap */
+EmitChar(c, ce)
+long c;
+struct char_entry *ce;
+{
+ register int i;
+ register unsigned char *sl;
+ unsigned short nbpl, nwpl;
+ long total;
+#ifdef LJ
+ unsigned char cnv_buffer[10];
+#endif
+
+
+#ifdef LJ
+/*
+printf("Emit character %c(%d) id=%d, yoff=%d[%d], w=%d[%d], h=%d[%d]\n",
+ (char)c,(int)c,
+ fontptr->plusid,
+ ce->yOffset, fontptr->max_yoff,
+ ce->width, fontptr->max_width,
+ ce->height, fontptr->max_height
+);
+*/
+#endif
+
+
+
+ if ( fontptr->ncdl == 0 ) {
+#ifdef IBM3812
+ used_fontstorage += 1028;
+#endif
+#ifdef LJ
+ if (fontptr->max_width == 0) { /* we have no realistic values */
+ fontptr->max_yoff = CHAR_HEIGTH_LARGE;
+ fontptr->max_width = CHAR_WIDTH_LARGE;
+ fontptr->max_height = CHAR_HEIGTH_LARGE*2;
+ }
+
+ /* open font dict before first char, set active font */
+ INT_ASCII(cnv_buffer,fontptr->plusid);
+#ifdef LJ4
+ EMIT(outfp, "\033*c%sD\033)s68W", cnv_buffer);
+ EMITB(6, "\0\104\024\2\0\0");
+#else
+ EMIT(outfp, "\033*c%sD\033)s26W", cnv_buffer);
+#ifdef SEVENBIT
+ EMITB(6, "\0\032\0\1\0\0");
+#else
+ EMITB(6, "\0\032\0\2\0\0");
+#endif
+#endif /* LJ 4 */
+ EMITWORD( fontptr->max_yoff);
+ EMITWORD( fontptr->max_width);
+ EMITWORD( fontptr->max_height);
+ EMITB(8, "\0\1\1\25\0\4\0\4");
+ EMITB(6, "\0\0\0\0\0\0");
+#ifdef LJ4
+ EMITB(22,"\0\0\0\0\0\0\0\0\0\0\0\0\0\377\0\0\0\0\0\0\0\0");
+ EMITB(16," ");
+ EMITB(4 ,"\2\130\2\130");
+#endif
+ EMIT(outfp, "\033*c4F");
+#endif
+ }
+ if ( fontptr != prevfont ) { /* because this isn't done on pass 0 */
+#ifdef LJ
+ INT_ASCII(cnv_buffer,fontptr->plusid);
+ EMIT(outfp, "\033(%sX", cnv_buffer);
+#endif
+ prevfont = fontptr;
+ }
+
+#ifdef USEPXL
+ if (fontptr->id == pk89) {
+ nwpl = 0; /* initialize variable */
+ nbpl = ((int)(ce->width) + 7) >> 3;
+ total = (long)ce->height * nbpl;
+ } else if (fontptr->id == id1002) {
+ nwpl = 0; /* initialize variable */
+ nbpl = ((int)(ce->width) + 7) >> 3;
+ total = (long)ce->height * nbpl;
+ } else if (fontptr->id == id1001) {
+ nwpl = ((int)(ce->width) + 31) >> 5;
+ nbpl = ((int)(ce->width) + 7) >> 3;
+ total = (long)ce->height * nbpl;
+ } else {
+ /* should never be necessary */
+ nwpl = 0;
+ nbpl = 0;
+ total = 0;
+ }
+#else
+ nbpl = (num_cols + 7) >> 3;
+ total = num_rows * nbpl;
+#endif
+/***************************************************************
+ if ( ((char) c == 'i') && (fontptr->plusid == 0)) {
+ long j;
+ fprintf(stderr, "cols=%ld, ncols=%ld\n",nwpl,nbpl);
+
+ fprintf(stderr, "%ld Bytes:->",total);
+ for (j=0; j<total;j++) {
+ char *ch; char ic;
+ ch = (char *)(ce->where.address.pixptr);
+ ic = *(ch+j);
+ fprintf(stderr,"%X.",ic);
+ }
+ fprintf(stderr,"<- Now Emitting\n");
+ }
+***************************************************************/
+#ifdef USEPXL
+#ifdef IBM3812
+ if ((short)(ce->height) - ce->yOffset > 55) {
+ ce->yyOffset = (short) ce->height - ce->yOffset;
+ ce->yOffset = (short) ce->height;
+ } else {
+ ce->yyOffset = (short) 0;
+ }
+#endif
+#ifdef LJ
+ ce->yyOffset = (short) 0;
+#endif
+#endif
+
+ /* ce->cw = (long)(((double)ce->tfmw / (double)hconv) +0.5); */
+ /* set active font to nn, load font pattern xx ... */
+#ifdef IBM3812
+ PMPcont(total + 9);
+#ifdef USEPXL
+ sprintf(PMPformat, "\323%c\360%c%c%c",
+ (unsigned char)fontptr->plusid,
+ (unsigned char)VisChar((char)c),
+ (unsigned char)ce->height,
+ (unsigned char)ce->width);
+ PMPout(6, PMPformat);
+ PMPoutC((char)(-(ce->xOffset)));
+ PMPoutC((char)(ce->cw - (-ce->xOffset + ce->width)));
+ PMPoutC((char)(ce->yOffset));
+#else
+ sprintf(PMPformat, "\323%c\360%c%c%c",
+ (unsigned char)fontptr->plusid,
+ (unsigned char)VisChar((char)c),
+ (unsigned char)num_rows,
+ (unsigned char)num_cols);
+ PMPout(6, PMPformat);
+ PMPoutC((char)(-x_offset));
+ PMPoutC((char)(ce->cw - (-x_offset + num_cols)));
+ PMPoutC((char)num_rows-y_offset);
+#endif
+#endif
+#ifdef LJ
+ INT_ASCII(cnv_buffer,fontptr->plusid);
+ EMIT(outfp, "\033*c%sd%dE\033(s%ldW", cnv_buffer,
+ (unsigned int)VisChar((char)c), (long)(total + 16));
+ EMITB(4, "\4\0\016\1");
+/* EMITC((char)(Landscape==TRUE)); */
+ EMITC((char)0);
+ EMITC((char)0);
+#ifdef USEPXL
+ EMITWORD(-ce->xOffset);
+ EMITWORD(ce->yOffset);
+ EMITWORD(ce->width);
+ EMITWORD(ce->height);
+#else
+ EMITWORD(-x_offset);
+ EMITWORD(num_rows-y_offset);
+ EMITWORD(num_cols);
+ EMITWORD(num_rows);
+#endif
+ EMITWORD((int)ce->cw * 4);
+#endif
+#ifdef USEPXL
+
+ if (fontptr->id == pk89)
+ PkRaster(ce, FALSE);
+ else if (fontptr->id == id1002)
+ for (i = 0; i < (int) ce->height; i++) {
+ sl = ((unsigned char *)(ce->where.address.pixptr) + i * nbpl);
+ EMITL(nbpl, sl);
+ }
+ else if (fontptr->id == id1001)
+ for (i = 0; i < (int) ce->height; i++) {
+ sl = (unsigned char *)(ce->where.address.pixptr + i * nwpl);
+ EMITL(nbpl, sl);
+ }
+#else
+ for (i = num_rows; i > 0; i--)
+ {
+ EMITL (nbpl, bits + (i-1) * nbpl);
+ }
+#endif
+#ifdef IBM3812
+#ifdef USEPXL
+ used_fontstorage += (long)ce->height * ((ce->width + 15) >> 4)
+ *2 + 14;
+#else
+ used_fontstorage += (long)num_rows * ((num_cols + 15) >> 4)
+ *2 + 14;
+#endif
+#endif
+#ifdef LJ
+#ifdef USEPXL
+ used_fontstorage += 64 * (((int)((ce->height * ce->width) - 1) / 64) + 1);
+#else
+ used_fontstorage += 64 * ((((num_rows * num_cols) - 1) / 64) + 1);
+#endif
+#endif
+ fontptr->ncdl += 1;
+ G_ncdl += 1;
+}
+
+
+/*-->RasterLine*/
+/**********************************************************************/
+/**************************** RasterLine ****************************/
+/**********************************************************************/
+void
+RasterLine(ce, nbpl, current_line, buffer)
+struct char_entry *ce;
+unsigned short nbpl, current_line;
+char *buffer;
+{
+#ifdef IBM3812
+ long total;
+ static unsigned short maxlines;
+
+ if (current_line == 0) {
+#ifdef USEPXL
+ maxlines = ce->height;
+
+ MoveVert(-ce->yOffset); /* move cursor up */
+ MoveHor(-ce->xOffset); /* move cursor right */
+#else
+ maxlines = num_rows;
+
+ MoveVert(-(num_rows-y_offset)); /* move cursor up */
+ MoveHor(-x_offset); /* move cursor right */
+#endif
+ last_ry = UNKNOWN; /* next time full positioning */
+ }
+
+ if (current_line % maxlines == 0) {
+ if (current_line > 0) { /* maxlines lines have been printed*/
+ MoveVert(maxlines); /* move cursor down */
+ last_ry = UNKNOWN; /* next time full positioning */
+ }
+#ifdef USEPXL
+ total = (long)(ce->height - current_line) * (long)nbpl;
+#else
+ total = (long)(num_rows - current_line) * (long)nbpl;
+#endif
+ if ((total + 9) > 65535) {
+ maxlines = (unsigned short)((65535 - 9) / nbpl);
+ total = (long)maxlines * (long)nbpl;
+ }
+
+ PMPcont(total + 9);
+ PMPout(2, "\365\0");
+ EMITWORD(maxlines);
+#ifdef USEPXL
+ EMITWORD(ce->width);
+#else
+ EMITWORD(num_cols);
+#endif
+ PMPoutC((unsigned char) (total >> 16) & 0xFF);
+ PMPoutC((unsigned char) (total >> 8 ) & 0xFF);
+ PMPoutC((unsigned char) total & 0xFF);
+ }
+ EMITL((int)nbpl, buffer);
+#endif
+#ifdef LJ
+ register int emitbytes;
+
+ for (emitbytes = (int)nbpl;
+ (*(buffer + emitbytes - 1) == '\0') && (emitbytes > 0);
+ emitbytes--) ;
+ EMIT(outfp, "\033*b%dW", emitbytes);
+ EMITL(emitbytes, buffer);
+#endif
+}
+
+
+/*-->RasterChar*/
+/**********************************************************************/
+/**************************** RasterChar ****************************/
+/**********************************************************************/
+void /* raster a character bitmap */
+RasterChar(ce)
+struct char_entry *ce;
+{
+ int i;
+ register unsigned char *sl;
+ unsigned short nbpl, nwpl;
+ unsigned char raster_line_buf[BYTES_PER_PIXEL_LINE];
+
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"Raster character ...size=%d \n", (int)ce->charsize );
+#endif
+
+#ifdef USEPXL
+ if (fontptr->id == pk89) {
+ nwpl = 0; /* initialize variable */
+ nbpl = ((int)(ce->width) + 7) >> 3;
+ } else if (fontptr->id == id1002) {
+ nwpl = 0; /* initialize variable */
+ nbpl = ((int) ce->width + 7) >> 3;
+ } else if (fontptr->id == id1001) {
+ nwpl = ((int) ce->width + 31) >> 5;
+ nbpl = ((int) ce->width + 7) >> 3;
+ } else {
+ /* should never be necessary */
+ nwpl = 0;
+ nbpl = 0;
+ }
+#else
+ nbpl = (num_cols + 7) >> 3;
+#endif
+
+#ifdef LJ
+ EMIT(outfp, "\033*t%dR\033*r1A",RESOLUTION);
+#endif
+ { /* read pixel from file */
+ if ((ce->charsize == HUGE_SIZE) && (fontptr->id != pk89))
+ OpenFontFile();
+#ifdef USEPXL
+ fseek(pxlfp, ce->where.address.fileOffset, 0);
+#else
+ fseek(gfin, ce->where.address.fileOffset, 0);
+ gettochar();
+ readbits();
+#endif
+ }
+
+#ifdef USEPXL
+ if (fontptr->id == pk89)
+ PkRaster(ce, TRUE);
+ else if (fontptr->id == id1002) {
+ for (i = 0; i < (int) ce->height; i++) {
+ if (ce->charsize == HUGE_SIZE) {
+ fread(raster_line_buf, 1, (int) nbpl, pxlfp);
+ sl = raster_line_buf;
+ } else
+ sl = ((unsigned char *)(ce->where.address.pixptr)
+ + i * nbpl);
+
+ RasterLine(ce, (unsigned int)nbpl, i, sl);
+ }
+ } else if (fontptr->id == id1001) {
+ long filediff;
+ filediff = (long)nwpl * 4 - nbpl;
+ for (i = 0; i < (int) ce->height; i++) {
+ if (ce->charsize == HUGE_SIZE) {
+ fread(raster_line_buf, 1, (int) nbpl, pxlfp);
+ /* skip fill bytes */
+ fseek(pxlfp, filediff, 1);
+ sl = raster_line_buf;
+ } else
+ sl = (unsigned char *)(ce->where.address.pixptr + i * nwpl);
+
+ RasterLine(ce, (unsigned int)nbpl, i, sl);
+ }
+ }
+#else
+ for (i = num_rows; i > 0; i--)
+ RasterLine(ce, (unsigned int)nbpl, i, bits + (i-1) * nbpl);
+#endif
+#ifdef LJ
+ EMIT(outfp, "\033*rB");
+#endif
+ last_ry = UNKNOWN;
+}
+
+
+/*-->Fatal*/
+/**********************************************************************/
+/****************************** Fatal *******************************/
+/**********************************************************************/
+void
+Fatal(fmt, a, b, c) /* issue a fatal error message */
+char *fmt; /* format */
+char *a, *b, *c; /* arguments */
+{
+ fprintf(stderr, "\n");
+ fprintf(stderr, "%s: FATAL--", G_progname);
+ fprintf(stderr, fmt, a, b, c);
+ fprintf(stderr, "\n\n");
+#ifndef vms
+ exit(2);
+#else
+ exit(SS$_ABORT);
+#endif
+}
+
+
+/*-->FindPostAmblePtr*/
+/**********************************************************************/
+/************************ FindPostAmblePtr **************************/
+/**********************************************************************/
+void
+FindPostAmblePtr(postambleptr)
+long *postambleptr;
+/* this routine will move to the end of the file and find the start
+ of the postamble */
+{
+ long i;
+ fseek (dvifp, 0l, 2); /* goto end of file */
+ *postambleptr = ftell (dvifp) - 4;
+ fseek (dvifp, *postambleptr, 0);
+ while (TRUE) {
+ fseek (dvifp, --(*postambleptr), 0);
+ if (((i = NoSignExtend(dvifp, 1)) != 223) &&
+ (i != DVIFORMAT))
+ Fatal ("Bad end of DVI file");
+ if (i == DVIFORMAT)
+ break;
+ }
+ fseek (dvifp, (*postambleptr) - 4, 0);
+ (*postambleptr) = NoSignExtend(dvifp, 4);
+ fseek (dvifp, *postambleptr, 0);
+}
+
+
+/*-->GetBytes*/
+/**********************************************************************/
+/***************************** GetBytes *****************************/
+/**********************************************************************/
+void
+GetBytes(fp, cp, n) /* get n bytes from file fp */
+/*register*/ FILE *fp; /* file pointer */
+register char *cp; /* character pointer */
+int n; /* number of bytes */
+{
+ while (n--)
+ *cp++ = (char)getc(fp);
+}
+
+
+/*-->GetFontDef*/
+/**********************************************************************/
+/**************************** GetFontDef *****************************/
+/**********************************************************************/
+void
+GetFontDef()
+/***********************************************************************
+ Read the font definitions as they are in the postamble of the DVI
+ file.
+***********************************************************************/
+{
+ unsigned char byte;
+ while (((byte = (unsigned char) NoSignExtend(dvifp, 1)) >= FNT_DEF1) &&
+ (byte <= FNT_DEF4)) {
+ switch (byte) {
+ case FNT_DEF1:
+ ReadFontDef ( NoSignExtend(dvifp, 1));
+ break;
+ case FNT_DEF2:
+ ReadFontDef ( NoSignExtend(dvifp, 2));
+ break;
+ case FNT_DEF3:
+ ReadFontDef ( NoSignExtend(dvifp, 3));
+ break;
+ case FNT_DEF4:
+ ReadFontDef ( NoSignExtend(dvifp, 4));
+ break;
+ default:
+ Fatal ("Bad byte value in font defs");
+ break;
+ }
+ }
+ if (byte != POST_POST)
+ Fatal ("POST_POST missing after fontdefs");
+}
+
+
+/*-->GetKeyStr*/
+/**********************************************************************/
+/***************************** GetKeyStr ****************************/
+/**********************************************************************/
+/* extract first keyword-value pair from string (value part may be null)
+ * return pointer to remainder of string
+ * return NULL if none found
+ */
+char KeyStr[STRSIZE];
+char ValStr[STRSIZE];
+char
+*GetKeyStr( str, kw )
+char *str;
+KeyWord *kw;
+{
+ char *s, *k, *v, t;
+ if ( !str )
+ return( NULL );
+ for ( s = str; *s == ' '; s++)
+ ; /* skip over blanks */
+ if ( *s == '\0' )
+ return( NULL );
+ for ( k = KeyStr; /* extract keyword portion */
+ *s != ' ' && *s != '\0' && *s != '=';
+ *k++ = *s++)
+ ;
+ *k = '\0';
+ kw->Key = KeyStr;
+ kw->Val = v = NULL;
+ kw->vt = None;
+ for ( ; *s == ' '; s++)
+ ; /* skip over blanks */
+ if ( *s != '=' ) /* look for "=" */
+ return( s );
+ for ( s++; *s == ' '; s++); /* skip over blanks */
+ if ( *s == '\'' || *s == '\"' ) /* get string delimiter */
+ t = *s++;
+ else
+ t = ' ';
+ for ( v = ValStr; /* copy value portion up to delim */
+ *s != t && *s != '\0';
+ *v++ = *s++)
+ ;
+ if ( t != ' ' && *s == t )
+ s++;
+ *v = '\0';
+ kw->Val = ValStr;
+ kw->vt = String;
+ return( s );
+}
+
+
+/*-->GetKeyVal*/
+/**********************************************************************/
+/***************************** GetKeyVal ****************************/
+/**********************************************************************/
+/* get next keyword-value pair decode value according to table entry */
+bool
+GetKeyVal( kw, tab, nt, tno)
+KeyWord *kw;
+KeyDesc tab[];
+int nt;
+int *tno;
+{
+ int i;
+ char c = '\0';
+ *tno = -1;
+ for (i = 0; i < nt; i++)
+ if ( IsSame(kw->Key, tab[i].Entry) ) {
+ *tno = i;
+ switch ( tab[i].Typ ) {
+ case None:
+ if ( kw->vt != None )
+ return( FALSE );
+ break;
+ case String:
+ if ( kw->vt != String )
+ return( FALSE );
+ break;
+ case Integer:
+ if ( kw->vt != String )
+ return( FALSE );
+ if ( sscanf(kw->Val, "%d%c",
+ &(kw->v.i), &c) != 1
+ || c != '\0' )
+ return( FALSE );
+ break;
+/* case Number:
+ * case Dimension:
+ * if( kw->vt != String ) return( FALSE );
+ * if( sscanf(kw->Val,"%f%c",
+ * &(kw->v.n), &c) != 1
+ * || c != '\0' ) return( FALSE );
+ * break;
+ */
+ }
+ kw->vt = tab[i].Typ;
+ return( TRUE );
+ }
+ return( TRUE );
+}
+
+
+
+/*-->IsSame*/
+/**********************************************************************/
+/******************************* IsSame *****************************/
+/**********************************************************************/
+bool /* compare strings, ignore case */
+IsSame(a, b)
+char *a, *b;
+{
+ char *x, *y;
+ x = a;
+ y = b;
+ for ( ; *a != '\0'; a++,b++)
+ if ( tolower(*a) != tolower(*b) )
+ return( FALSE );
+ return( *x == *y ? TRUE : FALSE );
+}
+
+
+/*-->NoSignExtend*/
+/**********************************************************************/
+/*************************** NoSignExtend ***************************/
+/**********************************************************************/
+long
+NoSignExtend(fp, n) /* return n byte quantity from file fd */
+register FILE *fp; /* file pointer */
+register int n; /* number of bytes */
+{
+ long x; /* number being constructed */
+ x = 0;
+ while (n--) {
+ x <<= 8;
+ x |= getc(fp);
+ }
+ return(x);
+}
+
+
+/*-->OpenFontFile*/
+/**********************************************************************/
+/************************** OpenFontFile *****************************/
+/**********************************************************************/
+void
+OpenFontFile()
+/***********************************************************************
+ The original version of this dvi driver reopened the font file each
+ time the font changed, resulting in an enormous number of relatively
+ expensive file openings. This version keeps a cache of up to
+ MAXOPEN open files, so that when a font change is made, the file
+ pointer, pxlfp, can usually be updated from the cache. When the
+ file is not found in the cache, it must be opened. In this case,
+ the next empty slot in the cache is assigned, or if the cache is
+ full, the least used font file is closed and its slot reassigned for
+ the new file. Identification of the least used file is based on the
+ counts of the number of times each file has been "opened" by this
+ routine. On return, the file pointer is always repositioned to the
+ beginning of the file.
+***********************************************************************/
+{
+ int i, least_used, current;
+ struct pixel_list tmp;
+
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"open font file %d\n", fontptr->font_file_id);
+#endif
+/*
+fprintf(stderr,"? %lx == %lx\n", pfontptr,fontptr);
+*/
+ if ((pfontptr == fontptr) && (pxlfp != NO_FILE))
+ return; /* we need not have been called */
+
+ if (fontptr->font_file_id == NO_FILE)
+ return; /* we need not have been called */
+
+ tmp = pixel_files[1];
+ for (current = 1;
+ (current <= nopen) && (tmp.pixel_file_id != fontptr->font_file_id); ) {
+ ++current;
+ tmp = pixel_files[current];
+ }
+ /* try to find file in open list */
+
+ if (current <= nopen) /* file already open */ {
+ if ( (pxlfp = pixel_files[current].pixel_file_id) != NO_FILE )
+ fseek(pxlfp, 0l, 0);
+ /* reposition to start of file */
+ } else {
+ /* file not in open list */
+ if (nopen < MAXOPEN) /* just add it to list */
+ current = ++nopen;
+ else {
+ /* list full -- find least used file, */
+ /* close it, and reuse slot for new file */
+ least_used = 1;
+ for (i = 2; i <= MAXOPEN; ++i)
+ if (pixel_files[least_used].use_count>pixel_files[i].use_count)
+ least_used = i;
+ if (pixel_files[least_used].pixel_file_id != NO_FILE) {
+ FILE * fid;
+ struct font_entry *fp;
+ fid = pixel_files[least_used].pixel_file_id;
+ /* mark file as being closed in the entry */
+ fp = hfontptr;
+ while (fp != NULL && fp->font_file_id != fid) fp = fp->next;
+ if (fp == NULL)
+ Fatal("Open file %x not found in font entry list.\n", fid);
+ else {
+ fp->font_file_id = NULL;
+ }
+ fclose( fid );
+ }
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"\n__reuse slot %d\n", least_used);
+#endif
+ current = least_used;
+ }
+ if ((pxlfp = BINOPEN(fontptr->name)) == NULL) {
+ Warning("PXL-file %s could not be opened", fontptr->name);
+ pxlfp = NO_FILE;
+ } else {
+#ifdef DEBUG
+ if (Debug) fprintf(stderr,
+ "Opening File <%s> /%x/, Size(font_entry)=%d\n",
+ fontptr->name, pxlfp, sizeof(struct font_entry ));
+#endif
+
+ }
+ pixel_files[current].pixel_file_id = pxlfp;
+ pixel_files[current].use_count = 0;
+ }
+ pfontptr = fontptr; /* make previous = current font */
+ fontptr->font_file_id = pxlfp; /* set file identifier */
+ pixel_files[current].use_count++; /* update reference count */
+#ifndef USEPXL
+ gfin = pxlfp;
+#endif
+}
+
+
+/*-->PixRound*/
+/**********************************************************************/
+/***************************** PixRound *****************************/
+/**********************************************************************/
+long
+PixRound(x, conv) /* return rounded number of pixels */
+long x; /* in DVI units */
+long conv; /* conversion factor */
+{
+ return((x + conv) / conv);
+}
+
+#ifdef LJ_RESIDENT_FONTS
+/*-->TryResident*/
+/**********************************************************************/
+/**************************** TryResident ***************************/
+/**********************************************************************/
+bool
+TryResident(fontptr)
+struct font_entry *fontptr;
+{
+ extern bool tfm_read_info ();
+ tfm_info_type tfm_info;
+
+ /* To determine if a font is resident, check for a special family
+ value (header bytes 12..16 in the TFM file). This seems cleaner,
+ and certainly more convenient, than somehow reading an external
+ ljfonts.map file in which we'd have to specify information for all
+ the resident fonts. */
+ if (tfm_read_info (fontptr->n, &tfm_info)
+ && tfm_info.family[0]
+ && strcmp (tfm_info.family, "HPAUTOTFM") == 0) {
+ unsigned i;
+ double factor = fontptr->s / (double) 0x100000;
+
+ resident_count++;
+ fontptr->resident_p = TRUE;
+ strcpy (fontptr->symbol_set, tfm_info.coding_scheme);
+ fontptr->resid = tfm_info.typeface_id;
+ fontptr->spacing = tfm_info.spacing;
+ fontptr->style = tfm_info.style;
+ fontptr->weight = tfm_info.weight;
+
+ if (fontptr->spacing == SPACING_FIXED) {
+ /* Have to select the point in pitch (characters per inch) instead
+ of point size, and thus have to figure out the pitch that
+ corresponds to the point size at which the font is used.
+
+ To do this, take the width of the interword space, and see how
+ many of those characters will fit in the at size. Then convert
+ to how many characters will fit in one inch. That's our pitch.
+
+ All the builtin LJ4 fonts that are monospaced are Intellifont,
+ which have 72.307 points per inch. Not that it really makes any
+ difference. We don't worry about this elsewhere, since all
+ point sizes are rounded to .25pt anyway, which is more than the
+ difference between the various definitions of `point'. */
+ double ds_in_points = fontptr->s / 65536.0;
+ double w_in_points = tfm_info.interword / (double) 0x100000;
+ if (ds_in_points == 0 || w_in_points == 0) {
+ /* Avoid division by zero if no interword space. */
+ Warning ("%s: Can't determine pitch for this monospaced font.\n",
+ fontptr->n);
+ fontptr->pitch = 10; /* Result will look awful, which is good. */
+ } else {
+ fontptr->pitch = 72.307 / (ds_in_points * w_in_points);
+ }
+ }
+
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr, "%6s: typeface=%u\tspacing=%u\tstyle=%u\tweight=%d\n",
+ fontptr->n, fontptr->resid, fontptr->spacing,
+ fontptr->style, fontptr->weight);
+#endif
+ for (i = 0; i < NFNTCHARS; i++) {
+ struct char_entry *cptr = &(fontptr->ch[i]);
+ cptr->tfmw = (long) (tfm_info.widths[i] * factor);
+ cptr->cw = ((fontptr->ch[i].tfmw) / (double) hconv) + .5;
+ cptr->width =
+ cptr->height =
+ cptr->xOffset =
+ cptr->yOffset =
+ cptr->yyOffset = 0;
+ }
+ return TRUE;
+ } else {
+ fontptr->resident_p = FALSE;
+
+ if (tfm_info.family[0]
+ && strcmp (tfm_info.family, "UNSPECIFIED") == 0) {
+ Warning("font family for %s is UNSPECIFIED; need to run dvicopy?",
+ fontptr->n);
+ fontptr->font_file_id = NO_FILE;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+}
+#endif
+
+
+
+/*-->ReadFontDef*/
+/**********************************************************************/
+/**************************** ReadFontDef ***************************/
+/**********************************************************************/
+void
+ReadFontDef(k)
+long k;
+{
+ long t;
+ unsigned short i;
+ struct font_entry *tfontptr; /* temporary font_entry pointer */
+ struct char_entry *tcharptr; /* temporary char_entry pointer */
+ static int plusid = 0;
+ bool font_found = FALSE;
+#ifdef LJ_RESIDENT_FONTS
+ bool resident_font_located = FALSE;
+#endif
+#ifdef LJ
+ int depth, max_depth;
+#endif
+
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"Mallocating %d Bytes)...\n",
+ sizeof(struct font_entry ));
+#endif
+
+ if ((tfontptr = NEW(struct font_entry )) == NULL)
+ Fatal("can't malloc space for font_entry");
+
+ allocated_storage += sizeof(struct font_entry );
+
+ tfontptr->next = hfontptr;
+ tfontptr->font_file_id = NULL;
+ fontptr = hfontptr = tfontptr;
+ tfontptr->ncdl = 0;
+ tfontptr->k = k;
+ tfontptr->c = NoSignExtend(dvifp, 4); /* checksum */
+ tfontptr->s = NoSignExtend(dvifp, 4); /* space size */
+ tfontptr->d = NoSignExtend(dvifp, 4); /* design size */
+ tfontptr->a = (int) NoSignExtend(dvifp, 1); /* length for font name */
+ tfontptr->l = (int) NoSignExtend(dvifp, 1); /* device length */
+
+#ifdef LJ
+ tfontptr->max_width = tfontptr->max_height = tfontptr->max_yoff =
+ max_depth = 0;
+#endif
+
+ GetBytes(dvifp, tfontptr->n, tfontptr->a + tfontptr->l);
+ tfontptr->n[tfontptr->a+tfontptr->l] = '\0';
+
+ tfontptr->font_mag = (long)((
+ ActualFactor((long)(1000.0*tfontptr->s/(double)tfontptr->d+0.5))
+ * ActualFactor(mag)
+#ifdef USEPXL
+ * RESOLUTION * 5.0
+#else
+ * RESOLUTION
+#endif
+ ) + 0.5);
+/*
+printf("[%ld]=%lf * %lf * %lf + 0.5 = %ld\n",
+ ((long)(1000.0*tfontptr->s/(double)tfontptr->d+0.5)),
+ ActualFactor((long)(1000.0*tfontptr->s/(double)tfontptr->d+0.5)),
+ ActualFactor(mag),
+ (double)RESOLUTION * 5,
+ tfontptr->font_mag );
+*/
+
+#ifdef LJ_RESIDENT_FONTS
+ /* Pass in the name; fills in resident_p and resid (if resident). */
+
+ resident_font_located = (bool) TryResident(tfontptr);
+
+ if (tfontptr->resident_p)
+ return;
+
+ if (!(resident_font_located)) {
+#endif
+
+ if (!(findfile(PXLpath,
+ tfontptr->n,
+ tfontptr->font_mag,
+ tfontptr->name,
+ FALSE,
+ 0))) {
+ Warning(tfontptr->name); /* contains error messsage */
+ tfontptr->font_file_id = NO_FILE;
+ }
+ else {
+ font_found = TRUE;
+ if (!( (G_noverbatim) || (G_quiet) ) )
+ fprintf(stderr,"%d: using font <%s>\n",
+ plusid,tfontptr->name);
+ }
+#ifdef LJ_RESIDENT_FONTS
+ }
+#endif
+ tfontptr->plusid = plusid;
+ plusid++;
+
+ /* sprintf(tfontptr->psname,"%s.%ld.%d",
+ tfontptr->n,tfontptr->font_mag,tfontptr->plusid);*/
+
+#ifdef LJ
+ if (plusid >= HANDLE_MAX_FONTS)
+ Fatal("can handle only %d fonts! ask a wizzard...\n",
+ HANDLE_MAX_FONTS);
+#endif
+ if (tfontptr != pfontptr) {
+ if (font_found) OpenFontFile();
+ else
+ pxlfp = NO_FILE;
+ }
+#ifdef USEPXL
+ if ( pxlfp == NO_FILE ) { /* allow missing pxl files */
+ tfontptr->magnification = 0;
+ tfontptr->designsize = 0;
+#endif
+ for (i = FIRSTFNTCHAR; i <= LASTFNTCHAR; i++) {
+ tcharptr = &(tfontptr->ch[i]);
+#ifdef USEPXL
+ tcharptr->width = 0;
+ tcharptr->height = 0;
+ tcharptr->xOffset = 0;
+ tcharptr->yOffset = 0;
+#endif
+ tcharptr->where.isloaded = FALSE;
+ tcharptr->where.address.fileOffset = NONEXISTANT;
+ tcharptr->tfmw = 0;
+ }
+#ifdef USEPXL
+ return;
+ }
+ t = (long) NoSignExtend(pxlfp, 1);
+ if (t == 0) {
+ t = (long) NoSignExtend(pxlfp, 1);
+ t = (long) NoSignExtend(pxlfp, 2);
+ if (t == 1002)
+ tfontptr->id = id1002;
+ else if (t == 1001)
+ tfontptr->id = id1001;
+ else
+ Fatal("Unknown Version of PXL-format\n");
+ } else {
+ if (t == PK_PRE) {
+ unsigned char temp_byte;
+ temp_byte = (unsigned char) NoSignExtend(pxlfp, 1);
+ if (temp_byte != PK_ID) Fatal(
+ "Wrong Version of pk file! (%d should be 89)\n",
+ (int)temp_byte);
+ else
+ tfontptr->id = pk89;
+ } else
+ Fatal("unknown font format in file <%s> !\n",fontptr->name);
+ }
+
+ if ((tfontptr->id == id1002) || (tfontptr->id == id1001)) {
+ fseek(pxlfp, -20l, 2);
+
+ t = NoSignExtend(pxlfp, 4);
+ if ((tfontptr->c != 0) && (t != 0) && (tfontptr->c != t))
+ Warning("font = \"%s\",\n->tfm checksum = %lX,\n->pxl checksum = %lX",
+ tfontptr->name, tfontptr->c, t);
+ tfontptr->magnification = NoSignExtend(pxlfp, 4);
+ tfontptr->designsize = NoSignExtend(pxlfp, 4);
+
+ if (tfontptr->id == id1001)
+ fseek(pxlfp, (long) (NoSignExtend(pxlfp, 4) * 4), 0);
+ else
+ fseek(pxlfp, (long) NoSignExtend(pxlfp, 4) , 0);
+
+ for (i = FIRSTFNTCHAR; i <= 127; i++) { /* only defined for 7bit*/
+ tcharptr = &(tfontptr->ch[i]);
+ tcharptr->width = (unsigned short) NoSignExtend(pxlfp, 2);
+ tcharptr->height = (unsigned short) NoSignExtend(pxlfp, 2);
+ tcharptr->xOffset = (short) SignExtend(pxlfp, 2);
+ tcharptr->yOffset = (short) SignExtend(pxlfp, 2);
+ tcharptr->where.isloaded = FALSE;
+ if (tfontptr->id == id1001)
+ tcharptr->where.address.fileOffset = NoSignExtend(pxlfp,4) * 4;
+ else
+ tcharptr->where.address.fileOffset = NoSignExtend(pxlfp,4);
+ tcharptr->tfmw = (long)
+ ( (double)(NoSignExtend(pxlfp, 4))
+ * (double)tfontptr->s / (double) 0x100000 );
+ tcharptr->cw = (long)(((double)tcharptr->tfmw/(double)hconv) + 0.5);
+
+ if (tcharptr->width > CHAR_WIDTH_LARGE ||
+ tcharptr->height > CHAR_HEIGTH_LARGE )
+ tcharptr->charsize = LARGE_SIZE;
+ else
+ tcharptr->charsize = SMALL_SIZE;
+#ifdef LJ
+ max(tfontptr->max_width,tcharptr->width);
+ max(tfontptr->max_height,tcharptr->height);
+ if (tcharptr->yOffset > 0 && (int)tfontptr->max_yoff < (int)tcharptr->yOffset)
+ tfontptr->max_yoff = tcharptr->yOffset;
+ if ((depth = tcharptr->height - tcharptr->yOffset)>max_depth)
+ max_depth = depth;
+#endif
+
+ }
+#ifdef LJ
+ tfontptr->max_height = max_depth ? tfontptr->max_yoff+max_depth :
+ tfontptr->max_yoff+1;
+#endif
+ } else { /* PK 89 format */
+ unsigned char temp_byte;
+ register unsigned char flag_byte;
+ long hppp, vppp, pkloc, packet_length;
+ int car, ii;
+
+ /* read comment */
+ for ( ii = temp_byte = (unsigned char) NoSignExtend(pxlfp, 1);
+ ii>0; ii--) {
+ flag_byte = (unsigned char) NoSignExtend(pxlfp, 1);
+#ifdef DEBUG
+ if (Debug) fprintf(stderr, "%c", flag_byte ) ;
+#endif
+ }
+#ifdef DEBUG
+ if (Debug) fprintf(stderr, "\n");
+#endif
+ pkloc = 3 + (int)temp_byte;
+ tfontptr->designsize = NoSignExtend(pxlfp, 4);
+
+ t = NoSignExtend(pxlfp, 4);
+ if ((tfontptr->c != 0) && (t != 0) && (tfontptr->c != t))
+ Warning("font = \"%s\",\n->tfm checksum = %lX,\n->pxl checksum = %lX",
+ tfontptr->name, tfontptr->c, t);
+
+ hppp = NoSignExtend(pxlfp, 4);
+ vppp = NoSignExtend(pxlfp, 4);
+ if (hppp != vppp)
+ Warning("aspect ratio is %ld:%ld (should be 1:1)!", hppp,vppp);
+ tfontptr->magnification = (long)(hppp * 72.27 * 5 / 65536l + 0.5);
+
+ pkloc += 16;
+ flag_byte = skip_specials(&pkloc);
+
+ while (flag_byte != PK_POST) {
+ if ((flag_byte & 7) == 7) {
+ /* fprintf(stderr,"\nRead long character preamble\n"); */
+
+ packet_length = (unsigned long)NoSignExtend(pxlfp,4);
+ if ((car = (int)NoSignExtend(pxlfp, 4)) > (LASTFNTCHAR))
+ Fatal("Bad character (%d) in PK-File\n",(int)car) ;
+
+ tcharptr = &(tfontptr->ch[car]);
+ tcharptr->where.address.fileOffset = pkloc;
+ /* set pkloc to end_of_packet */
+ pkloc += packet_length + 8;
+
+ tcharptr->tfmw = (long) NoSignExtend(pxlfp, 4);
+ (void) NoSignExtend(pxlfp, 4); /* horesc not used */
+ (void) NoSignExtend(pxlfp, 4); /* not used */
+
+ tcharptr ->width = (unsigned short) NoSignExtend(pxlfp, 4);
+ tcharptr ->height = (unsigned short) NoSignExtend(pxlfp, 4);
+ tcharptr ->xOffset = (short) SignExtend(pxlfp, 4);
+ tcharptr ->yOffset = (short) SignExtend(pxlfp, 4);
+ tcharptr ->where.isloaded = FALSE;
+ } else if (flag_byte & 4) {
+ /* fprintf(stderr,"Read extended short character preamble\n"); */
+
+ packet_length = ((long) flag_byte & 3) * 65536l +
+ (unsigned short) NoSignExtend(pxlfp, 2);
+ if ((car = (int)NoSignExtend(pxlfp, 1)) > (LASTFNTCHAR))
+ Fatal("Bad character (%d) in PK-File\n",(int)car) ;
+
+ tcharptr = &(tfontptr->ch[car]);
+ tcharptr->where.address.fileOffset = pkloc;
+ /* set pkloc to end_of_packet */
+ pkloc += packet_length + 3;
+
+ tcharptr->tfmw = (long) NoSignExtend(pxlfp, 3);
+/*
+ { register unsigned short t;
+ t = (unsigned short) NoSignExtend(pxlfp, 1);
+ tcharptr->tfmw = t * 65536l +
+ (unsigned short) NoSignExtend(pxlfp, 2);
+ }
+*/
+ /* horesc not used */
+ (void) NoSignExtend(pxlfp, 2) ;
+ tcharptr ->width = (unsigned short) NoSignExtend(pxlfp,2);
+ tcharptr ->height = (unsigned short) NoSignExtend(pxlfp,2);
+ tcharptr ->xOffset = (short) SignExtend(pxlfp, 2);
+ tcharptr ->yOffset = (short) SignExtend(pxlfp, 2);
+ tcharptr ->where.isloaded = FALSE;
+ } else {
+ /* fprintf(stderr,"<Read short character preamble@>\n"); */
+
+ packet_length = ((long)flag_byte & 3) * 256 +
+ NoSignExtend(pxlfp, 1) ;
+ if ((car = (int)NoSignExtend(pxlfp, 1)) > (LASTFNTCHAR))
+ Fatal("Bad character (%d) in PK-File\n",(int)car) ;
+
+ tcharptr = &(tfontptr->ch[car]);
+ tcharptr->where.address.fileOffset = pkloc;
+ /* set pkloc to end_of_packet */
+ pkloc += packet_length + 2 ;
+
+ tcharptr->tfmw = (long) NoSignExtend(pxlfp, 3);
+/*
+ { register unsigned short t;
+ t = (unsigned short) NoSignExtend(pxlfp, 1);
+ tcharptr->tfmw = t * 65536l +
+ (unsigned short) NoSignExtend(pxlfp, 2);
+ }
+*/
+ /* horesc not used */
+ (void) NoSignExtend(pxlfp, 1) ;
+ tcharptr ->width = (unsigned short) NoSignExtend(pxlfp,1);
+ tcharptr ->height = (unsigned short) NoSignExtend(pxlfp,1);
+ tcharptr ->xOffset = (short) SignExtend(pxlfp, 1);
+ tcharptr ->yOffset = (short) SignExtend(pxlfp, 1);
+ tcharptr ->where.isloaded = FALSE;
+ }
+
+ tcharptr->tfmw = (long)
+ ( tcharptr->tfmw * (double)tfontptr->s / (double) 0x100000 );
+
+ tcharptr->cw = (long)(((double)tcharptr->tfmw /
+ (double)hconv) + 0.5);
+
+ if (tcharptr->width > CHAR_WIDTH_LARGE ||
+ tcharptr->height > CHAR_HEIGTH_LARGE )
+ tcharptr->charsize = LARGE_SIZE;
+ else
+ tcharptr->charsize = SMALL_SIZE;
+
+#ifdef LJ
+/*
+printf("char=%d: this=%d, max_width=%d, this=%d,max_height=%d, this=%d,max_yoff=%d\n",
+ car, tcharptr->width, tfontptr->max_width,
+ tcharptr->height,tfontptr->max_height,
+ tcharptr->yOffset,tfontptr->max_yoff);
+*/
+ max(tfontptr->max_width, tcharptr->width);
+ max(tfontptr->max_height,tcharptr->height);
+ if (tcharptr->yOffset > 0 && (int)tfontptr->max_yoff < (int)tcharptr->yOffset)
+ tfontptr->max_yoff = tcharptr->yOffset;
+
+ if ((depth = tcharptr->height - tcharptr->yOffset) > max_depth)
+ max_depth = depth;
+#endif
+/*
+fprintf(stderr,"char=%d, yotcharptr=%lx, flag_byte=%d, font=%lx\n",car, tcharptr,flag_byte,tfontptr);
+*/
+ tcharptr->flag_byte = flag_byte;
+ fseek(pxlfp, (long) pkloc, 0);
+ flag_byte = skip_specials(&pkloc);
+
+ } /* end of while */
+#ifdef LJ
+tfontptr->max_height = max_depth ? tfontptr->max_yoff+max_depth :
+ tfontptr->max_yoff+1;
+#endif
+
+/*
+printf("fontid=%d: max_width=%u, max_height=%d, max_yoff=%u\n",
+ tfontptr->plusid, tfontptr->max_width,
+ tfontptr->max_height, tfontptr->max_yoff);
+*/
+
+#else
+ if ( pxlfp == NO_FILE ) /* allow missing pxl files */
+ return;
+
+ gfin = pxlfp;
+ seekpost();
+ readpost();
+ if ((tfontptr->c != 0) && (checksum != 0) && (tfontptr->c != checksum))
+ Warning("font = \"%s\",\n-->font checksum = %d,\n-->dvi checksum = %d",
+ tfontptr->name, tfontptr->c, checksum);
+
+ for(i=FIRSTFNTCHAR; i<=LASTFNTCHAR; i++) {
+ if (char_exists[i]) {
+ tcharptr = &(tfontptr->ch[i]);
+ tcharptr->tfmw = (long)(((float)tfm_wd[i]*(float)tfontptr->s) /
+ (float)((long)1l<<20));
+ tcharptr->where.address.fileOffset = char_pointer[i];
+ }
+#ifdef LJ
+/* GF USER PLEASE CHECK IF THIS CODE WORKS
+ tfontptr->max_width = gf_font_max_m;
+ tfontptr->max_height = gf_font_max_n;
+ tfontptr->max_yoff = gf_font_min_n;
+*/
+#endif
+#endif
+/*****************************************************************************/
+/*if (tcharptr->charsize==LARGE_SIZE)
+ fprintf(stderr,"%d:\t <%c> w=%d h=%d xO=%d yO=%d tfmw=%ld cw=%ld %d\n",
+ i,(char) i,
+ tcharptr->width,tcharptr->height,tcharptr->xOffset,tcharptr->yOffset,
+ tcharptr->tfmw, tcharptr->cw, (int)(tcharptr->charsize));
+ */
+/*****************************************************************************/
+ }
+ }
+
+
+unsigned char
+skip_specials( pkloc )
+long *pkloc;
+{
+ long i, j;
+ register unsigned char flag_byte;
+ do {
+ flag_byte = (unsigned char) NoSignExtend(pxlfp, 1);
+/*
+fprintf(stderr,"flagbyte = %d, pkloc=%ld\n",(int)flag_byte,*pkloc);
+*/
+
+ (*pkloc) ++;
+ if (flag_byte >= 240)
+ switch (flag_byte) {
+ case 240:
+ case 241:
+ case 242:
+ case 243 : {
+ i = 0 ;
+ for (j = 240; j <= (long)flag_byte; j++) {
+ i = 256 * i + NoSignExtend(pxlfp, 1) ;
+ (*pkloc) ++;
+ }
+ for (j = 1; j <= i; j++) {
+ (void) NoSignExtend(pxlfp, 1) ;
+ (*pkloc) ++;
+ }
+ break;
+ }
+ case 244 : {
+ i = NoSignExtend(pxlfp, 4);
+ (*pkloc) += 4;
+ break;
+ }
+ case 245 :
+ break;
+ case 246 :
+ break ;
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255: {
+ Fatal("Unexpected flagbyte %d!\n",
+ (int)flag_byte) ;
+ }
+ }
+ } while (!((flag_byte < 240) || (flag_byte == PK_POST))) ;
+ return(flag_byte);
+}
+
+
+/*-->ReadPostAmble*/
+/**********************************************************************/
+/************************** ReadPostAmble ***************************/
+/**********************************************************************/
+/***********************************************************************
+ This routine is used to read in the postamble values. It
+ initializes the magnification and checks the stack height prior to
+ starting printing the document.
+***********************************************************************/
+void
+ReadPostAmble(load)
+bool load;
+{
+ FindPostAmblePtr (&postambleptr);
+ if (NoSignExtend(dvifp, 1) != POST)
+ Fatal ("POST missing at head of postamble");
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"got POST command\n");
+#endif
+ ppagep = NoSignExtend(dvifp, 4);
+ num = NoSignExtend(dvifp, 4);
+ den = NoSignExtend(dvifp, 4);
+ mag = NoSignExtend(dvifp, 4);
+ if ( usermag > 0 && usermag != mag )
+ Warning("DVI magnification of %ld over-ridden by user (%ld)",
+ mag, usermag );
+ if ( usermag > 0 )
+ mag = usermag;
+ hconv = DoConv(num, den, hconvRESOLUTION);
+ vconv = DoConv(num, den, vconvRESOLUTION);
+ (void) NoSignExtend(dvifp, 4); /* height-plus-depth of tallest page */
+ (void) NoSignExtend(dvifp, 4); /* width of widest page */
+ if (NoSignExtend(dvifp, 2) >= STACK_SIZE)
+ Fatal ("Stack size is too small");
+ (void) NoSignExtend(dvifp, 2); /* this reads the number of pages in */
+ /* the DVI file */
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"now reading font defs");
+#endif
+ if (load)
+ GetFontDef ();
+}
+
+
+/*-->LoadAChar*/
+/**********************************************************************/
+/***************************** LoadAChar ******************************/
+/**********************************************************************/
+void
+LoadAChar(c, ptr)
+long c;
+register struct char_entry *ptr;
+{
+ long *pr;
+ long bytes;
+
+ if (ptr->where.address.fileOffset == NONEXISTANT
+#ifdef LJ_RESIDENT_FONTS
+ || fontptr->resident_p
+#endif
+ ) {
+ ptr->where.isloaded = FALSE;
+ return;
+ }
+
+ OpenFontFile();
+
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr, "LoadAChar: <%c>(%ld) from file at pos %ld\n",
+ (char)c,c,ptr->where.address.fileOffset);
+#endif
+
+#ifdef USEPXL
+
+ fseek(pxlfp, ptr->where.address.fileOffset, 0);
+
+ if (fontptr->id == pk89) {
+#ifdef PARANOIA
+ unsigned char temp;
+ temp = (unsigned char) NoSignExtend(pxlfp, 1);
+
+ if ((int)(ptr->flag_byte) != (int)temp) {
+ fprintf(stderr,"font=%lx, ptr=%lx\n",fontptr,ptr);
+ Fatal("%d: oh boy! old flag %d, new flag %d, ptr=%lx\n",
+ (int)c,(int)(ptr->flag_byte),(int)temp,ptr);
+ }
+#endif
+
+ if ((ptr->flag_byte & 7) == 7) {
+ bytes = ((long) NoSignExtend(pxlfp, 4)) - 28;
+ fseek(pxlfp, ptr->where.address.fileOffset + 36, 0);
+/*
+fprintf(stderr,"bytes=%d, seeking at %ld\n",
+ bytes, ptr->where.address.fileOffset + 36);
+*/
+ } else if ((ptr->flag_byte & 4) == 4) {
+ bytes = ((long)ptr->flag_byte & 3)
+ * 65536l + NoSignExtend(pxlfp, 2) - 13;
+ fseek(pxlfp, ptr->where.address.fileOffset + 16, 0);
+ } else {
+ bytes = ((long)ptr->flag_byte & 3)
+ * 256 + NoSignExtend(pxlfp, 1) - 8;
+ fseek(pxlfp, ptr->where.address.fileOffset + 10, 0);
+ }
+ } else if (fontptr->id == id1002)
+ bytes = ((( (long)ptr->width + 7) >> 3) * (long) ptr->height);
+ else if (fontptr->id == id1001)
+ bytes = 4 * (((long)ptr->width + 31) >> 5) * (long)ptr->height;
+ else
+ bytes = 0;
+
+ if (bytes > 0) {
+ /* do NOT load Huge characters */
+ if ((bytes > HUGE_CHAR_PATTERN) && (fontptr->id != pk89)) {
+ qfprintf(stderr,"Huge Character <%c> (%ld Bytes)\n", (char)c, bytes);
+ ptr->charsize = HUGE_SIZE;
+ ptr->where.isloaded = FALSE;
+ } else {
+ if ( (pr = (long *)malloc( bytes )) == NULL )
+ Fatal("Unable to allocate %ld bytes for char <%c>\n",
+ bytes, (char)c);
+/*
+ * else fprintf(stderr,"allocating %ld bytes char <%c>(%d)\t at 0x%lx\n",
+ * bytes, (char)c,(int)c,pr);
+ */
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,
+ "Allocating Char <%c>, FileOffset=%lX, Bytes=%ld (%d) <%d>\n",
+ (char) c, ptr->where.address.fileOffset, bytes,
+ (int)bytes, (unsigned int)bytes);
+#endif
+ allocated_storage += bytes;
+ fread(pr, 1, (int) bytes , pxlfp);
+ ptr->where.address.pixptr = pr;
+ }
+ }
+#else
+ fseek(gfin, ptr->where.address.fileOffset, 0);
+ gettochar();
+ readbits();
+ if (num_bytes > HUGE_CHAR_PATTERN)
+ ptr->charsize = HUGE_SIZE;
+#endif
+ ptr->where.isloaded = TRUE;
+ if (ptr->charsize != SMALL_SIZE
+#ifdef LJ
+ /* we might have problems at the edge of the paper with diff. sized characters
+ * the correct treatment would be to check whether the bounding box of
+ * tfontptr is within the paper relative to the current position
+ */
+ || fontptr->max_height > CHAR_HEIGTH_LARGE
+ || (rasterfont[fontptr->plusid])
+#endif
+ )
+ return;
+
+ EmitChar(c, ptr);
+#ifdef USEPXL
+ /* we should really free the space used by the PXL data after this
+ point, but it is not large, and besides, we may want to be
+ more clever in the future, about sending bitmaps. So keep
+ the data around */
+#endif
+}
+/*-->SetChar*/
+/**********************************************************************/
+/***************************** SetChar ******************************/
+/**********************************************************************/
+void
+SetChar(c, command, PassNo, do_posn,in_string)
+long c;
+short command;
+int PassNo;
+bool do_posn,in_string;
+{
+ register struct char_entry *ptr; /* temporary char_entry pointer */
+ bool pos_after = FALSE;
+
+ ptr = &(fontptr->ch[c]);
+ if (!((ptr->where.isloaded) || (ptr->charsize == HUGE_SIZE)))
+ LoadAChar(c, ptr);
+ if (PassNo == 0)
+ return;
+
+ if (do_posn) {
+#ifdef IBM3812
+ if (CharStringPos>0) {
+ fprintf(stderr,"!!!! That should never happen!!!\n");
+ CharStringOut;
+ }
+#endif
+ SetPosn(h, v);
+ }
+
+/*
+printf("(%d) hh=%ld (+%ld/+%ld), h=%ld, xh=%ld,xhh=%ld, [%ld|%ld] ->%d\n",
+ (int)do_posn,hh,(long)ptr->cw,(long)ptr->cw*(long)hconv,h,
+ PIXROUND(h, hconv),
+ PIXROUND(hh, hconv),
+ labs((hh-h)),hconv,(labs((hh-h))>hconv)
+ );
+*/
+
+ if (in_string && (labs((hh-h))>hconv)) {
+#ifdef IBM3812
+ CharStringOut;
+#endif
+ SetPosn(h, v);
+ }
+
+/*
+fprintf(stderr,"raster?=%d - last_ry=%d, last_rx=%d,mmax-height=%d\n",
+ (int)last_ry < fontptr->max_height, (int)last_ry,(int)last_rx,
+ (int)fontptr->max_height);
+*/
+
+ if (fontptr->font_file_id != NO_FILE) { /* ignore missing fonts */
+ if (
+#ifdef LJ_RESIDENT_FONTS
+ !fontptr->resident_p &&
+#endif
+ (ptr->charsize != SMALL_SIZE
+#ifdef LJ
+ /* the LaserJet cannot print characters
+ * where the bounding box lies outside the
+ * paper edge. Missing: right paper edge
+ */
+ || last_ry < (int)fontptr->max_height
+ || fontptr->max_height > CHAR_HEIGTH_LARGE
+ || (rasterfont[fontptr->plusid])
+#endif
+ )) {
+#ifdef LJ
+ int tmp;
+ char sign;
+
+ if (!do_posn) {
+ SetPosn(h, v);
+ }
+#ifdef USEPXL
+ tmp = (int) -ptr->yOffset;
+#else
+ tmp = (int) num_rows-y_offset;
+#endif
+ if (tmp != 0) {
+ if (tmp < 0) {
+ sign = '-'; tmp = -tmp;
+ } else
+ sign = '+';
+ EMIT(outfp, "\033*p%c%dY", sign, tmp);
+ }
+#ifdef USEPXL
+ tmp = (int) -ptr->xOffset;
+#else
+ tmp = (int) -x_offset;
+#endif
+ if (tmp != 0) {
+ if (tmp < 0) {
+ sign = '-'; tmp = -tmp;
+ } else
+ sign = '+';
+ EMIT(outfp, "\033*p%c%dX", sign, tmp);
+ }
+#endif
+#ifdef IBM3812
+ CharStringOut;
+#endif
+#ifdef DEBUG
+ if (Debug)
+#ifndef vms
+ fprintf(stderr,"Raster character <%c> %hd\n", (char) c,(short)c);
+#else
+ fprintf(stderr,"Raster character <%c> %d\n", (char) c,(short)c);
+#endif
+#endif
+ RasterChar(ptr);
+ pos_after = TRUE;
+ } else {
+ unsigned char cc;
+ cc = VisChar((char)c);
+#ifdef IBM3812
+#ifdef USEPXL
+ if ( ptr->yyOffset || (!in_string) ) {
+ CharStringOut;
+ MoveVert(ptr->yyOffset);
+ sprintf(PMPformat, "\01%c", cc);
+ PMPout(2, PMPformat);
+ MoveVert((int)-(ptr->yyOffset));
+ } else {
+#endif
+ if (CharStringPos==CHARSTRINGMAX)
+ CharStringOut;
+
+ CharString[CharStringPos] = cc;
+ CharStringPos++;
+#ifdef USEPXL
+ }
+#endif
+#endif
+#ifdef LJ
+#define TRANSPARENTCHAR(ch) \
+ if ((ch == 0l) || (ch >= 7l && ch <= 15l) || (ch == 27l)) \
+ EMIT(outfp, "\033&p1X%c", (unsigned char)ch); \
+ else EMITC((unsigned char)ch)
+#ifdef USEPXL
+ if (ptr->yyOffset) {
+#ifndef vms
+ EMIT(outfp, "\033*p+%hdY", ptr->yyOffset);
+ TRANSPARENTCHAR(cc);
+ EMIT(outfp, "\033*p-%hdY", ptr->yyOffset); /* GUGUGU 255 */
+#else
+ EMIT(outfp, "\033*p+%dY", ptr->yyOffset);
+ TRANSPARENTCHAR(cc);
+ EMIT(outfp, "\033*p-%dY", ptr->yyOffset); /* GUGUGU 255 */
+#endif
+ } else
+#endif
+/* EMITC( (unsigned char)c);*/
+ { TRANSPARENTCHAR(cc);}
+#endif
+ }
+ hh += (long) ptr->cw*hconv;
+ }
+ if (command <= SET4)
+ h += ptr->tfmw;
+ if (pos_after) {
+ SetPosn(h, v);
+ }
+}
+
+
+void
+DoBop()
+{
+ struct font_entry *p;
+#ifdef LJ
+ register short i;
+ if (fonts_used_on_this_page > MAX_FONTS_PER_PAGE) {
+ for (i = 0; i < HANDLE_MAX_FONTS; i++)
+ rasterfont[i] = FALSE;
+ }
+ fonts_used_on_this_page = 0;
+#endif
+ for (p = hfontptr; p; p = p->next) {
+ p->used_on_this_page = FALSE;
+ }
+}
+
+
+/*-->SetFntNum*/
+/**********************************************************************/
+/**************************** SetFntNum *****************************/
+/**********************************************************************/
+void
+SetFntNum(k, Emitting)
+long k;
+bool Emitting;
+/* this routine is used to specify the font to be used in printing future
+ characters */
+{
+#ifdef LJ
+ static unsigned short plusid = 0;
+#endif
+ fontptr = hfontptr;
+ while ((fontptr != NULL) && (fontptr->k != k))
+ fontptr = fontptr->next;
+ if (fontptr == NULL)
+ Fatal("font %ld undefined", k);
+ if (Emitting && fontptr->font_file_id != NO_FILE) {
+ if (!fontptr->used_on_this_page
+#ifdef LJ_RESIDENT_FONTS
+ && !fontptr->resident_p
+#endif
+ ) {
+ fontptr->used_on_this_page = TRUE;
+#ifdef LJ
+ if (++fonts_used_on_this_page > MAX_FONTS_PER_PAGE) {
+ qfprintf(stderr,"this is the %d. font on this page!",
+ fonts_used_on_this_page);
+ qfprintf(stderr," (max = %d) rastering characters!\n",
+ MAX_FONTS_PER_PAGE);
+ rasterfont[fontptr->plusid] = TRUE;
+ }
+#endif
+ }
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr, "Switching to font #%d (%s).\n", k, fontptr->n);
+#endif
+ /* activate font */
+#ifdef IBM3812
+ sprintf(PMPformat, "\323%c", (unsigned char)fontptr->plusid);
+ PMPout(2, PMPformat);
+#endif
+#ifdef LJ
+ if (!rasterfont[fontptr->plusid]) {
+#ifdef LJ_RESIDENT_FONTS
+ if (fontptr->resident_p) {
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr, "Resident font #%d.\n", fontptr->resid);
+#endif
+ EMIT(outfp, "\033(%s", fontptr->symbol_set);
+ EMIT(outfp, "\033(s%up%.2f%c%us%db%uT",
+ fontptr->spacing,
+ /* height in points, or pitch */
+ fontptr->spacing ? fontptr->s / 65536.0
+ : fontptr->pitch ,
+ fontptr->spacing ? 'v' : 'h', /* height or pitch? */
+ fontptr->style, /* upright, italic, ... */
+ fontptr->weight, /* regular, bold, ... */
+ fontptr->resid);
+ } else
+#endif /* LJ_RESIDENT_FONTS */
+ if (fontptr->plusid>0) EMIT(outfp, "\033(%dX", fontptr->plusid);
+ else EMIT(outfp, "\033(X");
+ }
+/* else fprintf(stderr,"I am doing rasterfont for plusid=%d instead\n",
+ fontptr->plusid);
+*/
+#endif
+ }
+#ifdef LJ /* reassignment of printer font id 0.48 */
+ else if (fontptr->font_file_id != NO_FILE
+#ifdef LJ_RESIDENT_FONTS
+ && !fontptr->resident_p
+#endif
+ ) {
+ if (fontptr->ncdl == 0) {
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr, "Changing plusid from %d to %d\n",
+ fontptr->plusid, (int)plusid);
+#endif
+ fontptr -> plusid = plusid;
+ plusid ++;
+ }
+ }
+#endif
+}
+
+
+/*-->SetPosn*/
+/**********************************************************************/
+/***************************** SetPosn ******************************/
+/**********************************************************************/
+void /* output a positioning command */
+SetPosn(x, y)
+long x, y;
+{
+ int rx, ry;
+ rx = (int)PIXROUND(x, hconv) + x_goffset;
+ ry = (int)PIXROUND(y, vconv) + y_goffset;
+
+/*
+* fprintf(stderr,"setposn to %ld/%ld, %d/%d\n",x,y,rx,ry);
+*/
+
+#ifdef IBM3812
+ PMPcont(3);
+ PMPoutC('\340');
+ EMITWORD(LARGER(rx,0));
+
+ if (last_ry != ry) { /* necessary to set new y-position */
+ PMPcont(3);
+ PMPoutC('\341');
+ EMITWORD(LARGER(ry,0));
+ }
+#endif
+#ifdef LJ
+ if (last_ry != ry) /* necessary to set new y-position */
+ EMIT(outfp, "\033*p%dx%dY", LARGER(rx,0), LARGER(ry,0));
+ else
+ EMIT(outfp, "\033*p%dX", LARGER(rx,0));
+#endif
+
+ last_ry = ry; /* last y-position on output device */
+ last_rx = rx; /* last x-position on output device */
+/*
+ * must know where device "really" is horizontally, for rel. posning.
+ * (maybe in the future), but we always use direct positioning for
+ * vertical movement.
+ */
+ /* hh = rx * hconv; */
+ hh = x;
+ vv = y;
+/*
+ * fprintf(stderr,"DoPosn: x=%ld, y=%ld, rx=%d, ry=%d, hh=%ld, vv=%ld\n",
+ * x,y,rx,ry,hh,vv);
+ */
+}
+
+
+#ifdef IBM3812
+/*-->PMPLine*/
+/**********************************************************************/
+/***************************** PMPLine ******************************/
+/**********************************************************************/
+void /* drawing lines on the 3812 using PMP vector commands */
+PMPLine(w, y, x)
+int w, y, x;
+{
+
+ if ((w == 0) || ((x == 0) && (y == 0)))
+ return;
+
+/*
+fprintf(stderr,"w=%d / %d - %d, y=%d / %d - %d, x=%d / %d - %d\n",
+ w,(char)(w & 0xff),(int)((signed_char)(w & 0xff)),
+ y,(char)(y & 0xff),(int)((signed_char)(y & 0xff)),
+ x,(char)(x & 0xff),(int)((signed_char)(x & 0xff)));
+*/
+
+ if ( (((signed_char)(x & 0xff)) == x ) &&
+ ( ((signed_char)(y & 0xff)) == y ) ) {
+ PMPcont(6);
+ PMPout(1, "\370");
+ EMITWORD(3); /* length of vector */
+ PMPoutC((unsigned char)(0x80 | 0x00 | (unsigned char) w));
+ PMPoutC((signed_char)(y & 0xff));
+ PMPoutC((signed_char)(x & 0xff));
+/*
+ fprintf(stderr,"F8 00 03: w=%d, x=%d(%d-%.2X), y=%d(%d-%.2X),\n",
+ w,x,(char)(x & 0xff),(signed_char)(x & 0xff),
+ y,(char)(y & 0xff),(signed_char)(y & 0xff));
+*/
+
+ } else {
+ PMPcont(8);
+ PMPout(1, "\370");
+ EMITWORD(4 + 1); /* length of vector */
+ PMPoutC((unsigned char)(0xC0 | 0x00 | (unsigned char) w));
+ EMITWORD(y);
+ EMITWORD(x);
+/*
+ fprintf(stderr,"F8 00 05: w=%d, x=%d, y=%d,\n", w,x,y);
+*/
+ }
+}
+
+
+#endif
+/*-->SetRule*/
+/**********************************************************************/
+/***************************** SetRule ******************************/
+/**********************************************************************/
+void /* this routine will draw a rule */
+SetRule(a, b, Set)
+long a, b;
+int Set;
+{
+ long xx, yy;
+#ifdef IBM3812
+ short hor_offset, vert_offset, ll;
+#endif
+ if ( a > 0 && b > 0 ) {
+ SetPosn(h, v); /* lower left corner */
+ xx = (long)PIXROUND(b, hconv); /* width */
+ yy = (long)PIXROUND(a, vconv); /* height */
+
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,"Rule xx=%ld, yy=%ld\n", xx, yy);
+#endif
+
+#ifdef IBM3812
+ hor_offset = (short)(last_ry - yy);
+ if (hor_offset < 0) yy += hor_offset;
+ if (last_rx < 0) xx += last_rx;
+
+ if (Landscape) {
+ if (last_ry > MAX_PAGE_WIDTH) yy += MAX_PAGE_WIDTH-last_ry;
+ hor_offset = (short)(MAX_PAGE_HEIGHT - (last_rx + xx));
+ } else {
+ if (last_ry > MAX_PAGE_HEIGHT) yy += MAX_PAGE_HEIGHT-last_ry;
+ hor_offset = (short)(MAX_PAGE_WIDTH - (last_rx + xx));
+ }
+ if (hor_offset < 0) xx += hor_offset;
+
+ if ((xx > 31) && (yy > 31)) {
+/*
+ * fill area by multiple lines (kind of a mess)
+ * process for simplicity always horizontally
+ */
+
+/* fprintf(stderr, "large box: w=%d, x=%d, y=%d\n",(int)yy,(int)xx,0);*/
+
+ hor_offset = HOR_HALF(30);
+ MoveHor(hor_offset);
+ vert_offset = VERT_HALF(30);
+ MoveVert(-vert_offset);
+ ll = (short)xx - 30;
+
+ for (; yy > 30; yy -= 30) {
+ PMPLine(30, 0, ll);
+ MoveHor(-ll);
+ MoveVert(-30);
+ }
+
+ hor_offset = -hor_offset + HOR_HALF(yy);
+ MoveHor(hor_offset);
+ vert_offset = (vert_offset - 30) + VERT_HALF(yy);
+ MoveVert(-vert_offset);
+
+ PMPLine((int)yy, 0, (int)(xx - yy));
+
+ } else if ( (yy < xx) && (xx > 0) ) {
+
+/* fprintf(stderr, "hori rule: w=%d, x=%d, y=%d\n",(int)yy,(int)(xx-yy),0);*/
+
+ hor_offset = HOR_HALF(yy);
+ vert_offset = VERT_HALF(yy);
+
+ MoveHor(hor_offset);
+ MoveVert(-vert_offset);
+
+ PMPLine((int)yy, 0, (int)(xx - yy));
+ } else if ( (xx < yy) && (yy > 0)) {
+
+ hor_offset = HOR_HALF(xx);
+ vert_offset = VERT_HALF(xx);
+/*
+ fprintf(stderr, "move: x=%d, y=%d\n",hor_offset,-vert_offset);
+ fprintf(stderr, "vert rule: w=%d, x=%d, y=%d\n",(int)xx,0,(int)-(yy-xx));
+*/
+ MoveHor(hor_offset);
+ MoveVert(-vert_offset);
+
+ PMPLine((int)xx, (int)-(yy - xx), 0);
+ } else if (xx == yy) {
+ short y0; /* small square box!! */
+
+ y0 = (short)yy / 2;
+ hor_offset = HOR_HALF(y0);
+ MoveHor(hor_offset);
+ vert_offset = VERT_HALF(y0);
+ MoveVert(-vert_offset);
+ ll = (short)xx - y0;
+
+ PMPLine((int)y0, 0, ll);
+
+ hor_offset = -(ll + hor_offset);
+ vert_offset = (y0 - vert_offset);
+
+ yy -= (long)y0;
+ hor_offset += HOR_HALF(yy);
+ MoveHor(hor_offset);
+ vert_offset += VERT_HALF(yy);
+ MoveVert(-vert_offset);
+
+ PMPLine((int)yy, 0, (int)xx - yy);
+ }
+#endif
+#ifdef LJ
+ if (last_ry + 1 < yy) yy = last_ry + 1;
+ if (last_rx < 0) xx += last_rx;
+
+ if (((int)pgsiz_dots >0) && ((int)last_ry > (int)pgsiz_dots))
+ yy += (long)pgsiz_dots - (long)last_ry;
+
+ if ((yy>0) && (xx>0))
+ EMIT(outfp, "\033*p-%ldY\033*c%lda%ldbP", yy - 1, xx, yy);
+#endif
+ last_ry = UNKNOWN; /* next time full positioning */
+ }
+ if (Set)
+ h += b;
+}
+
+
+/*-->SetString*/
+/**********************************************************************/
+/***************************** SetString ****************************/
+/**********************************************************************/
+void
+SetString(firstch, PassNo) /* read and set a consecutive string of chars */
+short firstch;
+int PassNo;
+{
+ short c;
+ register unsigned short i;
+
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr, "SetString ");
+#endif
+ for (i = 0, c = firstch; c >= SETC_000 && c <= SETC_127; i++) {
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr, "%d(%c) ", c, c);
+#endif
+ SetChar((long)c, c, PassNo, (bool)(i==0),TRUE);
+ c = (short) NoSignExtend(dvifp, 1);
+ }
+ fseek(dvifp, -1l, 1); /* backup one character */
+#ifdef IBM3812
+ CharStringOut;
+#endif
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr, "...SetString\n");
+#endif
+}
+
+#ifndef ARITHMETIC_RIGHT_SHIFT
+long signTab[5] = {0,0x00000080,0x00008000,0x00800000,0x00000000};
+long extendTab[5] = {0,~0^0xff,~0^0xffff,~0^0xffffff,~0^0xffffffff};
+#endif
+
+/*-->SignExtend*/
+/**********************************************************************/
+/**************************** SignExtend ****************************/
+/**********************************************************************/
+long
+SignExtend(fp, n) /* return n byte quantity from file fd */
+register FILE *fp; /* file pointer */
+register int n; /* number of bytes */
+{
+ int n1; /* number of bytes */
+ long x; /* number being constructed */
+#ifdef SIGN_DEBUG
+ long x0; /* copy of x */
+#endif
+ x = getc(fp); /* get first (high-order) byte */
+ n1 = n--;
+ while (n--) {
+ x <<= 8;
+ x |= getc(fp);
+ }
+/*
+ * NOTE: This code assumes that the right-shift is an arithmetic, rather
+ * than logical, shift which will propagate the sign bit right. According
+ * to Kernighan and Ritchie, this is compiler dependent!
+ */
+
+#ifdef SIGN_DEBUG
+ x0 = x;
+#endif
+
+#ifdef ARITHMETIC_RIGHT_SHIFT
+ x <<= 32 - 8 * n1;
+ x >>= 32 - 8 * n1; /* sign extend */
+#else
+ if (x & signTab[n1]) x |= extendTab[n1];
+#endif
+
+#ifdef SIGN_DEBUG
+ fprintf(stderr,"\tSignExtend(fp,%d)=%X, was=%X,%d\n",
+ n1,x,x0,x0&signTab[n1]);
+#endif
+
+#ifdef DEBUG
+ if (Debug > 1)
+ fprintf(stderr,"\tSignExtend(fp,%d)=%X\n", n1, x);
+#endif
+ return(x);
+}
+
+
+/*-->SkipFontDef*/
+/**********************************************************************/
+/**************************** SkipFontDef ***************************/
+/**********************************************************************/
+void
+SkipFontDef()
+{
+ int a, l;
+ char n[STRSIZE];
+
+ (void) NoSignExtend(dvifp, 4);
+ (void) NoSignExtend(dvifp, 4);
+ (void) NoSignExtend(dvifp, 4);
+ a = (int) NoSignExtend(dvifp, 1);
+ l = (int) NoSignExtend(dvifp, 1);
+ GetBytes(dvifp, n, a + l);
+}
+
+
+/*-->Warning*/
+/**********************************************************************/
+/***************************** Warning ******************************/
+/**********************************************************************/
+void /* issue a warning */
+Warning(fmt, a, b, c, d)
+char *fmt; /* format */
+char *a, *b, *c, *d; /* arguments */
+{
+#ifndef vms
+ G_errenc = 1;
+#else
+ G_errenc = (SS$_ABORT | STS$M_INHIB_MSG); /* no message on screen */
+#endif
+ if ( G_nowarn || G_quiet )
+ return;
+
+ fprintf(stderr, "warning : ");
+ fprintf(stderr, fmt, a, b, c, d);
+ fprintf(stderr, "\n");
+}
+
+void
+PutWord(w)
+int w;
+{
+ EMITC((char)(w >> 8) & 0xff);
+ EMITC((char)w & 0xff);
+}
+
+
+#ifdef IBM3812
+/*-->PMPout*/
+/*****************************************************************************/
+/* This routine produces the PMP-envelopes for the 3812. Its semantics are:
+
+ first arg == 0 ... flush buffer
+ first arg == -1 ... number of bytes specified in the second argument
+ have to be continuous, that is they must not
+ be disrupted by ENTER PMP etc.
+ first arg > 0 output first arg bytes
+
+ If arg2 > OUTBUFSIZE ... flush buffer,
+ switch to unbuffered mode
+ (dont't collect PMP commands)
+ If arg2+bufferpointer > OUTBUFSIZE ... flush buffer,
+ block will fit into buffer
+ otherwise ..... block will fit into buffer
+
+ Buffering is done to reduce the ENTER PMP-commands. Initially
+ the 3812 is in PC-ASCII mode. In order to issue a PMP-command it is
+ necessary to enter PMP mode. The ENTER-PMP-command contains the
+ number of bytes that will be interpreted as PMP-commands. In the
+ most naive approach for each primitive command (eg. set cursor) you
+ have to produce a seperate ENTER-PMP-envelope (5 bytes). It is
+ favourable to collect as many PMP commands as possible in one envelope. */
+/*****************************************************************************/
+void
+PMPout(l, s)
+char *s;
+int l;
+{
+ static char buffer[OUTBUFSIZE];
+ static unsigned short bp = 0; /* range 0..OUTBUFSIZE */
+ static long continuous = 0l;
+ static bool buffered = TRUE;
+
+ if (l == 0) {
+ if (bp == 0)
+ return;
+ EMIT(outfp, "\033[C%c%c", (unsigned char)(bp & 0xFF),
+ (unsigned char)(bp >> 8));
+ EMITB((int)bp, buffer);
+ bp = 0;
+ return;
+ }
+ if (l == -1) {
+ continuous = (long)s;
+ if (continuous + (long)bp + 5l > (long) OUTBUFSIZE)
+ PMPflush;
+ buffered = (bool) ((continuous + 5l <= (long) OUTBUFSIZE));
+ if (!buffered) {
+ EMIT(outfp, "\033[C%c%c",
+ (unsigned char)(continuous & 0xFF),
+ (unsigned char)((continuous >> 8) & 0xFF));
+ }
+ return;
+ }
+ if (buffered) {
+ register int i;
+ if ( ((long)l + bp) > OUTBUFSIZE)
+ PMPflush;
+ for (i = 0; i < l; i++)
+ buffer[bp+i] = s[i];
+ bp += (unsigned short)l;
+ } else {
+ EMITB((int)l, s);
+ buffered = (bool) ((continuous -= (long)l) <= 0) ;
+ }
+}
+
+
+void
+PMPoutC(c)
+char (c);
+{
+ PMPout(1, &c);
+}
+
+
+#endif
+#ifdef MSDOS
+/*-->AssureBinary*/
+/**********************************************************************/
+/*************************** AssureBinary *****************************/
+/**********************************************************************/
+/* This procedure is both DOS AND MSC dependent. The MSC file open on */
+/* a device ignores the 'binary' of the "wb" parameter and opens the */
+/* file in ascii mode. This procedure sets the file f to binary mode */
+/* if it is connected to a device that is not console input or output */
+/* or the null device. For other operating systems this routine is */
+/* useless. (Background: MSDOS 3.2 Technical Reference upd 1 pg 6-137 */
+/**********************************************************************/
+void
+AssureBinary(f)
+FILE *f;
+{
+ union REGS regs; /* registers for bios call */
+
+ regs.h.ah = (unsigned char) 0x44; /* IOCTL */
+ regs.h.al = (unsigned char) 0x00; /* get device information */
+ regs.x.bx = (unsigned int) fileno(f); /* handle from MSC */
+ intdos(&regs, &regs); /* call DOS interrupt */
+ /* ---> result in DX */
+
+ if ( (regs.h.dl & 0x80) /* file handle points to a device */
+ && !(regs.h.dl & 0x07) ) /* neither console i/o or null */ {
+
+ regs.h.dl |= 0x20; /* set BINARY bit in device info */
+
+ regs.h.ah = (unsigned char) 0x44; /* IOCTL */
+ regs.h.al = (unsigned char) 0x01; /* set device information*/
+ regs.x.bx = (unsigned int) fileno(f); /* handle from MSC */
+ regs.h.dh = (unsigned char) 0x00; /* clear DH */
+ intdos(&regs, &regs); /* call DOS interrupt */
+ }
+}
+
+
+#endif
+
+#ifdef USEPXL
+bool getbit ();
+unsigned char getnyb ();
+long pk_packed_num ();
+
+
+#define PKBYTE *pkloc; pkloc ++
+#define OUTCHAR(c) raster_line_buf[bp]= (unsigned char)c; bp++
+
+unsigned char bitweight, inputbyte ;
+unsigned char dyn_f ;
+unsigned char *pkloc;
+int repeatcount;
+
+void /* <Read and translate raster description@>*/
+PkRaster(ce, raster)
+struct char_entry *ce;
+bool raster;
+{
+ int rp;
+ int current_line;
+ int wordwidth ;
+ bool turnon;
+ unsigned short nbpl;
+ long rowsleft, word, wordweight, hbit, count, i, j, tl;
+ long row[101] ;
+ unsigned char raster_line_buf[BYTES_PER_PIXEL_LINE];
+ unsigned short bp;
+
+
+ if (ce->charsize == HUGE_SIZE)
+ Fatal( "cannot process currently PK font patterns of that size!\n");
+
+
+ current_line = 0;
+ pkloc = (unsigned char *)ce->where.address.pixptr;
+ dyn_f = (unsigned char)(ce->flag_byte >> 4);
+ turnon = (bool)((ce->flag_byte & 8) == 8);
+ wordwidth = (int)(ce->width + 31) >> 5 ;
+ nbpl = ((int)(ce->width) + 7) >> 3;
+
+ bitweight = 0 ;
+ if (dyn_f == 14) {
+ /*printf("<Get raster by bits@>\n");*/
+ for (i = 1; i <= (long)ce->height; i++) {
+ word = 0 ;
+ wordweight = 31 ;
+ bp = 0; /* Sowa */
+
+#ifdef DRAWGLYPH
+ printf(" |");
+#endif
+ for (j = 1; j <= (long) ce->width; j++) {
+ bool getbit;
+ /* bp = 0; SOWA */
+/*******************************************begin Getbit *********/
+ bitweight /= 2 ;
+ if ( bitweight == 0 ) {
+ inputbyte = PKBYTE ;
+ bitweight = 128 ;
+ }
+ getbit = (bool)
+ ( inputbyte >= bitweight ) ;
+ if ( getbit )
+ inputbyte -= bitweight ;
+/*********************************************end Getbit *********/
+
+ if (getbit)
+ word += power[wordweight] ;
+
+ wordweight --;
+ if (wordweight == -1) {
+
+#ifdef DRAWGLYPH
+ { int k;
+ for (k=31; k>=0; k--) {
+ if ((power[k] & word)!=0) printf("M");
+ else printf(".");
+ }
+ }
+#endif
+
+ OUTCHAR((word >> 24 & 0xFF));
+ OUTCHAR((word >> 16 & 0xFF));
+ OUTCHAR((word >> 8 & 0xFF));
+ OUTCHAR((word & 0xFF));
+
+ word = 0 ;
+ wordweight = 31 ;
+ }
+ }
+ if (wordweight < 31) {
+#ifdef COMMENT
+#ifdef DRAWGLYPH
+ { int k;
+ for (k=15; k>=0; k--) {
+ if ((power[k] & word)!=0) printf("Z");
+ else printf(":");
+ }
+ }
+ printf("|\n ----|");
+#endif
+#endif
+
+ for (j = 3; j >= (wordwidth * 4 - (long)nbpl);
+ j--) {
+
+ OUTCHAR(((word >> (j << 3)) & 0xff));
+
+#ifdef DRAWGLYPH
+ { int k;
+ for (k=7; k>=0; k--) {
+ if ((power[k] & ((word >> (j << 3)) & 0xff))!=0) printf("M");
+ else printf(".");
+ }
+ }
+#endif
+
+ }
+ }
+
+ if (raster) {
+ RasterLine(ce, (unsigned int)nbpl,
+ current_line, raster_line_buf);
+ current_line++;
+ } else
+ EMITL(bp, raster_line_buf);
+
+#ifdef DRAWGLYPH
+ printf("|\n");
+#endif
+ }
+ } else {
+ /* fprintf(stderr, "@<Create normally packed raster@>\n"); */
+ rowsleft = (long) ce->height ;
+ hbit = (long) ce->width ;
+ repeatcount = 0 ;
+ wordweight = 32 ;
+ word = 0 ;
+ rp = 1 ;
+ while ( rowsleft > 0 ) {
+ count = pk_packed_num() ;
+ bp = 0;
+
+ while (count > 0) {
+ if ((count < wordweight) && (count < hbit)) {
+ if (turnon)
+ word +=
+ gpower[wordweight] -
+ gpower[wordweight - count] ;
+
+ hbit -= count ;
+ wordweight -= count ;
+ count = 0 ;
+ } else if ((count >= hbit) && (hbit <=
+ wordweight)) {
+
+ if (turnon)
+ word +=
+ gpower[wordweight] -
+ gpower[wordweight - hbit] ;
+
+ row[rp] = word ;
+
+ /*fprintf(stderr, " @<Send row@> \n");*/
+ for (i = 0; i <= (long) repeatcount; i++) { int ii;
+
+#ifdef DRAWGLYPH
+ printf("*** |");
+#endif
+ for (ii = 1; ii < wordwidth; ii++) {
+ tl = row[ii];
+
+ OUTCHAR((tl >> 24 & 0xFF));
+ OUTCHAR((tl >> 16 & 0xFF));
+ OUTCHAR((tl >> 8 & 0xFF));
+ OUTCHAR((tl & 0xFF));
+
+#ifdef DRAWGLYPH
+ { int k;
+ for (k=31; k>=0; k--) {
+ if ((power[k] & row[ii])!=0) printf("M");
+ else printf(".");
+ }
+ }
+#endif
+ }
+ tl = row[wordwidth];
+ for (j = 3; j >= (wordwidth *4 - (long)nbpl);
+ j--) {
+
+ OUTCHAR(((tl >> (j << 3)) & 0xff));
+
+#ifdef DRAWGLYPH
+ { int k;
+ for (k=7; k>=0; k--) {
+ if ((power[k] & ((tl >> (j << 3)) & 0xff))!=0) printf("M");
+ else printf(".");
+ }
+ }
+#endif
+ }
+
+ if (raster) {
+ RasterLine(ce,
+ (unsigned int)nbpl,
+ current_line,
+ raster_line_buf);
+ current_line++;
+ } else
+ EMITL(bp, raster_line_buf);
+
+ bp = 0;
+
+#ifdef DRAWGLYPH
+ printf("| ");
+ for (j=1;j<=(long)wordwidth;j++) printf("%02lX/",row[j]);
+ printf(" raster=%d\n",raster);
+#endif
+ }
+
+ rowsleft -= (long)repeatcount + 1 ;
+ repeatcount = 0 ;
+ rp = 1 ;
+ word = 0 ;
+ wordweight = 32 ;
+ count -= hbit ;
+ hbit = (long)ce->width ;
+ } else {
+ if (turnon) word += gpower[wordweight] ;
+ row[rp] = word ;
+ rp = rp + 1 ;
+ word = 0 ;
+ count -= wordweight ;
+ hbit -= wordweight ;
+ wordweight = 32 ;
+ }
+ } /* .....while count > 0 */
+ if (turnon)
+ turnon = FALSE;
+ else
+ turnon = TRUE;
+ } /* ...... rowsleft > 0 */
+ if ((rowsleft != 0) || (hbit != (long)ce->width))
+ Fatal("Bad pk file----more bits than required!\n");
+ } /* .... create normally packed raster */
+}
+
+
+unsigned char getnyb ()
+{
+ register unsigned char temp ;
+ if ( bitweight == 0 ) {
+ inputbyte = PKBYTE ;
+ bitweight = 16 ;
+ }
+ temp = inputbyte / bitweight ;
+ inputbyte -= temp * bitweight ;
+ bitweight /= 16 ;
+ return ( temp ) ;
+}
+
+
+long
+pk_packed_num ()
+{ /*@<Packed number procedure@>= */
+ register int i;
+ long j;
+
+ i = (int)getnyb();
+ if (i == 0) {
+ do {
+ j = (long)getnyb();
+ i++;
+ } while (j == 0) ;
+ while (i > 0) {
+ j = j * 16 + (long)getnyb() ;
+ i--;
+ };
+ return (j - 15 + (13 - dyn_f) * 16 + dyn_f) ;
+ } else if (i <= (int)dyn_f) {
+ return ((long)i);
+ } else if (i < 14) {
+ return ((i-(long)dyn_f - 1) * 16 + (long)getnyb() + dyn_f + 1);
+ } else {
+ if (i == 14) {
+ repeatcount = (int) pk_packed_num() ;
+ } else {
+ repeatcount = 1 ;
+ }
+ /* fprintf(stderr,"repeatcount = [%d]\n",repeatcount); */
+ return (pk_packed_num()) ; /* tail end recursion !! */
+ }
+}
+#endif
+
+#ifndef USEPXL
+void bad_gf(n)
+ int n;
+{
+ Fatal("Bad gf file, case %d\n",n); /* See gf.c */
+}
+#endif
+/*-->FormFeed*/
+/**********************************************************************/
+/***************************** FormFeed ******************************/
+/**********************************************************************/
+void
+FormFeed()
+{
+
+#ifdef IBM3812
+ unsigned short pages;
+ if ( (ndone == 0) && (FirstAlternate)){
+ for (pages = 1; pages < ncopies; pages++) {
+ PMPout(2, "\321\300"); /* PMP-command xD1C0 */
+ }
+ PMPout(2, "\321\100"); /* PMP-command xD140 */
+ } else {
+ for (pages = 1; pages < ncopies; pages++){
+ PMPout(2, "\321\200"); /* PMP-command xD180 */
+ }
+ PMPout(2, "\321\0"); /* PMP-command xD100 */
+ }
+#endif
+#ifdef LJ
+ EMITC('\f');
+#endif
+}
diff --git a/obsolete/dviware/dvi2xx/dvi2xx.history b/obsolete/dviware/dvi2xx/dvi2xx.history
new file mode 100644
index 0000000000..07f559f90f
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/dvi2xx.history
@@ -0,0 +1,643 @@
+
+ MINIDESCRIPTION FOR DVI2XX
+
+This is a description of a dvi converter (dvi= TeX's device independent
+output format) that runs on PCs (XTs, ATs or compatible) under MS/DOS.
+DVI2XX is able to produce either device dependent code for the
+HP-LaserJet+ or for the IBM3812 (model 1) depending on a preproscessor
+switch at compile time. The documentation concerning compile switches
+is located in the source.
+
+DVI2XX can be called with the following options:
+
+ -aXXX directory to take fonts from
+ -b take paper for first page from alternate cassette (only 3812)
+ -eXXX output file: either drive:path\name of outputfile
+ or device (such as lpt1, nul etc)
+ (default is drive:path\name of dvi file and extentsion
+ '.lj' for laserjet and '.pmp' for 3812)
+ -hXXX headerfile to be copied before translation of dvi-file
+ (you can send arbitrary commands to the laserprinter)
+ -fXXX print from begin of page xxx
+ -tXXX print to end of page xxx
+ -mXXX magnification
+ -xXXX global x-offset in mm on output page
+ -yXXX global y-offset in mm on output page
+ -r toggle reverse/not reverse order for output
+ (default reverse=FALSE for 3812, reverse=TRUE for LJ)
+ -p turn off font preload
+ -q quiet operation
+ -w no warnings
+
+If no arguments are specifyed a short help file is displayed.
+
+Two 'special' commands are implemented for the 3812:
+
+ \special{file=drive:path/name}
+ copy specified file to the printer;
+ either vector- or bitmap-graphics PMP commands
+
+ \special{orientation=Value}
+ set page orientation to 0, 1, 2, 3;
+ rotate following output to landscape mode etc.
+ Depending on print direction!
+
+With the file= special TeX command I have faked the signature of
+my boss with nice thick ink. It is simply the pmp command for a
+polygon drawing and it looks surprisingly natural.
+
+The program part for redirection of the output to the printer without
+intermediate spool file was relatively tricky and uses a IOCTL bios-call.
+The performance of the program is about 6 to 7 seconds per page on a
+AT with 8Mhz in the 3812 mode. It is running on our configuration
+via PC-NET.
+
+Currently two font formats are supported: PXL 1001 and PXL 1002.
+
+The program assumes the following pixelfile structure (the characters
+under quotes are mandatory):
+
+ someroot
+ ...
+ "pxl"1500
+ amr10.pxl
+ cmr10.pxl
+ ...
+ "pxl"1643
+ amr10.pxl
+ cmr10.pxl
+ ...
+ ...
+
+300dpi files can be used with an adequate magnification (-m#1250 option).
+
+The following characters (all of them occur in the program) might be
+translated wrongly by the ASCII-EBCDIC-ASCII conversion during uploading
+and downloading respectively:
+
+! exclamation point
+[ left square bracket
+\ left slash (backslash)
+] right square bracket
+{ left curly bracket
+| vertical bar
+} right curly bracket
+
+If the characters in the first column do not correspond to their verbal
+description fix the C-program adequately.
+
+The program can be compiled with microsoft C Rel.3 or later using the
+-AL compiler option. If you have no adequate C-compiler at your site I can
+send also the compiled code via e-mail. If you have troubles with downloading
+please send me a floppy.
+
+On troubles please read first comments ot the begin of the source
+program. Otherwise contact me.
+
+- Gustaf Neumann
+ Wirtschaftsuniversitaet Wien
+ Institut fuer Informationsverabeitung und Informationswirtschaft
+ A-1090 Vienna
+ Augasse 2-6
+ Austria (Europe)
+
+EARN/BITNET: NEUMANN at AWIWUW11
+ARPA: neumann%awiwuw11.bitnet@wiscvm.ARPA
+=========================================================================
+Date: 25 August 1987, 16:58:19 WUT
+From: NEUMANN at AWIWUW11
+Subject: New release (0.30) of dvi2xx
+
+Hi (potential) dvi2xx-user...
+
+There is a new relase (0.30) of the dvi/3812 and dvi/HPLJ+
+converter. The new release features in the following points:
+
+- it accepts the new PK 89 format (Rokicki, Tugboat Vol 6, 1985, No. 3)
+ that uses much less disk storage (about 1/4th of PXL1001 files),
+- it is possible to specify a 'string of paths' to be searched for the
+ PXL- or PK-files; the paths are separated by semicolons,
+- it accepts as file-extension either '.pxl' or '.pk',
+- the formats of the pixel-files (PXL-1001, PXL-1002, PK-89)
+ can be arbitrarily mixed;
+ eg. CMR10 can be in PXL-1002 format, CMINCH can be in PK-89,
+- the amount of storage in the PC is reduced especially when
+ PK-files are used,
+- an unimportant bug from the timing measurements has been removed,
+- verbatim mode can be set via commandline option -v, that informs
+ the user, which fonts are loaded.
+
+We are using the driver here in the following setup.
+We have a print-server (IBM PC-AT) that is connected on one side with
+the 3812 via 19200/asynchronous port, and on the other side with a bunch
+of PC-ATs via IBM PC-Net. We use PC-TeX on the ATs. Historically
+all of the PXL-files have been on the print-server in 1002-format
+being accessed from the dvi-driver over the network.
+
+In the new setup, each of the PCs has a small set of the most used
+PK-fonts. By specifying with the commandline option of dvi2xx
+'-aLOCALFONTS;SERVERFONTS' where LOCALFONTS and SERVERFONTS are valid
+fontdirectories, each font is searched first in LOCALFONTS
+and if it is not found there in SERVERFONTS. Only seldomly used fonts
+are accessed via PC-NET. The network load was reduced in this way
+drastically, the speed improvement is about 30%.
+
+If you have interest to receive the new version, please send a short
+note ....
+
+-gustaf
+=========================================================================
+Date: 12 November 1987, 12:11:00 WUT
+From: NEUMANN at AWIWUW11
+Subject: New release (0.31) of dvi2xx .. supports also new dir-structure
+
+The newer versions of PCTeX (and some TeX-drivers) are distributed with
+fonts put into a different directory structure that uses in the
+directory names RESOLUTIONS rather than MAGNIFICATIONS.
+
+The old directory structure standard was:
+
+ somerootA
+ ...
+ "pxl"1500
+ amr10.pxl
+ cmr10.pxl
+ cminch.pk
+ ...
+ "pxl"1643
+ amr10.pxl
+ cmr10.pxl
+ tt10.pk
+ ...
+ ...
+
+The new directory structure looks like:
+
+ somerootB
+ ...
+ "DPI"300
+ amr10.pxl
+ cmr10.pxl
+ cminch.pk
+ ...
+ "DPI"329
+ amr10.pxl
+ cmr10.pxl
+ tt10.pk
+ ...
+ ...
+
+Rel 0.31 supports both structures, it is possible to specify
+a path ('-a' option eg '-asomerootA;somerootB').
+
+The search order in one directory is:
+ 1) look for DPI....\font.pk where '...' is eg 240
+ 2) look for DPI....\font.pxl or 300
+ 3) look for pxl....\font.pk where '...' is eg 1200
+ 4) look for pxl....\font.pxl or 240
+=========================================================================
+Date: 1 Dezember 1987, 14:11:00 WUT
+
+Rel 0.32 initializes in LJ-mode the printer and resets it after run;
+helps when operating with the LJ2
+=========================================================================
+Date: 18 Dezember 1987, 18:18:00 WUT
+
+Rel 0.33 runs without any modifications under Unix V (HP/UX);
+improved messages for missing fonts.
+========================================================================
+Date: 5 January 1988, 04:04:04 WUT
+From: NEUMANN at AWIWUW11
+Subject: New release (0.40) of dvi2xx
+
+Hi everybody!
+
+The holidays are over and there comes a new release (0.40) of DVI2XX.
+It has two major improvements over the previous release:
+
+a) It supports 'HUGE' pixel characters;
+b) it does a better positioning which is important mainly for the 3812.
+c) Page origin is now on the 3812 and on the LJ2 1 inch from the left and
+ right edge of the paper.
+d) Smaller output files (== higher printing speed).
+
+ad a)
+ The driver knows now about three types of characters:
+ - Small characters are loaded into the font-storage of
+ the printer. When a small character occurs in the text,
+ the character is copied internally in the printer
+ to the output page. The bitmaps of small characters
+ are transmitted only once to the printer.
+ - Large characters are loaded into the memory of the driver
+ and are transmitted on each occurance in the text as a
+ raster graphic to the printer.
+ - Huge characters (characters which raster information has
+ a size more than 32767 bytes) are read on each occurance from
+ the disk and are transmitted as raster graphics. They are
+ not loaded permanently into the memory of the driver.
+
+ Why huge Characters?
+ It is quite easy to include graphics into TeX by packing
+ bitmap graphics into TeX fonts. I've written some programs
+ to convert graphics generated from Drawing Gallery, Framework II,
+ Scanning Gallery etc. into 1001 fonts and adequate TFM files
+ (if you want to have more info on that send me a note).
+ The graphics easily reach a size of 100 or 200K each, and so
+ it is certainly a problem to keep these in memory.
+
+ There are essentially 2 common ways to include graphics in TeX.
+ - Using \special to include printer dependent code.
+ - Putting the graphics into characters.
+
+ Advantages of the latter are:
+ 1) The reproduction of the graphics is not device dependent
+ (rather resolution dependent). It is possible to see
+ text and graphics with a good previewer together on
+ the screen.
+ 2) TeX sizes the graphics as it sizes characters. It is not
+ necessary to include size infos about the graphics in the
+ TeX file. When a graphic changes its size or shape, TeX is
+ able to rearrange the output.
+
+ I have scanned some photos and logos and included it in TeX
+ documents. It really looks great.
+
+ Please note that a standard LJ+ has not enough memory to generate
+ big raster graphics.
+
+ad b) The driver has had some problems with positioning of rules.
+ In heavy formula djungles very often some lines have been placed
+ wrong by one pixel. It is not so easy to draw lines exactly where
+ you want using the 3812 vector drawing facilities... Additionally
+ the conversion of the internal TeX units into pixels has gotten
+ more accurate (also for the LJ). The result is a overall better
+ outlook of the printed pages.
+
+ad c) This is true at least for the European A4 paper trays.
+
+ad d) Output has been reduced by more intelligent positioning (for
+ both supported printers). Additionally the driver is more clever
+ now in sending bitmap graphics to the LJ. The 3812-code is
+ reduced approximately by 25% on a 20 page document.
+
+Caveat: the driver is a little bit slower.
+I hope I have not introduced to many new bugs.
+=========================================================================
+Date: 12 February 1988, 02:39:20 WUT
+From: NEUMANN at AWIWUW11
+Subject: New release (0.41) of dvi2xx
+
+Hi everybody!
+
+It's time for a new release of dvi2xx. The newest version (0.41)
+features in the following points:
+
+ - significantly better performance
+ - a bunch of new options
+
+Performance:
+ The following figures are measured on a reasonably standard TeX
+ document (16 pages long, contains several formulas and tables)
+ on a PC/AT. The last two colums are also valid on Unix machines.
+
+ time to convert dvi file size of output file printing speed
+ (times faster than 0.40) (index rel to 0.40) (index rel 0.40)
+
+ 3812: 2.5 0.64 0.70
+ LJ: 2.7 0.53 0.90
+
+ The relative poor performance increase in printing speed for the LJ
+ is due to the parallel (centronics) connection in the test configura-
+ tion. It would increase to a similar value as for the 3812 if the
+ printer is connected by a serial line and communication becomes the
+ bottleneck.
+
+ 3 reasons are responsible for the improvements:
+ - More intelligent positioning commands for setting the characters
+ on the page.
+ - Parts of the floating point arithmetic are changed now to integer
+ arithmetic.
+ - MSC Rel. 5 is significantly faster than MSC Rel. 4 for the large
+ memory model.
+
+New options:
+ -c (copies): specify number of copies to print
+ -X define X page origin in dots
+ -Y define Y page origin in dots
+ HINT: -X and -Y allows you to set the page origin on your
+ printer exactly to 1in/1in from the left corner. The
+ provided testfile TESTPAGE.TEX helps you to figure out
+ where the page origin is currently set to.
+ (Mostly important for LJs and clones)
+ -g (go): print without resetting the LJ at begin of file.
+
+Changed options:
+ -r option (reverse) on LJ: default changed to "print from
+ first page to last"
+ -x (set x offset relative to page origin in mm):
+ accepts now floating point numbers
+ -y (set y offset relative to page origin in mm):
+ accepts now floating point numbers
+
+ NOTE that options are now case sensitive!
+
+Other changes:
+ - Warning messages are printed now to stdout instead of stderr.
+ It is therefore easy now to redirect it.
+ - A bug in the computation of magnifications for directory names
+ is removed (the computed value was sometimes wrong by 1).
+ - Several warning messages has been improved.
+
+Send me a short note if you want to receive 0.41. Please indicate
+your favorite flavor (source/compiled, uuencode etc).
+
+-gustaf
+=========================================================================
+Date: 22 July 1988, 03:12:20 WUT
+From: NEUMANN at AWIWUW11
+Subject: New release (0.42) of dvi2xx
+
+Bug fix relevant for IBM3812 AND HP LJ-family:
+Bug fixed that occured when last y-position of output on preceding page
+equals first y-position on the next page (eg: printing e 'empty' pages
+that have nothing but page-numbers on it).
+
+=========================================================================
+Date: 26 September 1988, 22:01:12 WUT
+From: NEUMANN at AWIWUW11
+Subject: New release (0.43) of dvi2xx
+
+Dear user of the dvi2xx driver for the ibm3812 and the lj-family:
+
+Rel 0.43 of dvi2xx introduces some enhancements for the lj-mode
+of the driver:
+
+* The new command line option -z causes the printer to perform a
+ selftest at the end of a print job. As a consequence a test page
+ is printed out that shows (among other useful information) the
+ current value of the internal page counter of the printer (might be
+ useful for accounting issues).
+
+* In rel 0.43 It is possible to print under certain circumstances
+ documents with more than 16 fonts on a page: The driver treats now
+ character glyphs of the 17th, 18th... and so on font on one page as
+ bitmap graphics (instead of aborting as in the earlier releases of
+ the program). The number of fonts per page is hence limited by the
+ amount of storage the printer has.
+
+ In general it is not recommended to use more than 16 fonts per page
+ because after crossing this boundary each appearance of each
+ character in the additional fonts causes the driver to send the
+ bitmap of the character to the printer. As a consequence the size of
+ the printfile grows rapidly, the print speed goes down and (worst)
+ the printer runs fairly soon out of memory. If that happens firstly
+ the previous loaded font definitions are overwritten in the memory
+ of the printer and the following printout is messed up.
+
+ However, it is possible now to print eg the Pictex manual on a LJ/2
+ with 1.5 meg.
+
+ The program informs you whenever more than 16 fonts are used on a
+ page (unless the '-q' commandline option has been used).
+
+-gustaf
+=========================================================================
+Date: 20 Jan 1989, 16:20:12
+From: NEUMANN at AWIWUW11
+Subject: New release (0.44) of dvi2xx
+
+Dear user of the dvi2xx driver for the ibm3812 and the lj-family!
+Rel 0.44 of dvi2xx introduces some enhancements for the lj-mode
+of the driver:
+
+* The new command line option -D causes the printer to print
+ in doublepage mode, that is - roughly speaking - printing first
+ the even pagen and then the odd pages of a document. After the
+ first half of the pages are printed the following happens:
+ o 3812: the printer beeps, shows message U1. An operator
+ has to refill the printed pages into the paper tray and to
+ push the continue button on the printer.
+ o LJ-family: the printer stops, shows message "FEED" and switches
+ on manual feed led. The printer continues when either
+ the printed pages are fed into the manual page feeder,
+ or the operator pushes the continue button (after placing first
+ the printed pages into the paper tray).
+
+ The driver allows the -D option for both print-directions (front-
+ to-back or back-to-front printing). It tries to be clever in certain
+ cases:
+ o when a document has an odd number of pages it inserts in the
+ right place an empty page
+ o when a document starts with page 0 the driver inserts an empty
+ page after the 0-page
+ o when a piece of a document is printed that starts with
+ an even page-number it prints this page at the backside
+ of the first page to ensure that the odd sides are always
+ on the frontside. The 0-page is treated like an odd page.
+
+ The doubleside option works for all LJs, not only for the
+ new D model with does doubleside-printing (actually, i don't
+ know whether it makes much sense on the new LJ II D at all).
+
+ Caveat on the doubleside-option: When it is used frequently
+ or on very large files, it might become necessary to clean
+ the printer much more frequently.
+
+* The new command line option -pX can be used to abort printing
+ after the output of X pages (can lead to strange results together
+ with -D). I personally dislike this option. The secure way of
+ printing a part of a document is using -f (from) and -t (to).
+
+* graphic includes files specified for the HP-LJ-family.
+ Format is \special{file=DOSNAME}, where DOSNAME has
+ the form drive:path/name.ext.
+
+If you want to receive the distribution please send a short note.
+-gustaf
+=========================================================================
+Date: Wed, 10 May 89 22:56:30 WUT
+From: Gustaf Neumann <NEUMANN@AWIWUW11>
+Subject: New version (0.46) of the TeX-driver dvi2xx available
+
+Dear user of the dvi2xx driver for the ibm3812 and the lj-family!
+The new release features in the following points:
+
+General enhancements:
+ * Environment variable TEXPXL is checked for the fontpath.
+
+LJ-features:
+ * Driver is now able to print closer to the paper margins.
+ * \graybox-macro for lj (LaTeX Style Option) generates \fboxes with
+ gray-shaded background.
+ * The driver is able to overcome the printer limit of 32 fonts per
+ document by rastering fonts a pixle maps above that limit.
+ * More compact output (lj-file) to speedup printing on serial lines.
+
+Unix-features:
+ * -e- switch in the argument list redirects output to stdout. This
+ feature is useful especially on unix systems where the output can
+ be piped directly into the printer spooler.
+ * Man page provided.
+ * gf-support (thanks Joe Pacer); only tested for lj under unix.
+ * Support for Unix TeX font naming conventions: eg <path>/cmr12.300pk
+
+If you want to receive the new distribution please send a short note.
+
+-gustaf neumann
+University of Economics and
+Business Administration
+Vienna, Austria
+=========================================================================
+Date: Wed, 15 June 89 13:12:11WUT
+From: Gustaf Neumann <NEUMANN@AWIWUW11>
+Subject: New version (0.47) of the TeX-driver dvi2xx available
+
+Dear user of the dvi2xx driver for the ibm3812 and the lj-family!
+The new release (0.47) features in the following points:
+
+General enhancements:
+ * Clipping of rules for 3812 and lj-family at paper edges.
+
+ In the previous releases the
+ 3812 ... simply refused to draw lines that left the drawable area
+ LJ ... positioned the line wrongly
+ A new testpage.tex file shows the difference.
+
+LJ-features:
+ * new commandline option -sX to spezify pagesize
+ X = 1: executive (7.25in * 10.5in)
+ X = 2: letter (8.5in * 11in)
+ X = 3: legal (8.5in * 14in)
+ X = 26: A4 (210mm * 297mm)
+ X = 80: monarch (3.875in * 7.5in)
+ X = 81: commercial-10 (4.125in * 9.5in)
+ X = 90: international DL (110mm * 220mm)
+ X = 91: international C5 (162mm * 229mm)
+ All values are from the LJ2 technical reference manual.
+ If the -s commandline option is omitted no clipping is performed
+ at the bottom of the page.
+
+Please send a short note indicating wether you want to receive the new
+distribution.
+
+-gustaf neumann
+University of Economics and
+Business Administration
+Vienna, Austria
+=========================================================================
+Date: 30 Oct 89 10:22:01 WUT
+From: Gustaf Neumann <NEUMANN@AWIWUW11>
+Subject: New version (0.48) of the TeX-driver dvi2xx available
+
+Dear user of the dvi2xx driver for the ibm3812 and the lj-family!
+The new release (0.48) features in the following points:
+
+LJ enhancements:
+
+ * Bug eliminated that caused the driver to generate an output
+ file that was much to large. The bug only showed up on
+ dvi files using more than 32 fonts (example: pictex manual).
+
+ * The new version of the driver uses a different font-id assignment
+ heuristic that leads in 2/3 of my test files to smaller output
+ files.
+
+Please send a short note indicating wether you want to receive the new
+distribution (source and/or PC-binary).
+
+-gustaf neumann
+University of Economics and
+Business Administration
+Vienna, Austria
+=========================================================================
+Date: 25 Mar 91 18:21:11 WUT
+From: Gustaf Neumann <NEUMANN@AWIWUW11>
+Subject: New version (0.49) of the TeX-driver dvi2xx available
+
+Dear user of the dvi2xx driver for the ibm3812 and the lj-family!
+The new release (0.49) features in the following points:
+
+Enhancements:
+
+ * Support of landscape printing:
+
+ A new command-line option -l was added to support
+ landscape printing on the IBM 3812 and on various
+ LaserJet printers such as
+
+ o Laserjet II P
+ o Laserjet 2000
+ o LaserJet III
+
+ * Small bug fixes for IBM 3812 and LaserJet mode and
+ improved compatibility (the driver runs now under MS/DOS,
+ HP/UX, Ultrix Risc, AIX and OS/2)
+
+ * new naming:
+ dvilj2[.exe] dvi converter for HP LaserJet+, HP LaserJet II
+ and compatibles
+ dvilj2p[.exe] dvi converter for HP LaserJet II P, HP LaserJet III,
+ HP LaserJet 2000 and compatibles
+ dvi3812[.exe] dvi converter for IBM 3812 Pageprinter
+
+ * 8-bit clean (256 character font files)
+
+The new distribution may be obtained
+ - via anonymous ftp from nestroy.wu-wien.ac.at:pub/src/Typeset/dvi2xx
+ (source and msdos .exe-files, os2 .exe files, binaries for DecStations
+ under ultrix 4.1, rs6000 under aix 3.1 and hp9000/835 under hpux 7.0
+ The ip-address of nestroy.wu-wien.ac.at is 137.208.3.4
+ - from Simtel20 (soon); at least pc-binaries and sources
+ - via sending a short note indicating wether you want to receive the new
+ distribution (source and/or PC-binaries).
+
+-gustaf neumann
+-----------------------------------------------------------------------------
+Gustaf Neumann neumann@dec4.wu-wien.ac.at, neumann@awiwuw11.bitnet
+Vienna University of Economics and Business Administration
+Augasse 2-6, A-1090 Vienna, Austria
+Tel: +43 (222) 31-336 x4533 Fax 347-555
+=========================================================================
+Date: 5 May 91 16:11:21 WUT
+From: Gustaf Neumann <NEUMANN@AWIWUW11>
+Subject: New version (0.50) of the TeX-driver dvi2xx available
+
+Dear user of the dvi2xx driver for the ibm3812 and the lj-family!
+The new release (0.50) features in the following points:
+
+Enhancements:
+
+ * 2 new versions:
+
+ o dvilj
+ o dviljp
+
+ These versions are for older HP Laserjet clones that do NOT support
+ 256 character fonts (type 2 fonts)
+
+ * new options for double sided printing
+ -D print double sided and try to stop printer for paper change
+ -D1 print odd sides only (NEW)
+ -D2 print even sides only (NEW)
+ -D-, -D1-, -D2- like above, but suppress empty padding pages (NEW)
+
+The new distribution may be obtained
+
+ - via anonymous ftp from nestroy.wu-wien.ac.at:pub/src/Typeset/dvi2xx
+ (source and msdos .exe-files, os2 .exe files, binaries for DecStations
+ under ultrix 4.1, rs6000 under aix 3.1 and hp9000/835 under hpux 7.0
+ The ip-address of nestroy.wu-wien.ac.at is 137.208.3.4
+
+ - from Simtel20 (soon); at least pc-binaries and sources
+
+ - via sending a short note indicating wether you want to receive the new
+ distribution (source and/or PC-binaries).
+
+-gustaf neumann
+-----------------------------------------------------------------------------
+Gustaf Neumann neumann@dec4.wu-wien.ac.at, neumann@awiwuw11.bitnet
+Vienna University of Economics and Business Administration
+Augasse 2-6, A-1090 Vienna, Austria
+Tel: +43 (222) 31-336 4533 ~Fax 347-555
+
+
diff --git a/obsolete/dviware/dvi2xx/dvi2xx.make b/obsolete/dviware/dvi2xx/dvi2xx.make
new file mode 100644
index 0000000000..37917ac38e
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/dvi2xx.make
@@ -0,0 +1,182 @@
+-------------------------------------------------------------------------
+@REM To compile dvi2xx.c for MSDOS with MSC Rel 6.0:
+
+set MSC=\C600
+set INCLUDE=%MSC%\include
+set LIB=%MSC%\lib
+
+set CFLAGS=-AL -W2 -Gs -Ox
+set LFLAGS=/stack:9000 /EXEPACK
+
+@REM For all version (LJ and 3812)
+
+ cl %CFLAGS% -c findfile.c ;;
+
+
+@REM LaserJet+ and LaserJet II Version:
+
+ cl %CFLAGS% -DLJ2 dvi2xx.c findfile.obj -link %LFLAGS%
+ copy dvi2xx.exe dvilj2.exe
+
+
+@REM LaserJet II P and LaserJet III and LaserJet 2000 Version:
+
+ cl %CFLAGS% -DLJ2P dvi2xx.c findfile.obj -link %LFLAGS%
+ copy dvi2xx.exe dvilj2p.exe
+
+@REM IBM3812 Version:
+
+ cl %CFLAGS% -DIBM3812 dvi2xx.c findfile.obj -link %LFLAGS%
+ copy dvi2xx.exe dvi3812.exe
+
+@REM LaserJet with 7 bit
+
+ cl %CFLAGS% -DLJ -DSEVENBIT dvi2xx.c findfile.obj -link %LFLAGS%
+ copy dvi2xx.exe dvilj.exe
+
+
+@REM LaserJet II P with 7 bit and landscape
+
+ cl %CFLAGS% -DLJ2P -DSEVENBIT dvi2xx.c findfile.obj -link %LFLAGS%
+ copy dvi2xx.exe dviljp.exe
+
+ del dvi2xx.exe
+-------------------------------------------------------------------------
+@REM To compile dvi2xx.c under MSDOS for OS/2 with MSC Rel 6.0:
+
+set MSC=\C600
+set INCLUDE=%MSC%\include
+set LIB=%MSC%\lib
+
+set CFLAGS=-AL -W2 -Gs -UMSDOS -DOS2 -Ox -Lp -Fb
+set LFLAGS=/stack:9000 /EXEPACK /PMTYPE:VIO
+
+@REM For all version (LJ and 3812)
+
+ cl %CFLAGS% -c findfile.c ;;
+
+
+@REM LaserJet II Version:
+
+ cl %CFLAGS% -DLJ2 dvi2xx.c findfile.obj -link %LFLAGS%
+ markexe -t windowcompat dvi2xx.exe
+ copy dvi2xx.exe odvilj2.exe
+
+
+@REM LaserJet II P and LaserJet III and LaserJet 2000 Version:
+
+ cl %CFLAGS% -DLJ2P dvi2xx.c findfile.obj -link %LFLAGS%
+ markexe -t windowcompat dvi2xx.exe
+ copy dvi2xx.exe odvilj2p.exe
+
+
+@REM LaserJet with 7 bit
+
+ cl %CFLAGS% -DLJ -DSEVENBIT dvi2xx.c findfile.obj -link %LFLAGS%
+ markexe -t windowcompat dvi2xx.exe
+ copy dvi2xx.exe odvilj.exe
+
+
+@REM LaserJet II P with 7 bit and landscape
+
+ cl %CFLAGS% -DLJ2P -DSEVENBIT dvi2xx.c findfile.obj -link %LFLAGS%
+ markexe -t windowcompat dvi2xx.exe
+ copy dvi2xx.exe odviljp.exe
+
+
+@REM IBM3812 Version:
+
+ cl %CFLAGS% -DIBM3812 dvi2xx.c findfile.obj -link %LFLAGS%
+ markexe -t windowcompat dvi2xx.exe
+ copy dvi2xx.exe odvi3812.exe
+
+ del dvi2xx.exe
+
+-------------------------------------------------------------------------
+# makefile for the dvi-to-(3812 || lj + || lj II || lj IIp ) filter.
+#
+CFLAGS=-O -s -Dunix
+BINDIR=/usr/local/bin
+MANDIR=/usr/man
+MANSEC=1
+CC=cc
+
+# under Ultrix 4.1 use:
+CFLAGS=-O1 -s -Dunix
+
+# for gcc you might wish to set the following flags
+CC=gcc
+CFLAGS=-O2 -Dunix -ansi -pedantic
+
+# under AIX 3.1 add the following line:
+#LFLAGS=-lbsd
+
+OBJS=findlj.o find3812.o
+HFILES=commands.h config.h
+PROGRAMS=dvilj2p dvilj2 dvi3812 dvilj dviljp
+
+all: $(PROGRAMS) dvi2xx.txt
+
+dvi3812: dvi2xx.c find3812.o $(HFILES)
+ $(CC) ${CFLAGS} -DIBM3812 -o $@ dvi2xx.c find3812.o ${LFLAGS}
+
+dvilj2p: dvi2xx.c findlj.o $(HFILES)
+ $(CC) ${CFLAGS} -DLJ2P -o $@ dvi2xx.c findlj.o ${LFLAGS}
+
+dvilj2: dvi2xx.c findlj.o $(HFILES)
+ $(CC) ${CFLAGS} -DLJ2 -o $@ dvi2xx.c findlj.o ${LFLAGS}
+
+dvilj: dvi2xx.c findlj.o $(HFILES)
+ $(CC) ${CFLAGS} -DLJ -DSEVENBIT -o $@ dvi2xx.c findlj.o ${LFLAGS}
+
+dviljp: dvi2xx.c findlj.o $(HFILES)
+ $(CC) ${CFLAGS} -DLJ2P -DSEVENBIT -o $@ dvi2xx.c findlj.o ${LFLAGS}
+
+findlj.o: findfile.c config.h
+ $(CC) ${CFLAGS} -DLJ -c findfile.c
+ mv findfile.o $@
+
+find3812.o: findfile.c config.h
+ $(CC) ${CFLAGS} -DIBM3812 -c findfile.c
+ mv findfile.o $@
+
+clean:
+ rm -f core $(OBJS) $(PROGRAMS)
+
+DISTFILES = \
+ ./dvi2xx.c ./commands.h ./config.h ./findfile.c ./Makefile \
+ ./testpage.tex ./dvi2xx.history ./dvi2xx.man ./graybox.sty \
+ ./dvi2xx.make ./dvi2xx.051 ./README \
+ ./MakeTeXPK ./lj3-filter ./printcap.sample ./README.vms \
+ ./sample2.tex ./2up.sty ./README.dell-unix ./dvi2xx.tex
+
+shar:
+ shar ${DISTFILES} > dvi2xx.shar
+
+
+tar:
+ pdtar zcvf dvi2xx.tar.Z ${DISTFILES}
+ shar dvi2xx.tar.Z > dvi2xx.shar
+
+testfiles:
+ ./dvilj2 -eftable.lj2 ftable
+ ./dvilj2p -eftable.lj2p ftable
+ ./dvi3812 ftab2
+
+
+install:
+ @for f in $(PROGRAMS); do \
+ echo installing $$f in $(BINDIR); \
+ install -c $$f $(BINDIR); \
+ done
+ cp dvi2xx.man dvi2xx.$(MANSEC)
+ install dvi2xx.$(MANSEC) $(MANDIR)/man$(MANSEC)
+
+dvi2xx.txt: dvi2xx.man
+ -nroff -man dvi2xx.man | col -b > dvi2xx.txt
+
+
+
+
+
+
diff --git a/obsolete/dviware/dvi2xx/dvi2xx.man b/obsolete/dviware/dvi2xx/dvi2xx.man
new file mode 100644
index 0000000000..1123230238
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/dvi2xx.man
@@ -0,0 +1,321 @@
+.TH DVILJ2 1
+.ad b
+.SH NAME
+dvilj2, dvilj2p, dvilj, dviljp, dvi3812 \- convert dvi files to HP
+LaserJet or IBM 3812 format
+.SH SYNOPSIS
+\f3dvi2lj\f1 [\f3-a\f2fontpath\f1]
+[\f3-b \f1]
+[\f3-c\f2copies\f1]
+[\f3-d\f2mode\f1]
+[\f3-D\f1]
+[\f3-E\f1]
+[\f3-e\f2output file\f1]
+[\f3-f\f2frompage\f1]
+[\f3-g\f1]
+[\f3-h\f2header file\f1]
+[\f3-l\f1]
+[\f3-M\f2flag\f1]
+[\f3-m\f2mag\f1]
+[\f3-p\f2pages\f1]
+[\f3-q\f1]
+[\f3-r\f1]
+[\f3-t\f2topage\f1]
+[\f3-s\f2pagesize\f1]
+[\f3-v\f1]
+[\f3-w\f1]
+[\f3-x\f2xoff(mm)\f1]
+[\f3-y\f2yoff(mm)\f1]
+[\f3-X\f2xoff(dots)\f1]
+[\f3-Y\f2yoff(dots)\f1]
+[\f3-z\f1]
+[\f2filename\f1]
+.SH DESCRIPTION
+Dvilj2 converts TeX-output .dvi files into HP PCL (i.e. HP Printer
+Control Language) commands suitable for printing on a HP LaserJet+,
+HP LaserJet II and fully compatible printers.
+.br
+Dvilj2p converts TeX-output .dvi files into HP PCL commands suitable
+for printing on a HP LaserJet IIp, HP LaserJet III or HP Laserjet 2000
+and fully compatible printers. This version uses a newer PCL command
+set and provides landscape printing.
+.br
+Dviljp and dvilj are similar to dvilj2p and dvilj2 but they support
+only 128 character fonts. They may be used for Laserjet clones which do
+not support 256 character fonts.
+.br
+Dvilj4 is for the HP LasterJet IV printer familiy and fully compatible
+clones. It implements a superset of the commands available for dvilj2p
+and prints with an resolution of 600 dpi. In addition it provides support
+for the printers builtin fonts using Karl Berry's coding scheme.
+.br
+Dvi3812 converts TeX-output .dvi files into PMP files,
+the native command language of the IBM 3812 page printer.
+.br
+All programs are generated from the same source dvi2xx.c.
+They are usually called by a shell script or as a line printer filter.
+
+.SH OPTIONS
+.TP
+\f3-a\f2fontpath\f1
+directory to take fonts from (alternative to environment variable TEXPXL);
+see below for details about the font directory structure
+.TP
+\f3-b\f1
+.br
+take paper for first page from alternate cassette (only 3812)
+.TP
+\f3-c\f2number\f1
+print each page \f2number\f1 times (including original)
+.TP
+\f3-d\f2number\f1
+print in duplex mode. The option -d\f21\f1 means long edge binding,
+-d\f22\f1 stands for short edge binding. This option is only
+selectable from \fIdvilj2p\fP, and is known to works on a LaserJet IId or a
+LaserJet IIId or LaserJet IV.
+.TP
+\f3-D\f1
+.br
+Double-sided printing - see below; -D\f21\f1 prints odd sides only,
+-D\f22\f1 is for even pages, a trailing \f2-\f1 suppresses printing of
+empty padding pages.
+.TP
+\f3-E\f1
+Switch printer into econo mode (dvilj4 only)
+.TP
+\f3-e\f2output file\f1
+default output filename is the basename of dvi file and extension '.lj'
+for laserjet and '.pmp' for 3812. The '-e' option can be used to override
+this default and to direct the output to a different file.
+If the output filename is set to '-` (option '-e-') the output is directed
+to stdout and can be directly piped into a spooler.
+.TP
+\f3-f\f2page number \f1
+start printing at top of given page number
+.TP
+\f3-g\f1
+.br
+go - do not reset printer at start of job
+.TP
+\f3-h\f2header file\f1
+headerfile to be copied before translation of dvi-file.
+Used to send arbitrary commands to the laserprinter.
+.TP
+\f3-l\f1
+.br
+landscape - print output in landscape mode. This option is provided
+only for dvilj2p, dvilj4 and dvi3812.
+.TP
+\f3-M\f2flag\f1
+Do not call MakeTeXPK. \f3-M\f21\f1 and \f3-M\f1 are equivalent,
+\f3-M\f20\f1 switches to the default behavior (like no \f3-M\f1
+specified). This flag is only valid if dvi2xx was compiled with
+support for MakeTeXPK.
+.TP
+\f3-m\f2magnification\f1
+Specifiy the magnification to use. The following are available:
+.br
+\f3-m#\f2usermag\f1 e.g. \f3#1200\f1
+.br
+\f3-m0\f1 equivalent to \f3-m#1000\f1
+.br
+\f3-mh\f1 equivalent to \f3-m#1095\f1
+.br
+\f3-m1\f1 equivalent to \f3-m#1200\f1
+.br
+\f3-mq\f1 equivalent to \f3-m#1250\f1
+.br
+\f3-m2\f1 equivalent to \f3-m#1440\f1
+.br
+\f3-m3\f1 equivalent to \f3-m#1728\f1
+.br
+\f3-m4\f1 equivalent to \f3-m#2074\f1
+.br
+\f3-m5\f1 equivalent to \f3-m#2488\f1
+.TP
+\f3-p\f2number of pages\f1
+print given number of pages
+.TP
+\f3-q\f1
+.br
+quiet operation
+.TP
+\f3-r\f1
+.br
+toggle reverse/not reverse order for output.
+By default reverse=FALSE for 3812, reverse=TRUE for laserjet.
+.TP
+\f3-s\f2pagesize \f1
+Spezify pagesize (LJ-family only!)
+.br
+\f3-s1\f1: executive (7.25in * 10.5in)
+.br
+\f3-s2\f1: letter (8.5in * 11in)
+.br
+\f3-s3\f1: legal (8.5in * 14in)
+.br
+\f3-s26\f1: A4 (210mm * 297mm)
+.br
+\f3-s80\f1: monarch (3.875in * 7.5in)
+.br
+\f3-s81\f1: commercial-10 (4.125in * 9.5in)
+.br
+\f3-s90\f1: international DL (110mm * 220mm)
+.br
+\f3-s91\f1: international C5 (162mm * 229mm)
+.br
+All values are from the LJ II technical reference manual.
+If the -s commandline option is omitted no clipping is performed
+at the bottom of the page.
+.TP
+\f3-t\f2page number \f1
+print to end of given page number
+.TP
+\f3-v\f1
+.br
+verbose mode, list used fonts
+.TP
+\f3-w\f1
+.br
+print no warnings
+.TP
+\f3-x\f2offset\f1
+global x-offset in mm on output page
+relative to 1 inch/1 inch origin
+.TP
+\f3-y\f2offset\f1
+global y-offset in mm on output page
+relative to 1 inch/1 inch origin
+.TP
+\f3-X\f2offset\f1
+global x-offset in dots on output page
+(to set 1 inch/1 inch origin)
+.TP
+\f3-Y\f2offset\f1
+global y-offset in dots on output page
+(to set 1 inch/1 inch origin)
+.TP
+\f3-z\f1
+.br
+print a test page with the page counter at end of job
+(only for laserjet)
+.TP
+.br
+If no arguments are specified a short help file is displayed.
+.PP
+.SH font directory structure
+The specified fontpath may contain more than directory names. Under
+Unix the direcory names are separated by a ':', under MSDOS by a ';'.
+The paths are searched from left to right. For each directory in the
+searchpath the following font naming conventions are tried:
+.br 6
+-
+dpi<resolution>/<fontname>.pk
+(eg: ./dpi300/cmr10.pk)
+.br
+-
+dpi<resolution>/<fontname>.pxl
+(eg: ./dpi300/cmr10.pxl)
+.br
+-
+pxl<magnification>/<fontname>.pk
+(eg: ./pxl1500/cmr10.pk)
+.br
+-
+pxl<magnification>/<fontname>.pxl
+(eg:./pxl1500/cmr10.pxl)
+.br
+-
+<fontname>.<resolution>pk
+(eg: ./cmr10.300pk)
+.br
+-
+<fontname>.<resolution>pxl
+(eg: ./cmr10.300pxl)
+.br
+-
+<fontname>.<resolution>
+(eg: ./cmr10.300)
+.PP
+.SH \especial commands
+Two TeX '\especial' commands are implemented:
+.TP
+\f3\especial{file=<filename>}\f1
+copy specified file to the printer; either vector- or bitmap-graphics PMP
+commands (for laserjet and 3812)
+.TP
+\f3\especial{orientation=<value>}\f1
+set page orientation to 0, 1, 2, 3;
+rotate following output to landscape mode etc.
+(3812 only).
+.TP 0
+others:
+There are a few other special commands implented for the LJ-series,
+which should only be used in connection with the distributed style
+files (eg graybox.sty). They are likely to be changed in forthcoming
+versions.
+.PP
+.SH Double Page Printing
+The command line option -D causes the printer to print
+in doublepage mode, that is - roughly speaking - printing first
+the even pagen and then the odd pages of a document.
+If -D is used to print both even and odd pages (-D is used
+without the optional \f21\f1 or \f22\f1)
+the following will happen after
+half of the pages is printed:
+.TP 6
+\f33812: \f1
+the printer beeps, shows message U1. An operator
+has to refill the printed pages into the paper tray and to
+push the continue button on the printer.
+.TP
+\f3LJ:\f1
+the printer stops, shows message "FEED" and switches
+on manual feed led. The printer continues when either
+the printed pages are fed into the manual page feeder,
+or the operator pushes the continue button (after placing first
+the printed pages into the paper tray).
+.PP
+If -D1 was specified only odd pages will be printed, -D2 can be used
+for even pages. A trailing `-' (as in -D-, -D1- or -D2-) supresses
+printing of empty pages which are generated for padding otherwise.
+.PP
+The driver allows the -D option for both print-directions (front-to-back
+or back-to-front printing). It tries to be clever in certain cases:
+when a document has an odd number of pages it inserts in the
+right place an empty page
+when a document starts with page 0 the driver inserts an empty
+page after the 0-page
+when a piece of a document is printed that starts with
+an even page-number it prints this page at the backside
+of the first page to ensure that the odd sides are always
+on the frontside. The 0-page is treated like an odd page.
+.PP
+The doubleside option works for all LJs, not only for the
+new D model with does doubleside-printing (actually, i don't
+know wether it makes much sense on the new LJ II D at all).
+.PP
+Caveat on the doubleside-option: When it is used frequently
+or on very large files, it might become necessary to clean
+the printer much more frequently.
+.PP
+The command line option -pX can be used to abort printing
+after the output of X pages (can lead to strange results together
+with -D). I personally dislike this option. The secure way of
+printing a part of a document is using -f (from) and -t (to).
+.PP
+.SH ENVIRONMENT
+The environment variable TEXPXL can be used to specify one or
+more paths to the raster fonts (.pk, .pxl). The path separator
+under Unix is ':', under MSDOS ';'. GF-fonts can be used
+when the source is compiled without the preprocessor switch
+USEPIXEL set.
+.PP
+Dvilj4 reads .tmf files and uses the contents of the
+environment variable TEXFONTS as search path.
+.PP
+.SH AUTHOR
+Gustaf Neumann, Wirtschaftsuniversitaet Wien
+.br
+neumann@wu-wien.ac.at
+
diff --git a/obsolete/dviware/dvi2xx/dvi2xx.txt b/obsolete/dviware/dvi2xx/dvi2xx.txt
new file mode 100644
index 0000000000..18cf56aa3b
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/dvi2xx.txt
@@ -0,0 +1,330 @@
+
+
+
+DVILJ2(1) DVILJ2(1)
+
+
+NAME
+ dvilj2, dvilj2p, dvilj, dviljp, dvi3812 - convert dvi
+ files to HP LaserJet or IBM 3812 format
+
+SYNOPSIS
+ dvi2lj [-afontpath] [-b ] [-ccopies] [-dmode] [-D] [-E]
+ [-eoutput file] [-ffrompage] [-g] [-hheader file] [-l]
+ [-Mflag] [-mmag] [-ppages] [-q] [-r] [-ttopage] [-spage-
+ size] [-v] [-w] [-xxoff(mm)] [-yyoff(mm)] [-Xxoff(dots)]
+ [-Yyoff(dots)] [-z] [filename]
+
+DESCRIPTION
+ Dvilj2 converts TeX-output .dvi files into HP PCL (i.e. HP
+ Printer Control Language) commands suitable for printing
+ on a HP LaserJet+, HP LaserJet II and fully compatible
+ printers.
+ Dvilj2p converts TeX-output .dvi files into HP PCL com-
+ mands suitable for printing on a HP LaserJet IIp, HP
+ LaserJet III or HP Laserjet 2000 and fully compatible
+ printers. This version uses a newer PCL command set and
+ provides landscape printing.
+ Dviljp and dvilj are similar to dvilj2p and dvilj2 but
+ they support only 128 character fonts. They may be used
+ for Laserjet clones which do not support 256 character
+ fonts.
+ Dvilj4 is for the HP LasterJet IV printer familiy and
+ fully compatible clones. It implements a superset of the
+ commands available for dvilj2p and prints with an resolu-
+ tion of 600 dpi. In addition it provides support for the
+ printers builtin fonts using Karl Berry's coding scheme.
+ Dvi3812 converts TeX-output .dvi files into PMP files, the
+ native command language of the IBM 3812 page printer.
+ All programs are generated from the same source dvi2xx.c.
+ They are usually called by a shell script or as a line
+ printer filter.
+
+
+OPTIONS
+ -afontpath
+ directory to take fonts from (alternative to envi-
+ ronment variable TEXPXL); see below for details
+ about the font directory structure
+
+ -b
+ take paper for first page from alternate cassette
+ (only 3812)
+
+ -cnumber
+ print each page number times (including original)
+
+ -dnumber
+ print in duplex mode. The option -d1 means long
+ edge binding, -d2 stands for short edge binding.
+ This option is only selectable from dvilj2p, and is
+
+
+
+ 1
+
+
+
+
+
+DVILJ2(1) DVILJ2(1)
+
+
+ known to works on a LaserJet IId or a LaserJet IIId
+ or LaserJet IV.
+
+ -D
+ Double-sided printing - see below; -D1 prints odd
+ sides only, -D2 is for even pages, a trailing -
+ suppresses printing of empty padding pages.
+
+ -E Switch printer into econo mode (dvilj4 only)
+
+ -eoutput file
+ default output filename is the basename of dvi file
+ and extension '.lj' for laserjet and '.pmp' for
+ 3812. The '-e' option can be used to override this
+ default and to direct the output to a different
+ file. If the output filename is set to '-` (option
+ '-e-') the output is directed to stdout and can be
+ directly piped into a spooler.
+
+ -fpage number
+ start printing at top of given page number
+
+ -g
+ go - do not reset printer at start of job
+
+ -hheader file
+ headerfile to be copied before translation of dvi-
+ file. Used to send arbitrary commands to the
+ laserprinter.
+
+ -l
+ landscape - print output in landscape mode. This
+ option is provided only for dvilj2p, dvilj4 and
+ dvi3812.
+
+ -Mflag Do not call MakeTeXPK. -M1 and -M are equivalent,
+ -M0 switches to the default behavior (like no -M
+ specified). This flag is only valid if dvi2xx was
+ compiled with support for MakeTeXPK.
+
+ -mmagnification
+ Specifiy the magnification to use. The following
+ are available:
+ -m#usermag e.g. #1200
+ -m0 equivalent to -m#1000
+ -mh equivalent to -m#1095
+ -m1 equivalent to -m#1200
+ -mq equivalent to -m#1250
+ -m2 equivalent to -m#1440
+ -m3 equivalent to -m#1728
+ -m4 equivalent to -m#2074
+ -m5 equivalent to -m#2488
+
+
+
+
+
+ 2
+
+
+
+
+
+DVILJ2(1) DVILJ2(1)
+
+
+ -pnumber of pages
+ print given number of pages
+
+ -q
+ quiet operation
+
+ -r
+ toggle reverse/not reverse order for output. By
+ default reverse=FALSE for 3812, reverse=TRUE for
+ laserjet.
+
+ -spagesize
+ Spezify pagesize (LJ-family only!)
+ -s1: executive (7.25in * 10.5in)
+ -s2: letter (8.5in * 11in)
+ -s3: legal (8.5in * 14in)
+ -s26: A4 (210mm * 297mm)
+ -s80: monarch (3.875in * 7.5in)
+ -s81: commercial-10 (4.125in * 9.5in)
+ -s90: international DL (110mm * 220mm)
+ -s91: international C5 (162mm * 229mm)
+ All values are from the LJ II technical reference
+ manual. If the -s commandline option is omitted no
+ clipping is performed at the bottom of the page.
+
+ -tpage number
+ print to end of given page number
+
+ -v
+ verbose mode, list used fonts
+
+ -w
+ print no warnings
+
+ -xoffset
+ global x-offset in mm on output page relative to 1
+ inch/1 inch origin
+
+ -yoffset
+ global y-offset in mm on output page relative to 1
+ inch/1 inch origin
+
+ -Xoffset
+ global x-offset in dots on output page (to set 1
+ inch/1 inch origin)
+
+ -Yoffset
+ global y-offset in dots on output page (to set 1
+ inch/1 inch origin)
+
+ -z
+ print a test page with the page counter at end of
+ job (only for laserjet)
+
+
+
+
+ 3
+
+
+
+
+
+DVILJ2(1) DVILJ2(1)
+
+
+ If no arguments are specified a short help file is dis-
+ played.
+
+
+font directory structure
+ The specified fontpath may contain more than directory
+ names. Under Unix the direcory names are separated by a
+ ':', under MSDOS by a ';'. The paths are searched from
+ left to right. For each directory in the searchpath the
+ following font naming conventions are tried:
+ - dpi<resolution>/<fontname>.pk (eg: ./dpi300/cmr10.pk)
+ - dpi<resolution>/<fontname>.pxl (eg: ./dpi300/cmr10.pxl)
+ - pxl<magnification>/<fontname>.pk (eg:
+ ./pxl1500/cmr10.pk)
+ - pxl<magnification>/<fontname>.pxl
+ (eg:./pxl1500/cmr10.pxl)
+ - <fontname>.<resolution>pk (eg: ./cmr10.300pk)
+ - <fontname>.<resolution>pxl (eg: ./cmr10.300pxl)
+ - <fontname>.<resolution> (eg: ./cmr10.300)
+
+
+\special commands
+ Two TeX '\special' commands are implemented:
+
+ \special{file=<filename>}
+ copy specified file to the printer; either vector-
+ or bitmap-graphics PMP commands (for laserjet and
+ 3812)
+
+ \special{orientation=<value>}
+ set page orientation to 0, 1, 2, 3; rotate follow-
+ ing output to landscape mode etc. (3812 only).
+
+ others:
+ There are a few other special commands implented for the
+ LJ-series, which should only be used in connection with
+ the distributed style files (eg graybox.sty). They are
+ likely to be changed in forthcoming versions.
+
+
+Double Page Printing
+ The command line option -D causes the printer to print in
+ doublepage mode, that is - roughly speaking - printing
+ first the even pagen and then the odd pages of a document.
+ If -D is used to print both even and odd pages (-D is used
+ without the optional 1 or 2) the following will happen
+ after half of the pages is printed:
+
+ 3812: the printer beeps, shows message U1. An operator has
+ to refill the printed pages into the paper tray and
+ to push the continue button on the printer.
+
+ LJ: the printer stops, shows message "FEED" and switches
+ on manual feed led. The printer continues when
+
+
+
+ 4
+
+
+
+
+
+DVILJ2(1) DVILJ2(1)
+
+
+ either the printed pages are fed into the manual
+ page feeder, or the operator pushes the continue
+ button (after placing first the printed pages into
+ the paper tray).
+
+ If -D1 was specified only odd pages will be printed, -D2
+ can be used for even pages. A trailing `-' (as in -D-,
+ -D1- or -D2-) supresses printing of empty pages which are
+ generated for padding otherwise.
+
+ The driver allows the -D option for both print-directions
+ (front-to-back or back-to-front printing). It tries to be
+ clever in certain cases: when a document has an odd number
+ of pages it inserts in the right place an empty page when
+ a document starts with page 0 the driver inserts an empty
+ page after the 0-page when a piece of a document is
+ printed that starts with an even page-number it prints
+ this page at the backside of the first page to ensure that
+ the odd sides are always on the frontside. The 0-page is
+ treated like an odd page.
+
+ The doubleside option works for all LJs, not only for the
+ new D model with does doubleside-printing (actually, i
+ don't know wether it makes much sense on the new LJ II D
+ at all).
+
+ Caveat on the doubleside-option: When it is used fre-
+ quently or on very large files, it might become necessary
+ to clean the printer much more frequently.
+
+ The command line option -pX can be used to abort printing
+ after the output of X pages (can lead to strange results
+ together with -D). I personally dislike this option. The
+ secure way of printing a part of a document is using -f
+ (from) and -t (to).
+
+
+ENVIRONMENT
+ The environment variable TEXPXL can be used to specify one
+ or more paths to the raster fonts (.pk, .pxl). The path
+ separator under Unix is ':', under MSDOS ';'. GF-fonts can
+ be used when the source is compiled without the preproces-
+ sor switch USEPIXEL set.
+
+ Dvilj4 reads .tmf files and uses the contents of the envi-
+ ronment variable TEXFONTS as search path.
+
+
+AUTHOR
+ Gustaf Neumann, Wirtschaftsuniversitaet Wien
+ neumann@wu-wien.ac.at
+
+
+
+
+
+
+ 5
+
+
diff --git a/obsolete/dviware/dvi2xx/findfile.c b/obsolete/dviware/dvi2xx/findfile.c
new file mode 100644
index 0000000000..baec7db75d
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/findfile.c
@@ -0,0 +1,324 @@
+#include "config.h"
+#include <string.h>
+#include <stdio.h>
+#ifndef vms
+#include <sys/types.h>
+#include <sys/stat.h>
+#else
+#include <types.h>
+#include <stat.h>
+#endif
+
+int stat();
+
+char *path_segment();
+char *pprint();
+extern void Warning();
+extern bool G_quiet;
+extern int Debug;
+
+#ifdef MAKETEXPK
+extern bool makeTexPK ;
+#endif
+
+#ifdef unix
+#ifdef DO_SUBDIRECTORIES
+#include <glob.h>
+#endif
+#endif
+
+#ifdef unix
+ static char* raster_table[] = {
+#ifdef USEPXL
+ "%P/%N.%Rpk",
+ "%P/%N.%Rpxl",
+ "%P/dpi%R/%N.pk",
+ "%P/%R/%N.pxl",
+ "%P/dpi%R/%N.pxl",
+ "%P/pxl%M/%N.pk",
+ "%P/pxl%M/%N.pxl",
+ "%P/%N.%R",
+#else
+ "%P/%N.%Rgf",
+ "%P/%N.%Mgf",
+#endif
+ NULL
+ };
+#endif
+
+#ifdef vms
+ static char* raster_table[] = {
+#ifdef USEPXL
+ "%P[%R]%N.pk;",
+ "%P%N.%Rpk;",
+ "%P:[%R]%N.pk;",
+ "%P:%N.%Rpk;",
+ "%P[%R]%N.pk;",
+ "%P%N.%Mpxl;",
+ "%P:[%M]%N.pxl;",
+ "%P:%N.%Mpxl;",
+#else
+ "%P%N.%Rgf;",
+ "%P:%N.%Rgf;",
+ "%P%N.%Mgf;",
+ "%P:%N.%Mgf;",
+#endif
+ NULL
+ };
+#endif
+
+#ifdef MSDOS
+ static char* raster_table[] = {
+#ifdef USEPXL
+ "%P/dpi%R/%N.pk",
+ "%P/%R/%N.pk",
+ "%P/dpi%R/%N.pxl",
+ "%P/%R/%N.pxl",
+ "%P/pxl%M/%N.pk",
+ "%P/pxl%M/%N.pxl",
+ "%P/%N.%R",
+#else
+ "%P/%R/%N.gf",
+ "%P/dpi%R/%N.gf",
+ "%P/pxl%M/%N.gf",
+#endif
+ NULL
+ };
+#endif
+
+#ifdef _AMIGA
+ static char* raster_table[] = {
+#ifdef USEPXL
+ "%P/%N.%Rpk",
+ "%P/%N.%Rpxl",
+ "%P/dpi%R/%N.pk",
+ "%P/%R/%N.pxl",
+ "%P/dpi%R/%N.pxl",
+ "%P/pxl%M/%N.pk",
+ "%P/pxl%M/%N.pxl",
+ "%P/%R/%N.%Rpk",
+ "%P/%N.%R",
+#else
+ "%P/%N.%Rgf",
+ "%P/%N.%Mgf",
+#endif
+ NULL
+ };
+#endif
+
+
+
+
+bool
+findfile(path,n,fontmag,name,tfm,level)
+char path[STRSIZE]; /* PIXEL path */
+char n[STRSIZE]; /* name of font */
+long fontmag; /* magnification */
+char name[STRSIZE]; /* full name of PXL file (returned) */
+bool tfm; /* are we searching for a tfm file? */
+int level; /* recursion level to prevent calling of MakeTeXPK */
+{
+ char local_path[STRSIZE];
+#ifdef MAKETEXPK
+ char MakePKCommand[STRSIZE];
+#endif
+ char *pathpt;
+ struct stat s;
+ int resolution, i;
+ char **pattern;
+
+ if (tfm) {
+ resolution = 0; /* dont'care */
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,
+ "locating tfm %s, path %s, depth=%d\n",
+ n, path, level);
+#endif
+ } else {
+ resolution = (int)(fontmag/5.0 + 0.5);
+#ifdef DEBUG
+ if (Debug)
+ fprintf(stderr,
+ "locating raster %s, resolution %d on path %s, depth=%d\n",
+ n, resolution, path, level);
+#endif
+ }
+
+
+#ifndef vms
+ for( i=0; (pathpt = path_segment(i, path, local_path)) != NULL; i++) {
+ if (tfm) {
+ if (!stat( pprint(name,"%P/%N.tfm",pathpt,n,resolution,fontmag), &s))
+ return(TRUE);
+ } else {
+ for (pattern = raster_table; *pattern; pattern++) {
+ if (!stat( pprint(name,*pattern,pathpt,n,resolution,fontmag), &s))
+ return(TRUE);
+ }
+ }
+ }
+#else
+ if (tfm) {
+ if ( !stat(pprint(name,"%P/%N.tfm",pathpt,n,resolution,fontmag), &s))
+ return(TRUE);
+ } else {
+ for (pattern = raster_table; *pattern; pattern++) {
+ if (!stat( pprint(name,*pattern,path,n,resolution,fontmag), &s))
+ return(TRUE);
+ }
+ }
+#endif
+
+#ifdef FUTURE
+ for(i=0; (pathpt=path_segment((bool)(i==0),VFPATH,local_path))!=NULL;i++) {
+ sprintf(name,"%s/%s.vfm",pathpt,n);
+ printf("searching virtual font <%s>\n",name);
+ if (stat(name,&s) == 0) return(TRUE);
+ }
+#endif
+
+#ifdef DO_SUBDIRECTORIES
+ if (level < MAX_SUBDIR_SEARCH_DEPTH) {
+ for( i=0; (pathpt = path_segment(i, path, local_path)) != NULL; i++) {
+ glob_t globbuf;
+ char glob_path[STRSIZE + 3];
+ int i;
+ sprintf( glob_path, "%s/*", pathpt );
+ if (glob( glob_path, 0, NULL, &globbuf ) == 0) {
+ for (i = 0; i < globbuf.gl_pathc; i++) {
+ if ((stat( globbuf.gl_pathv[i], &s) == 0) && S_ISDIR(s.st_mode)) {
+ if (findfile(globbuf.gl_pathv[i],
+ n,
+ fontmag,
+ name,
+ tfm,
+ level+1 ) == TRUE) {
+ globfree( &globbuf );
+ return(TRUE);
+ }
+ }
+ }
+ globfree( &globbuf );
+ }
+ }
+ } else {
+ Warning("maximal searchdepth (%d) exceeded, path=%s",
+ MAX_SUBDIR_SEARCH_DEPTH, path);
+ }
+#endif
+
+#ifdef MAKETEXPK
+ if (makeTexPK && level == 0 && !tfm) {
+ sprintf(MakePKCommand,"%s %s %d %d %.4f %s",MAKETEXPK,
+ n,resolution,RESOLUTION,
+ (float)((float)resolution/RESOLUTION),MFMODE);
+ if (!G_quiet)
+ fprintf(stderr,"calling: %s\n",MakePKCommand);
+ system(MakePKCommand);
+ if (findfile(path,n,fontmag,name,tfm,1))
+ return(TRUE);
+ }
+#endif
+
+ if (level == 0) {
+ /* return error message */
+ if (tfm) {
+ sprintf(name, "tfm file not found: path=%s, name=%s", path,n);
+ } else {
+ sprintf(name,
+#ifdef USEPXL
+ "pk or pxl font not found: path=%s, name=%s, resolution=%d, magn=%ld",
+#else
+ "gf font not found: path=%s, name=%s, resolution=%d, magn=%ld",
+#endif
+ path,n,resolution,fontmag);
+ }
+ }
+ return(FALSE);
+}
+
+
+char *
+pprint (buffer, input, path, name, resolution, fontmag)
+char *buffer;
+char *input;
+char *path;
+char *name;
+int resolution;
+long fontmag;
+{
+ char *output = buffer;
+
+ /* fprintf(stderr, "pprint called with <%s>\n", input);*/
+ for (; *input != '\0'; input++)
+ {
+ if (*input == '%') {
+ switch (*(++input))
+ {
+ case 'P':
+ strcpy(output, path);
+ output += strlen(output);
+ break;
+
+ case 'N':
+ strcpy(output, name);
+ output += strlen(output);
+ break;
+
+ case 'R':
+ sprintf(output, "%d", resolution);
+ output += strlen(output);
+ break;
+
+ case 'M':
+#ifdef vms
+ sprintf(output, "%d", fontmag);
+#else
+ sprintf(output, "%ld", fontmag);
+#endif
+ output += strlen(output);
+ break;
+
+ default:
+ *output++ = '%';
+ *output++ = *input;
+ break;
+ }
+ } else {
+ *output++ = *input;
+ }
+ }
+ *output = '\0';
+ /* fprintf(stderr, "pprint returns <%s>\n", buffer); */
+ return buffer;
+}
+
+
+char *
+path_segment(index,full_path,local_path)
+int index;
+char *full_path, *local_path;
+{
+ static char *pppt;
+ char *pathpt;
+
+ if (index == 0) pathpt = strcpy(local_path,full_path);
+ else pathpt = pppt;
+ if (pathpt != NULL) {
+#ifdef unix
+ pppt = strchr(pathpt , ':' );
+#else
+ pppt = strchr(pathpt , ';' );
+#endif
+ if (pppt != NULL) {
+ *pppt = '\0';
+ pppt++;
+ }
+ }
+ return pathpt;
+}
+
+
+
+
diff --git a/obsolete/dviware/dvi2xx/graybox.sty b/obsolete/dviware/dvi2xx/graybox.sty
new file mode 100644
index 0000000000..ad66bf9873
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/graybox.sty
@@ -0,0 +1,48 @@
+% graybox.sty 9.3.1989
+% print fboxes with various backgrounds
+%
+% graybox#1#2
+% #1 -> grayscale; valid values are 2, 10, 15, 30, 45, 70, 90, 100
+% #2 -> textargument (exactly like fbox)
+%
+% patbox#1#2
+% #1 -> pattern; valid values are:
+% 1: horizontal lines
+% 2: vertical lines
+% 3: diagonal lines
+% 4: diagonal lines
+% 5: square grid
+% 6: diagonal grid
+% #2 -> textargument (exactly like fbox)
+%
+\makeatletter
+%
+%
+%
+
+\long\def\graybox#1#2{\leavevmode\setbox\@tempboxa\hbox{#2}\@tempdima\fboxrule
+\advance\@tempdima \fboxsep \advance\@tempdima \dp\@tempboxa
+ \hbox{\lower \@tempdima\hbox
+ {\vbox{\special{defpoint=1(,)}%
+ \hrule \@height \fboxrule
+ \hbox{\vrule \@width \fboxrule \hskip\fboxsep
+ \vbox{\vskip\fboxsep \box\@tempboxa\vskip\fboxsep}\hskip
+ \fboxsep\vrule \@width \fboxrule%
+ \special{defpoint=2(,)}\special{gray=#1}%
+ \special{fill=1/2}%
+ }\hrule \@height \fboxrule%
+ }}}}
+
+
+\long\def\patbox#1#2{\leavevmode\setbox\@tempboxa\hbox{#2}\@tempdima\fboxrule
+\advance\@tempdima \fboxsep \advance\@tempdima \dp\@tempboxa
+ \hbox{\lower \@tempdima\hbox
+ {\vbox{\special{defpoint=11(,)}%
+ \hrule \@height \fboxrule
+ \hbox{\vrule \@width \fboxrule \hskip\fboxsep
+ \vbox{\vskip\fboxsep \box\@tempboxa\vskip\fboxsep}\hskip
+ \fboxsep\vrule \@width \fboxrule%
+ \special{defpoint=12(,)}\special{pattern=#1}%
+ \special{fill=11/12}%
+ }\hrule \@height \fboxrule%
+ }}}}
diff --git a/obsolete/dviware/dvi2xx/lj3-filter b/obsolete/dviware/dvi2xx/lj3-filter
new file mode 100644
index 0000000000..da9f04a2e7
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/lj3-filter
@@ -0,0 +1,116 @@
+#!/usr/local/bin/perl
+#####################################################################
+# Stefan Esser
+#
+# /usr/local/lib/lpdfilters/lj3-filter
+#
+# BSD line printer filter for HP-PCL 5 printer
+# with independent init and uninit strings
+# for HP-PCL and HP-GL modes
+#
+# Fri Jan 3 12:39:43 1992 -- Gustaf Neumann
+# added support for printing of dvi-files
+#
+# CONFIGURATION:
+# - the location of perl (headerline) /usr/local/bin/perl
+# - the location of the tmp file (variable $tmpfile below)
+# - the name of the dvi-filter and its options (variable $dvifilter below)
+
+$tmpfile = "/usr/tmp/dvilj$$.dvi";
+$dvifilter = "/usr/local/bin/dvilj -q -s26 -e- $tmpfile";
+
+#--------------------------------------------------------------------
+# init and uninit strings for HP-PCL and HP-GL modes
+#
+$text_inistr = "\033E\033&k2G"; # Text init string
+$text_unistr = "\033E"; # Text un_init string
+
+#$hpgl_inistr = "\033E\033%0B"; # HP-GL init string
+$hpgl_inistr = "\033E\033&l1O\033%0B"; # HP-GL init string (rot 90 degree)
+$hpgl_unistr = "\033E"; # HP-GL un_init string
+$stdpwcmd = "PW 0.15;"; # default pen width in HP-GL mode
+
+#--------------------------------------------------------------------
+# describe (a superset of :-) the HP-GL commands
+#
+$hpglcmd = '(SM.|LB[^\003]*\003|[A-Z][A-Z][-\d,.\s]*|[.,;]|\033\..([\d;\s]*:)?|\s)';
+
+#--------------------------------------------------------------------
+# lprm sends SIGINT (is THIS signal handler necessary ???)
+#
+$SIG{'INT'} = 'CLEANUP';
+
+sub CLEANUP {
+ print ($hpglfile ? $hpgl_unistr : $text_unistr);
+ unlink $tmpfile if $dvifile;
+ close(STDOUT);
+ exit 2;
+}
+
+#--------------------------------------------------------------------
+# read enough (=4KByte) data to choose HP-GL or HP-PCL mode
+#
+$numread = read(STDIN,$buffer,4096);
+
+#--------------------------------------------------------------------
+# check whether the file is a dvi-file
+
+$dvifile = $buffer =~ m/^\367\002/oi;
+if ($dvifile) {
+ open(SPOOL,">$tmpfile") || die "Can't open $tmpfile for writing!";
+ while ($numread > 0) {
+ print SPOOL $buffer;
+ $numread=read(STDIN,$buffer,4096);
+ }
+ close(SPOOL) || exit (1);
+ system $dvifilter || exit (1);
+ unlink $tmpfile;
+ close(STDOUT) || exit (1);
+ exit (0);
+}
+
+
+#--------------------------------------------------------------------
+# look for a sequence of HP-GL commands
+#
+$buffer =~ m/^$hpglcmd+/oi;
+
+$matchlen= length($&);
+$hpglfile= $matchlen > 10 && $matchlen / $numread > 0.95;
+
+#--------------------------------------------------------------------
+# add command to set pen width after 'IN', if found within the first 20 bytes
+# else that default pen width
+#
+if ($hpglfile && substr($buffer,0,20) =~ m/IN/i) {
+ $pwcmd = ($buffer =~ m/(PW\s*\d+\.?\d*\s*;)/i)[0] || $stdpwcmd;
+ $buffer =~ s/IN\s*;/IN;$pwcmd/i;
+}
+
+
+#--------------------------------------------------------------------
+# print init string, all data, uninit string to STDOUT
+#
+print ($hpglfile ? $hpgl_inistr : $text_inistr);
+
+while ($numread > 0) {
+ print $buffer;
+ $numread=read(STDIN,$buffer,4096);
+}
+
+print ($hpglfile ? $hpgl_unistr : $text_unistr);
+
+close(STDOUT) || exit (1);
+
+exit (0);
+
+
+
+
+
+
+
+
+
+
+
diff --git a/obsolete/dviware/dvi2xx/printcap.sample b/obsolete/dviware/dvi2xx/printcap.sample
new file mode 100644
index 0000000000..70a6315ad3
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/printcap.sample
@@ -0,0 +1,9 @@
+# sample printcap entry for SUN SparcStation, supplied by Ted Cox
+#
+# Centronics printer attached to the first parallel port
+# Can detect .dvi files automatically via outputfilter and invokes dvi-converter.
+tp|tex|pp0|Antares Printer Port 1:\
+ :lp=/dev/pp0:sd=/var/spool/pp0:\
+ :lf=/var/spool/pp0/error_log:\
+ :fs#06020:fc#0300:xc#040:pw#80:sh:\
+ :of=/usr/local/lib/lpdfilters/lj3-filter:
diff --git a/obsolete/dviware/dvi2xx/sample2.tex b/obsolete/dviware/dvi2xx/sample2.tex
new file mode 100644
index 0000000000..ddf6af5b92
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/sample2.tex
@@ -0,0 +1,179 @@
+% This is a sample LaTeX input file. (Version of 9 April 1986)
+%
+% A '%' character causes TeX to ignore all remaining text on the line,
+% and is used for comments like this one.
+
+\documentstyle[2up]{article} % Specifies the document style.
+\twouparticle
+ % The preamble begins here.
+\title{A Sample Document} % Declares the document's title.
+\author{Leslie Lamport} % Declares the author's name.
+\date{December 12, 1984} % Deleting this command produces today's date.
+
+\begin{document} % End of preamble and beginning of text.
+
+\maketitle % Produces the title.
+
+This is a sample input file. Comparing it with the output it
+generates can show you how to produce a simple document of
+your own.
+
+\section{Ordinary Text} % Produces section heading. Lower-level
+ % sections are begun with similar
+ % \subsection and \subsubsection commands.
+
+The ends of words and sentences are marked
+ by spaces. It doesn't matter how many
+spaces you type; one is as good as 100. The
+end of a line counts as a space.
+
+One or more blank lines denote the end
+of a paragraph.
+
+Since any number of consecutive spaces are treated like a single
+one, the formatting of the input file makes no difference to
+ \TeX, % The \TeX command generates the TeX logo.
+but it makes a difference to you.
+When you use
+ \LaTeX, % The \LaTeX command generates the LaTeX logo.
+making your input file as easy to read as possible
+will be a great help as you write your document and when you
+change it. This sample file shows how you can add comments to
+your own input file.
+
+Because printing is different from typewriting, there are a
+number of things that you have to do differently when preparing
+an input file than if you were just typing the document directly.
+Quotation marks like
+ ``this''
+have to be handled specially, as do quotes within quotes:
+ ``\,`this' % \, separates the double and single quote.
+ is what I just
+ wrote, not `that'\,''.
+
+Dashes come in three sizes: an
+ intra-word
+dash, a medium dash for number ranges like
+ 1--2,
+and a punctuation
+ dash---like
+this.
+
+A sentence-ending space should be larger than the space between words
+within a sentence. You sometimes have to type special commands in
+conjunction with punctuation characters to get this right, as in the
+following sentence.
+ Gnats, gnus, etc.\ % `\ ' makes an inter-word space.
+ all begin with G\@. % \@ marks end-of-sentence punctuation.
+You should check the spaces after periods when reading your output to
+make sure you haven't forgotten any special cases.
+Generating an ellipsis
+ \ldots\ % `\ ' needed because TeX ignores spaces after
+ % command names like \ldots made from \ + letters.
+ %
+ % Note how a `%' character causes TeX to ignore the
+ % end of the input line, so these blank lines do not
+ % start a new paragraph.
+with the right spacing around the periods
+requires a special command.
+
+\TeX\ interprets some common characters as commands, so you must type
+special commands to generate them. These characters include the
+following:
+ \$ \& \% \# \{ and \}.
+
+In printing, text is emphasized by using an
+ {\em italic\/} % The \/ command produces the tiny extra space that
+ % should be added between a slanted and a following
+ % unslanted letter.
+type style.
+
+\begin{em}
+ A long segment of text can also be emphasized in this way. Text within
+ such a segment given additional emphasis
+ with\/ {\em Roman}
+ type. Italic type loses its ability to emphasize and become simply
+ distracting when used excessively.
+\end{em}
+
+It is sometimes necessary to prevent \TeX\ from breaking a line where
+it might otherwise do so. This may be at a space, as between the
+``Mr.'' and ``Jones'' in
+ ``Mr.~Jones'', % ~ produces an unbreakable interword space.
+or within a word---especially when the word is a symbol like
+ \mbox{\em itemnum\/}
+that makes little sense when hyphenated across
+ lines.
+
+Footnotes\footnote{This is an example of a footnote.}
+pose no problem.
+
+\TeX\ is good at typesetting mathematical formulas like
+ \( x-3y = 7 \)
+or
+ \( a_{1} > x^{2n} / y^{2n} > x' \).
+Remember that a letter like
+ $x$ % $ ... $ and \( ... \) are equivalent
+is a formula when it denotes a mathematical symbol, and should
+be treated as one.
+
+\section{Displayed Text}
+
+Text is displayed by indenting it from the left margin.
+Quotations are commonly displayed. There are short quotations
+\begin{quote}
+ This is a short a quotation. It consists of a
+ single paragraph of text. There is no paragraph
+ indentation.
+\end{quote}
+and longer ones.
+\begin{quotation}
+ This is a longer quotation. It consists of two paragraphs
+ of text. The beginning of each paragraph is indicated
+ by an extra indentation.
+
+ This is the second paragraph of the quotation. It is just
+ as dull as the first paragraph.
+\end{quotation}
+Another frequently-displayed structure is a list.
+The following is an example of an {\em itemized} list.
+\begin{itemize}
+ \item This is the first item of an itemized list. Each item
+ in the list is marked with a ``tick''. The document
+ style determines what kind of tick mark is used.
+
+ \item This is the second item of the list. It contains another
+ list nested inside it. The inner list is an {\em enumerated}
+ list.
+ \begin{enumerate}
+ \item This is the first item of an enumerated list that
+ is nested within the itemized list.
+
+ \item This is the second item of the inner list. \LaTeX\
+ allows you to nest lists deeper than you really should.
+ \end{enumerate}
+ This is the rest of the second item of the outer list. It
+ is no more interesting than any other part of the item.
+ \item This is the third item of the list.
+\end{itemize}
+You can even display poetry.
+\begin{verse}
+ There is an environment for verse \\ % The \\ command separates lines
+ Whose features some poets will curse. % within a stanza.
+
+ % One or more blank lines separate stanzas.
+
+ For instead of making\\
+ Them do {\em all\/} line breaking, \\
+ It allows them to put too many words on a line when they'd
+ rather be forced to be terse.
+\end{verse}
+
+Mathematical formulas may also be displayed. A displayed formula is
+one-line long; multiline formulas require special formatting
+instructions.
+ \[ x' + y^{2} = z_{i}^{2}\]
+Don't start a paragraph with a displayed equation, nor make
+one a paragraph by itself.
+
+\end{document} % End of document.
diff --git a/obsolete/dviware/dvi2xx/testpage.tex b/obsolete/dviware/dvi2xx/testpage.tex
new file mode 100644
index 0000000000..393dc86ec9
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/testpage.tex
@@ -0,0 +1,78 @@
+% testpage.tex - created 20 July 1987
+% Copyright (C) 1987 by Leslie Lamport
+%
+% Test of how accurately printer reproduces dimensions specified
+% by LaTeX output.
+%
+% Revised by Stephen Gildea to:
+% make 10 tic marks instead of 9
+% add a long rule through the tics to show the exact edge of the paper
+% short tics on right-hand ruler positioned correctly
+% some comments added
+
+\documentstyle{article}
+\pagestyle{empty}
+
+\oddsidemargin 0pt
+\evensidemargin 0pt
+\marginparwidth 1in
+\marginparsep 0pt
+
+\topmargin 0pt
+\headheight 0pt
+\headsep 0pt
+\topskip 0pt
+
+\footheight 0pt
+\footskip 0pt
+\textheight 9in
+\textwidth 6.5in
+\setlength{\unitlength}{1in}
+\newcounter{foo}
+\begin{document}
+\parindent 0pt
+\begin{picture}(0,0)
+\scriptsize
+\put(0,-9){\framebox(6.5,9){}}
+% left ruler
+\put(0,-4.5){\line(-1,0){2.5}}
+\multiput(-.1,-4.6)(-.1,0){10}{\line(0,1){.2}}
+\multiput(-.05,-4.55)(-.1,0){10}{\line(0,1){.1}}
+\setcounter{foo}{1}\multiput(-.1,-4.35)(-.1,0){9}{\makebox
+ (0,0){\arabic{foo}}\addtocounter{foo}{1}}
+% right ruler
+\put(6.5,-4.5){\line(1,0){2.5}}
+\multiput(6.6,-4.6)(.1,0){10}{\line(0,1){.2}}
+\multiput(6.55,-4.55)(.1,0){10}{\line(0,1){.1}} %fixed mit-erl!gildea 13Feb86
+%\multiput(6.55,-4.6)(.1,0){10}{\line(0,1){.1}}
+\setcounter{foo}{1}\multiput(6.6,-4.35)(.1,0){9}{\makebox
+ (0,0){\arabic{foo}}\addtocounter{foo}{1}}
+% top ruler
+\put(3.25,0){\line(0,1){2.5}}
+\multiput(3.15,.1)(0,.1){10}{\line(1,0){.2}}
+\multiput(3.2,.05)(0,.1){10}{\line(1,0){.1}}
+\setcounter{foo}{1}\multiput(3.4,.1)(0,.1){9}{\makebox
+ (0,0){\arabic{foo}}\addtocounter{foo}{1}}
+% bottom ruler
+\put(3.25,-9){\line(0,-1){2.5}}
+\multiput(3.15,-9.1)(0,-.1){10}{\line(1,0){.2}}
+\multiput(3.2,-9.05)(0,-.1){10}{\line(1,0){.1}}
+\setcounter{foo}{1}\multiput(3.4,-9.1)(0,-.1){9}{\makebox
+ (0,0){\arabic{foo}}\addtocounter{foo}{1}}
+\end{picture}
+\vfill
+\mbox{}\hfill
+\begin{minipage}{4in}
+The frame on this page should be $6\frac{1}{2}'' \times 9''$. When
+printed on $8\frac{1}{2}'' \times 11''$ paper, the frame should be one
+inch from each edge of the paper.\\[10pt]
+The rulers at the four edges will indicate how much of the page is
+useable. The large ticks are $.1''$ apart.
+\end{minipage}
+\hfill\mbox{}
+
+\vfill
+\mbox{}
+\end{document}
+
+
diff --git a/obsolete/dviware/dvi2xx/tfm.c b/obsolete/dviware/dvi2xx/tfm.c
new file mode 100644
index 0000000000..4100fa7899
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/tfm.c
@@ -0,0 +1,255 @@
+/* tfm.c -- read tfm widths resident font support in dvilj. */
+
+#include "config.h" /* for STRSIZE and tfm_info_type, at least */
+#include <stdio.h>
+
+
+#ifdef vms
+#include <ssdef.h>
+#include <stsdef.h>
+#define getenv vms_getenv
+#endif
+
+/* Defined in dvi2xx.c. */
+extern long NoSignExtend ();
+#define TFM_GET_TWO() NoSignExtend (tfm_fp, 2)
+#define TFM_GET_FOUR() NoSignExtend (tfm_fp, 4)
+extern char* TFMpath;
+extern bool G_quiet;
+extern void Warning();
+
+/* Defined in xmalloc.c. */
+extern void *xmalloc ();
+
+
+
+/* Read N words (N * 4 bytes) from TFM_FP and return it in *OUTBUF, unless
+ OUTBUF==NULL, in which case throw them away. */
+
+static void
+tfm_get_n (tfm_fp, nwords, outbuf)
+ FILE *tfm_fp;
+ unsigned nwords;
+ void **outbuf;
+{
+ unsigned n = nwords * 4;
+ void *buf = (void *) xmalloc (n);
+
+ if (fread (buf, n, 1, tfm_fp) != 1) {
+ fprintf (stderr, "dvi2xx: Could not read %u bytes from TFM file.\n", n);
+ exit (1);
+ }
+
+ /* If OUTBUF is null, free what we just read, else return it. */
+ if (outbuf) {
+ *outbuf = buf;
+ } else {
+ free (buf);
+ }
+}
+
+
+/* Read a string in BCPL format from DATA into STR, and terminate with a
+ null byte. First byte of DATA says how many characters follow.
+ Assume STR is long enough. */
+
+static void
+get_bcpl (data, str)
+ unsigned char *data;
+ unsigned char *str;
+{
+ unsigned length;
+
+ for (length = *(data ++); length; length --) {
+ *(str ++) = *(data ++);
+ }
+ *str = 0;
+}
+
+/* Header word 18:
+ 2 bytes: "KN" for Karl and Norm---this identifies our extensions
+ 1 byte : 1 if proportional, 0 otherwise
+ 1 byte : reserved (to extend the style, if necessary)
+ Header word 19:
+ 2 bytes: PCL style selection number
+ 1 byte : reserved (to extend weight, if necessary)
+ 1 byte : weight (signed, 2's complement, valid -7 to +7)
+ Header word 20:
+ 2 bytes: reserved (to extend typeface id, if necessary)
+ 2 bytes: PCL typeface selection number
+
+ The first (BigEndian) byte of header word #18 is DATA[0].
+ Assume DATA is long enough for everything we might try to read. */
+
+static bool
+get_pcl_info (data, spacing, style, weight, typeface_id)
+ unsigned char *data;
+ unsigned *spacing;
+ unsigned *style;
+ int *weight;
+ unsigned *typeface_id;
+{
+ /* No magic number for our extensions => forget it. */
+ if (data[0] != 'K' && data[1] != 'N')
+ return FALSE;
+
+ *spacing = data[(0* 4) + 2]; /* Third byte of first word. */
+
+ /* First two bytes of second word. */
+ *style = (data[(1 * 4)] << 8) + data[(1 * 4) + 1];
+
+ /* Last byte of second word, signed two-complement. */
+ *weight = data[(1 * 4) + 3];
+ if (*weight >= 128) *weight -= 256;
+
+ /* Effectively all four bytes of third word. */
+ *typeface_id = (data[(2 * 4) + 0] << 24) + (data[(2 * 4) + 1] << 16)
+ + (data[(2 * 4) + 2] << 8) + (data[(2 * 4) + 3]);
+
+ return TRUE;
+}
+
+/* If the TFM file NAME exists, set the elements of RET and return true.
+ Otherwise, return false. */
+
+bool
+tfm_read_info (name, ret)
+ char *name;
+ tfm_info_type *ret;
+{
+ /* Don't use a structure for this, since then it might occupy more
+ than the exactly four bytes that we need. */
+ unsigned char *char_info;
+ char full_name[STRSIZE];
+ FILE *tfm_fp;
+ unsigned char *header_data;
+ unsigned char *width_raw; /* array of 1-byte data */
+ unsigned long *width_table; /* array of 4-byte fixes */
+ unsigned i;
+ unsigned lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np;
+
+
+ if (findfile(TFMpath, name, NULL, full_name, TRUE, 0)) {
+
+ /* fprintf(stderr,"full_name=<%s>\n", full_name);*/
+ tfm_fp = fopen (full_name, READ_BINARY);
+ if (tfm_fp == NULL) {
+ /* this can happen, if the calculation for max number of open
+ * files has to be corrected
+ */
+ fprintf(stderr,"Error: file <%s> could not be opened\n", full_name);
+ return FALSE;
+ }
+ } else {
+ Warning("tfm file %s.tfm not found on path <%s>\n", name, TFMpath);
+ return FALSE;
+ }
+
+ (void) TFM_GET_TWO (); /* word length of file */
+ lh = TFM_GET_TWO (); /* words of header data */
+ bc = TFM_GET_TWO (); /* smallest character code */
+ ec = TFM_GET_TWO (); /* largest character code */
+ nw = TFM_GET_TWO (); /* words in width table */
+ nh = TFM_GET_TWO (); /* words in height table */
+ nd = TFM_GET_TWO (); /* words in depth table */
+ ni = TFM_GET_TWO (); /* words in italic correction table */
+ nl = TFM_GET_TWO (); /* words in lig/kern table */
+ nk = TFM_GET_TWO (); /* words in kern table */
+ ne = TFM_GET_TWO (); /* words in extensible char table */
+ np = TFM_GET_TWO (); /* words of font parameter data */
+
+ tfm_get_n (tfm_fp, lh, &header_data);
+ /* Only two headerbyte words are required by the TFM format, so don't
+ insist on all this extra stuff. */
+ if (lh > 2) {
+ get_bcpl (header_data + (2 * 4), ret->coding_scheme);
+ } else {
+ ret->coding_scheme[0] = 0;
+ }
+
+ if (lh > 12) {
+ get_bcpl (header_data + (12 * 4), ret->family);
+ } else {
+ ret->family[0] = 0;
+ }
+
+ /* Sorry for the convoluted logic. The idea is that if the family
+ is HPAUTOTFM, we better have our extensions -- so if we don't
+ have enough header words, or if we don't find what we need in
+ the header words, something's seriously wrong, and we shouldn't
+ claim to have succeeded at reading a good TFM file. */
+
+ if (strcmp (ret->family, "HPAUTOTFM") == 0
+ && (lh < 20
+ || !get_pcl_info (&(header_data[18 * 4]),
+ &ret->spacing, &ret->style, &ret->weight,
+ &ret->typeface_id))) {
+ return FALSE;
+ }
+
+/*
+ if (strcmp (ret->family, "HPAUTOTFM") == 0) {
+ if (lh < 20 || !get_pcl_info (&(header_data[18 * 4]),
+ &ret->spacing, &ret->style, &ret->weight,
+ &ret->typeface_id)) {
+ fclose (tfm_fp);
+ return FALSE;
+ }
+ } else {
+ if (strcmp (ret->family, "UNSPECIFIED") == 0) {
+ Warning("font family for %s is UNSPECIFIED; did you run dvicopy?",
+ full_name);
+ }
+ }
+*/
+
+ /* Initialize our returned array of widths to zero, since the TFM file
+ need not contain info for all character codes. */
+ for (i = 0; i < bc; i++) {
+ ret->widths[i] = 0;
+ }
+ for (i = ec + 1; i < 256; i++) {
+ ret->widths[i] = 0;
+ }
+
+ /* The char_info is one word (four bytes) for each character in the font. */
+ tfm_get_n (tfm_fp, ec - bc + 1, &char_info);
+
+ /* The width table is just nw words. */
+ tfm_get_n (tfm_fp, nw, &width_raw);
+ width_table = (unsigned long *) xmalloc (nw * 4);
+
+ /* But the width table contains four-byte numbers, so have to convert
+ from BigEndian to host order. */
+ for (i = 0; i < nw; i++) {
+ unsigned byte_offset = i * 4;
+ unsigned b1 = width_raw[byte_offset];
+ unsigned b2 = width_raw[byte_offset + 1];
+ unsigned b3 = width_raw[byte_offset + 2];
+ unsigned b4 = width_raw[byte_offset + 3];
+ width_table[i] = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
+ }
+
+ /* For each character, retrieve and store the TFM width. */
+ for (i = bc; i <= ec; i++) {
+ unsigned char w_i = char_info[(i - bc) * 4];
+ ret->widths[i] = width_table[w_i];
+ }
+
+ /* Throw away everything up to the second font parameter. (Could just
+ seek, but I don't want to pull in the include files, etc.) */
+ if (np >= 2) {
+ tfm_get_n (tfm_fp, nh + nd + ni + nl + nk + ne + 1, NULL);
+ ret->interword = TFM_GET_FOUR ();
+ } else {
+ ret->interword = 0;
+ }
+
+ free (header_data);
+ free (char_info);
+ free (width_raw);
+ free (width_table);
+
+ fclose (tfm_fp);
+ return TRUE;
+}
diff --git a/obsolete/dviware/dvi2xx/xmalloc.c b/obsolete/dviware/dvi2xx/xmalloc.c
new file mode 100644
index 0000000000..69f6db26b9
--- /dev/null
+++ b/obsolete/dviware/dvi2xx/xmalloc.c
@@ -0,0 +1,41 @@
+/* xmalloc.c: malloc with error checking.
+
+Copyright (C) 1992, 93 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Don't include config.h or all our other usual includes, since
+ it's useful to just throw this file into other programs. */
+
+#include <stdio.h>
+extern char *malloc ();
+
+
+void *
+xmalloc (size)
+ unsigned size;
+{
+ void *new_mem = (void *) malloc (size);
+
+ if (new_mem == NULL)
+ {
+ fprintf (stderr, "fatal: memory exhausted (xmalloc of %u bytes).\n",
+ size);
+ /* 1 means success on VMS, so pick a random number (ASCII `K'). */
+ exit (75);
+ }
+
+ return new_mem;
+}
diff --git a/obsolete/dviware/dvicopy/README b/obsolete/dviware/dvicopy/README
new file mode 120000
index 0000000000..3ce516d7db
--- /dev/null
+++ b/obsolete/dviware/dvicopy/README
@@ -0,0 +1 @@
+read.me \ No newline at end of file
diff --git a/obsolete/dviware/dvicopy/dvicopy.web b/obsolete/dviware/dvicopy/dvicopy.web
new file mode 100644
index 0000000000..70cabca04b
--- /dev/null
+++ b/obsolete/dviware/dvicopy/dvicopy.web
@@ -0,0 +1,4480 @@
+% Copyright (C) 1990,95 Peter Breitenlohner (peb@@mppmu.mpg.de)
+%
+% This program is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 1, or (at your option)
+% any later version.
+%
+% You should have received a copy of the GNU General Public License
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%
+% Version 0.9 was finished May 21, 1990.
+% Version 1.0 pixel rounding for real devices (August 6, 1990).
+% Version 1.1 major rearrangements for DVIprint (October 7, 1990).
+% Version 1.2 fixed some bugs, page selection (February 13, 1991).
+% Version 1.3 several more changes, command line options,
+% don't load fonts that are never used (August 25, 1992).
+% Version 1.4 fixed a typo (March 28, 1995).
+% Version 1.5 avoided cur_name_length identifier conflict (October 15, 1995).
+
+% Here is TeX material that gets inserted after \input webmac
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps for names like SAIL
+\def\PASCAL{Pascal}
+\font\logo=manfnt % font used for the METAFONT logo
+\def\MF{{\logo META}\-{\logo FONT}}
+\mathchardef\RA="3221 % right arrow
+
+\def\(#1){} % this is used to make section names sort themselves better
+\def\9#1{} % this is used for sort keys in the index
+
+\def\title{DVI\lowercase{copy}} % don't change this line!
+\def\contentspagenumber{1}
+\def\topofcontents{\null
+ \def\titlepage{F} % include headline on the contents page
+ \def\rheader{\mainfont\hfil \contentspagenumber}
+ \vfill
+ \centerline{\titlefont The {\ttitlefont DVIcopy} processor}
+ \vskip 5pt
+ \centerline{Copyright (C) 1990,95 Peter Breitenlohner}
+ \centerline{Distributed under terms of GNU General Public License}
+ \vskip 15pt
+ \centerline{(Version 1.5, October 1995)}
+ \vfill}
+\def\botofcontents{\vfill
+ \centerline{\hsize 5in\baselineskip9pt
+ \vbox{\ninerm\noindent
+ This program was developed at the Max-Planck-Institut f\"ur Physik
+ (Werner-Heisenberg-Institut), Munich, Germany.
+ `\TeX' is a trademark of the American Mathematical Society.
+ `{\logo hijklmnj}\kern1pt' is a trademark of Addison-Wesley
+ Publishing Company.}}}
+\pageno=\contentspagenumber \advance\pageno by 1
+
+@* Introduction.
+The \.{DVIcopy} utility program copies (selected pages of) binary
+device-independent (``\.{DVI}'') files that are produced by document
+compilers such as \TeX, and replaces all references to characters from
+virtual fonts by the typesetting instructions specified for them in
+binary virtual-font (``\.{VF}'') files.
+This program has two chief purposes: (1)~It can be used as preprocessor
+for existing \.{DVI}-related software in cases where this software is
+unable to handle virtual fonts or (given suitable \.{VF} files) where
+this software cannot handle fonts with more than 128~characters;
+and (2)~it serves as an example of a program that reads \.{DVI} and
+\.{VF} files correctly, for system programmers who are developing
+\.{DVI}-related software.
+
+Goal number (1) is important since quite a few existing programs have
+to be adapted to the extened capabilities of Version~3 of \TeX\ which
+will require some time. Moreover some existing programs are `as is' and
+the source code is, unfortunately, not available.
+Goal number (2) needs perhaps a bit more explanation. Programs for
+typesetting need to be especially careful about how they do arithmetic; if
+rounding errors accumulate, margins won't be straight, vertical rules
+won't line up, and so on (see the documentaion of \.{DVItype} for more
+details). This program is written as if it were a \.{DVI}-driver for a
+hypothetical typesetting device |out_file|, the output file receiving
+the copy of the input |dvi_file|. In addition all code related to
+|out_file| is concentrated in two chapters at the end of this program
+and quite independent of the rest of the code concerned with the
+decoding of \.{DVI} and \.{VF} files and with font substitutions. Thus
+it should be relatively easy to replace the device dependent code of
+this program by the corresponding code required for a real typesetting
+device. Having this in mind \.{DVItype}'s pixel rounding algorithms are
+included as conditional code not used by \.{DVIcopy}.
+
+The |banner| and |preamble_comment| strings defined here should be
+changed whenever \.{DVIcopy} gets modified.
+
+@d banner=='This is DVIcopy, Version 1.5' {printed when the program starts}
+@d title=='DVIcopy' {the name of this program, used in some messages}
+@d copyright=='Copyright (C) 1990,95 Peter Breitenlohner'
+@#
+@d preamble_comment=='DVIcopy 1.5 output from '
+@d comm_length=24 {length of |preamble_comment|}
+@d from_length=6 {length of its |' from '| part}
+
+@ This program is written in standard \PASCAL, except where it is necessary
+to use extensions; for example, \.{DVIcopy} must read files whose names
+are dynamically specified, and that would be impossible in pure \PASCAL.
+All places where nonstandard constructions are used have been listed in
+the index under ``system dependencies.''
+@!@^system dependencies@>
+
+One of the extensions to standard \PASCAL\ that we shall deal with is the
+ability to move to a random place in a binary file; another is to
+determine the length of a binary file. Such extensions are not necessary
+for reading \.{DVI} files; since \.{DVIcopy} is (a model for) a
+production program it should, however, be made as efficient as possible
+for a particular system. If \.{DVIcopy} is being used with
+\PASCAL s for which random file positioning is not efficiently available,
+the following definition should be changed from |true| to |false|; in such
+cases, \.{DVIcopy} will not include the optional feature that reads the
+postamble first.
+
+@d random_reading==true {should we skip around in the file?}
+
+@ The program begins with a fairly normal header, made up of pieces that
+@^system dependencies@>
+will mostly be filled in later. The \.{DVI} input comes from file
+|dvi_file|, the \.{DVI} output goes to file |out_file|, and messages
+go to \PASCAL's standard |output| file.
+The \.{TFM} and \.{VF} files are defined later since their external
+names are determined dynamically.
+
+If it is necessary to abort the job because of a fatal error, the program
+calls the `|jump_out|' procedure, which goes to the label |final_end|.
+
+@d final_end = 9999 {go here to wrap it up}
+
+@p @t\4@>@<Compiler directives@>@/
+program DVI_copy(@!dvi_file,@!out_file,@!output);
+label final_end;
+const @<Constants in the outer block@>@/
+type @<Types in the outer block@>@/
+var @<Globals in the outer block@>@/
+@<Error handling procedures@>@/
+procedure initialize; {this procedure gets things started properly}
+ var @<Local variables for initialization@>@/
+ begin print_ln(banner);@/
+ print_ln(copyright);
+ print_ln('Distributed under terms of GNU General Public License');@/
+ @<Set initial values@>@/
+ end;
+
+@ The definition of |max_font_type| should be adapted to the number of
+font types used by the program; the first three values have a fixed
+meaning: |defined_font=0| indicates that a font has been defined,
+|loaded_font=1| indicates that the \.{TFM} file has been loaded but the
+font has not yet been used, and |vf_font_type=2| indicates a virtual
+font. Font type values |>=real_font=3| indicate real fonts and
+different font types are used to distinguish various kinds of font files
+(\.{GF} or \.{PK} or \.{PXL}). \.{DVIcopy} uses |out_font_type=3| for
+fonts that appear in the output \.{DVI} file.
+@!@^font types@>
+
+@d defined_font=0 {this font has been defined}
+@d loaded_font=1 {this font has been defined and loaded}
+@d vf_font_type=2 {this font is a virtual font}
+@d real_font=3 {smallest font type for real fonts}
+@#
+@d out_font_type=3 {this font appears in the output file}
+@d max_font_type=3
+
+@ The following parameters can be changed at compile time to extend or
+reduce \.{DVIcopy}'s capacity.
+
+@d max_select=10 {maximum number of page selection ranges}
+
+@<Constants...@>=
+@!max_fonts=100; {maximum number of distinct fonts}
+@!max_chars=10000; {maximum number of different characters among all fonts}
+@!max_widths=3000; {maximum number of different characters widths}
+@!max_packets=5000; {maximum number of different characters packets;
+ must be less than 65536}
+@!max_bytes=30000; {maximum number of bytes for characters packets}
+@!max_recursion=10; {\.{VF} files shouldn't recurse beyond this level}
+@!stack_size=100; {\.{DVI} files shouldn't |push| beyond this depth}
+@!terminal_line_length=150; {maximum number of characters input in a single
+ line of input from the terminal}
+@!name_length=50; {a file name shouldn't be longer than this}
+
+@ As mentioned above, \.{DVIcopy} has two chief purposes: (1)~It produces
+a copy of the input \.{DVI} file with all references to characters from
+virtual fonts replaced by their expansion as specified in the character
+packets of \.{VF} files; and (2)~it serves as an example of a program
+that reads \.{DVI} and \.{VF} files correctly, for system programmers
+who are developing \.{DVI}-related software.
+
+In fact, a very large section of code (starting with the second chapter
+`Introduction (continued)' and ending with the fifteenth chapter
+`The main program') is used in identical form in \.{DVIcopy} and in
+\.{DVIprint}, a prototype \.{DVI}-driver. This has been made possible
+mostly by using several \.{WEB} coding tricks, such as not to make the
+resulting \PASCAL\ program inefficient in any way.
+
+Parts of the program that are needed in \.{DVIprint} but not in
+\.{DVIcopy} are delimited by the codewords `$|device|\ldots|ecived|$';
+these are mostly the pixel rounding algorithms used to convert the
+\.{DVI} units of a \.{DVI} file to the raster units of a real output
+device and have been copied more or less verbatim from \.{DVItype}.
+
+@d device==@{ {change this to `$\\{device}\equiv\null$' when output
+ for a real device is produced}
+@d ecived==@t@>@} {change this to `$\\{ecived}\equiv\null$' when output
+ for a real device is produced}
+@f device==begin
+@f ecived==end
+
+@* Introduction (continued).
+On some systems it is necessary to use various integer subrange types
+in order to make \.{\title} efficient; this is true in particular for
+frequently used variables such as loop indices. Consider an integer
+variable |x| with values in the range |0..255|: on most small systems
+|x| should be a one or two byte integer whereas on most large systems
+|x| should be a four byte integer.
+Clearly the author of a program knows best which range of values is
+required for each variable; thus \.{\title} never uses \PASCAL's |integer|
+type. All integer variables are declared as one of the integer subrange
+types defined below as \.{WEB} macros or \PASCAL\ types; these definitions
+can be used without system-dependent changes, provided the signed 32~bit
+integers are a subset of the standard type |integer|, and the compiler
+automatically uses the optimal representation for integer subranges
+(both conditions need not be satisfied for a particular system).
+@^system dependencies@>
+
+The complementary problem of storing large arrays of integer type
+variables as compactly as possible is addressed differently; here
+\.{\title} uses a \PASCAL\ |type|~declaration for each kind of array
+element.
+
+Note that the primary purpose of these definitions is optimizations, not
+range checking. All places where optimization for a particular system is
+highly desirable have been listed in the index under ``optimization.''
+@!@^optimization@>
+
+@d int_32 == integer {signed 32~bit integers}
+
+@<Types...@>=
+@!int_31 = 0..@"7FFFFFFF; {unsigned 31~bit integer}
+@!int_24u = 0..@"FFFFFF; {unsigned 24~bit integer}
+@!int_24 = -@"800000..@"7FFFFF; {signed 24~bit integer}
+@!int_23 = 0..@"7FFFFF; {unsigned 23~bit integer}
+@!int_16u = 0..@"FFFF; {unsigned 16~bit integer}
+@!int_16 = -@"8000..@"7FFF; {signed 16~bit integer}
+@!int_15 = 0..@"7FFF; {unsigned 15~bit integer}
+@!int_8u = 0..@"FF; {unsigned 8~bit integer}
+@!int_8 = -@"80..@"7F; {signed 8~bit integer}
+@!int_7 = 0..@"7F; {unsigned 7~bit integer}
+
+@ Some of this code is optional for use when debugging only;
+such material is enclosed between the delimiters |debug| and $|gubed|$.
+Other parts, delimited by |stat| and $|tats|$, are optionally included
+if statistics about \.{\title}'s memory usage are desired.
+
+@d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
+@d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
+@f debug==begin
+@f gubed==end
+@#
+@d stat==@{ {change this to `$\\{stat}\equiv\null$'
+ when gathering usage statistics}
+@d tats==@t@>@} {change this to `$\\{tats}\equiv\null$'
+ when gathering usage statistics}
+@f stat==begin
+@f tats==end
+
+@ The \PASCAL\ compiler used to develop this program has ``compiler
+directives'' that can appear in comments whose first character is a dollar sign.
+In production versions of \.{\title} these directives tell the compiler that
+@^system dependencies@>
+it is safe to avoid range checks and to leave out the extra code it inserts
+for the \PASCAL\ debugger's benefit, although interrupts will occur if
+there is arithmetic overflow.
+
+@<Compiler directives@>=
+@{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead}
+@!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging}
+
+@ Labels are given symbolic names by the following definitions. We insert
+the label `|exit|:' just before the `\ignorespaces|end|\unskip' of a
+procedure in which we have used the `|return|' statement defined below;
+the label `|restart|' is occasionally used at the very beginning of a
+procedure; and the label `|reswitch|' is occasionally used just prior to
+a \&{case} statement in which some cases change the conditions and we wish to
+branch to the newly applicable case.
+Loops that are set up with the \&{loop} construction defined below are
+commonly exited by going to `|done|' or to `|found|' or to `|not_found|',
+and they are sometimes repeated by going to `|continue|'.
+
+@d exit=10 {go here to leave a procedure}
+@d restart=20 {go here to start a procedure again}
+@d reswitch=21 {go here to start a case statement again}
+@d continue=22 {go here to resume a loop}
+@d done=30 {go here to exit a loop}
+@d found=31 {go here when you've found it}
+@d not_found=32 {go here when you've found something else}
+
+@ The term |print| is used instead of |write| when this program writes on
+|output|, so that all such output could easily be redirected if desired;
+the term |d_print| is used for conditional output if we are debugging.
+
+@d print(#)==write(output,#)
+@d print_ln(#)==write_ln(output,#)
+@d new_line==write_ln(output) {start new line}
+@d print_nl(#)== {print information starting on a new line}
+ begin new_line; print(#);
+ end
+@#
+@d d_print(#)==@!debug print(#) @; @+ gubed
+@d d_print_ln(#)==@! debug print_ln(#) @; @+ gubed
+
+@ Here are some macros for common programming idioms.
+
+@d incr(#) == #:=#+1 {increase a variable by unity}
+@d decr(#) == #:=#-1 {decrease a variable by unity}
+@#
+@d Incr_Decr_end(#)==#
+@d Incr(#)==#:=#+Incr_Decr_end {we use |Incr(a)(b)| to increase \dots}
+@d Decr(#)==#:=#-Incr_Decr_end {\dots\ and |Decr(a)(b)| to decrease
+ variable |a| by |b|; this can be optimized for some compilers}
+@#
+@d loop == @+ while true do@+ {repeat over and over until a |goto| happens}
+@d do_nothing == {empty statement}
+@d return == goto exit {terminate a procedure call}
+@f return == nil
+@f loop == xclause
+
+@ We assume that |case| statements may include a default case that applies
+if no matching label is found. Thus, we shall use constructions like
+@^system dependencies@>
+$$\vbox{\halign{#\hfil\cr
+|case x of|\cr
+1: $\langle\,$code for $x=1\,\rangle$;\cr
+3: $\langle\,$code for $x=3\,\rangle$;\cr
+|othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
+|endcases|\cr}}$$
+since most \PASCAL\ compilers have plugged this hole in the language by
+incorporating some sort of default mechanism. For example, the compiler
+used to develop \.{WEB} and \TeX\ allows `|others|:' as a default label,
+and other \PASCAL s allow syntaxes like `\ignorespaces|else|\unskip' or
+`\&{otherwise}' or `\\{otherwise}:', etc. The definitions of |othercases|
+and |endcases| should be changed to agree with local conventions. (Of
+course, if no default mechanism is available, the |case| statements of
+this program must be extended by listing all remaining cases.
+Donald~E. Knuth, the author of the \.{WEB} system program \.{TANGLE},
+@^Knuth, Donald Ervin@>
+would have taken the trouble to modify \.{TANGLE} so that such extensions
+were done automatically, if he had not wanted to encourage \PASCAL\
+compiler writers to make this important change in \PASCAL, where it belongs.)
+
+@d othercases == others: {default for cases not listed explicitly}
+@d endcases == @+end {follows the default case in an extended |case| statement}
+@f othercases == else
+@f endcases == end
+
+@* The character set.
+Like all programs written with the \.{WEB} system, \.{\title} can be
+used with any character set. But it uses ASCII code internally, because
+the programming for portable input-output is easier when a fixed internal
+code is used, and because \.{DVI} and \.{VF} files use ASCII code for
+file names and certain other strings.
+
+The next few sections of \.{\title} have therefore been copied from the
+analogous ones in the \.{WEB} system routines. They have been considerably
+simplified, since \.{\title} need not deal with the controversial
+ASCII codes less than @'40 or greater than @'176.
+If such codes appear in the \.{DVI} file,
+they will be printed as question marks.
+
+@<Types...@>=
+@!ASCII_code=" ".."~"; {a subrange of the integers}
+
+@ The original \PASCAL\ compiler was designed in the late 60s, when six-bit
+character sets were common, so it did not make provision for lower case
+letters. Nowadays, of course, we need to deal with both upper and lower case
+alphabets in a convenient way, especially in a program like \.{\title}.
+So we shall assume that the \PASCAL\ system being used for \.{\title}
+has a character set containing at least the standard visible characters
+of ASCII code (|"!"| through |"~"|).
+
+Some \PASCAL\ compilers use the original name |char| for the data type
+associated with the characters in text files, while other \PASCAL s
+consider |char| to be a 64-element subrange of a larger data type that has
+some other name. In order to accommodate this difference, we shall use
+the name |text_char| to stand for the data type of the characters in the
+output file. We shall also assume that |text_char| consists of
+the elements |chr(first_text_char)| through |chr(last_text_char)|,
+inclusive. The following definitions should be adjusted if necessary.
+@^system dependencies@>
+
+@d text_char == char {the data type of characters in text files}
+@d first_text_char=0 {ordinal number of the smallest element of |text_char|}
+@d last_text_char=127 {ordinal number of the largest element of |text_char|}
+
+@<Types...@>=
+@!text_file=packed file of text_char;
+
+@ @<Local variables for init...@>=
+@!i:int_16; {loop index for initializations}
+
+@ The \.{\title} processor converts between ASCII code and
+the user's external character set by means of arrays |xord| and |xchr|
+that are analogous to \PASCAL's |ord| and |chr| functions.
+
+@<Globals...@>=
+@!xord: array [text_char] of ASCII_code;
+ {specifies conversion of input characters}
+@!xchr: array [0..255] of text_char;
+ {specifies conversion of output characters}
+
+@ Under our assumption that the visible characters of standard ASCII are
+all present, the following assignment statements initialize the
+|xchr| array properly, without needing any system-dependent changes.
+
+@<Set init...@>=
+for i:=0 to @'37 do xchr[i]:='?';
+xchr[@'40]:=' ';
+xchr[@'41]:='!';
+xchr[@'42]:='"';
+xchr[@'43]:='#';
+xchr[@'44]:='$';
+xchr[@'45]:='%';
+xchr[@'46]:='&';
+xchr[@'47]:='''';@/
+xchr[@'50]:='(';
+xchr[@'51]:=')';
+xchr[@'52]:='*';
+xchr[@'53]:='+';
+xchr[@'54]:=',';
+xchr[@'55]:='-';
+xchr[@'56]:='.';
+xchr[@'57]:='/';@/
+xchr[@'60]:='0';
+xchr[@'61]:='1';
+xchr[@'62]:='2';
+xchr[@'63]:='3';
+xchr[@'64]:='4';
+xchr[@'65]:='5';
+xchr[@'66]:='6';
+xchr[@'67]:='7';@/
+xchr[@'70]:='8';
+xchr[@'71]:='9';
+xchr[@'72]:=':';
+xchr[@'73]:=';';
+xchr[@'74]:='<';
+xchr[@'75]:='=';
+xchr[@'76]:='>';
+xchr[@'77]:='?';@/
+xchr[@'100]:='@@';
+xchr[@'101]:='A';
+xchr[@'102]:='B';
+xchr[@'103]:='C';
+xchr[@'104]:='D';
+xchr[@'105]:='E';
+xchr[@'106]:='F';
+xchr[@'107]:='G';@/
+xchr[@'110]:='H';
+xchr[@'111]:='I';
+xchr[@'112]:='J';
+xchr[@'113]:='K';
+xchr[@'114]:='L';
+xchr[@'115]:='M';
+xchr[@'116]:='N';
+xchr[@'117]:='O';@/
+xchr[@'120]:='P';
+xchr[@'121]:='Q';
+xchr[@'122]:='R';
+xchr[@'123]:='S';
+xchr[@'124]:='T';
+xchr[@'125]:='U';
+xchr[@'126]:='V';
+xchr[@'127]:='W';@/
+xchr[@'130]:='X';
+xchr[@'131]:='Y';
+xchr[@'132]:='Z';
+xchr[@'133]:='[';
+xchr[@'134]:='\';
+xchr[@'135]:=']';
+xchr[@'136]:='^';
+xchr[@'137]:='_';@/
+xchr[@'140]:='`';
+xchr[@'141]:='a';
+xchr[@'142]:='b';
+xchr[@'143]:='c';
+xchr[@'144]:='d';
+xchr[@'145]:='e';
+xchr[@'146]:='f';
+xchr[@'147]:='g';@/
+xchr[@'150]:='h';
+xchr[@'151]:='i';
+xchr[@'152]:='j';
+xchr[@'153]:='k';
+xchr[@'154]:='l';
+xchr[@'155]:='m';
+xchr[@'156]:='n';
+xchr[@'157]:='o';@/
+xchr[@'160]:='p';
+xchr[@'161]:='q';
+xchr[@'162]:='r';
+xchr[@'163]:='s';
+xchr[@'164]:='t';
+xchr[@'165]:='u';
+xchr[@'166]:='v';
+xchr[@'167]:='w';@/
+xchr[@'170]:='x';
+xchr[@'171]:='y';
+xchr[@'172]:='z';
+xchr[@'173]:='{';
+xchr[@'174]:='|';
+xchr[@'175]:='}';
+xchr[@'176]:='~';
+for i:=@'177 to 255 do xchr[i]:='?';
+
+@ The following system-independent code makes the |xord| array contain a
+suitable inverse to the information in |xchr|.
+
+@<Set init...@>=
+for i:=first_text_char to last_text_char do xord[chr(i)]:=@'40;
+for i:=" " to "~" do xord[xchr[i]]:=i;
+
+@* Reporting errors to the user.
+The \.{\title} processor does not verify that every single bit read from
+one of its binary input files is meaningful and consistent; there are
+other programs, e.g., \.{DVItype}, \.{TFtoPL}, and \.{VFtoPL}, specially
+designed for that purpose.
+
+On the other hand, \.{\title} is designed to avoid unpredictable results
+due to undetected arithmetic overflow, or due to violation of integer
+subranges or array bounds under {\it all\/} circumstances. Thus a fair
+amount of checking is done when reading and analyzing the input data,
+even in cases where such checking reduces the efficiency of the program
+to some extent.
+
+@ A global variable called |history| will contain one of four values
+at the end of every run: |spotless| means that no unusual messages were
+printed; |harmless_message| means that a message of possible interest
+was printed but no serious errors were detected; |error_message| means that
+at least one error was found; |fatal_message| means that the program
+terminated abnormally. The value of |history| does not influence the
+behavior of the program; it is simply computed for the convenience
+of systems that might want to use such information.
+
+@d spotless=0 {|history| value for normal jobs}
+@d harmless_message=1 {|history| value when non-serious info was printed}
+@d error_message=2 {|history| value when an error was noted}
+@d fatal_message=3 {|history| value when we had to stop prematurely}
+@#
+@d mark_harmless==@t@>@+if history=spotless then history:=harmless_message
+@d mark_error==history:=error_message
+@d mark_fatal==history:=fatal_message
+
+@<Glob...@>=@!history:spotless..fatal_message; {how bad was this run?}
+
+@ @<Set init...@>=history:=spotless;
+
+@ If an input (\.{DVI}, \.{TFM}, \.{VF}, or other) file is badly malformed,
+the whole process must be aborted; \.{\title} will give up, after issuing
+an error message about what caused the error. These messages will, however,
+in most cases just indicate which input file caused the error. One of the
+programs \.{DVItype}, \.{TFtoPL} or \.{VFtoVP} should then be used to
+diagnose the error in full detail.
+
+Such errors might be discovered inside of subroutines inside of subroutines,
+so a procedure called |jump_out| has been introduced. This procedure, which
+transfers control to the label |final_end| at the end of the program,
+contains the only non-local |@!goto| statement in \.{\title}.
+@^system dependencies@>
+Some \PASCAL\ compilers do not implement non-local |goto| statements. In
+such cases the |goto final_end| in |jump_out| should simply be replaced
+by a call on some system procedure that quietly terminates the program.
+@^system dependencies@>
+
+@d abort(#)==begin print_ln(' ',#,'.'); jump_out;
+ end
+
+@<Error handling...@>=
+@<Basic printing procedures@>@;
+procedure close_files_and_terminate; forward;
+@#
+procedure jump_out;
+begin mark_fatal; close_files_and_terminate;
+goto final_end;
+end;
+
+@ Sometimes the program's behavior is far different from what it should
+be, and \.{\title} prints an error message that is really for the
+\.{\title} maintenance person, not the user. In such cases the program
+says |confusion(|indication of where we are|)|.
+
+@<Error handling...@>=
+procedure confusion(@!p:pckt_pointer);
+begin print(' !This can''t happen ('); print_packet(p); print_ln(').');
+@.This can't happen@>
+jump_out;
+end;
+
+@ An overflow stop occurs if \.{\title}'s tables aren't large enough.
+
+@<Error handling...@>=
+procedure overflow(@!p:pckt_pointer;@!n:int_16u);
+begin print(' !Sorry, ',title,' capacity exceeded ['); print_packet(p);
+@.Sorry, {\title} capacity exceeded@>
+print_ln('=',n:1,'].');
+jump_out;
+end;
+
+@* Binary data and binary files.
+A detailed description of the \.{DVI} file format can be found in the
+documentation of \TeX, \.{DVItype}, or \.{GFtoDVI}; here we just define
+symbolic names for some of the \.{DVI} command bytes.
+
+@d set_char_0=0 {typeset character 0 and move right}
+@d set1=128 {typeset a character and move right}
+@d set_rule=132 {typeset a rule and move right}
+@d put1=133 {typeset a character}
+@d put_rule=137 {typeset a rule}
+@d nop=138 {no operation}
+@d bop=139 {beginning of page}
+@d eop=140 {ending of page}
+@d push=141 {save the current positions}
+@d pop=142 {restore previous positions}
+@d right1=143 {move right}
+@d w0=147 {move right by |w|}
+@d w1=148 {move right and set |w|}
+@d x0=152 {move right by |x|}
+@d x1=153 {move right and set |x|}
+@d down1=157 {move down}
+@d y0=161 {move down by |y|}
+@d y1=162 {move down and set |y|}
+@d z0=166 {move down by |z|}
+@d z1=167 {move down and set |z|}
+@d fnt_num_0=171 {set current font to 0}
+@d fnt1=235 {set current font}
+@d xxx1=239 {extension to \.{DVI} primitives}
+@d xxx4=242 {potentially long extension to \.{DVI} primitives}
+@d fnt_def1=243 {define the meaning of a font number}
+@d pre=247 {preamble}
+@d post=248 {postamble beginning}
+@d post_post=249 {postamble ending}
+@#
+@d dvi_id=2 {identifies \.{DVI} files}
+@d dvi_pad=223 {pad bytes at end of \.{DVI} file}
+
+@ A \.{DVI}, \.{VF}, or \.{TFM} file is a sequence of 8-bit bytes.
+The bytes appear physically in what is called a `|packed file of 0..255|'
+in \PASCAL\ lingo. One, two, three, or four consecutive bytes are often
+interpreted as (signed or unsigned) integers.
+We might as well define the corresponding data types.
+@!@^system dependencies@>
+
+@<Types...@>=
+@!signed_byte=-@"80..@"7F; {signed one-byte quantity}
+@!eight_bits=0..@"FF; {unsigned one-byte quantity}
+@!signed_pair=-@"8000..@"7FFF; {signed two-byte quantity}
+@!sixteen_bits=0..@"FFFF; {unsigned two-byte quantity}
+@!signed_trio=-@"800000..@"7FFFFF; {signed three-byte quantity}
+@!twentyfour_bits=0..@"FFFFFF; {unsigned three-byte quantity}
+@!signed_quad=int_32; {signed four-byte quantity}
+
+@ Packing is system dependent, and many \PASCAL\ systems fail to implement
+such files in a sensible way (at least, from the viewpoint of producing
+good production software). For example, some systems treat all
+byte-oriented files as text, looking for end-of-line marks and such
+things. Therefore some system-dependent code is often needed to deal with
+binary files, even though most of the program in this section of
+\.{\title} is written in standard \PASCAL.
+@^system dependencies@>
+
+One common way to solve the problem is to consider files of |integer|
+numbers, and to convert an integer in the range $-2^{31}\L x<2^{31}$ to
+a sequence of four bytes $(a,b,c,d)$ using the following code, which
+avoids the controversial integer division of negative numbers:
+$$\vbox{\halign{#\hfil\cr
+|if x>=0 then a:=x div @'100000000|\cr
+|else begin x:=(x+@'10000000000)+@'10000000000; a:=x div @'100000000+128;|\cr
+\quad|end|\cr
+|x:=x mod @'100000000;|\cr
+|b:=x div @'200000; x:=x mod @'200000;|\cr
+|c:=x div @'400; d:=x mod @'400;|\cr}}$$
+The four bytes are then kept in a buffer and output one by one. (On 36-bit
+computers, an additional division by 16 is necessary at the beginning.
+Another way to separate an integer into four bytes is to use/abuse
+\PASCAL's variant records, storing an integer and retrieving bytes that are
+packed in the same place; {\sl caveat implementor!\/}) It is also desirable
+in some cases to read a hundred or so integers at a time, maintaining a
+larger buffer.
+
+@ We shall stick to simple \PASCAL\ in the standard version of this program,
+for reasons of clarity, even if such simplicity is sometimes unrealistic.
+
+@<Types...@>=
+@!byte_file=packed file of eight_bits; {files that contain binary data}
+
+@ For some operating systems it may be convenient or even necessary to
+close the input files.
+
+@d close_in(#)==do_nothing {close an input file}
+
+@ Character packets extracted from \.{VF} files will be stored in a large
+array |byte_mem|. Other packets of bytes, e.g., character packets
+extracted from a \.{GF} or \.{PK} or \.{PXL} file could be stored in the
+same way. A `|pckt_pointer|' variable, which signifies a packet,
+is an index into another array |pckt_start|. The actual sequence of bytes
+in the packet pointed to by |p| appears in positions |pckt_start[p]| to
+|pckt_start[p+1]-1|, inclusive, in |byte_mem|.
+
+Packets will also be used to store sequences of |ASCII_code|s; in this
+respect the |byte_mem| array is very similar to \TeX's string pool and
+part of the following code has, in fact, been copied more or less
+verbatim from \TeX.
+
+In other respects the packets resemble the identifiers used by
+\.{TANGLE} and \.{WEAVE} (also stored in an array called |byte_mem|)
+since there is, in general, at most one packet with a given contents;
+thus part of the code below has been adapted from the corresponding code
+in these programs.
+
+Some \PASCAL\ compilers won't pack integers into a single byte unless the
+integers lie in the range |-128..127|. To accommodate such systems we
+access the array |byte_mem| only via macros that can easily be redefined.
+@^system dependencies@>
+
+@d bi(#) == # {convert from |eight_bits| to |packed_byte|}
+@d bo(#) == # {convert from |packed_byte| to |eight_bits|}
+
+@<Types...@>=
+@!packed_byte = eight_bits; {elements of |byte_mem| array}
+@!byte_pointer = 0..max_bytes; {an index into |byte_mem|}
+@!pckt_pointer = 0..max_packets; {an index into |pckt_start|}
+
+@ The global variable |byte_ptr| points to the first unused location in
+|byte_mem| and |pckt_ptr| points to the first unused location in
+|pckt_start|.
+
+@<Globals...@>=
+@!byte_mem: packed array [byte_pointer] of packed_byte; {bytes of packets}
+@!pckt_start: array [pckt_pointer] of byte_pointer;
+ {directory into |byte_mem|}
+@!byte_ptr: byte_pointer;
+@!pckt_ptr: pckt_pointer;
+
+@ Several of the elementary operations with packets are performed using
+\.{WEB} macros instead of \PASCAL\ procedures, because many of the
+operations are done quite frequently and we want to avoid the
+overhead of procedure calls. For example, here is
+a simple macro that computes the length of a packet.
+@.WEB@>
+
+@d pckt_length(#)==(pckt_start[#+1]-pckt_start[#]) {the number of bytes
+ in packet number \#}
+
+@ Packets are created by appending bytes to |byte_mem|.
+The |append_byte| macro, defined here, does not check to see if the
+value of |byte_ptr| has gotten too high; this test is supposed to be
+made before |append_byte| is used. There is also a |flush_byte|
+macro, which erases the last byte appended.
+
+To test if there is room to append |l| more bytes to |byte_mem|,
+we shall write |pckt_room(l)|, which aborts \.{\title} and gives an
+apologetic error message if there isn't enough room.
+
+@d append_byte(#) == {put byte \# at the end of |byte_mem|}
+begin byte_mem[byte_ptr]:=bi(#); incr(byte_ptr);
+end
+@d flush_byte == decr(byte_ptr) {forget the last byte in |byte_mem|}
+@d pckt_room(#) == {make sure that |byte_mem| hasn't overflowed}
+ if max_bytes-byte_ptr<# then overflow(str_bytes,max_bytes)
+@#
+@d append_one(#) ==
+begin pckt_room(1); append_byte(#);
+end
+
+@ The length of the current packet is called |cur_pckt_length|:
+
+@d cur_pckt_length == (byte_ptr - pckt_start[pckt_ptr])
+
+@ Once a sequence of bytes has been appended to |byte_mem|, it
+officially becomes a packet when the |make_packet| function is called.
+This function returns as its value the identification number of either
+an existing packet with the same contents or, if no such packet exists,
+of the new packet. Thus two packets have the same contents if and only
+if they have the same identification number. In order to locate the
+packet with a given contents, or to find out that no such packet exists,
+we need a hash table. The hash table is kept by the method of simple
+chaining, where the heads of the individual lists appear in the |p_hash|
+array. If |h| is a hash code, the hash table list starts at |p_hash[h]|
+and proceeds through |p_link| pointers.
+
+@d hash_size=353 {should be prime, must be |>256|}
+
+@<Types...@>=
+@!hash_code=0..hash_size;
+
+@ @<Glob...@>=
+@!p_link:array[pckt_pointer] of pckt_pointer; {hash table}
+@!p_hash:array[hash_code] of pckt_pointer;
+
+@ Initially |byte_mem| and all the hash lists are empty; |empty_packet|
+is the empty packet.
+
+@d empty_packet=0 {the empty packet}
+@d invalid_packet==max_packets {used when there is no packet}
+
+@<Set init...@>=
+pckt_ptr:=1; byte_ptr:=1;
+pckt_start[0]:=1; pckt_start[1]:=1;
+for h:=0 to hash_size-1 do p_hash[h]:=0;
+
+@ @<Local variables for init...@>=
+@!h:hash_code; {index into hash-head arrays}
+
+@ Here now is the |make_packet| function used to create packets (and
+strings).
+
+@p function make_packet:pckt_pointer;
+label found;
+var i,@!k:byte_pointer; {indices into |byte_mem|}
+@!h:hash_code; {hash code}
+@!s,@!l:byte_pointer; {start and length of the given packet}
+@!p:pckt_pointer; {where the packet is being sought}
+begin s:=pckt_start[pckt_ptr]; l:=byte_ptr-s; {compute start and length}
+if l=0 then p:=empty_packet
+else begin @<Compute the packet hash code |h|@>;
+ @<Compute the packet location |p|@>;
+ if pckt_ptr=max_packets then overflow(str_packets,max_packets);
+ incr(pckt_ptr); pckt_start[pckt_ptr]:=byte_ptr;
+ end;
+found:make_packet:=p;
+end;
+
+@ A simple hash code is used: If the sequence of bytes is
+$b_1b_2\ldots b_n$, its hash value will be
+$$(2^{n-1}b_1+2^{n-2}b_2+\cdots+b_n)\,\bmod\,|hash_size|.$$
+
+@<Compute the packet hash...@>=
+h:=bo(byte_mem[s]); i:=s+1;
+while i<byte_ptr do
+ begin h:=(h+h+bo(byte_mem[i])) mod hash_size; incr(i);
+ end
+
+@ If the packet is new, it will be placed in position |p=pckt_ptr|,
+otherwise |p| will point to its existing location.
+
+@<Compute the packet location...@>=
+p:=p_hash[h];
+while p<>0 do
+ begin if pckt_length(p)=l then
+ @<Compare packet |p| with current packet, |goto found| if equal@>;
+ p:=p_link[p];
+ end;
+p:=pckt_ptr; {the current packet is new}
+p_link[p]:=p_hash[h]; p_hash[h]:=p {insert |p| at beginning of hash list}
+
+@ @<Compare packet |p|...@>=
+begin i:=s; k:=pckt_start[p];
+while (i<byte_ptr)and(byte_mem[i]=byte_mem[k]) do
+ begin incr(i); incr(k);
+ end;
+if i=byte_ptr then {all bytes agree}
+ begin byte_ptr:=pckt_start[pckt_ptr]; goto found;
+ end;
+end
+
+@ Some packets are initialized with predefined strings of |ASCII_code|s;
+a few macros permit us to do the initialization with a compact program.
+Since this initialization is done when |byte_mem| is still empty, and
+since |byte_mem| is supposed to be large enough for all the predefined
+strings, |pckt_room| is used only if we are debugging.
+
+@d pid0(#)==#:=make_packet
+@d pid1(#)==byte_mem[byte_ptr-1]:=bi(#); pid0
+@d pid2(#)==byte_mem[byte_ptr-2]:=bi(#); pid1
+@d pid3(#)==byte_mem[byte_ptr-3]:=bi(#); pid2
+@d pid4(#)==byte_mem[byte_ptr-4]:=bi(#); pid3
+@d pid5(#)==byte_mem[byte_ptr-5]:=bi(#); pid4
+@d pid6(#)==byte_mem[byte_ptr-6]:=bi(#); pid5
+@d pid7(#)==byte_mem[byte_ptr-7]:=bi(#); pid6
+@d pid8(#)==byte_mem[byte_ptr-8]:=bi(#); pid7
+@d pid9(#)==byte_mem[byte_ptr-9]:=bi(#); pid8
+@d pid10(#)==byte_mem[byte_ptr-10]:=bi(#); pid9
+@#
+@d pid_init(#)==
+ @!debug pckt_room(#); @+ gubed @;
+ Incr(byte_ptr)(#)
+@#
+@d id1==pid_init(1); pid1
+@d id2==pid_init(2); pid2
+@d id3==pid_init(3); pid3
+@d id4==pid_init(4); pid4
+@d id5==pid_init(5); pid5
+@d id6==pid_init(6); pid6
+@d id7==pid_init(7); pid7
+@d id8==pid_init(8); pid8
+@d id9==pid_init(9); pid9
+@d id10==pid_init(10); pid10
+
+@ Here we initialize some strings used as argument of the |overflow| and
+|confusion| procedures.
+
+@<Initialize predefined strings@>=
+id5("f")("o")("n")("t")("s")(str_fonts);
+id5("c")("h")("a")("r")("s")(str_chars);
+id6("w")("i")("d")("t")("h")("s")(str_widths);
+id7("p")("a")("c")("k")("e")("t")("s")(str_packets);
+id5("b")("y")("t")("e")("s")(str_bytes);
+id9("r")("e")("c")("u")("r")("s")("i")("o")("n")(str_recursion);
+id5("s")("t")("a")("c")("k")(str_stack);
+id10("n")("a")("m")("e")("l")("e")("n")("g")("t")("h")(str_name_length);
+
+@ @<Glob...@>=
+@!str_fonts,@!str_chars,@!str_widths,@!str_packets,@!str_bytes,
+@!str_recursion,@!str_stack,@!str_name_length:pckt_pointer;
+
+@ Some packets, e.g., the preamble comments of \.{DVI} and \.{VF} files,
+are needed only temporarily. In such cases |new_packet| is used to
+create a packet (which might duplicate an existing packet) and
+|flush_packet| is used to discard it; the calls to |new_packet| and
+|flush_packet| must occur in balanced pairs, without any intervening
+calls to |make_packet|.
+
+@p function new_packet: pckt_pointer;
+begin if pckt_ptr=max_packets then overflow(str_packets,max_packets);
+new_packet:=pckt_ptr; incr(pckt_ptr); pckt_start[pckt_ptr]:=byte_ptr;
+end;
+@#
+procedure flush_packet;
+begin decr(pckt_ptr); byte_ptr:=pckt_start[pckt_ptr];
+end;
+
+@ The |print_packet| procedure prints the contents of a packet; such a
+packets should, of course, consists of a sequence of |ASCII_code|s.
+
+@<Basic printing...@>=
+procedure print_packet(p:pckt_pointer);
+var k:byte_pointer;
+begin for k:=pckt_start[p] to pckt_start[p+1]-1 do
+ print(xchr[bo(byte_mem[k])]);
+end;
+
+@ When we interpret a packet we will use two (global or local) variables:
+|cur_loc| will point to the byte to be used next, and |cur_limit| will
+point to the start of the next packet. The macro |pckt_extract| will be
+used to extract one byte; it should, however, never be used with
+|cur_loc>=cur_limit|.
+
+@d pckt_extract(#) ==
+@!debug if cur_loc>=cur_limit then confusion(str_packets) @+ else @/
+gubed @;
+ begin #:=bo(byte_mem[cur_loc]); incr(cur_loc); @+ end
+
+@<Globals...@>=
+@!cur_pckt: pckt_pointer; {the current packet}
+@!cur_loc: byte_pointer; {current location in a packet}
+@!cur_limit: byte_pointer; {start of next packet}
+
+@ We will need routines to extract one, two, three, or four bytes from
+|byte_mem|, from the \.{DVI} file, or from a \.{VF} file and assemble
+them into (signed or unsigned) integers and these routines should be
+optimized for efficiency. Here we define \.{WEB} macros to be used for
+the body of these routines; thus the changes for system dependent
+optimization have to be applied only once.
+@^system dependencies@>
+@^optimization@>
+
+In addition we demonstrates how these macros can be used to define
+functions that extract one, two, three, or four bytes from a character
+packet and assemble them into signed or unsigned integers (assuming that
+|cur_loc| and |cur_limit| are initialized suitably).
+
+@d begin_byte(#) ==
+var a:eight_bits;
+begin #(a)
+@d comp_sbyte(#) == if a<128 then #:=a @+ else #:=a-256
+@d comp_ubyte(#) == #:=a
+@f begin_byte == begin
+
+@p function pckt_sbyte:int_8; {returns the next byte, signed}
+@!begin_byte(pckt_extract); comp_sbyte(pckt_sbyte);
+end;
+@#
+function pckt_ubyte:int_8u; {returns the next byte, unsigned}
+@!begin_byte(pckt_extract); comp_ubyte(pckt_ubyte);
+end;
+
+@ @d begin_pair(#) ==
+var a,@!b:eight_bits;
+begin #(a); #(b)
+@d comp_spair(#) == if a<128 then #:=a*256+b @+ else #:=(a-256)*256+b
+@d comp_upair(#) == #:=a*256+b
+@f begin_pair == begin
+
+@p function pckt_spair:int_16; {returns the next two bytes, signed}
+@!begin_pair(pckt_extract); comp_spair(pckt_spair);
+end;
+@#
+function pckt_upair:int_16u; {returns the next two bytes, unsigned}
+@!begin_pair(pckt_extract); comp_upair(pckt_upair);
+end;
+
+@ @d begin_trio(#) ==
+var a,@!b,@!c:eight_bits;
+begin #(a); #(b); #(c)
+@d comp_strio(#) ==
+if a<128 then #:=(a*256+b)*256+c @+ else #:=((a-256)*256+b)*256+c
+@d comp_utrio(#) == #:=(a*256+b)*256+c
+@f begin_trio == begin
+
+@p function pckt_strio:int_24; {returns the next three bytes, signed}
+@!begin_trio(pckt_extract); comp_strio(pckt_strio);
+end;
+@#
+function pckt_utrio:int_24u; {returns the next three bytes, unsigned}
+@!begin_trio(pckt_extract); comp_utrio(pckt_utrio);
+end;
+
+@ @d begin_quad(#) ==
+var a,@!b,@!c,@!d:eight_bits;
+begin #(a); #(b); #(c); #(d)
+@d comp_squad(#) ==
+if a<128 then #:=((a*256+b)*256+c)*256+d
+else #:=(((a-256)*256+b)*256+c)*256+d
+@f begin_quad == begin
+
+@p function pckt_squad:int_32; {returns the next four bytes, signed}
+@!begin_quad(pckt_extract); comp_squad(pckt_squad);
+end;
+
+@ A similar set of routines is needed for the inverse task of
+decomposing a \.{DVI} command into a sequence of bytes to be appended
+to |byte_mem| or, in the case of \.{DVIcopy}, to be written to the
+output file. Again we define \.{WEB} macros to be used for the body
+of these routines; thus the changes for system dependent optimization
+have to be applied only once.
+@^system dependencies@>
+@^optimization@>
+
+First, the |pckt_one| outputs one byte, negative values are represented
+in two's complement notation.
+
+@d begin_one == begin
+@d comp_one(#) ==
+if x<0 then Incr(x)(256);
+#(x)
+@f begin_one == begin
+
+@p @!device
+procedure pckt_one(@!x:int_32); {output one byte}
+@!begin_one; pckt_room(1); comp_one(append_byte);
+end;
+ecived
+
+@ The |pckt_two| outputs two bytes, negative values are represented in
+two's complement notation.
+
+@d begin_two == begin
+@d comp_two(#) ==
+if x<0 then Incr(x)(@"10000);
+#(x div @"100); #(x mod @"100)
+@f begin_two == begin
+
+@p @!device
+procedure pckt_two(@!x:int_32); {output two byte}
+@!begin_two; pckt_room(2); comp_two(append_byte);
+end;
+ecived
+
+@ The |pckt_four| procedure outputs four bytes in two's complement
+notation, without risking arithmetic overflow.
+
+@d begin_four == begin
+@d comp_four(#) ==
+if x>=0 then #(x div @"1000000)
+else begin Incr(x)(@"40000000); Incr(x)(@"40000000);
+ #((x div @"1000000) + 128);
+ end;
+x:=x mod @"1000000; #(x div @"10000);
+x:=x mod @"10000; #(x div @"100);
+#(x mod @"100)
+@f begin_four == begin
+
+@p procedure pckt_four(@!x:int_32); {output four bytes}
+@!begin_four; pckt_room(4); comp_four(append_byte);
+end;
+
+@ Next, the |pckt_char| procedure outputs a |set_char| or \\{set} command
+or, if |upd=false|, a |put| command.
+
+@d begin_char ==
+var o:eight_bits; {|set1| or |put1|}
+begin
+@d comp_char(#) ==
+if (not upd)or(res>127)or(ext<>0) then
+ begin o:=dvi_char_cmd[upd]; {|set1| or |put1|}
+ if ext<0 then Incr(ext)(@"1000000);
+ if ext=0 then #(o) @+ else @;
+ begin if ext<@"100 then #(o+1) @+ else @;
+ begin if ext<@"10000 then #(o+2) @+ else @;
+ begin #(o+3); #(ext div @"10000); ext:=ext mod @"10000;
+ end;
+ #(ext div @"100); ext:=ext mod @"100;
+ end;
+ #(ext);
+ end;
+ end;
+#(res)
+@f begin_char == begin
+
+@p procedure pckt_char(@!upd:boolean;@!ext:int_32;@!res:eight_bits);
+ {output \\{set} or |put|}
+@!begin_char; pckt_room(5); comp_char(append_byte);
+end;
+
+@ Then, the |pckt_unsigned| procedure outputs a |fnt| or |xxx|
+command with its first parameter (normally unsigned); a |fnt| command
+is converted into |fnt_num| whenever this is possible.
+
+@d begin_unsigned == begin
+@d comp_unsigned(#) ==
+if (x<@"100)and(x>=0) then
+ if (o=fnt1)and(x<64) then Incr(x)(fnt_num_0) @+ else #(o)
+else
+ begin if (x<@"10000)and(x>=0) then #(o+1) @+ else @;
+ begin if (x<@"1000000)and(x>=0) then #(o+2) @+ else @;
+ begin #(o+3);
+ if x>=0 then #(x div @"1000000)
+ else begin Incr(x)(@"40000000); Incr(x)(@"40000000);
+ #((x div @"1000000) + 128);
+ end;
+ x:=x mod @"1000000;
+ end;
+ #(x div @"10000); x:=x mod @"10000;
+ end;
+ #(x div @"100); x:=x mod @"100;
+ end;
+#(x)
+@f begin_unsigned == begin
+
+@p procedure pckt_unsigned(@!o:eight_bits;@!x:int_32);
+ {output |fnt_num|, |fnt|, or |xxx|}
+@!begin_unsigned; pckt_room(5); comp_unsigned(append_byte);
+end;
+
+@ Finally, the |pckt_signed| procedure outputs a movement (|right|, |w|,
+|x|, |down|, |y|, or |z|) command with its (signed) parameter.
+
+@d begin_signed ==
+var xx:int_31; {`absolute value' of |x|}
+begin
+@d comp_signed(#) ==
+if x>=0 then xx:=x @+ else xx:=-(x+1);
+if xx<@"80 then
+ begin #(o); @+ if x<0 then Incr(x)(@"100); @+ end
+else begin if xx<@"8000 then
+ begin #(o+1); @+ if x<0 then Incr(x)(@"10000); @+ end
+ else begin if xx<@"800000 then
+ begin #(o+2); @+ if x<0 then Incr(x)(@"1000000); @+ end
+ else begin #(o+3);
+ if x>=0 then #(x div @"1000000)
+ else begin x:=@"7FFFFFFF-xx; #((x div @"1000000) + 128); @+ end;
+ x:=x mod @"1000000;
+ end;
+ #(x div @"10000); x:=x mod @"10000;
+ end;
+ #(x div @"100); x:=x mod @"100;
+ end;
+#(x)
+@f begin_signed == begin
+
+@p procedure pckt_signed(@!o:eight_bits;@!x:int_32);
+ {output |right|, |w|, |x|, |down|, |y|, or |z|}
+@!begin_signed; pckt_room(5); comp_signed(append_byte);
+end;
+
+@ The |hex_packet| procedure prints the contents of a packet in
+hexadecimal form.
+
+@<Basic printing...@>=
+@!debug procedure hex_packet(@!p:pckt_pointer); {prints a packet in hex}
+var j,@!k,@!l:byte_pointer; {indices into |byte_mem|}
+@!d:int_8u;
+begin j:=pckt_start[p]-1; k:=pckt_start[p+1]-1;
+print_ln(' packet=',p:1,' start=',j+1:1,' length=',k-j:1);
+for l:=j+1 to k do
+ begin d:=(bo(byte_mem[l])) div 16;
+ if d<10 then print(xchr[d+"0"]) @+ else print(xchr[d-10+"A"]);
+ d:=(bo(byte_mem[l])) mod 16;
+ if d<10 then print(xchr[d+"0"]) @+ else print(xchr[d-10+"A"]);
+ if (l=k)or(((l-j) mod 16)=0) then new_line
+ else if ((l-j) mod 4)=0 then print(' ')
+ else print(' ');
+ end;
+end;
+gubed
+
+@* File names.
+The structure of file names is different for different systems; therefore
+this part of the program will, in most cases, require system dependent
+modifications. Here we assume that a file name consists of three parts:
+an area or directory specifying where the file can be found, a name
+proper and an extension; \.{\title} assumes that these three parts appear
+in order stated above but this need not be true in all cases.
+
+The font names extracted from \.{DVI} and \.{VF} files consist of an area
+part and a name proper; these are stored as packets consisting of the
+length of the area part followed by the area and the name proper.
+When we print an external font name we simple print the area and the name
+contained in the `file name packet' without delimiter between them.
+This may need to be modified for some systems.
+@^system dependencies@>
+
+@<Basic printing...@>=
+procedure print_font(@!f:font_number);
+var p:pckt_pointer; {the font name packet}
+@!k:byte_pointer; {index into |byte_mem|}
+@!m:int_31; {font magnification}
+begin print(' = '); p:=font_name(f);
+for k:=pckt_start[p]+1 to pckt_start[p+1]-1 do
+ print(xchr[bo(byte_mem[k])]);
+m:=round((font_scaled(f)/font_design(f))*out_mag);
+if m<>1000 then print(' scaled ',m:1);
+end;
+
+@ Before a font file can be opened for input we must build a string
+with its external name.
+
+@<Glob...@>=
+@!cur_name:packed array[1..name_length] of char; {external name,
+ with no lower case letters}
+@!l_cur_name:int_15; {this many characters are actually relevant in
+ |cur_name|}
+
+@ For \.{TFM} and \.{VF} files we just append the apropriate extension
+to the file name packet; in addition a system dependent area part
+(usually different for \.{TFM} and \.{VF} files) is prepended if
+the file name packet contains no area part.
+@^system dependencies@>
+
+@d append_to_name(#)==
+ if l_cur_name<name_length then
+ begin incr(l_cur_name); cur_name[l_cur_name]:=#;
+ end
+ else overflow(str_name_length,name_length)
+@d make_font_name_end(#)==
+ append_to_name(#[l]); make_name
+@d make_font_name(#)==
+ l_cur_name:=0; for l:=1 to # do make_font_name_end
+
+@ For files with character raster data (e.g., \.{GF} or \.{PK} files) the
+the extension and\slash or area part will in most cases depend on the
+resolution of the output device (corrected for font magnification).
+If the special character |res_char| occurs in the extension and\slash or
+default area, a character string representing the device resolution will
+be substituted.
+@^system dependencies@>
+
+@d res_char=='?' {character to be replaced by font resolution}
+@d res_ASCII="?" {|xord[res_char]|}
+@#
+@d append_res_to_name(#)==
+ begin c:=#;
+ @!device if c=res_char then
+ for ll:=n_res_digits downto 1 do append_to_name(res_digits[ll])
+ else ecived@;@/
+ append_to_name(c);
+ end
+@d make_font_res_end(#)==
+ append_res_to_name(#[l]); make_name
+@d make_font_res(#)==
+ make_res; l_cur_name:=0; for l:=1 to # do make_font_res_end
+
+@ @<Glob...@>=
+@!device
+@!f_res:int_16u; {font resolution}
+@!res_digits:array [1..5] of char;
+@!n_res_digits:int_7; {number of significant characters in |res_digits|}
+ecived
+
+@ The |make_res| procedure creates a sequence of characters representing
+to the font resolution |f_res|.
+
+@p @!device procedure make_res;
+var r:int_16u;
+begin n_res_digits:=0; r:=f_res;
+repeat incr(n_res_digits);
+ res_digits[n_res_digits]:=xchr["0"+(r mod 10)]; r:=r div 10;
+until r=0;
+end;
+ecived
+
+@ The |make_name| procedure used to build the external file name. The
+global variable |l_cur_name| contains the length of a default area
+which has been copied to |cur_name| before |make_name| is called.
+@^system dependencies@>
+
+@p procedure make_name(@!e:pckt_pointer);
+var b:eight_bits; {a byte extracted from |byte_mem|}
+@!n:pckt_pointer; {file name packet}
+@!cur_loc,@!cur_limit:byte_pointer; {indices into |byte_mem|}
+@!device
+@!ll:int_15; {loop index}
+ecived@;@/
+@!c:char; {a character to be appended to |cur_name|}
+begin n:=font_name(cur_fnt);
+cur_loc:=pckt_start[n]; cur_limit:=pckt_start[n+1];
+pckt_extract(b); {length of area part}
+if b>0 then l_cur_name:=0;
+while cur_loc<cur_limit do
+ begin pckt_extract(b);
+ if (b>="a")and(b<="z") then Decr(b)("a"-"A"); {convert to upper case}
+ append_to_name(xchr[b]);
+ end;
+cur_loc:=pckt_start[e]; cur_limit:=pckt_start[e+1];
+while cur_loc<cur_limit do
+ begin pckt_extract(b); append_res_to_name(xchr[b]);
+ end;
+while l_cur_name<name_length do
+ begin incr(l_cur_name); cur_name[l_cur_name]:=' ';
+ end;
+end;
+
+@* Font data.
+\.{DVI} file format does not include information about character widths, since
+that would tend to make the files a lot longer. But a program that reads
+a \.{DVI} file is supposed to know the widths of the characters that appear
+in \\{set\_char} commands. Therefore \.{\title} looks at the font metric
+(\.{TFM}) files for the fonts that are involved.
+@.TFM {\rm files}@>
+
+The character-width data appears also in other files (e.g., in \.{VF} files
+or in \.{GF} and \.{PK} files that specify bit patterns for digitized
+characters); thus, it is usually possible for \.{DVI} reading programs
+to get by with accessing only one file per font. For \.{VF} reading
+programs there is, however, a problem: (1)~when reading the character
+packets from a \.{VF} file the \.{TFM} width for its local fonts should
+be known in order to analyze and optimize the packets (e.g., determine
+if a packet must indeed be enclosed with |push| and |pop| as implied by
+the \.{VF} format); and (2)~ in order to avoid infinite recursion such
+programs must not try to read a \.{VF} file for a font before a
+character from that font is actually used. Thus \.{\title} reads the
+\.{TFM} file whenever a new font is encountered and delays the decision
+whether this is a virtual font or not.
+
+@ First of all we need to know for each font~|f| such things as its
+external name, design and scaled size, and the approximate size of
+inter-word spaces. In addition we need to know the range |bc..ec| of
+valid characters for this font, and for each character~|c| in~|f| we
+need to know if this character exists and if so what is the width of~|c|.
+Depending on the font type of~|f| we may want to know a few other things
+about character~|c| in~|f| such as the character packet from a \.{VF}
+file or the raster data from a \.{PK} file.
+@^font types@>
+
+In \.{\title} we want to be able to handle the full range
+|@t$-2^{31}$@><=c<@t$2^{31}$@>| of character codes; each character code
+is decomposed into a character residue |0<=res<256| and character
+extension |@t$-2^{23}$@><=ext<@t$2^{23}$@>| such that |c=256*ext+res|.
+At present \.{VFtoVP}, \.{VPtoVF}, and the standard version of \TeX\ use
+only characters in the range |0<=c<256| (i.e., |ext=0|), there are,
+however, extensions of \TeX\ which use characters with |ext<>0|.
+In any case characters with |ext<>0| will be used rather infrequently
+and we want to handle this possibility without too much overhead.
+
+Some of the data for each character~|c| depend only on its residue:
+first of all its width and escapement; others, such as \.{VF} packets or
+raster data will also depend on its extension. The later will be stored
+as packets in |byte_mem|, and the packets for characters with the same
+residue but different extension will be chained.
+
+Thus we have to maintain several variables for each character
+residue~|bc<=res<=ec| from each font~|f|; we store each type of variable
+in a large array such that the array index |font_chars(f)+res| points to
+the value for characters with residue |res| from font~|f|.
+
+@ Quite often a particular width value is shared by several characters in
+a font or even by characters from different fonts; the later will
+probably occur in particular for virtual fonts and the local fonts used
+by them. Thus the array |widths| is used to store all different \.{TFM}
+width values of all legal characters in all fonts; a variable of type
+|width_pointer| is an index into |widths| or is zero if a characters does
+not exist.
+
+In order to locate a given width value we use again a hash
+table with simple chaining; this time the heads of the individual lists
+appear in the |w_hash| array and the lists proceed through |w_link|
+pointers.
+
+@<Types...@>=
+@!width_pointer=0..max_widths; {an index into |widths|}
+
+@ @<Glob...@>=
+@!widths:array[width_pointer] of int_32; {the different width values}
+@!w_link:array[width_pointer] of width_pointer; {hash table}
+@!w_hash:array[hash_code] of width_pointer;
+@!n_widths:width_pointer; {first unoccupied position in |widths|}
+
+@ Initially the |widths| array and all the hash lists are empty, except
+for one entry: the width value zero; in addition we set |widths[0]:=0|.
+
+@d invalid_width=0 {width pointer for invalid characters}
+@d zero_width=1 {a width pointer to the value zero}
+
+@<Set init...@>=
+w_hash[0]:=1; w_link[1]:=0; widths[0]:=0; widths[1]:=0; n_widths:=2;
+for h:=1 to hash_size-1 do w_hash[h]:=0;
+
+@ The |make_width| function returns an index into |widths| and, if
+necessary, adds a new width value; thus two characters will have the
+same |width_pointer| if and only if their widths agree.
+
+@p function make_width(@!w:int_32):width_pointer;
+label found;
+var h:hash_code; {hash code}
+@!p:width_pointer; {where the identifier is being sought}
+@!x:int_16; {intermediate value}
+begin widths[n_widths]:=w;
+@<Compute the width hash code |h|@>;
+@<Compute the width location |p|, |goto| found unless the value is new@>;
+if n_widths=max_widths then overflow(str_widths,max_widths);
+incr(n_widths);
+found:make_width:=p;
+end;
+
+@ A simple hash code is used: If the width value consists of the four
+bytes $b_0b_1b_2b_3$, its hash value will be
+$$(8*b_0+4*b_1+2*b_2+b_3)\,\bmod\,|hash_size|.$$
+
+@<Compute the width hash...@>=
+if w>=0 then x:=w div @"1000000
+else begin w:=w+@"40000000; w:=w+@"40000000; x:=(w div @"1000000)+@"80;
+ end;
+w:=w mod @"1000000; x:=x+x+(w div @"10000);
+w:=w mod @"10000; x:=x+x+(w div @"100);
+h:=(x+x+(w mod @"100)) mod hash_size
+
+@ If the width is new, it has been placed into position |p=n_widths|,
+otherwise |p| will point to its existing location.
+
+@<Compute the width location...@>=
+p:=w_hash[h];
+while p<>0 do
+ begin if widths[p]=widths[n_widths] then goto found;
+ p:=w_link[p];
+ end;
+p:=n_widths; {the current width is new}
+w_link[p]:=w_hash[h]; w_hash[h]:=p {insert |p| at beginning of hash list}
+
+@ The |char_widths| array is used to store the |width_pointer|s for all
+different characters among all fonts. The |char_packets| array is used
+to store the |pckt_pointer|s for all different characters among all
+fonts; they can point to character packets from \.{VF} files or, e.g.,
+raster packets from \.{PK} files.
+
+@<Types...@>=
+@!char_offset=-255..max_chars; {|char_pointer| offset for a font}
+@!char_pointer=0..max_chars; {index into |char_widths| or similar arrays}
+
+@ @<Glob...@>=
+@!char_widths:array[char_pointer] of width_pointer; {width pointers}
+@!char_packets:array[char_pointer] of pckt_pointer; {packet pointers}
+@!n_chars:char_pointer; {first unused position in |char_widths|}
+
+@ @<Set init...@>=
+n_chars:=0;
+
+@ The current number of known fonts is |nf|; each known font has an
+internal number |f|, where |0<=f<nf|. For the moment we need for each
+known font: |font_check|, |font_scaled|, |font_design|, |font_name|,
+|font_bc|, |font_ec|, |font_chars|, and |font_type|. Here |font_scaled|
+and |font_design| are measured in \.{DVI} units and |font_chars| is of
+type |char_offset|: the width pointer for character~|c| of the font is
+stored in |char_widths[char_offset+c]| (for |font_bc<=c<=font_ec|).
+Lateron we will need additional information depending on the font type:
+\.{VF} or real (\.{GF}, \.{PK}, or \.{PXL}).
+
+@<Types...@>=
+@!f_type=defined_font..max_font_type; {type of a font}
+@!font_number=0..max_fonts;
+
+@ @<Glob...@>=
+@!nf:font_number;
+
+@ These data are stored in several arrays and we use \.{WEB} macros
+to access the various fields. Thus it would be simple to store the
+data in an array of record structures and adapt the \.{WEB} macros
+accordingly.
+
+We will say, e.g., |font_name(f)| for the name field of font~|f|, and
+|font_width(f)(c)| for the width pointer of character~|c| in font~|f|
+and |font_packet(f)(c)| for its character packet (this character
+exists provided |font_bc(f)<=c<=font_ec(f)| and
+|font_width(f)(c)<>invalid_width|). The actual width of character~|c| in
+font~|f| is stored in |widths[font_width(f)(c)]|.
+
+@d font_check(#)==fnt_check[#] {checksum}
+@d font_scaled(#)==fnt_scaled[#] {scaled or `at' size}
+@d font_design(#)==fnt_design[#] {design size}
+@d font_name(#)==fnt_name[#] {area plus name packet}
+@d font_bc(#)==fnt_bc[#] {first character}
+@d font_ec(#)==fnt_ec[#] {last character}
+@d font_chars(#)==fnt_chars[#] {character info offset}
+@d font_type(#)==fnt_type[#] {type of this font}
+@d font_font(#)==fnt_font[#] {use depends on |font_type|}
+@#
+@d font_width_end(#)==#]
+@d font_width(#)==char_widths[font_chars(#)+font_width_end
+@d font_packet(#)==char_packets[font_chars(#)+font_width_end
+
+@<Glob...@>=
+@!fnt_check:array [font_number] of int_32; {checksum}
+@!fnt_scaled:array [font_number] of int_31; {scaled size}
+@!fnt_design:array [font_number] of int_31; {design size}
+@!device @<Declare device dependent font data arrays@>@; @+ ecived @; @/
+@!fnt_name:array [font_number] of pckt_pointer; {pointer to area plus
+ name packet}
+@!fnt_bc:array [font_number] of eight_bits; {first character}
+@!fnt_ec:array [font_number] of eight_bits; {last character}
+@!fnt_chars:array [font_number] of char_offset; {character info offset}
+@!fnt_type:array [font_number] of f_type; {type of font}
+@!fnt_font:array [font_number] of font_number; {use depends on |font_type|}
+
+@ @d invalid_font==max_fonts {used when there is no valid font}
+
+@<Set init...@>=
+@!device @<Initialize device dependent font data@>@; @+ ecived @;@/
+nf:=0;
+
+@ A \.{VF}, or \.{GF}, or \.{PK} file may contain information for
+several characters with the same residue but with different extension;
+all except the first of the corresponding packets in |byte_mem| will
+contain a pointer to the previous one and |font_packet(f)(res)|
+identifies the last such packet.
+
+A character packet in |byte_mem| starts with a flag byte
+$$\hbox{|flag=@"40*ext_flag+@"20*chain_flag+type_flag|}$$
+with |0<=ext_flag<=3|, |0<=chain_flag<=1|, |0<=type_flag<=@"1F|,
+followed by |ext_flag| bytes with the character extension for this
+packet and, if |chain_flag=1|, by a two byte packet pointer to the
+previous packet for the same font and character residue. The actual
+character packet follows after these header bytes and the
+interpretation of the |type_flag| depends on whether this is a \.{VF}
+packet or a packet for raster data.
+
+The empty packet is interpreted as a special case of a packet with
+|flag=0|.
+
+@d ext_flag=@"40
+@d chain_flag=@"20
+
+@<Types...@>=
+@!type_flag=0..chain_flag-1; {the range of values for the |type_flag|}
+
+@ The global variable |cur_fnt| is the internal font number of the
+currently selected font, or equals |invalid_font| if no font has
+been selected; |cur_res| and |cur_ext| are the residue and extension
+part of the current character code. The type of a character packet
+located by the |find_packet| function defined below is |cur_type|.
+While building a character packet for a character, |pckt_ext| and
+|pckt_res| are the extension and residue of this character; |pckt_dup|
+indicates whether a packet for this extension exists already.
+
+@<Glob...@>=
+@!cur_fnt:font_number; {the currently selected font}
+@!cur_ext:int_24; {the current character extension}
+@!cur_res:int_8u; {the current character residue}
+@!cur_type:type_flag; {type of the current character packet}
+@!pckt_ext:int_24; {character extension for the current character packet}
+@!pckt_res:int_8u; {character residue for the current character packet}
+@!pckt_dup:boolean; {is there a previous packet for the same extension?}
+@!pckt_prev:pckt_pointer; {a previous packet for the same extension}
+@!pckt_m_msg,@!pckt_s_msg,@!pckt_d_msg:int_7; {counts for various character
+ packet error messages}
+
+@ @<Set init...@>=
+cur_fnt:=invalid_font; pckt_m_msg:=0; pckt_s_msg:=0; pckt_d_msg:=0;
+
+@ The |find_packet| functions is used to locate the character packet for
+the character with residue~|cur_res| and extension~|cur_ext| from
+font~|cur_fnt| and returns |false| if no packet exists for any extension;
+otherwise the result is |true| and the global variables |cur_packet|,
+|cur_type|, |cur_loc|, and |cur_limit| are initialized. In case none of
+the character packets has the correct extension, the last one in the
+chain (the one defined first) is used instead and |cur_ext| is changed
+accordingly.
+
+@p function find_packet:boolean;
+label found,exit;
+var p,@!q:pckt_pointer; {current and next packet}
+@!f:eight_bits; {a flag byte}
+@!e:int_24; {extension for a packet}
+begin @<Locate a character packet and |goto found| if found@>;
+if font_packet(cur_fnt)(cur_res)=invalid_packet then
+ begin if pckt_m_msg<10 then {stop telling after first 10 times}
+ begin print_ln('---missing character packet for character ',cur_res:1,
+@.missing character packet...@>
+ ' font ',cur_fnt:1);
+ incr(pckt_m_msg); mark_error;
+ if pckt_m_msg=10 then print_ln('---further messages suppressed.');
+ end;
+ find_packet:=false; return;
+ end;
+if pckt_s_msg<10 then {stop telling after first 10 times}
+ begin print_ln('---substituted character packet with extension ',
+@.substituted character packet...@>
+ e:1,' instead of ',cur_ext:1,' for character ',cur_res:1,
+ ' font ',cur_fnt:1);
+ incr(pckt_s_msg); mark_error;
+ if pckt_s_msg=10 then print_ln('---further messages suppressed.');
+ end;
+cur_ext:=e;
+found: cur_pckt:=p; cur_type:=f; find_packet:=true;
+exit: end;
+
+@ @<Locate a character packet and |goto found| if found@>=
+q:=font_packet(cur_fnt)(cur_res);
+while q<>invalid_packet do
+ begin p:=q; q:=invalid_packet;
+ cur_loc:=pckt_start[p]; cur_limit:=pckt_start[p+1];
+ if p=empty_packet then
+ begin e:=0; f:=0;
+ end
+ else begin pckt_extract(f);
+ case (f div ext_flag) of
+ 0: e:=0;
+ 1: e:=pckt_ubyte;
+ 2: e:=pckt_upair;
+ 3: e:=pckt_strio;
+ end; {there are no other cases}
+ if (f mod ext_flag)>=chain_flag then q:=pckt_upair;
+ f:=f mod chain_flag;
+ end;
+ if e=cur_ext then goto found;
+ end
+
+@ The |start_packet| procedure is used to create the header bytes of a
+character packet for the character with residue~|cur_res| and
+extension~|cur_ext| from font~|cur_fnt|; if a previous such a packet
+exists, we try to build an exact duplicate, i.e., use the chain field of
+that previous packet.
+
+@p procedure start_packet(@!t:type_flag);
+label found,not_found;
+var p,@!q:pckt_pointer; {current and next packet}
+@!f:int_8u; {a flag byte}
+@!e:int_32; {extension for a packet}
+@!cur_loc: byte_pointer; {current location in a packet}
+@!cur_limit: byte_pointer; {start of next packet}
+begin @<Locate a character packet and |goto found| if found@>;
+q:=font_packet(cur_fnt)(cur_res); pckt_dup:=false; goto not_found;
+found: pckt_dup:=true; pckt_prev:=p;
+not_found: pckt_ext:=cur_ext; pckt_res:=cur_res; pckt_room(6);
+@!debug if byte_ptr<>pckt_start[pckt_ptr] then confusion(str_packets);
+gubed @;@/
+if q=invalid_packet then f:=t @+ else f:=t+chain_flag;
+e:=cur_ext;
+if e<0 then Incr(e)(@"1000000);
+if e=0 then append_byte(f) @+ else @;
+ begin if e<@"100 then append_byte(f+ext_flag) @+ else @;
+ begin if e<@"10000 then append_byte(f+ext_flag+ext_flag) @+ else @;
+ begin append_byte(f+ext_flag+ext_flag+ext_flag);
+ append_byte(e div @"10000); e:=e mod @"10000;
+ end;
+ append_byte(e div @"100); e:=e mod @"100;
+ end;
+ append_byte(e);
+ end;
+if q<>invalid_packet then
+ begin append_byte(q div @"100); append_byte(q mod @"100);
+ end;
+end;
+
+@ The |build_packet| procedure is used to finish a character packet.
+If a previous packet for the same character extension exists, the new
+one is discarded; if the two packets are identical, as it occasionally
+occurs for raster files, this is done without an error message.
+
+@p procedure build_packet;
+var k,@!l:byte_pointer; {indices into |byte_mem|}
+begin if pckt_dup then
+ begin k:=pckt_start[pckt_prev+1]; l:=pckt_start[pckt_ptr];
+ if (byte_ptr-l)<>(k-pckt_start[pckt_prev]) then pckt_dup:=false;
+ while pckt_dup and(byte_ptr>l) do
+ begin flush_byte; decr(k);
+ if byte_mem[byte_ptr]<>byte_mem[k] then pckt_dup:=false;
+ end;
+ if (not pckt_dup)and(pckt_d_msg<10) then {stop telling after first 10 times}
+ begin print('---duplicate packet for character ',pckt_res:1);
+@.duplicate packet for character...@>
+ if pckt_ext<>0 then print('.',pckt_ext:1);
+ print_ln(' font ',cur_fnt:1);
+ incr(pckt_d_msg); mark_error;
+ if pckt_d_msg=10 then print_ln('---further messages suppressed.');
+ end;
+ byte_ptr:=l;
+ end
+else font_packet(cur_fnt)(pckt_res):=make_packet;
+end;
+
+@* Defining fonts.
+A detailed description of the \.{TFM} file format can be found in the
+documentation of \TeX, \MF, or \.{TFtoPL}. In order to read \.{TFM}
+files the program uses the binary file variable |tfm_file|.
+
+@<Glob...@>=
+@!tfm_file:byte_file; {a \.{TFM} file}
+@!tfm_ext:pckt_pointer; {extension for \.{TFM} files}
+
+@ @<Initialize predefined strings@>=
+id4(".")("T")("F")("M")(tfm_ext); {file name extension for \.{TFM} files}
+
+@ If no font directory has been specified, \.{\title} is supposed to use
+the default \.{TFM} directory, which is a system-dependent place where
+the \.{TFM} files for standard fonts are kept.
+The string variable |TFM_default_area| contains the name of this area.
+@^system dependencies@>
+
+@d TFM_default_area_name=='TeXfonts:' {change this to the correct name}
+@d TFM_default_area_name_length=9 {change this to the correct length}
+
+@<Glob...@>=
+@!TFM_default_area:packed array[1..TFM_default_area_name_length] of char;
+
+@ @<Set init...@>=
+TFM_default_area:=TFM_default_area_name;
+
+@ If a \.{TFM} file is badly malformed, we say |bad_font|; for a \.{TFM}
+file the |bad_tfm| procedure is used to give an error message which
+refers the user to \.{TFtoPL} and \.{PLtoTF}, and terminates \.{\title}.
+
+@<Error handling...@>=
+procedure bad_tfm;
+begin print('Bad TFM file'); print_font(cur_fnt); print_ln('!');
+@.Bad TFM file@>
+abort('Use TFtoPL/PLtoTF to diagnose and correct the problem');
+@.Use TFtoPL/PLtoTF@>
+end;
+@#
+procedure bad_font;
+begin new_line;
+case font_type(cur_fnt) of
+ defined_font: confusion(str_fonts);
+ loaded_font: bad_tfm;
+ @<Cases for |bad_font|@>@;@/
+ end; {there are no other cases}
+end;
+
+@ To prepare |tfm_file| for input we |reset| it.
+
+@<TFM: Open |tfm_file|@>=
+make_font_name(TFM_default_area_name_length)(TFM_default_area)(tfm_ext);
+reset(tfm_file,cur_name);
+if eof(tfm_file) then
+@^system dependencies@>
+ abort('---not loaded, TFM file can''t be opened!')
+@.TFM file can\'t be opened@>
+
+@ It turns out to be convenient to read four bytes at a time, when we
+are inputting from \.{TFM} files. The input goes into global variables
+|tfm_b0|, |tfm_b1|, |tfm_b2|, and |tfm_b3|, with |tfm_b0| getting the
+first byte and |tfm_b3| the fourth.
+
+@<Glob...@>=
+@!tfm_b0,@!tfm_b1,@!tfm_b2,@!tfm_b3: eight_bits; {four bytes input at once}
+
+@ Reading a \.{TFM} file should be done as efficient as possible for a
+particular system; on many systems this means that a large number of
+bytes from |tfm_file| is read into a buffer and will then be extracted
+from that buffer. In order to simplify such system dependent changes
+we use the \.{WEB} macro |tfm_byte| to extract the next \.{TFM} byte;
+this macro and |eof(tfm_file)| are used only in the |read_tfm_word|
+procedure which sets |tfm_b0| through |tfm_b3| to the next four bytes
+in the current \.{TFM} file. Here we give simple minded definitions in
+terms of standard \PASCAL.
+@^system dependencies@>
+@^optimization@>
+
+@d tfm_byte(#)==read(tfm_file,#) {read next \.{TFM} byte}
+
+@p procedure read_tfm_word;
+begin tfm_byte(tfm_b0); tfm_byte(tfm_b1);
+tfm_byte(tfm_b2); tfm_byte(tfm_b3);
+if eof(tfm_file) then bad_font;
+end;
+
+@ Here are three procedures used to check the consistency of font files:
+First, the |check_check_sum| procedure compares two check sum values: a
+warning is given if they differ and are both non-zero; if the second
+value is not zero it may replace the first one.
+Next, the |check_design_size| procedure compares two design size
+values: a warning is given if they differ by more than a small amount.
+Finally, the |check_width| function compares the character width value
+for character |cur_res| read from a \.{VF} or raster file for font
+|cur_fnt| with the value previously read from the \.{TFM} file and
+returns the width pointer for that value; a warning is given if the two
+values differ.
+
+@p procedure check_check_sum(@!c:int_32;@!u:boolean);
+ {compare |font_check(cur_fnt)| with |c|}
+begin if (c<>font_check(cur_fnt))and(c<>0) then
+ begin
+ if font_check(cur_fnt)<>0 then
+ begin new_line; print_ln('---beware: check sums do not agree! (',
+@.beware: check sums do not agree@>
+@.check sums do not agree@>
+ c:1,' vs. ',font_check(cur_fnt):1,')');
+ mark_harmless;
+ end;
+ if u then font_check(cur_fnt):=c;
+ end;
+end;
+@#
+procedure check_design_size(@!d:int_32);
+ {compare |font_design(cur_fnt)| with |d|}
+begin if abs(d-font_design(cur_fnt))>2 then
+ begin new_line; print_ln('---beware: design sizes do not agree! (',
+@.beware: design sizes do not agree@>
+@.design sizes do not agree@>
+ d:1,' vs. ',font_design(cur_fnt):1,')');
+ mark_error;
+ end;
+end;
+@#
+function check_width(w:int_32):width_pointer;
+ {compare |widths[font_width(cur_fnt)(cur_res)]| with |w|}
+var wp:width_pointer; {pointer to \.{TFM} width value}
+begin if (cur_res>=font_bc(cur_fnt))and(cur_res<=font_ec(cur_fnt)) then
+ wp:=font_width(cur_fnt)(cur_res)
+else wp:=invalid_width;
+if wp=invalid_width then
+ begin print_nl('Bad char ',cur_res:1);
+@.Bad char c@>
+ if cur_ext<>0 then print('.',cur_ext:1);
+ print(' font ',cur_fnt:1); print_font(cur_fnt);
+ abort(' (compare TFM file)');
+ end;
+if w<>widths[wp] then
+ begin new_line; print_ln('---beware: char widths do not agree! (',
+@.beware: char widths do not agree@>
+@.char widths do not agree@>
+ w:1,' vs. ',widths[wp]:1,')');
+ mark_error;
+ end;
+check_width:=wp;
+end;
+
+@ The |load_font| procedure reads the \.{TFM} file for a font and puts
+the data extracted into position |cur_fnt| of the font data arrays.
+
+@p procedure load_font; {reads a \.{TFM} file}
+var l:int_16; {loop index}
+@!p:char_pointer; {index into |char_widths|}
+@!q:width_pointer; {index into |widths|}
+@!bc,@!ec:int_15; {first and last character in this font}
+@!lh:int_15; {length of header in four byte words}
+@!nw:int_15; {number of words in width table}
+@!w:int_32; {a four byte integer}
+@<Variables for scaling computation@>@;
+begin print('TFM: font ',cur_fnt:1); print_font(cur_fnt);
+font_type(cur_fnt):=loaded_font;
+@<TFM: Open |tfm_file|@>;
+@<TFM: Read past the header data@>;
+@<TFM: Store character-width indices@>;
+@<TFM: Read and convert the width values@>;
+@<TFM: Convert character-width indices to character-width pointers@>;
+close_in(tfm_file);
+@!device @<Initialize device dependent data for a font@>@; @+ ecived @; @/
+d_print(' loaded at ',font_scaled(cur_fnt):1,' DVI units');
+print_ln('.');
+end;
+
+@ @<Glob...@>=
+@!tfm_conv:real; {\.{DVI} units per absolute \.{TFM} unit}
+
+@ We will use the following \.{WEB} macros to construct integers from
+two or four of the four bytes read by |read_tfm_word|.
+@^system dependencies@>
+
+@d tfm_b01(#)== {|tfm_b0..tfm_b1| as non-negative integer}
+if tfm_b0>127 then bad_font
+else #:=tfm_b0*256+tfm_b1
+@d tfm_b23(#)== {|tfm_b2..tfm_b3| as non-negative integer}
+if tfm_b2>127 then bad_font
+else #:=tfm_b2*256+tfm_b3
+@d tfm_squad(#)== {|tfm_b0..tfm_b3| as signed integer}
+if tfm_b0<128 then #:=((tfm_b0*256+tfm_b1)*256+tfm_b2)*256+tfm_b3
+else #:=(((tfm_b0-256)*256+tfm_b1)*256+tfm_b2)*256+tfm_b3
+@d tfm_uquad== {|tfm_b0..tfm_b3| as unsigned integer}
+(((tfm_b0*256+tfm_b1)*256+tfm_b2)*256+tfm_b3)
+
+@<TFM: Read past the header data@>=
+read_tfm_word; tfm_b23(lh);
+read_tfm_word; tfm_b01(bc); tfm_b23(ec);
+if ec<bc then
+ begin bc:=1; ec:=0;
+ end
+else if ec>255 then bad_font;
+read_tfm_word; tfm_b01(nw);
+if (nw=0)or(nw>256) then bad_font;
+for l:=-2 to lh do
+ begin read_tfm_word;
+ if l=1 then
+ begin tfm_squad(w); check_check_sum(w,true);
+ end
+ else if l=2 then
+ begin if tfm_b0>127 then bad_font;
+ check_design_size(round(tfm_conv*tfm_uquad));
+ end;
+ end
+
+@ The width indices for the characters are stored in positions |n_chars|
+through |n_chars-bc+ec| of the |char_widths| array; if characters on
+either end of the range |bc..ec| do not exist, they are ignored and the
+range is adjusted accordingly.
+
+@<TFM: Store character-width indices@>=
+read_tfm_word;
+while (tfm_b0=0)and(bc<=ec) do
+ begin incr(bc); read_tfm_word;
+ end;
+font_bc(cur_fnt):=bc; font_chars(cur_fnt):=n_chars-bc;
+if ec>=max_chars-font_chars(cur_fnt) then overflow(str_chars,max_chars);
+for l:=bc to ec do
+ begin char_widths[n_chars]:=tfm_b0; incr(n_chars); read_tfm_word;
+ end;
+while (char_widths[n_chars-1]=0)and(ec>=bc) do
+ begin decr(n_chars); decr(ec);
+ end;
+font_ec(cur_fnt):=ec
+
+@ The most important part of |load_font| is the width computation, which
+involves multiplying the relative widths in the \.{TFM} file by the
+scaling factor in the \.{DVI} file. A similar computation is used for
+dimensions read from \.{VF} files. This fixed-point multiplication must
+be done with precisely the same accuracy by all \.{DVI}-reading programs,
+in order to validate the assumptions made by \.{DVI}-writing programs
+like \TeX82.
+
+Let us therefore summarize what needs to be done. Each width in a \.{TFM}
+file appears as a four-byte quantity called a |fix_word|. A |fix_word|
+whose respective bytes are $(a,b,c,d)$ represents the number
+$$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr
+b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=0;\cr
+-16+b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=255.\cr}}\right.$$
+(No other choices of $a$ are allowed, since the magnitude of a \.{TFM}
+dimension must be less than 16.) We want to multiply this quantity by the
+integer~|z|, which is known to be less than $2^{27}$.
+If $|z|<2^{23}$, the individual multiplications $b\cdot z$, $c\cdot z$,
+$d\cdot z$ cannot overflow; otherwise we will divide |z| by 2, 4, 8, or
+16, to obtain a multiplier less than $2^{23}$, and we can compensate for
+this later. If |z| has thereby been replaced by $|z|^\prime=|z|/2^e$, let
+$\beta=2^{4-e}$; we shall compute
+$$\lfloor(b+c\cdot2^{-8}+d\cdot2^{-16})\,z^\prime/\beta\rfloor$$ if $a=0$,
+or the same quantity minus $\alpha=2^{4+e}z^\prime$ if $a=255$.
+This calculation must be done exactly, for the reasons stated above; the
+following program does the job in a system-independent way, assuming
+that arithmetic is exact on numbers less than $2^{31}$ in magnitude. We
+use \.{WEB} macros for various versions of this computation.
+@^system dependencies@>
+@^optimization@>
+
+@d tfm_fix3u== {convert |tfm_b1..tfm_b3| to an unsigned scaled dimension}
+(((((tfm_b3*z)div@'400)+(tfm_b2*z))div@'400)+(tfm_b1*z))div beta
+@#
+@d tfm_fix4(#)== {convert |tfm_b0..tfm_b3| to a scaled dimension}
+ #:=tfm_fix3u;
+ if tfm_b0>0 then if tfm_b0=255 then Decr(#)(alpha) else bad_font
+@d tfm_fix3(#)== {convert |tfm_b1..tfm_b3| to a scaled dimension}
+ #:=tfm_fix3u; @+ if tfm_b1>127 then Decr(#)(alpha)
+@d tfm_fix2== {convert |tfm_b2..tfm_b3| to a scaled dimension}
+ if tfm_b2>127 then tfm_b1:=255 else tfm_b1:=0;
+ tfm_fix3
+@d tfm_fix1== {convert |tfm_b3| to a scaled dimension}
+ if tfm_b3>127 then tfm_b1:=255 else tfm_b1:=0;
+ tfm_b2:=tfm_b1; tfm_fix3
+
+@<Variables for scaling computation@>=
+@!z:int_32; {multiplier}
+@!alpha:int_32; {correction for negative values}
+@!beta:int_15; {divisor}
+
+@ @<Replace |z| by $|z|^\prime$ and compute $\alpha,\beta$@>=
+alpha:=16;
+while z>=@'40000000 do
+ begin z:=z div 2; alpha:=alpha+alpha;
+ end;
+beta:=256 div alpha; alpha:=alpha*z
+
+@ The first width value, which indicates that a character does not exist
+and which must vanish, is converted to |invalid_width|; the other width
+values are scaled by |font_scaled(cur_fnt)| and converted to width
+pointers by |make_width|. The resulting width pointers are stored
+temporarily in the |char_widths| array, following the with indices.
+
+@<TFM: Read and convert the width values@>=
+if nw-1>max_chars-n_chars then overflow(str_chars,max_chars);
+if (tfm_b0<>0)or(tfm_b1<>0)or(tfm_b2<>0)or(tfm_b3<>0) then bad_font
+ else char_widths[n_chars]:=invalid_width;
+z:=font_scaled(cur_fnt);
+@<Replace |z|...@>;
+for p:=n_chars+1 to n_chars+nw-1 do
+ begin read_tfm_word; tfm_fix4(w);
+ char_widths[p]:=make_width(w);
+ end
+
+@ We simply translate the width indices into width pointers. In addition
+we initialize the character packets with the invalid packet.
+
+@<TFM: Convert character-width indices to character-width pointers@>=
+for p:=font_chars(cur_fnt)+bc to n_chars-1 do
+ begin q:=char_widths[n_chars+char_widths[p]]; char_widths[p]:=q;
+ char_packets[p]:=invalid_packet;
+ end
+
+@ When processing a font definition we put the data extracted from the
+\.{DVI} or \.{VF} file into position |nf| of the font data arrays and
+call |define_font| to obtain the internal font number for this font.
+The parameter |load| is true if the \.{TFM} file should be loaded.
+
+@p function define_font(@!load:boolean):font_number;
+var save_fnt:font_number; {used to save |cur_fnt|}
+begin save_fnt:=cur_fnt; {save}
+cur_fnt:=0;
+while (font_name(cur_fnt)<>font_name(nf))or@|
+ (font_scaled(cur_fnt)<>font_scaled(nf)) do incr(cur_fnt);
+d_print(' => ',cur_fnt:1); print_font(cur_fnt);
+if cur_fnt<nf then
+ begin check_check_sum(font_check(nf),true);
+ check_design_size(font_design(nf));
+ @!debug if font_type(cur_fnt)=defined_font then print(' defined')
+ else print(' loaded');
+ print(' previously');
+ gubed@;
+ end
+else begin if nf=max_fonts then overflow(str_fonts,max_fonts);
+ incr(nf); font_font(cur_fnt):=invalid_font;
+ font_type(cur_fnt):=defined_font;
+ d_print(' defined');
+ end;
+print_ln('.');
+if load and(font_type(cur_fnt)=defined_font) then load_font;
+define_font:=cur_fnt;
+cur_fnt:=save_fnt; {restore}
+end;
+
+@* Low-level DVI input routines.
+The program uses the binary file variable |dvi_file| for its main input
+file; |dvi_loc| is the number of the byte about to be read next from
+|dvi_file|.
+
+@<Glob...@>=
+@!dvi_file:byte_file; {the stuff we are \.{\title}ing}
+@!dvi_loc:int_32; {where we are about to look, in |dvi_file|}
+
+@ If the \.{DVI} file is badly malformed, we say |bad_dvi|; this
+procedure gives an error message which refers the user to \.{DVItype},
+and terminates \.{\title}.
+
+@<Error handling...@>=
+procedure bad_dvi;
+begin new_line; print_ln('Bad DVI file: loc=',dvi_loc:1,'!');
+@.Bad DVI file@>
+print(' Use DVItype with output level');
+@.Use DVItype@>
+if random_reading then print('=4') @+ else print('<4');
+abort('to diagnose the problem');
+end;
+
+@ To prepare |dvi_file| for input, we |reset| it.
+
+@<Open input file(s)@>=
+reset(dvi_file); {prepares to read packed bytes from |dvi_file|}
+dvi_loc:=0;
+
+@ Reading the \.{DVI} file should be done as efficient as possible for a
+particular system; on many systems this means that a large number of
+bytes from |dvi_file| is read into a buffer and will then be extracted
+from that buffer. In order to simplify such system dependent changes
+we use a pair of \.{WEB} macros: |dvi_byte| extracts the next \.{DVI}
+byte and |dvi_eof| is |true| if we have reached the end of the \.{DVI}
+file. Here we give simple minded definitions for these macros in terms
+of standard \PASCAL.
+@^system dependencies@>
+@^optimization@>
+
+@d dvi_eof == eof(dvi_file) {has the \.{DVI} file been exhausted?}
+@d dvi_byte(#) ==
+ if dvi_eof then bad_dvi
+ else read(dvi_file,#) {obtain next \.{DVI} byte}
+
+@ Next we come to the routines that are used only if |random_reading| is
+|true|. The driver program below needs two such routines: |dvi_length| should
+compute the total number of bytes in |dvi_file|, possibly also
+causing |eof(dvi_file)| to be true; and |dvi_move(n)| should position
+|dvi_file| so that the next |dvi_byte| will read byte |n|, starting with
+|n=0| for the first byte in the file.
+@^system dependencies@>
+
+Such routines are, of course, highly system dependent. They are implemented
+here in terms of two assumed system routines called |set_pos| and |cur_pos|.
+The call |set_pos(f,n)| moves to item |n| in file |f|, unless |n| is
+negative or larger than the total number of items in |f|; in the latter
+case, |set_pos(f,n)| moves to the end of file |f|.
+The call |cur_pos(f)| gives the total number of items in |f|, if
+|eof(f)| is true; we use |cur_pos| only in such a situation.
+
+@p function dvi_length:int_32;
+begin set_pos(dvi_file,-1); dvi_length:=cur_pos(dvi_file);
+end;
+@#
+procedure dvi_move(@!n:int_32);
+begin set_pos(dvi_file,n); dvi_loc:=n;
+end;
+
+@ We need seven simple functions to read the next byte or bytes
+from |dvi_file|.
+
+@p function dvi_sbyte:int_8; {returns the next byte, signed}
+@!begin_byte(dvi_byte); incr(dvi_loc); comp_sbyte(dvi_sbyte);
+end;
+@#
+function dvi_ubyte:int_8u; {returns the next byte, unsigned}
+@!begin_byte(dvi_byte); incr(dvi_loc); comp_ubyte(dvi_ubyte);
+end;
+@#
+function dvi_spair:int_16; {returns the next two bytes, signed}
+@!begin_pair(dvi_byte); Incr(dvi_loc)(2); comp_spair(dvi_spair);
+end;
+@#
+function dvi_upair:int_16u; {returns the next two bytes, unsigned}
+@!begin_pair(dvi_byte); Incr(dvi_loc)(2); comp_upair(dvi_upair);
+end;
+@#
+function dvi_strio:int_24; {returns the next three bytes, signed}
+@!begin_trio(dvi_byte); Incr(dvi_loc)(3); comp_strio(dvi_strio);
+end;
+@#
+function dvi_utrio:int_24u; {returns the next three bytes, unsigned}
+@!begin_trio(dvi_byte); Incr(dvi_loc)(3); comp_utrio(dvi_utrio);
+end;
+@#
+function dvi_squad:int_32; {returns the next four bytes, signed}
+@!begin_quad(dvi_byte); Incr(dvi_loc)(4); comp_squad(dvi_squad);
+end;
+
+@ Three other functions are used in cases where a four byte integer
+(which is always signed) must have a non-negative value, a positive
+value, or is a pointer which must be either positive or |=-1|.
+
+@p function dvi_uquad:int_31; {result must be non-negative}
+var x:int_32;
+begin x:=dvi_squad; if x<0 then bad_dvi
+else dvi_uquad:=x;
+end;
+@#
+function dvi_pquad:int_31; {result must be positive}
+var x:int_32;
+begin x:=dvi_squad; if x<=0 then bad_dvi
+else dvi_pquad:=x;
+end;
+@#
+function dvi_pointer:int_32; {result must be positive or |=-1|}
+var x:int_32;
+begin x:=dvi_squad; if (x<=0)and(x<>-1) then bad_dvi
+else dvi_pointer:=x;
+end;
+
+@ Given the structure of the \.{DVI} commands it is fairly obvious
+that their interpretation consists of two steps: First zero to four
+bytes are read in order to obtain the value of the first parameter
+(e.g., zero bytes for |set_char_0|, four bytes for |set4|); then,
+depending on the command class, a specific action is performed (e.g.,
+typeset a character but don't move the reference point for |put1..put4|).
+
+The \.{DVItype} program uses large case statements for both steps;
+unfortunately some \PASCAL\ compilers fail to implement large case
+statements efficiently -- in particular those as the one used in the
+|first_par| function of \.{DVItype}. Here we use a pair of look up tables:
+|dvi_par| determines how to obtain the value of the first parameter, and
+|dvi_cl| determines the command class.
+
+A slight complication arises from the fact that we want to decompose the
+character code of each character to be typset into a residue
+|0<=char_res<256| and extension: |char_code=char_res+256*char_ext|;
+the \.{TFM} widths as well as the pixel widths for a given resolution
+are the same for all characters in a font with the same residue.
+
+@d two_cases(#)==#,#+1
+@d three_cases(#)==#,#+1,#+2
+@d five_cases(#)==#,#+1,#+2,#+3,#+4
+
+@ First we define the values used as array elements of |dvi_par|; we
+distinguish between pure numbers and dimensions because dimensions read
+from a \.{VF} file must be scaled.
+
+@d char_par=0 {character for \\{set} and |put|}
+@d no_par=1 {no parameter}
+@d dim1_par=2 {one-byte signed dimension}
+@d num1_par=3 {one-byte unsigned number}
+@d dim2_par=4 {two-byte signed dimension}
+@d num2_par=5 {two-byte unsigned number}
+@d dim3_par=6 {three-byte signed dimension}
+@d num3_par=7 {three-byte unsigned number}
+@d dim4_par=8 {four-byte signed dimension}
+@d num4_par=9 {four-byte signed number}
+@d numu_par=10 {four-byte non-negative number}
+@d rule_par=11 {dimensions for |set_rule| and |put_rule|}
+@d fnt_par=12 {font for |fnt_num| commands}
+@d max_par=12 {largest possible value}
+
+@<Types...@>=
+@!cmd_par=char_par..max_par;
+
+@ Here we declare the array |dvi_par|.
+
+@<Globals...@>=
+@!dvi_par:packed array [eight_bits] of cmd_par;
+
+@ And here we initialize it.
+
+@<Set init...@>=
+for i:=0 to put1+3 do dvi_par[i]:=char_par;@/
+for i:=nop to 255 do dvi_par[i]:=no_par;@/
+dvi_par[set_rule]:=rule_par; dvi_par[put_rule]:=rule_par;@/
+dvi_par[right1]:=dim1_par; dvi_par[right1+1]:=dim2_par;
+dvi_par[right1+2]:=dim3_par; dvi_par[right1+3]:=dim4_par;@/
+for i:=fnt_num_0 to fnt_num_0+63 do dvi_par[i]:=fnt_par;@/
+dvi_par[fnt1]:=num1_par; dvi_par[fnt1+1]:=num2_par;
+dvi_par[fnt1+2]:=num3_par; dvi_par[fnt1+3]:=num4_par;@/
+dvi_par[xxx1]:=num1_par; dvi_par[xxx1+1]:=num2_par;
+dvi_par[xxx1+2]:=num3_par; dvi_par[xxx1+3]:=numu_par;@/
+for i:=0 to 3 do
+ begin dvi_par[i+w1]:=dvi_par[i+right1];
+ dvi_par[i+x1]:=dvi_par[i+right1];
+ dvi_par[i+down1]:=dvi_par[i+right1];
+ dvi_par[i+y1]:=dvi_par[i+right1];
+ dvi_par[i+z1]:=dvi_par[i+right1];
+ dvi_par[i+fnt_def1]:=dvi_par[i+fnt1];
+ end;
+
+@ Next we define the values used as array elements of |dvi_cl|;
+several \.{DVI} commands (e.g., |nop|, |bop|, |eop|, |pre|, |post|) will
+always be treated separately and are therfore assigned to the invalid
+class here.
+
+@d char_cl=0
+@d rule_cl=char_cl+1
+@d xxx_cl=char_cl+2
+@d push_cl=3
+@d pop_cl=4
+@d w0_cl=5
+@d x0_cl=w0_cl+1
+@d right_cl=w0_cl+2
+@d w_cl=w0_cl+3
+@d x_cl=w0_cl+4
+@d y0_cl=10
+@d z0_cl=y0_cl+1
+@d down_cl=y0_cl+2
+@d y_cl=y0_cl+3
+@d z_cl=y0_cl+4
+@d fnt_cl=15
+@d fnt_def_cl=16
+@d invalid_cl=17
+@d max_cl=invalid_cl {largest possible value}
+
+@<Types...@>=
+@!cmd_cl=char_cl..max_cl;
+
+@ Here we declare the array |dvi_cl|.
+
+@<Globals...@>=
+@!dvi_cl:packed array [eight_bits] of cmd_cl;
+
+@ And here we initialize it.
+
+@<Set init...@>=
+for i:=set_char_0 to put1+3 do dvi_cl[i]:=char_cl;
+dvi_cl[set_rule]:=rule_cl; dvi_cl[put_rule]:=rule_cl;@/
+dvi_cl[nop]:=invalid_cl;
+dvi_cl[bop]:=invalid_cl; dvi_cl[eop]:=invalid_cl;@/
+dvi_cl[push]:=push_cl; dvi_cl[pop]:=pop_cl;@/
+dvi_cl[w0]:=w0_cl; dvi_cl[x0]:=x0_cl;@/
+dvi_cl[y0]:=y0_cl; dvi_cl[z0]:=z0_cl;@/
+for i:=0 to 3 do
+ begin dvi_cl[i+right1]:=right_cl;
+ dvi_cl[i+w1]:=w_cl;
+ dvi_cl[i+x1]:=x_cl;@/
+ dvi_cl[i+down1]:=down_cl;
+ dvi_cl[i+y1]:=y_cl;
+ dvi_cl[i+z1]:=z_cl;@/
+ dvi_cl[i+xxx1]:=xxx_cl;
+ dvi_cl[i+fnt_def1]:=fnt_def_cl;
+ end;
+for i:=fnt_num_0 to fnt1+3 do dvi_cl[i]:=fnt_cl;
+for i:=pre to 255 do dvi_cl[i]:=invalid_cl;
+
+@ A few small arrays are used to generate \.{DVI} commands.
+
+@<Glob...@>=
+@!dvi_char_cmd:array[boolean] of eight_bits; {|put1| and |set1|}
+@!dvi_rule_cmd:array[boolean] of eight_bits; {|put_rule| and |set_rule|}
+@!dvi_right_cmd:array[right_cl..x_cl] of eight_bits; {|right1|, |w1|, and |x1|}
+@!dvi_down_cmd:array[down_cl..z_cl] of eight_bits; {|down1|, |y1|, and |z1|}
+
+@ @<Set init...@>=
+dvi_char_cmd[false]:=put1;
+dvi_char_cmd[true]:=set1;@/
+dvi_rule_cmd[false]:=put_rule;
+dvi_rule_cmd[true]:=set_rule;@/
+dvi_right_cmd[right_cl]:=right1;
+dvi_right_cmd[w_cl]:=w1;
+dvi_right_cmd[x_cl]:=x1;@/
+dvi_down_cmd[down_cl]:=down1;
+dvi_down_cmd[y_cl]:=y1;
+dvi_down_cmd[z_cl]:=z1;
+
+@ The global variables |cur_cmd|, |cur_parm| and |cur_class| are used
+for the current \.{DVI} command, its first parameter (if any), and its
+command class respectively.
+
+@<Glob...@>=
+@!cur_cmd:eight_bits; {current \.{DVI} command byte}
+@!cur_parm:int_32; {its first parameter (if any)}
+@!cur_class:cmd_cl; {its class}
+
+@ When typesetting a character or rule, the boolean variable |cur_upd|
+is |true| for \\{set} commands, |false| for |put| commands.
+
+@<Glob...@>=
+@!cur_cp:char_pointer; {|char_widths| index for the current character}
+@!cur_wp:width_pointer; {width pointer of the current character}
+@!cur_upd:boolean; {is this a \\{set} or |set_rule| command ?}
+@!cur_v_dimen:int_32; {a vertical dimension}
+@!cur_h_dimen:int_32; {a horizontal dimension}
+
+@ @<Set init...@>=
+cur_cp:=0; cur_wp:=invalid_width; {so they can be saved and restored!}
+
+@ The |dvi_first_par| procedure first reads \.{DVI} command bytes into
+|cur_cmd| until |cur_cmd<>nop|; then |cur_parm| is set to the value of
+the first parameter (if any) and |cur_class| to the command class.
+
+@d set_cur_char(#)== {set up |cur_res|, |cur_ext|, and |cur_upd|}
+begin cur_ext:=0;
+if cur_cmd<set1 then
+ begin cur_res:=cur_cmd; cur_upd:=true
+ end
+else begin cur_res:=#; cur_upd:=(cur_cmd<put1);
+ Decr(cur_cmd)(dvi_char_cmd[cur_upd]);
+ while cur_cmd>0 do
+ begin if cur_cmd=3 then if cur_res>127 then cur_ext:=-1;
+ cur_ext:=cur_ext*256+cur_res; cur_res:=#; decr(cur_cmd);
+ end;
+ end;
+end
+
+@p procedure dvi_first_par;
+begin repeat cur_cmd:=dvi_ubyte;
+until cur_cmd<>nop; {skip over |nop|s}
+case dvi_par[cur_cmd] of
+char_par: set_cur_char(dvi_ubyte);
+no_par: do_nothing;
+dim1_par: cur_parm:=dvi_sbyte;
+num1_par: cur_parm:=dvi_ubyte;
+dim2_par: cur_parm:=dvi_spair;
+num2_par: cur_parm:=dvi_upair;
+dim3_par: cur_parm:=dvi_strio;
+num3_par: cur_parm:=dvi_utrio;
+two_cases(dim4_par): cur_parm:=dvi_squad; {|dim4_par| and |num4_par|}
+numu_par: cur_parm:=dvi_uquad;
+rule_par:
+ begin cur_v_dimen:=dvi_squad; cur_h_dimen:=dvi_squad;
+ cur_upd:=(cur_cmd=set_rule);
+ end;
+fnt_par:cur_parm:=cur_cmd-fnt_num_0;
+end; {there are no other cases}
+cur_class:=dvi_cl[cur_cmd];
+end;
+
+@ The global variable |dvi_nf| is used for the number of different
+\.{DVI} fonts defined so far; their external font numbers (as extracted
+from the \.{DVI} file) are stored in the array |dvi_e_fnts|, the
+corresponding internal font numbers used internally by \.{\title} are
+stored in the array |dvi_i_fnts|.
+
+@<Glob...@>=
+@!dvi_e_fnts:array[font_number] of int_32; {external font numbers}
+@!dvi_i_fnts:array[font_number] of font_number; {corresponding
+ internal font numbers}
+@!dvi_nf:font_number; {number of \.{DVI} fonts defined so far}
+
+@ @<Set ini...@>=
+dvi_nf:=0;
+
+@ The |dvi_font| procedure sets |cur_fnt| to the internal font number
+corresponding to the external font number |cur_parm| (or aborts the
+program if such a font was never defined).
+
+@p procedure dvi_font; {computes |cur_fnt| corresponding to |cur_parm|}
+var f:font_number; {where the font is sought}
+begin @<DVI: Locate font |cur_parm|@>;
+if f=dvi_nf then bad_dvi;
+cur_fnt:=dvi_i_fnts[f];
+if font_type(cur_fnt)=defined_font then load_font;
+end;
+
+@ @<DVI: Locate font |cur_parm|@>=
+f:=0; dvi_e_fnts[dvi_nf]:=cur_parm;
+while cur_parm<>dvi_e_fnts[f] do incr(f)
+
+@ Finally the |dvi_do_font| procedure is called when one of the command
+|fnt_def1..fnt_def4| and its first parameter have been read from the
+\.{DVI} file; the argument indicates whether this should be the second
+definition of the font (|true|) or not (|false|).
+
+@p procedure dvi_do_font(@!second:boolean);
+var f:font_number; {where the font is sought}
+@!k:int_15; {general purpose variable}
+begin print('DVI: font ',cur_parm:1);
+@<DVI: Locate font |cur_parm|@>;
+if (f=dvi_nf)=second then bad_dvi;
+font_check(nf):=dvi_squad;
+font_scaled(nf):=dvi_pquad;
+font_design(nf):=dvi_pquad;
+k:=dvi_ubyte; pckt_room(1); append_byte(k);
+Incr(k)(dvi_ubyte); pckt_room(k);
+while k>0 do begin append_byte(dvi_ubyte); decr(k);
+ end;
+font_name(nf):=make_packet; {the font area plus name}
+dvi_i_fnts[dvi_nf]:=define_font(false);
+if not second then
+ begin if dvi_nf=max_fonts then overflow(str_fonts,max_fonts);
+ incr(dvi_nf);
+ end
+else if dvi_i_fnts[f]<>dvi_i_fnts[dvi_nf] then bad_dvi;
+end;
+
+@* Low-level VF input routines.
+A detailed description of the \.{VF} file format can be found in the
+documentation of \.{VFtoVP}; here we just define symbolic names for
+some of the \.{VF} command bytes.
+
+@d long_char=242 {\.{VF} command for general character packet}
+@#
+@d vf_id=202 {identifies \.{VF} files}
+
+@ The program uses the binary file variable |vf_file| for input from
+\.{VF} files; |vf_loc| is the number of the byte about to be read next
+from |vf_file|.
+
+@<Glob...@>=
+@!vf_file:byte_file; {a \.{VF} file}
+@!vf_loc:int_32; {where we are about to look, in |vf_file|}
+@!vf_limit:int_32; {value of |vf_loc| at end of a character packet}
+@!vf_ext:pckt_pointer; {extension for \.{VF} files}
+@!vf_cur_fnt:font_number; {current font number in a \.{VF} file}
+
+@ @<Initialize predefined strings@>=
+id3(".")("V")("F")(vf_ext); {file name extension for \.{VF} files}
+
+@ If a \.{VF} file is badly malformed, we say |bad_font|; this procedure
+gives an error message which refers the user to \.{VFtoVP} and \.{VPtoVF},
+and terminates \.{\title}.
+
+@<Cases for |bad_font|@>=
+vf_font_type: begin print('Bad VF file'); print_font(cur_fnt);
+@.Bad VF file@>
+ print_ln(' loc=',vf_loc:1);
+ abort('Use VFtoVP/VPtoVF to diagnose and correct the problem');
+@.Use VFtoVP/VPtoVF@>
+ end;
+
+@ If no font directory has been specified, \.{\title} is supposed to use
+the default \.{VF} directory, which is a system-dependent place where
+the \.{VF} files for standard fonts are kept.
+The string variable |VF_default_area| contains the name of this area.
+@^system dependencies@>
+
+@d VF_default_area_name=='TeXvfonts:' {change this to the correct name}
+@d VF_default_area_name_length=10 {change this to the correct length}
+
+@<Glob...@>=
+@!VF_default_area:packed array[1..VF_default_area_name_length] of char;
+
+@ @<Set init...@>=
+VF_default_area:=VF_default_area_name;
+
+@ To prepare |vf_file| for input we |reset| it.
+
+@<VF: Open |vf_file| or |goto not_found|@>=
+make_font_name(VF_default_area_name_length)(VF_default_area)(vf_ext);
+reset(vf_file,cur_name);
+if eof(vf_file) then
+@^system dependencies@>
+ goto not_found;
+vf_loc:=0
+
+@ Reading a \.{VF} file should be done as efficient as possible for a
+particular system; on many systems this means that a large number of
+bytes from |vf_file| is read into a buffer and will then be extracted
+from that buffer. In order to simplify such system dependent changes
+we use a pair of \.{WEB} macros: |vf_byte| extracts the next \.{VF}
+byte and |vf_eof| is |true| if we have reached the end of the \.{VF}
+file. Here we give simple minded definitions for these macros in terms
+of standard \PASCAL.
+@^system dependencies@>
+@^optimization@>
+
+@d vf_eof == eof(vf_file) {has the \.{VF} file been exhausted?}
+@d vf_byte(#) ==
+ if vf_eof then bad_font
+ else read(vf_file,#) {obtain next \.{VF} byte}
+
+@ We need several simple functions to read the next byte or bytes
+from |vf_file|.
+
+@p function vf_ubyte:int_8u; {returns the next byte, unsigned}
+@!begin_byte(vf_byte); incr(vf_loc); comp_ubyte(vf_ubyte);
+end;
+@#
+function vf_upair:int_16u; {returns the next two bytes, unsigned}
+@!begin_pair(vf_byte); Incr(vf_loc)(2); comp_upair(vf_upair);
+end;
+@#
+function vf_strio:int_24; {returns the next three bytes, signed}
+@!begin_trio(vf_byte); Incr(vf_loc)(3); comp_strio(vf_strio);
+end;
+@#
+function vf_utrio:int_24u; {returns the next three bytes, unsigned}
+@!begin_trio(vf_byte); Incr(vf_loc)(3); comp_utrio(vf_utrio);
+end;
+@#
+function vf_squad:int_32; {returns the next four bytes, signed}
+@!begin_quad(vf_byte); Incr(vf_loc)(4); comp_squad(vf_squad);
+end;
+
+@ All dimensions in a \.{VF} file, except the design sizes of a virtual
+font and its local fonts, are |fix_word|s that must be scaled in exactly
+the same way as the character widths from a \.{TFM} file; we can use the
+same code, but this time |z|, |alpha|, and |beta| are global variables.
+
+@<Glob...@>=
+@<Variables for scaling computation@>@;
+
+@ We need five functions to read the next byte or bytes and convert a
+|fix_word| to a scaled dimension.
+
+@p function vf_fix1:int_32; {returns the next byte as scaled value}
+var x:int_32; {accumulator}
+begin vf_byte(tfm_b3); incr(vf_loc);
+tfm_fix1(x); vf_fix1:=x;
+end;
+@#
+function vf_fix2:int_32; {returns the next two bytes as scaled value}
+var x:int_32; {accumulator}
+begin vf_byte(tfm_b2); vf_byte(tfm_b3); Incr(vf_loc)(2);
+tfm_fix2(x); vf_fix2:=x;
+end;
+@#
+function vf_fix3:int_32; {returns the next three bytes as scaled value}
+var x:int_32; {accumulator}
+begin vf_byte(tfm_b1); vf_byte(tfm_b2); vf_byte(tfm_b3);
+Incr(vf_loc)(3);@/
+tfm_fix3(x); vf_fix3:=x;
+end;
+@#
+function vf_fix3u:int_32; {returns the next three bytes as scaled value}
+begin vf_byte(tfm_b1); vf_byte(tfm_b2); vf_byte(tfm_b3);
+Incr(vf_loc)(3);@/
+vf_fix3u:=tfm_fix3u;
+end;
+@#
+function vf_fix4:int_32; {returns the next four bytes as scaled value}
+var x:int_32; {accumulator}
+begin vf_byte(tfm_b0); vf_byte(tfm_b1); vf_byte(tfm_b2); vf_byte(tfm_b3);
+Incr(vf_loc)(4);@/
+tfm_fix4(x); vf_fix4:=x;
+end;
+
+@ Three other functions are used in cases where the result must have a
+non-negative value or a positive value.
+
+@p function vf_uquad:int_31; {result must be non-negative}
+var x:int_32;
+begin x:=vf_squad; if x<0 then bad_font @+ else vf_uquad:=x;
+end;
+@#
+function vf_pquad:int_31; {result must be positive}
+var x:int_32;
+begin x:=vf_squad; if x<=0 then bad_font @+ else vf_pquad:=x;
+end;
+@#
+function vf_fixp:int_31; {result must be positive}
+var x:int_32; {accumulator}
+begin vf_byte(tfm_b0); vf_byte(tfm_b1); vf_byte(tfm_b2); vf_byte(tfm_b3);
+Incr(vf_loc)(4);@/
+if tfm_b0>0 then bad_font;
+vf_fixp:=tfm_fix3u;
+end;
+
+@ The |vf_first_par| procedure first reads a \.{VF} command byte into
+|cur_cmd|; then |cur_parm| is set to the value of the first parameter
+(if any) and |cur_class| to the command class.
+
+@d set_cur_wp_end(#)== if cur_wp=invalid_width then #
+@d set_cur_wp(#)== {set |cur_wp| to the char's width pointer}
+cur_wp:=invalid_width;
+if #<>invalid_font then
+ if (cur_res>=font_bc(#))and(cur_res<=font_ec(#)) then
+ begin cur_cp:=font_chars(#)+cur_res; cur_wp:=char_widths[cur_cp];
+ end;
+set_cur_wp_end
+
+@p procedure vf_first_par;
+begin cur_cmd:=vf_ubyte;
+case dvi_par[cur_cmd] of
+char_par:
+ begin set_cur_char(vf_ubyte); set_cur_wp(vf_cur_fnt)(bad_font);
+ end;
+no_par: do_nothing;
+dim1_par: cur_parm:=vf_fix1;
+num1_par: cur_parm:=vf_ubyte;
+dim2_par: cur_parm:=vf_fix2;
+num2_par: cur_parm:=vf_upair;
+dim3_par: cur_parm:=vf_fix3;
+num3_par: cur_parm:=vf_utrio;
+dim4_par: cur_parm:=vf_fix4;
+num4_par: cur_parm:=vf_squad;
+numu_par: cur_parm:=vf_uquad;
+rule_par:
+ begin cur_v_dimen:=vf_fix4; cur_h_dimen:=vf_fix4;
+ cur_upd:=(cur_cmd=set_rule);
+ end;
+fnt_par:cur_parm:=cur_cmd-fnt_num_0;
+end; {there are no other cases}
+cur_class:=dvi_cl[cur_cmd];
+end;
+
+@ For a virtual font we set |font_type(f):=vf_font_type|; in this case
+|font_font(f)| is the default font for character packets from virtual
+font~|f|.
+@^font types@>
+
+The global variable |vf_nf| is used for the number of different local
+fonts defined in a \.{VF} file so far; their external font numbers (as
+extracted from the \.{VF} file) are stored in the array |vf_e_fnts|, the
+corresponding internal font numbers used internally by \.{\title} are
+stored in the array |vf_i_fnts|.
+
+@<Glob...@>=
+@!vf_e_fnts:array[font_number] of int_32; {external font numbers}
+@!vf_i_fnts:array[font_number] of font_number; {corresponding
+ internal font numbers}
+@!vf_nf:font_number; {number of local fonts defined so far}
+@!lcl_nf:font_number; {largest |vf_nf| value for any \.{VF} file}
+
+@ @<Set init...@>=
+lcl_nf:=0;
+
+@ The |vf_font| procedure sets |vf_cur_fnt| to the internal font number
+corresponding to the external font number |cur_parm| (or aborts the
+program if such a font was never defined).
+
+@p procedure vf_font; {computes |vf_cur_fnt| corresponding to |cur_parm|}
+var f:font_number; {where the font is sought}
+begin @<VF: Locate font |cur_parm|@>;
+if f=vf_nf then bad_font;
+vf_cur_fnt:=vf_i_fnts[f];
+end;
+
+@ @<VF: Locate font |cur_parm|@>=
+f:=0; vf_e_fnts[vf_nf]:=cur_parm;
+while cur_parm<>vf_e_fnts[f] do incr(f)
+
+@ Finally the |vf_do_font| procedure is called when one of the command
+|fnt_def1..fnt_def4| and its first parameter have been read from the
+\.{VF} file.
+
+@p procedure vf_do_font;
+var f:font_number; {where the font is sought}
+@!k:int_15; {general purpose variable}
+begin print('VF: font ',cur_parm:1);@/
+@<VF: Locate font |cur_parm|@>;
+if f<>vf_nf then bad_font;
+font_check(nf):=vf_squad;
+font_scaled(nf):=vf_fixp;
+font_design(nf):=round(tfm_conv*vf_pquad);
+k:=vf_ubyte; pckt_room(1); append_byte(k);
+Incr(k)(vf_ubyte); pckt_room(k);
+while k>0 do begin append_byte(vf_ubyte); decr(k);
+ end;
+font_name(nf):=make_packet; {the font area plus name}
+vf_i_fnts[vf_nf]:=define_font(true);
+if vf_nf=lcl_nf then
+ if lcl_nf=max_fonts then overflow(str_fonts,max_fonts)
+ else incr(lcl_nf);
+incr(vf_nf);
+end;
+
+@* Reading VF files.
+The |do_vf| function attempts to read the \.{VF} file for a font and
+returns |false| if the \.{VF} file could not be found; otherwise the
+font type is changed to |vf_font_type|.
+
+@p function do_vf:boolean; {read a \.{VF} file}
+label reswitch,done,not_found,exit;
+var temp_int:int_32; {integer for temporary variables}
+@!temp_byte:int_8u; {byte for temporary variables}
+@!k:byte_pointer; {index into |byte_mem|}
+@!l:int_15; {general purpose variable}
+@!save_ext:int_24; {used to save |cur_ext|}
+@!save_res:int_8u; {used to save |cur_res|}
+@!save_cp:width_pointer; {used to save |cur_cp|}
+@!save_wp:width_pointer; {used to save |cur_wp|}
+@!save_upd:boolean; {used to save |cur_upd|}
+@!vf_wp:width_pointer; {width pointer for the current character packet}
+@!vf_fnt:font_number; {current font in the current character packet}
+@!move_zero:boolean; {|true| if rule 1 is used}
+@!last_pop:boolean; {|true| if final |pop| has been manufactured}
+begin @<VF: Open |vf_file| or |goto not_found|@>;
+save_ext:=cur_ext; save_res:=cur_res; save_cp:=cur_cp; save_wp:=cur_wp;
+save_upd:=cur_upd; {save}
+font_type(cur_fnt):=vf_font_type;@/
+@<VF: Process the preamble@>;@/
+@<VF: Process the font definitions@>;@/
+while cur_cmd<=long_char do @<VF: Build a character packet@>;
+if cur_cmd<>post then bad_font;
+@!debug print('VF file for font ',cur_fnt:1); print_font(cur_fnt);
+print_ln(' loaded.');
+gubed @;@/
+close_in(vf_file);
+cur_ext:=save_ext; cur_res:=save_res; cur_cp:=save_cp; cur_wp:=save_wp;
+cur_upd:=save_upd; {restore}
+do_vf:=true; return;
+not_found:do_vf:=false;
+exit:end;
+
+@ @<VF: Process the preamble@>=
+if vf_ubyte<>pre then bad_font;
+if vf_ubyte<>vf_id then bad_font;
+temp_byte:=vf_ubyte; pckt_room(temp_byte);
+for l:=1 to temp_byte do append_byte(vf_ubyte);
+print('VF file: '''); print_packet(new_packet); print(''',');
+flush_packet;@/
+check_check_sum(vf_squad,false);
+check_design_size(round(tfm_conv*vf_pquad));@/
+z:=font_scaled(cur_fnt);
+@<Replace |z|...@>;@/
+print_nl(' for font ',cur_fnt:1); print_font(cur_fnt); print_ln('.')
+
+@ @<VF: Process the font definitions@>=
+vf_i_fnts[0]:=invalid_font; vf_nf:=0;@/
+cur_cmd:=vf_ubyte;
+while (cur_cmd>=fnt_def1)and(cur_cmd<=fnt_def1+3) do
+ begin case cur_cmd-fnt_def1 of
+ 0: cur_parm:=vf_ubyte;
+ 1: cur_parm:=vf_upair;
+ 2: cur_parm:=vf_utrio;
+ 3: cur_parm:=vf_squad;
+ end; {there are no other cases}
+ vf_do_font;
+ cur_cmd:=vf_ubyte;
+ end;
+font_font(cur_fnt):=vf_i_fnts[0]
+
+@ The \.{VF} format specifies that the interpretation of each packet
+begins with |w=x=y=z=0|; any |w0|, |x0|, |y0|, or |z0| command using
+these initial values will be ignored.
+
+@<Types...@>=
+@!vf_state=array[0..1,0..1] of boolean; {state of |w|, |x|, |y|, and |z|}
+
+@ As implied by the \.{VF} format the \.{DVI} commands read from the
+\.{VF} file are enclosed by |push| and |pop|; as we read \.{DVI}
+commands and append them to |byte_mem|, we perform a set of
+transformations in order to simplify the resulting packet: Let |zero| be
+any of the commands |put|, |put_rule|, |fnt_num|, |fnt|, or |xxx| which
+all leave the current position on the page unchanged, let |move| be any
+of the horizontal or vertical movement commands |right1..z4|, and let
+|any| be any sequence of commands containing |push| and |pop| in
+properly nested pairs; whenever possible we apply one of the following
+transformation rules: $$\def\n#1:{\hbox to 3cm{\hfil#1:}}
+\leqalignno{
+\hbox{|push| |zero|}&\RA\hbox{|zero| |push|}&\n1:\cr
+\hbox{|move| |pop|}&\RA\hbox{|pop|}&\n2:\cr
+\hbox{|push| |pop|}&\RA{}&\n3:\cr
+\hbox{|push| |set_char| |pop|}&\RA\hbox{|put|}&\n4a:\cr
+\hbox{|push| \\{set} |pop|}&\RA\hbox{|put|}&\n4b:\cr
+\hbox{|push| |set_rule| |pop|}&\RA\hbox{|put_rule|}&\n4c:\cr
+\hbox{|push| |push| |any| |pop|}&\RA\hbox{|push| |any| |pop| |push|}&\n5:\cr
+\hbox{|push| |any| |pop| |pop|}&\RA\hbox{|any| |pop|}&\n6:\cr
+}$$
+
+@ In order to perform these transformations we need a stack which is
+indexed by |vf_ptr|, the number of |push| commands without corresponding
+|pop| in the packet we are building; the |vf_push_loc| array contains
+the locations in |byte_mem| following such |push| commands.
+In view of rule~5 consecutive |push| commands are never stored, the
+|vf_push_num| array is used to count them.
+The |vf_last| array indicates the type of the last non-discardable item:
+a character, a rule, or a group enclosed by |push| and |pop|;
+the |vf_last_end| array points to the ending locations and, if
+|vf_last<>vf_other|, the |vf_last_loc| array points to the starting
+locations of these items.
+
+@d vf_set=0 {|vf_set=char_cl|, last item is a |set_char| or \\{set}}
+@d vf_rule=1 {|vf_rule=rule_cl|, last item is a |set_rule|}
+@d vf_group=2 {last item is a group enclosed by |push| and |pop|}
+@d vf_put=3 {last item is a |put|}
+@d vf_other=4 {last item (if any) is none of the above}
+
+@<Types...@>=
+@!vf_type=vf_set..vf_other;
+
+@ @<Glob...@>=
+@!vf_move: array[stack_pointer] of vf_state; {state of |w|, |x|, |y|, and |z|}
+@!vf_push_loc: array[stack_pointer] of byte_pointer; {end of a |push|}
+@!vf_last_loc: array[stack_pointer] of byte_pointer; {start of an item}
+@!vf_last_end: array[stack_pointer] of byte_pointer; {end of an item}
+@!vf_push_num: array[stack_pointer] of eight_bits; {|push| count}
+@!vf_last: array[stack_pointer] of vf_type; {type of last item}
+@!vf_ptr:stack_pointer; {current number of unfinished groups}
+@!stack_used:stack_pointer; {largest |vf_ptr| or |stack_ptr| value}
+
+@ We use two small arrays to determine the item type of a character or a
+rule.
+
+@<Glob...@>=
+@!vf_char_type:array[boolean] of vf_type;
+@!vf_rule_type:array[boolean] of vf_type;
+
+@ @<Set init...@>=
+vf_move[0][0][0]:=false; vf_move[0][0][1]:=false;
+vf_move[0][1][0]:=false; vf_move[0][1][1]:=false;@/
+stack_used:=0;@/
+vf_char_type[false]:=vf_put; vf_char_type[true]:=vf_set;@/
+vf_rule_type[false]:=vf_other; vf_rule_type[true]:=vf_rule;
+
+@ Here we read the first bytes of a character packet from the \.{VF}
+file and initialize the packet being built in |byte_mem|; the start of
+the whole packet is stored in |vf_push_loc[0]|. When the character
+packet is finished, a type is be assigned to it: |vf_simple| if the
+packet ends with a character of the correct width, or |vf_complex|
+otherwise. Moreover, if such a packet for a character with
+extension zero consists of just one character with extension zero and
+the same residue, and if there is no previous packet, the whole packet
+is replaced by the empty packet.
+
+@d vf_simple=0 {the packet ends with a character of the correct width}
+@d vf_complex=vf_simple+1 {otherwise}
+
+@<VF: Build a character packet@>=
+begin if cur_cmd<long_char then
+ begin vf_limit:=cur_cmd;
+ cur_ext:=0; cur_res:=vf_ubyte; vf_wp:=check_width(vf_fix3u);
+ end
+else begin vf_limit:=vf_uquad;
+ cur_ext:=vf_strio; cur_res:=vf_ubyte; vf_wp:=check_width(vf_fix4);
+ end;
+Incr(vf_limit)(vf_loc);
+vf_push_loc[0]:=byte_ptr; vf_last_end[0]:=byte_ptr;
+vf_last[0]:=vf_other; vf_ptr:=0;@/
+start_packet(vf_complex);
+@<VF: Append \.{DVI} commands to the character packet@>;@/
+k:=pckt_start[pckt_ptr];
+if vf_last[0]=vf_put then if cur_wp=vf_wp then
+ begin decr(byte_mem[k]); {change |vf_complex| into |vf_simple|}
+ if (byte_mem[k]=bi(0))and@|(vf_push_loc[0]=vf_last_loc[0])and@|
+ (cur_ext=0)and@|(cur_res=pckt_res) then byte_ptr:=k;
+ end;
+build_packet;
+cur_cmd:=vf_ubyte;
+end
+
+@ For every \.{DVI} command read from the \.{VF} file some action is
+performed; in addition the initial |push| and the final |pop| are
+manufactured here.
+
+@<VF: Append \.{DVI} commands to the character packet@>=
+vf_cur_fnt:=font_font(cur_fnt); vf_fnt:=vf_cur_fnt;@/
+last_pop:=false; cur_class:=push_cl; {initial |push|}
+loop begin
+reswitch:case cur_class of
+ three_cases(char_cl): @<VF: Do a |char|, |rule|, or |xxx|@>;
+ push_cl: @<VF: Do a |push|@>;
+ pop_cl: @<VF: Do a |pop|@>;
+ two_cases(w0_cl):
+ if vf_move[vf_ptr][0][cur_class-w0_cl] then append_one(cur_cmd);
+ three_cases(right_cl):
+ begin pckt_signed(dvi_right_cmd[cur_class],cur_parm);
+ if cur_class>=w_cl then vf_move[vf_ptr][0][cur_class-w_cl]:=true;
+ end;
+ two_cases(y0_cl):
+ if vf_move[vf_ptr][1][cur_class-y0_cl] then append_one(cur_cmd);
+ three_cases(down_cl):
+ begin pckt_signed(dvi_down_cmd[cur_class],cur_parm);
+ if cur_class>=y_cl then vf_move[vf_ptr][1][cur_class-y_cl]:=true;
+ end;
+ fnt_cl: vf_font;
+ fnt_def_cl: bad_font;
+ invalid_cl: if cur_cmd<>nop then bad_font;
+ end; {there are no other cases}
+ if vf_loc<vf_limit then vf_first_par
+ else if last_pop then goto done
+ else begin cur_class:=pop_cl; last_pop:=true; {final |pop|}
+ end;
+ end;
+done:if (vf_ptr<>0)or(vf_loc<>vf_limit) then bad_font
+
+@ For a |push| we either increase |vf_push_num| or start a new level and
+append a |push|.
+
+@d incr_stack(#)==
+if #=stack_used then
+ if stack_used=stack_size then overflow(str_stack,stack_size)
+ else incr(stack_used);
+incr(#)
+
+@<VF: Do a |push|@>=
+if (vf_ptr>0)and(vf_push_loc[vf_ptr]=byte_ptr) then
+ begin if vf_push_num[vf_ptr]=255 then overflow(str_stack,255);
+ incr(vf_push_num[vf_ptr]);
+ end
+else begin incr_stack(vf_ptr);
+ @<VF: Start a new level@>;
+ vf_push_num[vf_ptr]:=0;
+ end
+
+@ @<VF: Start a new level@>=
+append_one(push);
+vf_move[vf_ptr]:=vf_move[vf_ptr-1];
+vf_push_loc[vf_ptr]:=byte_ptr;
+vf_last_end[vf_ptr]:=byte_ptr;
+vf_last[vf_ptr]:=vf_other
+
+@ When a character, a rule, or an |xxx| is appended, transformation
+rule~1 might be applicable.
+
+@<VF: Do a |char|, |rule|, or |xxx|@>=
+begin if (vf_ptr=0)or(byte_ptr>vf_push_loc[vf_ptr]) then move_zero:=false
+else case cur_class of
+char_cl: move_zero:=(not cur_upd)or(vf_cur_fnt<>vf_fnt);
+rule_cl: move_zero:=not cur_upd;
+xxx_cl: move_zero:=true;
+end; {there are no other cases}
+if move_zero then
+ begin decr(byte_ptr); decr(vf_ptr);
+ end;
+case cur_class of
+char_cl: @<VF: Do a |fnt|, a |char|, or both@>;
+rule_cl: @<VF: Do a |rule|@>;
+xxx_cl: @<VF: Do an |xxx|@>;
+end; {there are no other cases}
+vf_last_end[vf_ptr]:=byte_ptr;
+if move_zero then
+ begin incr(vf_ptr); append_one(push); vf_push_loc[vf_ptr]:=byte_ptr;
+ vf_last_end[vf_ptr]:=byte_ptr;
+ if cur_class=char_cl then if cur_upd then goto reswitch;
+ end;
+end
+
+@ A special situation arises if transformation rule~1 is applied to a
+|fnt_num| of |fnt| command, but not to the |set_char| or \\{set} command
+following it; in this case |cur_upd| and |move_zero| are both |true| and
+the |set_char| or \\{set} command will be appended later.
+
+@<VF: Do a |fnt|, a |char|, or both@>=
+begin if vf_cur_fnt<>vf_fnt then
+ begin vf_last[vf_ptr]:=vf_other;
+ pckt_unsigned(fnt1,vf_cur_fnt); vf_fnt:=vf_cur_fnt;
+ end;
+if (not move_zero)or(not cur_upd) then
+ begin vf_last[vf_ptr]:=vf_char_type[cur_upd];
+ vf_last_loc[vf_ptr]:=byte_ptr;
+ pckt_char(cur_upd,cur_ext,cur_res);
+ end;
+end
+
+@ @<VF: Do a |rule|@>=
+begin vf_last[vf_ptr]:=vf_rule_type[cur_upd];
+vf_last_loc[vf_ptr]:=byte_ptr;
+append_one(dvi_rule_cmd[cur_upd]);
+pckt_four(cur_v_dimen); pckt_four(cur_h_dimen);
+end
+
+@ @<VF: Do an |xxx|@>=
+begin vf_last[vf_ptr]:=vf_other;
+pckt_unsigned(xxx1,cur_parm); pckt_room(cur_parm);
+while cur_parm>0 do
+ begin append_byte(vf_ubyte); decr(cur_parm);
+ end;
+end
+
+@ Transformation rules 2--6 are triggered by a |pop|, either read from
+the \.{VF} file or manufactured at the end of the packet.
+
+@<VF: Do a |pop|@>=
+begin if vf_ptr<1 then bad_font;
+byte_ptr:=vf_last_end[vf_ptr]; {this is rule 2}
+if vf_last[vf_ptr]<=vf_rule then
+ if vf_last_loc[vf_ptr]=vf_push_loc[vf_ptr] then
+ @<VF: Prepare for rule 4@>;
+if byte_ptr=vf_push_loc[vf_ptr] then @<VF: Apply rule 3 or 4@>
+else begin if vf_last[vf_ptr]=vf_group then @<VF: Apply rule 6@>;
+ append_one(pop); decr(vf_ptr); vf_last[vf_ptr]:=vf_group;
+ vf_last_loc[vf_ptr]:=vf_push_loc[vf_ptr+1]-1;
+ vf_last_end[vf_ptr]:=byte_ptr;
+ if vf_push_num[vf_ptr+1]>0 then @<VF: Apply rule 5@>;
+ end;
+end
+
+@ In order to implement transformation rule~4, we cancel the |set_char|,
+\\{set}, or |set_rule|, append a |pop|, and insert a |put| or |put_rule|
+with the old parameters.
+
+@<VF: Prepare for rule 4@>=
+begin cur_class:=vf_last[vf_ptr]; cur_upd:=false;
+byte_ptr:=vf_push_loc[vf_ptr];
+end
+
+@ @<VF: Apply rule 3 or 4@>=
+begin if vf_push_num[vf_ptr]>0 then
+ begin decr(vf_push_num[vf_ptr]);
+ vf_move[vf_ptr]:=vf_move[vf_ptr-1];
+ end
+else begin decr(byte_ptr); decr(vf_ptr);
+ end;
+if cur_class<>pop_cl then goto reswitch; {this is rule 4}
+end
+
+@ @<VF: Apply rule 6@>=
+begin Decr(byte_ptr)(2);
+for k:=vf_last_loc[vf_ptr]+1 to byte_ptr do byte_mem[k-1]:=byte_mem[k];
+vf_last[vf_ptr]:=vf_other; vf_last_end[vf_ptr]:=byte_ptr;
+end
+
+@ @<VF: Apply rule 5@>=
+begin incr(vf_ptr);
+@<VF: Start a new level@>;
+decr(vf_push_num[vf_ptr]);
+end
+
+@ The \.{VF} format specifies that after a character packet invoked by a
+|set_char| or \\{set} command, ``|h|~is increased by the \.{TFM} width
+(properly scaled)---just as if a simple character had been typeset'';
+for |vf_simple| packets this is achieved by changing the final |put|
+command into |set_char| or \\{set}, but for |vf_complex| packets an
+explicit movement must be done. This poses a problem for programs,
+such as \.{DVIcopy}, which write a new \.{DVI} file with all references
+to characters from virtual fonts replaced by their character packets:
+The \.{DVItype} program specifies that the horizontal movements after a
+|set_char| or \\{set} command, after a |set_rule| command, and after one
+of the commands |right1..x4|, are all treated differently when \.{DVI}
+units are converted to pixels.
+
+Thus we introduce a slight extension of \.{DVItype}'s pixel rounding
+algorithm and hope that this extension will become part of the standard
+\.{DVItype} program in the near future: If a \.{DVI} file contains a
+|set_rule| command for a rule with the negative height |width_dimen|,
+then this rule shall be treated in exactly the same way as a ficticious
+character whose width is the width of that rule; as value of |width_dimen|
+we choose $-2^{31}$, the smallest signed 32-bit integer.
+
+@<Glob...@>=
+@!width_dimen:int_32; {vertical dimension of special rules}
+
+@ When initializing |width_dimen| we are careful to avoid arithmetic
+overflow.
+
+@<Set init...@>=
+width_dimen:=-@"40000000; Decr(width_dimen)(@"40000000);
+
+@* Terminal communication.
+When \.{\title} begins, it engages the user in a brief dialog so that
+various options may be specified. This part of \.{\title} requires
+nonstandard \PASCAL\ constructions to handle the online interaction; so
+it may be preferable in some cases to omit the dialog and simply to
+stick to the default options. On other hand, the system-dependent
+routines that are needed are not complicated, so it will not be terribly
+difficult to introduce them; furthermore they are similar to those in
+\.{DVItype}.
+
+It may be desirable to (optionally) specify all the options in the
+command line and skip the dialog with the user, provided the operating
+system permits this. Here we just define the system-indepent part of the
+code required for this possibility. Since a complete option (a keyword
+possibly followed by one or several parameters) may have embedded blanks
+it might be necessary to replace these blanks by some other separator,
+e.g., by a '/'. Using, e.g., \.{UNIX} style options one might then say
+$$\.{\title\space-mag/2000 -sel/17.3/5 -sel/47 ...}$$
+to override the magnification factor that is stated in the \.{DVI} file,
+and to select five pages starting with the page numbered~17.3 as well as
+all remaining pages starting with the one numbered~47; alternatively one
+might simply say
+$$\.{\title\space- ...}$$
+to skip the dialog and use the default options.
+
+The system-dependent initialization code should set the |n_opt| variable
+to the number of options found in the command line. If |n_opt=0| the
+|input_ln| procedure defined below will promt the user for options. If
+|n_opt>0| the |k_opt| variable will be incremented and another piece of
+system-dependent code is invoked instead of the dialog; that code should
+place the value of command line option number |k_opt| as temporary
+string into the |byte-mem| array. This process will be repeated until
+|k_opt=n_opt|, indicating that all command line options have been
+processed.
+@^system dependencies@>
+
+@d opt_separator="/" {acts as blank when scanning (command line) options}
+
+@<Set init...@>=
+n_opt:=0; {change this to indicate the presence of command line options}
+k_opt:=0; {just in case}
+
+@ The |input_ln| routine waits for the user to type a line at his or her
+terminal; then it puts ASCII-code equivalents for the characters on that
+line into the |byte_mem| array as a temporary string. \PASCAL's
+standard |input| file is used for terminal input, as |output| is used
+for terminal output.
+
+Since the terminal is being used for both input and output, some systems
+need a special routine to make sure that the user can see a prompt message
+before waiting for input based on that message. (Otherwise the message
+may just be sitting in a hidden buffer somewhere, and the user will have
+no idea what the program is waiting for.) We shall invoke a system-dependent
+subroutine |update_terminal| in order to avoid this problem.
+@^system dependencies@>
+
+@d update_terminal == break(output) {empty the terminal output buffer}
+@#
+@d scan_blank(#)== {tests for `blank' when scanning (command line) options}
+ ((byte_mem[#]=bi(" "))or(byte_mem[#]=bi(opt_separator)))
+@d scan_skip== {skip `blanks'}
+ while scan_blank(scan_ptr)and(scan_ptr<byte_ptr) do incr(scan_ptr)
+@d scan_init== {initialize |scan_ptr|}
+ byte_mem[byte_ptr]:=bi(" "); scan_ptr:=pckt_start[pckt_ptr-1]; scan_skip
+
+@<Action procedures for |dialog|@>=
+procedure input_ln; {inputs a line from the terminal}
+var k:0..terminal_line_length;
+begin if n_opt=0 then
+ begin print('Enter option: '); update_terminal; reset(input);
+ if eoln(input) then read_ln(input);
+ k:=0; pckt_room(terminal_line_length);
+ while (k<terminal_line_length)and not eoln(input) do
+ begin append_byte(xord[input^]); incr(k); get(input);
+ end;
+ end
+else if k_opt<n_opt then
+ begin incr(k_opt);
+ {Copy command line option number |k_opt| into |byte_mem| array!}
+ end;
+end;
+
+@ The global variable |scan_ptr| is used while scanning the temporary
+packet; it points to the next byte in |byte_mem| to be examined.
+
+@<Glob...@>=
+@!n_opt:int_16; {number of options found in command line}
+@!k_opt:int_16; {number of command line options processed}
+@!scan_ptr:byte_pointer; {pointer to next byte to be examined}
+@!sep_char:text_char; {|' '| or |xchr[opt_separator]|}
+
+@ The |scan_keyword| function is used to test for keywords in a character
+string stored as temporary packet in |byte_mem|; the result is |true|
+(and |scan_ptr| is updated) if the characters starting at position
+|scan_ptr| are an abbreviation of a given keyword followed by at least
+one blank.
+
+@<Action procedures for |dialog|@>=
+function scan_keyword(@!p:pckt_pointer;@!l:int_7):boolean;
+var i,@!j,@!k:byte_pointer; {indices into |byte_mem|}
+begin i:=pckt_start[p]; j:=pckt_start[p+1]; k:=scan_ptr;
+while (i<j)and((byte_mem[k]=byte_mem[i])or(byte_mem[k]=byte_mem[i]-"a"+"A")) do
+ begin incr(i); incr(k);
+ end;
+if scan_blank(k)and(i-pckt_start[p]>=l) then
+ begin scan_ptr:=k; scan_skip; scan_keyword:=true;
+ end
+else scan_keyword:=false;
+end;
+
+@ Here is a routine that scans a (possibly signed) integer and computes
+the decimal value. If no decimal integer starts at |scan_ptr|, the
+value~0 is returned. The integer should be less than $2^{31}$ in
+absolute value.
+
+@<Action procedures for |dialog|@>=
+function scan_int:int_32;
+var x:int_32; {accumulates the value}
+@!negative:boolean; {should the value be negated?}
+begin if byte_mem[scan_ptr]="-" then
+ begin negative:=true; incr(scan_ptr);
+ end
+else negative:=false;
+x:=0;
+while (byte_mem[scan_ptr]>="0")and(byte_mem[scan_ptr]<="9") do
+ begin x:=10*x+byte_mem[scan_ptr]-"0"; incr(scan_ptr);
+ end;
+scan_skip;
+if negative then scan_int:=-x @+ else scan_int:=x;
+end;
+
+@ The selected options are put into global variables by the |dialog|
+procedure, which is called just as \.{\title} begins.
+@^system dependencies@>
+
+@p @<Action procedures for |dialog|@>@;
+procedure dialog;
+label exit;
+var p:pckt_pointer; {packet being created}
+begin @<Initialize options@>@;
+loop begin input_ln; p:=new_packet; scan_init;
+ if scan_ptr=byte_ptr then
+ begin flush_packet; return;
+ end@;@/
+ @<Cases for options@>@;@/
+ else begin if n_opt=0 then sep_char:=' '
+ else sep_char:=xchr[opt_separator];
+ print_options;
+ if n_opt>0 then
+ begin print('Bad command line option: ');
+ print_packet(p); abort('---run terminated');
+ end;
+ end;
+ flush_packet;
+ end;
+exit:end;
+
+@ The |print_options| procedure might be used in a `Usage message'
+displaying the command line syntax.
+
+@<Basic printing...@>=
+procedure print_options;
+begin print_ln('Valid options are:');
+@<Print valid options@>@;
+end;
+
+@* Subroutines for typesetting commands.
+This is the central part of the whole \.{\title} program:
+When a typesetting command from the \.{DVI} file or from a \.{VF} packet
+has been decoded, one of the typesetting routines defined below is
+invoked to execute the command; apart from the necessary book keeping,
+these routines invoke device dependent code defined later.
+
+@p @<Declare typesetting procedures@>
+
+@ These typesetting routines communicate with the rest of the program
+through global variables.
+
+@<Glob...@>=
+@!type_setting:boolean; {|true| while typesetting a page}
+
+@ @<Set init...@>=
+type_setting:=false;
+
+@ The user may select up to |max_select| ranges of consecutive pages to
+be processed. Each starting page specification is recorded in two global
+arrays called |start_count| and |start_there|. For example, `\.{1.*.-5}'
+is represented by |start_there[0]=true|, |start_count[0]=1|,
+|start_there[1]=false|, |start_there[2]=true|, |start_count[2]=-5|. We
+also set |start_vals=2|, to indicate that count 2 was the last one
+mentioned. The other values of |start_count| and |start_there| are not
+important, in this example. The number of pages is recorded in
+|max_pages|; a non positive value indicates that there is no limit.
+
+@d start_count==select_count[cur_select] {count values to select
+ starting page}
+@d start_there==select_there[cur_select] {is the |start_count| value
+ relevant?}
+@d start_vals==select_vals[cur_select] {the last count considered
+ significant}
+@d max_pages==select_max[cur_select] {at most this many |bop..eop| pages
+ will be printed}
+
+@<Glob...@>=
+@!select_count:array[0..max_select-1,0..9] of int_32;
+@!select_there:array[0..max_select-1,0..9] of boolean;
+@!select_vals:array[0..max_select-1] of 0..9;
+@!select_max:array[0..max_select-1] of int_32;
+@!out_mag:int_32; {output maginfication}
+@!count:array[0..9] of int_32; {the count values on the current page}
+@!num_select:0..max_select; {number of page selection ranges specified}
+@!cur_select:0..max_select; {current page selection range}
+@!selected:boolean; {has starting page been found?}
+@!all_done:boolean; {have all selected pages been processed?}
+@!str_mag,@!str_select:pckt_pointer;
+
+@ Here is a simple subroutine that tests if the current page might be the
+starting page.
+
+@p function start_match:boolean; {does |count| match the starting spec?}
+var k:0..9; {loop index}
+@!match:boolean; {does everything match so far?}
+begin match:=true;
+for k:=0 to start_vals do
+ if start_there[k]and(start_count[k]<>count[k]) then match:=false;
+start_match:=match;
+end;
+
+@ @<Initialize options@>=
+out_mag:=0; cur_select:=0; max_pages:=0; selected:=true;
+
+@ @<Print valid options@>=
+print_ln(' mag',sep_char,'<new_mag>');
+print_ln(' select',sep_char,'<start_count>',sep_char,
+ '[<max_pages>] (up to ',max_select:1,' ranges)');
+
+@ @<Action procedures for |dialog|@>=
+procedure scan_count; {scan a |start_count| value}
+begin if byte_mem[scan_ptr]=bi("*") then
+ begin start_there[start_vals]:=false; incr(scan_ptr); scan_skip;
+ end
+else begin start_there[start_vals]:=true;
+ start_count[start_vals]:=scan_int;
+ if cur_select=0 then selected:=false; {don't start at first page}
+ end;
+end;
+
+@ @<Cases for options@>=
+else if scan_keyword(str_mag,3) then out_mag:=scan_int
+else if scan_keyword(str_select,3) then
+ if cur_select=max_select then print_ln('Too many page selections')
+ else begin start_vals:=0; scan_count;
+ while (start_vals<9)and(byte_mem[scan_ptr]=bi(".")) do
+ begin incr(start_vals); incr(scan_ptr); scan_count;
+ end;
+ max_pages:=scan_int; incr(cur_select);
+ end
+
+@ @<Initialize predefined strings@>=
+id3("m")("a")("g")(str_mag);
+id6("s")("e")("l")("e")("c")("t")(str_select);
+
+@ A stack is used to keep track of the current horizonal and vertical
+position, |h| and |v|, and the four registers |w|, |x|, |y|, and |z|;
+the register pairs |(w,x)| and |(y,z)| are maintained as arrays.
+
+@<Types...@>=
+@!device @<Declare device dependend types@>@; @+ ecived @; @/
+@!stack_pointer=0..stack_size;@/
+@!stack_index=1..stack_size;@/
+@!pair_32=array[0..1] of int_32; {a pair of |int_32| variables}
+@!stack_record=record@;@/
+ @!h_field:int_32; {horizontal position |h|}
+ @!v_field:int_32; {vertical position |v|}
+ @!w_x_field:pair_32; {|w| and |x| register for horizontal movements}
+ @!y_z_field:pair_32; {|y| and |z| register for vertical movements}
+ @!device @<Device dependent stack record fields@>@; @+ ecived @; @/
+ end;
+
+@ The current values are kept in |cur_stack|; they are pushed onto and
+popped from |stack|. We use \.{WEB} macros to access the current values.
+
+@d cur_h==cur_stack.h_field {the current |@!h| value}
+@d cur_v==cur_stack.v_field {the current |@!v| value}
+@d cur_w_x==cur_stack.w_x_field {the current |@!w| and |@!x| value}
+@d cur_y_z==cur_stack.y_z_field {the current |@!y| and |@!z| value}
+
+@<Glob...@>=
+@!stack:array[stack_index] of stack_record; {the pushed values}
+@!cur_stack:stack_record; {the current values}
+@!zero_stack:stack_record; {initial values}
+@!stack_ptr:stack_pointer; {last used position in |stack|}
+
+@ @<Set init...@>=
+zero_stack.h_field:=0; zero_stack.v_field:=0;
+for i:=0 to 1 do
+ begin zero_stack.w_x_field[i]:=0; zero_stack.y_z_field[i]:=0;
+ end;
+@!device @<Initialize device dependent stack record fields@>@; @+ ecived @; @/
+
+@ When typesetting for a real device we must convert the current
+position from \.{DVI} units to pixels, i.e., |cur_h| and |cur_v| into
+|cur_hh| and |cur_vv|. This might be a good place to collect everything
+related to the conversion from \.{DVI} units to pixels and in particular
+all the pixel rounding algorithms.
+
+@d font_space(#)==fnt_space[#] {boundary between ``small'' and ``large''
+ spaces}
+
+@<Declare device dependent font data arrays@>=
+@!fnt_space:array [font_number] of int_32; {boundary between ``small''
+ and ``large'' spaces}
+
+@ @<Initialize device dependent font data@>=
+font_space(invalid_font):=0;
+
+@ @<Initialize device dependent data for a font@>=
+font_space(cur_fnt):=font_scaled(cur_fnt) div 6;
+ {this is a 3-unit ``thin space''}
+
+@ The |char_pixels| array is used to store the horizontal character
+escapements: for \.{PK} or \.{GF} files we use the values given there,
+otherwise we must convert the character widths to (horizontal) pixels.
+The horizontal escapement of character~|c| in font~|f| is given by
+|font_pixel(f)(c)|.
+
+@d font_pixel(#)==char_pixels[font_chars(#)+font_width_end
+@#
+@d max_pix_value==@"7FFF {largest allowed pixel value; this range may not
+ suffice for high resolution output devices}
+
+@<Declare device dependend types@>=
+@!pix_value=-max_pix_value..max_pix_value; {a pixel coordinate or displacement}
+
+@ @<Glob...@>=
+@!device
+@!char_pixels:array[char_pointer] of pix_value; {character escapements}
+@!h_pixels:pix_value; {a horizontal dimension in pixels}
+@!v_pixels:pix_value; {a vertical dimension in pixels}
+@!temp_pix:pix_value; {temporary value for pixel rounding}
+ecived
+
+@ @d cur_hh==cur_stack.hh_field {the current |@!hh| value}
+@d cur_vv==cur_stack.vv_field {the current |@!vv| value}
+
+@<Device dependent stack record fields@>=
+@!hh_field:pix_value; {horizontal pixel position |hh|}
+@!vv_field:pix_value; {vertical pixel position |vv|}
+
+@ @<Initialize device dependent stack record fields@>=
+zero_stack.hh_field:=0; zero_stack.vv_field:=0;
+
+@ For small movements we round the increment in position, for large
+movements we round the incremented position. The same applies to rule
+dimensions with the only difference that they will always be rounded
+towards larger values. For characters we increment the horizontal
+position by the escapement values obtained, e.g., from a \.{PK} file or
+by the \.{TFM} width converted to pixels.
+
+@d h_pixel_round(#)==round(h_conv*(#))
+@d v_pixel_round(#)==round(v_conv*(#))
+@^system dependencies@>
+@#
+@d large_h_space(#)==(#>=font_space(cur_fnt))or(#<=-4*font_space(cur_fnt))
+ {is this a ``large'' horizontal distance?}
+@d large_v_space(#)==(abs(#)>=5*font_space(cur_fnt))
+ {is this a ``large'' vertical distance?}
+@#
+@d h_rule_pixels== {converts the rule width |cur_h_dimen| to pixels}
+@!device if large_h_space(cur_h_dimen) then
+ begin h_pixels:=h_pixel_round(cur_h+cur_h_dimen)-cur_hh;
+ if h_pixels<=0 then if cur_h_dimen>0 then h_pixels:=1;
+ end
+else begin h_pixels:=trunc(h_conv*cur_h_dimen);
+ if h_pixels<h_conv*cur_h_dimen then incr(h_pixels);
+ end;
+ecived
+@#
+@d v_rule_pixels== {converts the rule height |cur_v_dimen| to pixels}
+@!device if large_v_space(cur_v_dimen) then
+ begin v_pixels:=cur_vv-v_pixel_round(cur_v-cur_v_dimen);
+ if v_pixels<=0 then v_pixels:=1; {used only for |cur_v_dimen>0|}
+ end
+else begin v_pixels:=trunc(v_conv*cur_v_dimen);
+ if v_pixels<v_conv*cur_v_dimen then incr(v_pixels);
+ end;
+ecived
+
+@ A sequence of consecutive rules, or consecutive characters in a
+fixed-width font whose width is not an integer number of pixels, can
+cause |hh| to drift far away from a correctly rounded value. \.{\title}
+ensures that the amount of drift will never exceed |max_h_drift| pixels;
+similarly |vv| shall never drift away from the correctly rounded value
+by more than |max_v_drift| pixels.
+
+@d h_upd_end(#)== {check for proper horizontal pixel rounding}
+begin Incr(cur_hh)(#); temp_pix:=h_pixel_round(cur_h);
+if abs(temp_pix-cur_hh)>max_h_drift then
+ if temp_pix>cur_hh then cur_hh:=temp_pix-max_h_drift
+ else cur_hh:=temp_pix+max_h_drift;
+end @+ ecived
+@d h_upd_char(#)==Incr(cur_h)(#)@;
+ @!device; h_upd_end
+@d h_upd_move(#)==Incr(cur_h)(#)@;
+ @!device; if large_h_space(#) then cur_hh:=h_pixel_round(cur_h)
+ else h_upd_end
+@#
+@d v_upd_end(#)== {check for proper vertical pixel rounding}
+begin Incr(cur_vv)(#); temp_pix:=v_pixel_round(cur_v);
+if abs(temp_pix-cur_vv)>max_v_drift then
+ if temp_pix>cur_vv then cur_vv:=temp_pix-max_v_drift
+ else cur_vv:=temp_pix+max_v_drift;
+end @+ ecived
+@d v_upd_move(#)==Incr(cur_v)(#)@;
+ @!device; if large_v_space(#) then cur_vv:=v_pixel_round(cur_v)
+ else v_upd_end
+
+@ The routines defined below use sections named `Declare local variables
+(if any) for \dots' or `Declare additional local variables for \dots';
+the former may declare variables (including the keyword \&{var}), whereas
+the later must at least contain the keyword \&{var}. In general, both may
+start with the declaration of labels, constants, and\slash or types.
+
+Let us start with the simple cases:
+The |do_pre| procedure is called when the preamble has been read from
+the \.{DVI} file; the preamble comment has just been converted into a
+temporary packet with the |new_packet| procedure.
+
+@p procedure do_pre;@/
+@<OUT: Declare local variables (if any) for |do_pre|@>@;
+begin all_done:=false; num_select:=cur_select; cur_select:=0;
+if num_select=0 then max_pages:=0;
+@!device
+h_conv:=(dvi_num/254000.0)*(h_resolution/dvi_den)*(out_mag/1000.0);
+v_conv:=(dvi_num/254000.0)*(v_resolution/dvi_den)*(out_mag/1000.0);
+ecived @; @/
+@<OUT: Process the |pre|@>@;@/
+end;
+
+@ The |do_bop| procedure is called when a |bop| has been read. This
+routine determines whether a page shall be processed or skipped and sets
+the variable |type_setting| accordingly.
+
+@p procedure do_bop;@/
+@<OUT: Declare additional local variables |do_bop|@>@;
+@!i,@!j:0..9; {indices into |count|}
+begin @<Determine whether this page should be processed or skipped@>;
+print('DVI: ');
+if type_setting then print('process') @+ else print('skipp');
+print('ing page ',count[0]:1); j:=9;
+while (j>0)and(count[j]=0) do decr(j);
+for i:=1 to j do print('.',count[i]:1);
+d_print(' at ',dvi_loc-45:1);
+print_ln('.');
+if type_setting then
+ begin stack_ptr:=0; cur_stack:=zero_stack; cur_fnt:=invalid_font;@/
+ @<OUT: Process a |bop|@>@;@/
+ end;
+end;
+
+@ Note that the device dependent code `OUT: Process a |bop|' may choose
+to set |type_setting| to false even if |selected| is true.
+
+@<Determine whether this page...@>=
+if not selected then selected:=start_match;
+type_setting:=selected
+
+@ The |do_eop| procedure is called in order to process an |eop|; the
+stack should be empty.
+
+@p procedure do_eop;@/
+@<OUT: Declare local variables (if any) for |do_eop|@>@;
+begin if stack_ptr<>0 then bad_dvi;
+@<OUT: Process an |eop|@>@;
+if max_pages>0 then
+ begin decr(max_pages);
+ if max_pages=0 then
+ begin selected:=false; incr(cur_select);
+ if cur_select=num_select then all_done:=true;
+ end;
+ end;
+type_setting:=false;
+end;
+
+@ The procedures |do_push| and |do_pop| are called in order to process
+|push| and |pop| commands; |do_push| must check for stack overflow,
+|do_pop| should never be called when the stack is empty.
+
+@p procedure do_push; {push onto stack}
+@<OUT: Declare local variables (if any) for |do_push|@>@;
+begin incr_stack(stack_ptr); stack[stack_ptr]:=cur_stack;@/
+@<OUT: Process a |push|@>@;
+end;
+@#
+procedure do_pop; {pop from stack}
+@<OUT: Declare local variables (if any) for |do_pop|@>@;
+begin if stack_ptr=0 then bad_dvi;
+cur_stack:=stack[stack_ptr]; decr(stack_ptr);
+@<OUT: Process a |pop|@>@;@/
+end;
+
+@ The |do_xxx| procedure is called in order to process a special command.
+The bytes of the special string have been put into |byte_mem| as the
+current string. They are converted to a temporary packet and discarded
+again.
+
+@p procedure do_xxx;@/
+@<OUT: Declare additional local variables for |do_xxx|@>@;
+@!p:pckt_pointer; {temporary packet}
+begin p:=new_packet;@/
+@<OUT: Process an |xxx|@>@;@/
+flush_packet;
+end;
+
+@ Next are the movement commands:
+The |do_right| procedure is called in order to process the horizontal
+movement commands |right|, |w|, and |x|.
+
+
+@p procedure do_right;@/
+@<OUT: Declare local variables (if any) for |do_right|@>@;
+begin if cur_class>=w_cl then cur_w_x[cur_class-w_cl]:=cur_parm
+else if cur_class<right_cl then cur_parm:=cur_w_x[cur_class-w0_cl];
+@<OUT: Process a |right| or |w| or |x|@>@;@/
+h_upd_move(cur_parm)(h_pixel_round(cur_parm));
+@<OUT: Move right@>@;
+end;
+
+@ The |do_down| procedure is called in order to process the vertical
+movement commands |down|, |y|, and |z|.
+
+@p procedure do_down;@/
+@<OUT: Declare local variables (if any) for |do_down|@>@;
+begin if cur_class>=y_cl then cur_y_z[cur_class-y_cl]:=cur_parm
+else if cur_class<down_cl then cur_parm:=cur_y_z[cur_class-y0_cl];
+@<OUT: Process a |down| or |y| or |z|@>@;@/
+v_upd_move(cur_parm)(v_pixel_round(cur_parm));
+@<OUT: Move down@>@;
+end;
+
+@ The |do_width| procedure, or actually the |do_a_width| macro, is
+called in order to increase the current horizontal position |cur_h| by
+|cur_h_dimen| in exactly the same way as if a character of width
+|cur_h_dimen| had been typeset.
+
+@d do_a_width(#)==
+ begin @!device h_pixels:=#; @+ ecived @; @+ do_width;
+ end
+
+@p procedure do_width;@/
+@<OUT: Declare local variables (if any) for |do_width|@>@;
+begin @<OUT: Typeset a |width|@>@;@/
+h_upd_char(cur_h_dimen)(h_pixels);
+@<OUT: Move right@>@;
+end;
+
+@ Finally we have the commands for the typesetting of rules and characters;
+the global variable |cur_upd| is |true| if the horizontal position shall
+be updated (\\{set} commands).
+
+The |do_rule| procedure is called in order to typeset a rule.
+
+@p procedure do_rule;@/
+@<OUT: Declare additional local variables |do_rule|@>@;
+@!visible:boolean;
+begin h_rule_pixels@;
+if (cur_h_dimen>0)and(cur_v_dimen>0) then
+ begin visible:=true; v_rule_pixels@;
+ @<OUT: Typeset a visible |rule|@>@;
+ end
+else begin visible:=false;
+ @<OUT: Typeset an invisible |rule|@>@;
+ end;
+if cur_upd then
+ begin h_upd_move(cur_h_dimen)(h_pixels);
+ @<OUT: Move right@>@;
+ end;
+end;
+
+@ Last not least the |do_char| procedure is called in order to typeset
+character~|cur_res| with extension~|cur_ext| from the real font~|cur_fnt|.
+
+@p procedure do_char;@/
+@<OUT: Declare local variables (if any) for |do_char|@>@;
+begin @<OUT: Typeset a |char|@>@;
+if cur_upd then
+ begin h_upd_char(widths[cur_wp])(char_pixels[cur_cp]);
+ @<OUT: Move right@>@;
+ end;
+end;
+
+@ If the program terminates abnormally, the following code may be
+invoked in the middle of a page.
+
+@<Finish output file(s)@>=
+begin if type_setting then @<OUT: Finish incomplete page@>;
+@<OUT: Finish output file(s)@>@;
+end
+
+@ When the first character of font~|cur_fnt| is about to be typeset, the
+|do_font| procedure is called in order to decide whether this is a
+virtual font or a real font.
+
+One step in this decision is the attempt to find and read the \.{VF}
+file for this font; other attempts to locate a font file may be
+performed before and after that, depending on the nature of the output
+device and on the structure of the file system at a particular
+installation. For a real device we convert the character widths to
+(horizontal) pixels.
+
+In any case |do_font| must change |font_type(cur_fnt)| to a value
+|>defined_font|; as a last resort one might use the \.{TFM} width data
+and draw boxes or leave blank spaces in the output.
+
+@p procedure do_font;@/
+label done;@/
+@<OUT: Declare additional local variables for |do_font|@>@;
+@!p:char_pointer; {index into |char_widths| and |char_pixels|}
+begin @!debug if font_type(cur_fnt)=defined_font then confusion(str_fonts);
+gubed@;
+@!device for p:=font_chars(cur_fnt)+font_bc(cur_fnt)
+ to font_chars(cur_fnt)+font_ec(cur_fnt) do
+ char_pixels[p]:=h_pixel_round(widths[char_widths[p]]);
+ecived@;
+@<OUT: Look for a font file before trying to read the \.{VF} file;
+ if found |goto done|@>@;@/
+if do_vf then goto done; {try to read the \.{VF} file}
+@<OUT: Look for a font file after trying to read the \.{VF} file@>@;@/
+done:
+@!debug if font_type(cur_fnt)<=loaded_font then confusion(str_fonts);
+gubed@;
+end;
+
+@ Before a character of font~|cur_fnt| is typeset the following piece of
+code ensures that the font is ready to be used.
+
+@<Prepare to use font |cur_fnt|@>=
+@<OUT: Prepare to use font |cur_fnt|@>@;
+if font_type(cur_fnt)<=loaded_font then do_font {|cur_fnt| was not yet used}
+
+@* Interpreting VF packets.
+The |pckt_first_par| procedure first reads a \.{DVI} command byte from
+the packet into |cur_cmd|; then |cur_parm| is set to the value of the
+first parameter (if any) and |cur_class| to the command class.
+
+@p procedure pckt_first_par;
+begin cur_cmd:=pckt_ubyte;
+case dvi_par[cur_cmd] of
+char_par: set_cur_char(pckt_ubyte);
+no_par: do_nothing;
+dim1_par: cur_parm:=pckt_sbyte;
+num1_par: cur_parm:=pckt_ubyte;
+dim2_par: cur_parm:=pckt_spair;
+num2_par: cur_parm:=pckt_upair;
+dim3_par: cur_parm:=pckt_strio;
+num3_par: cur_parm:=pckt_utrio;
+three_cases(dim4_par): cur_parm:=pckt_squad; {|dim4|, |num4|, or |numu|}
+rule_par:
+ begin cur_v_dimen:=pckt_squad; cur_h_dimen:=pckt_squad;
+ cur_upd:=(cur_cmd=set_rule);
+ end;
+fnt_par:cur_parm:=cur_cmd-fnt_num_0;
+end; {there are no other cases}
+cur_class:=dvi_cl[cur_cmd];
+end;
+
+@ The |do_vf_packet| procedure is called in order to interpret the
+character packet for a virtual character. Such a packet may contain the
+instruction to typeset a character from the same or an other virtual
+font; in such cases |do_vf_packet| calls itself recursively. The
+recursion level, i.e., the number of times this has happened, is kept
+in the global variable |n_recur| and should not exceed |max_recursion|.
+@^recursion@>
+
+@<Types...@>=
+@!recur_pointer=0..max_recursion;
+
+@ The \.{\title} processor should detect an infinite recursion caused by
+bad \.{VF} files; thus a new recursion level is entered even in cases
+where this could be avoided without difficulty.
+
+If the recursion level exceeds the allowed maximum, we want to give
+a traceback how this has happened; thus some of the global variables
+used in different invocations of |do_vf_packet| are saved in a stack,
+others are saved as local variables of |do_vf_packet|.
+
+@<Glob...@>=
+@!recur_fnt:array[recur_pointer] of font_number; {this packet's font}
+@!recur_ext:array[recur_pointer] of int_24; {this packet's extension}
+@!recur_res:array[recur_pointer] of eight_bits; {this packet's residue}
+@!recur_pckt:array[recur_pointer] of pckt_pointer; {the packet}
+@!recur_loc:array[recur_pointer] of byte_pointer; {next byte of packet}
+@!n_recur:recur_pointer; {current recursion level}
+@!recur_used:recur_pointer; {highest recursion level used so far}
+
+@ @<Set init...@>=
+n_recur:=0; recur_used:=0;
+
+@ Here now is the |do_vf_packet| procedure.
+
+@p procedure do_vf_packet;
+label continue,found,done;
+var k:recur_pointer; {loop index}
+@!f:int_8u; {packet type flag}
+@!save_upd:boolean; {used to save |cur_upd|}
+@!save_cp:width_pointer; {used to save |cur_cp|}
+@!save_wp:width_pointer; {used to save |cur_wp|}
+@!save_limit:byte_pointer; {used to save |cur_limit|}
+begin @<VF: Save values on entry to |do_vf_packet|@>;@/
+@<VF: Interpret the \.{DVI} commands in the packet@>@;@/
+if save_upd then
+ begin cur_h_dimen:=widths[save_wp]; do_a_width(char_pixels[save_cp]);
+ end;
+@<VF: Restore values on exit from |do_vf_packet|@>;@/
+end;
+
+@ On entry to |do_vf_packet| several values must be saved.
+
+@<VF: Save values on entry to |do_vf_packet|@>=
+save_upd:=cur_upd; save_cp:=cur_cp; save_wp:=cur_wp;@/
+recur_fnt[n_recur]:=cur_fnt;
+recur_ext[n_recur]:=cur_ext;
+recur_res[n_recur]:=cur_res
+
+@ Some of these values must be restored on exit from |do_vf_packet|.
+
+@<VF: Restore values on exit from |do_vf_packet|@>=
+cur_fnt:=recur_fnt[n_recur]
+
+@ If |cur_pckt| is the empty packet, we manufacture a |put| command;
+otherwise we read and interpret \.{DVI} commands from the packet.
+
+@<VF: Interpret the \.{DVI} commands in the packet@>=
+if find_packet then f:=cur_type @+ else goto done;
+recur_pckt[n_recur]:=cur_pckt;
+save_limit:=cur_limit;
+cur_fnt:=font_font(cur_fnt);
+if cur_pckt=empty_packet then
+ begin cur_class:=char_cl; goto found;
+ end;
+if cur_loc>=cur_limit then goto done;
+continue: pckt_first_par;
+found: case cur_class of
+char_cl: @<VF: Typeset a |char|@>;
+rule_cl: do_rule;
+xxx_cl:
+ begin pckt_room(cur_parm);
+ while cur_parm>0 do
+ begin append_byte(pckt_ubyte); decr(cur_parm);
+ end;
+ do_xxx;
+ end;
+push_cl: do_push;
+pop_cl: do_pop;
+five_cases(w0_cl): do_right; {|right|, |w|, or |x|}
+five_cases(y0_cl): do_down; {|down|, |y|, or |z|}
+fnt_cl: cur_fnt:=cur_parm;
+othercases confusion(str_packets); {font definition or invalid}
+endcases;
+if cur_loc<cur_limit then goto continue;
+done:
+
+@ The final |put| of a simple packet may be changed into |set_char| or
+\\{set}.
+
+@<VF: Typeset a |char|@>=
+begin @<Prepare to use font |cur_fnt|@>;
+cur_cp:=font_chars(cur_fnt)+cur_res; cur_wp:=char_widths[cur_cp];
+if (cur_loc=cur_limit)and(f=vf_simple) and save_upd then
+ begin save_upd:=false; cur_upd:=true;
+ end;
+if font_type(cur_fnt)=vf_font_type then
+ @<VF: Enter a new recursion level@>
+else do_char;
+end
+
+@ Before entering a new recursion level we must test for overflow; in
+addition a few variables must be saved and restored.
+A |set_char| or \\{set} followed by |pop| is changed into |put|.
+
+@<VF: Enter a new recursion level@>=
+begin recur_loc[n_recur]:=cur_loc; {save}
+if cur_loc<cur_limit then
+ if byte_mem[cur_loc]=bi(pop) then cur_upd:=false;
+if n_recur=recur_used then
+ if recur_used=max_recursion then
+ @<VF: Display the recursion traceback and terminate@>
+ else incr(recur_used);@/
+incr(n_recur); do_vf_packet; decr(n_recur); {recurse}
+cur_loc:=recur_loc[n_recur]; cur_limit:=save_limit; {restore}
+end
+
+@ @<VF: Display the recursion traceback and terminate@>=
+begin print_ln(' !Infinite VF recursion?');
+@.Infinite VF recursion?@>
+for k:=max_recursion downto 0 do
+ begin print('level=',k:1,' font');
+ d_print('=',recur_fnt[k]:1);
+ print_font(recur_fnt[k]);
+ print(' char=',recur_res[k]:1);
+ if recur_ext[k]<>0 then print('.',recur_ext[k]:1);
+ new_line;
+ @!debug hex_packet(recur_pckt[k]); print_ln('loc=',recur_loc[k]:1);
+ gubed@;
+ end;
+overflow(str_recursion,max_recursion);
+end
+
+@* Interpreting the DVI file.
+The |do_dvi| procedure reads the entire \.{DVI} file and initiates
+whatever actions may be necessary.
+
+@p procedure do_dvi;
+label done,exit;
+var temp_byte:int_8u; {byte for temporary variables}
+@!temp_int:int_32; {integer for temporary variables}
+@!dvi_start:int_32; {starting location}
+@!dvi_bop_post:int_32; {location of |bop| or |post|}
+@!dvi_back:int_32; {a back pointer}
+@!k:int_15; {general purpose variable}
+begin @<DVI: Process the preamble@>;
+if random_reading then @<DVI: Process the postamble@>;
+repeat dvi_first_par;
+ while cur_class=fnt_def_cl do
+ begin dvi_do_font(random_reading); dvi_first_par;
+ end;
+ if cur_cmd=bop then @<DVI: Process one page@>;
+until cur_cmd<>eop;
+if cur_cmd<>post then bad_dvi;
+exit:end;
+
+@ @<DVI: Process the preamble@>=
+if dvi_ubyte<>pre then bad_dvi;
+if dvi_ubyte<>dvi_id then bad_dvi;
+dvi_num:=dvi_pquad; dvi_den:=dvi_pquad; dvi_mag:=dvi_pquad;
+tfm_conv:=(25400000.0/dvi_num)*(dvi_den/473628672)/16.0;
+temp_byte:=dvi_ubyte; pckt_room(temp_byte);
+for k:=1 to temp_byte do append_byte(dvi_ubyte);
+print('DVI file: '''); print_packet(new_packet); print_ln(''',');
+print(' num=',dvi_num:1,', den=',dvi_den:1,', mag=',dvi_mag:1);
+if out_mag<=0 then out_mag:=dvi_mag @+ else print(' => ',out_mag:1);
+print_ln('.');
+do_pre; flush_packet
+
+@ @<Glob...@>=
+@!dvi_num:int_31; {numerator}
+@!dvi_den:int_31; {denominator}
+@!dvi_mag:int_31; {magnification}
+
+@ @<DVI: Process the postamble@>=
+begin dvi_start:=dvi_loc; {remember start of first page}
+@<DVI: Find the postamble@>;
+d_print_ln('DVI: postamble at ',dvi_bop_post:1);
+dvi_back:=dvi_pointer;
+if dvi_num<>dvi_pquad then bad_dvi;
+if dvi_den<>dvi_pquad then bad_dvi;
+if dvi_mag<>dvi_pquad then bad_dvi;
+temp_int:=dvi_squad; temp_int:=dvi_squad;
+if stack_size<dvi_upair then overflow(str_stack,stack_size);
+temp_int:=dvi_upair;
+dvi_first_par;
+while cur_class=fnt_def_cl do
+ begin dvi_do_font(false); dvi_first_par;
+ end;
+if cur_cmd<>post_post then bad_dvi;
+if not selected then @<DVI: Find the starting page@>;
+dvi_move(dvi_start); {go to first or starting page}
+end
+
+@ @<DVI: Find the postamble@>=
+temp_int:=dvi_length-5;
+repeat if temp_int<49 then bad_dvi;
+dvi_move(temp_int); temp_byte:=dvi_ubyte; decr(temp_int);
+until temp_byte<>dvi_pad;
+if temp_byte<>dvi_id then bad_dvi;
+dvi_move(temp_int-4); if dvi_ubyte<>post_post then bad_dvi;
+dvi_bop_post:=dvi_pointer;
+if (dvi_bop_post<15)or(dvi_bop_post>dvi_loc-34) then bad_dvi;
+dvi_move(dvi_bop_post); if dvi_ubyte<>post then bad_dvi
+
+@ @<DVI: Find the starting page@>=
+begin dvi_start:=dvi_bop_post; {just in case}
+while dvi_back<>-1 do
+ begin if (dvi_back<15)or(dvi_back>dvi_bop_post-46) then bad_dvi;
+ dvi_bop_post:=dvi_back; dvi_move(dvi_back);
+ if dvi_ubyte<>bop then bad_dvi;
+ for k:=0 to 9 do count[k]:=dvi_squad;
+ if start_match then dvi_start:=dvi_bop_post;
+ dvi_back:=dvi_pointer;
+ end;
+end
+
+@ When a |bop| has been read, the \.{DVI} commands for one page are
+interpreted until an |eop| is found.
+
+@<DVI: Process one page@>=
+begin for k:=0 to 9 do count[k]:=dvi_squad;
+temp_int:=dvi_pointer; do_bop;
+dvi_first_par;
+if type_setting then @<DVI: Process a page; then |goto done|@>
+else @<DVI: Skip a page; then |goto done|@>;
+done:if cur_cmd<>eop then bad_dvi;
+if selected then
+ begin do_eop;
+ if all_done then return;
+ end;
+end
+
+@ All \.{DVI} commands are processed, as long as |cur_class<>invalid_cl|;
+then we should have found an |eop|.
+
+@<DVI: Process a page; then |goto done|@>=
+loop begin
+ case cur_class of
+ char_cl: @<DVI: Typeset a |char|@>;
+ rule_cl:
+ if cur_upd and(cur_v_dimen=width_dimen) then
+ do_a_width(h_pixel_round(cur_h_dimen))
+ else do_rule;
+ xxx_cl:
+ begin pckt_room(cur_parm);
+ while cur_parm>0 do
+ begin append_byte(dvi_ubyte); decr(cur_parm);
+ end;
+ do_xxx;
+ end;
+ push_cl: do_push;
+ pop_cl: do_pop;
+ five_cases(w0_cl): do_right; {|right|, |w|, or |x|}
+ five_cases(y0_cl): do_down; {|down|, |y|, or |z|}
+ fnt_cl: dvi_font;
+ fnt_def_cl: dvi_do_font(random_reading);
+ invalid_cl: goto done;
+ end; {there are no other cases}
+dvi_first_par; {get the next command}
+end
+
+@ While skipping a page all commands other than font definitions are
+ignored.
+
+@<DVI: Skip a page; then |goto done|@>=
+loop begin
+ case cur_class of
+ xxx_cl: while cur_parm>0 do
+ begin temp_byte:=dvi_ubyte; decr(cur_parm);
+ end;
+ fnt_def_cl: dvi_do_font(random_reading);
+ invalid_cl: goto done;
+ othercases do_nothing;
+ endcases;
+dvi_first_par; {get the next command}
+end
+
+@ @<DVI: Typeset a |char|@>=
+begin @<Prepare to use font |cur_fnt|@>;
+set_cur_wp(cur_fnt)(bad_dvi);
+if font_type(cur_fnt)=vf_font_type then do_vf_packet @+ else do_char;
+end
+
+@* The main program.
+The code for real devices is still rather incomplete.
+Moreover several branches of the program have not been tested because
+they are never used with \.{DVI} files made by \TeX\ and \.{VF} files
+made by \.{VPtoVF}.
+
+@ At the end of the program the output file(s) have to be finished and
+on some systems it may be necessary to close input and\slash or output
+files.
+@^system dependencies@>
+
+@p procedure close_files_and_terminate;
+var k:@!int_15; {general purpose index}
+begin close_in(dvi_file);
+if history<fatal_message then @<Finish output file(s)@>;
+stat @<Print memory usage statistics@>;@+tats@;@/
+@<Close output file(s)@>@;
+@<Print the job |history|@>;
+end;
+
+@ Now we are ready to put it all together.
+Here is where \.{\title} starts, and where it ends.
+@^system dependencies@>
+
+@p begin initialize; {get all variables initialized}
+@<Initialize predefined strings@>@;
+dialog; {get options}
+@<Open input file(s)@>@;
+@<Open output file(s)@>@;
+do_dvi; {process the entire \.{DVI} file}
+close_files_and_terminate;
+final_end:end.
+
+@ @<Print memory usage statistics@>=
+print_ln('Memory usage statistics:');
+print(dvi_nf:1,' dvi, ',lcl_nf:1,' local, ');
+@<Print more font usage statistics@>@;@/
+print_ln('and ',nf:1,' internal fonts of ',max_fonts:1);
+print_ln(n_widths:1,' widths of ',max_widths:1,' for ',
+ n_chars:1,' characters of ',max_chars:1);
+print_ln(pckt_ptr:1,' byte packets of ',max_packets:1,' with ',
+ byte_ptr:1,' bytes of ',max_bytes:1);
+@<Print more memory usage statistics@>@;@/
+print_ln(stack_used:1,' of ',stack_size:1,' stack and ',
+ recur_used:1,' of ',max_recursion:1,' recursion levels.')
+
+@ Some implementations may wish to pass the |history| value to the
+operating system so that it can be used to govern whether or not other
+programs are started. Here we simply report the history to the user.
+@^system dependencies@>
+
+@<Print the job |history|@>=
+case history of
+spotless: print_ln('(No errors were found.)');
+harmless_message: print_ln('(Did you see the warning message above?)');
+error_message: print_ln('(Pardon me, but I think I spotted something wrong.)');
+fatal_message: print_ln('(That was a fatal error, my friend.)');
+end {there are no other cases}
+
+@* Low-level output routines.
+The program uses the binary file variable |out_file| for its main output
+file; |out_loc| is the number of the byte about to be written next on
+|out_file|.
+
+@<Glob...@>=
+@!out_file:byte_file; {the \.{DVI} file we are writing}
+@!out_loc:int_32; {where we are about to write, in |out_file|}
+@!out_back:int_32; {a back pointer}
+@!out_max_v:int_31; {maximum |v| value so far}
+@!out_max_h:int_31; {maximum |h| value so far}
+@!out_stack:int_16u; {maximum stack depth}
+@!out_pages:int_16u; {total number of pages}
+
+@ @<Set ini...@>=
+out_loc:=0; out_back:=-1;
+out_max_v:=0; out_max_h:=0;
+out_stack:=0; out_pages:=0;
+
+@ To prepare |out_file| for output, we |rewrite| it.
+
+@<Open output file(s)@>=
+rewrite(out_file); {prepares to write packed bytes to |out_file|}
+
+@ For some operating systems it may be necessary to close |out_file|.
+
+@<Close output file(s)@>=
+
+@ Writing the |out_file| should be done as efficient as possible for a
+particular system; on many systems this means that a large number of
+bytes will be accumulated in a buffer and is then written from that
+buffer to |out_file|. In order to simplify such system dependent changes
+we use the \.{WEB} macro |out_byte| to write the next \.{DVI} byte. Here
+we give a simple minded definition for this macro in terms of standard
+\PASCAL.
+@^system dependencies@>
+@^optimization@>
+
+@d out_byte(#) == write(out_file,#) {write next \.{DVI} byte}
+
+@ The \.{WEB} macro |out_one| is used to write one byte and to update
+|out_loc|.
+
+@d out_one(#) == begin out_byte(#); incr(out_loc); @+ end
+
+@ First the |out_packet| procedure copies a packet to |out_file|.
+
+@<Declare typesetting procedures@>=
+procedure out_packet(@!p:pckt_pointer);
+var k:byte_pointer; {index into |byte_mem|}
+begin Incr(out_loc)(pckt_length(p));
+for k:=pckt_start[p] to pckt_start[p+1]-1 do out_byte(bo(byte_mem[k]));
+end;
+
+@ Next are the procedures used to write integer numbers or even complete
+\.{DVI} commands to |out_file|; they all keep |out_loc| up to date.
+
+The |out_four| procedure outputs four bytes in two's complement notation,
+without risking arithmetic overflow.
+
+@<Declare typesetting procedures@>=
+procedure out_four(@!x:int_32); {output four bytes}
+@!begin_four; comp_four(out_byte); Incr(out_loc)(4);
+end;
+
+@ The |out_char| procedure outputs a |set_char| or \\{set} command or, if
+|upd=false|, a |put| command.
+
+@<Declare typesetting procedures@>=
+procedure out_char(@!upd:boolean;@!ext:int_32;@!res:eight_bits);
+ {output \\{set} or |put|}
+@!begin_char; comp_char(out_one);
+end;
+
+@ The |out_unsigned| procedure outputs a |fnt|, |xxx|, or |fnt_def|
+command with its first parameter (normally unsigned); a |fnt| command
+is converted into |fnt_num| whenever this is possible.
+
+@<Declare typesetting procedures@>=
+procedure out_unsigned(@!o:eight_bits;@!x:int_32);
+ {output |fnt_num|, |fnt|, |xxx|, or |fnt_def|}
+@!begin_unsigned; comp_unsigned(out_one);
+end;
+
+@ The |out_signed| procedure outputs a movement (|right|, |w|,
+|x|, |down|, |y|, or |z|) command with its (signed) parameter.
+
+@<Declare typesetting procedures@>=
+procedure out_signed(@!o:eight_bits;@!x:int_32);
+ {output |right|, |w|, |x|, |down|, |y|, or |z|}
+@!begin_signed; comp_signed(out_one);
+end;
+
+@ For an output font we set |font_type(f):=out_font_type|; in this case
+|font_font(f)| is the font number used for font~|f| in |out_file|.
+@^font types@>
+
+The global variable |out_nf| is the number of fonts already used in
+|out_file| and the array |out_fnts| contains their internal font numbers;
+the current font in |out_file| is called |out_fnt|.
+
+@<Glob...@>=
+@!out_fnts:array[font_number] of font_number; {internal font numbers}
+@!out_nf:font_number; {number of fonts used in |out_file|}
+@!out_fnt:font_number; {internal font number of current output font}
+
+@ @<Set init...@>=
+out_nf:=0;
+
+@ @<Print more font usage statistics@>=
+print(out_nf:1,' out, ');
+
+@ The |out_fnt_def| procedure outputs a complete font definition
+command.
+
+@<Declare typesetting procedures@>=
+procedure out_fnt_def(@!f:font_number);
+var p:pckt_pointer; {the font name packet}
+@!k,@!l:byte_pointer; {indices into |byte_mem|}
+@!a:eight_bits; {length of area part}
+begin out_unsigned(fnt_def1,font_font(f)); out_four(font_check(f));
+out_four(font_scaled(f)); out_four(font_design(f));@/
+p:=font_name(f); k:=pckt_start[p]; l:=pckt_start[p+1]-1;
+a:=bo(byte_mem[k]);@/
+Incr(out_loc)(l-k+2); out_byte(a); out_byte(l-k-a);
+while k<l do
+ begin incr(k); out_byte(bo(byte_mem[k]));
+ end;
+end;
+
+@* Writing the output file.
+Here we define the device dependent parts of the typesetting routines
+described earlier in this program.
+
+First we define a few quantities required by the device dependent code
+for a real output device in order to demonstrate how they might be
+defined and in order to be able to compile \.{DVIcopy} with the device
+dependent code included.
+
+@d h_resolution==300 {horizontal resolution in pixels per inch (dpi)}
+@d v_resolution==300 {vertical resolution in pixels per inch (dpi)}
+
+@d max_h_drift==2 {we insist that |abs(hh-h_pixel_round(h))<=max_h_drift|}
+@d max_v_drift==2 {we insist that |abs(vv-v_pixel_round(v))<=max_v_drift|}
+
+@<Glob...@>=
+@!device
+@!h_conv:real; {converts \.{DVI} units to horizontal pixels}
+@!v_conv:real; {converts \.{DVI} units to vertical pixels}
+ecived
+
+@ These are the local variables (if any) needed for |do_pre|.
+
+@<OUT: Declare local variables (if any) for |do_pre|@>=
+var k:int_15; {general purpose variable}
+@!p,@!q,@!r:byte_pointer; {indices into |byte_mem|}
+@!comment:packed array[1..comm_length] of char; {preamble comment prefix}
+
+@ And here is the device dependent code for |do_pre|; the \.{DVI} preamble
+comment written to |out_file| is similar to the one produced by \.{GFtoPK},
+but we want to apply our preamble comment prefix only once.
+
+@<OUT: Process the |pre|@>=
+out_one(pre); out_one(dvi_id);
+out_four(dvi_num); out_four(dvi_den); out_four(out_mag);@/
+p:=pckt_start[pckt_ptr-1]; q:=byte_ptr; {location of old \.{DVI} comment}
+comment:=preamble_comment; pckt_room(comm_length);
+for k:=1 to comm_length do append_byte(xord[comment[k]]);
+while byte_mem[p]=bi(" ") do incr(p); {remove leading blanks}
+if p=q then Decr(byte_ptr)(from_length)
+else begin k:=0;
+ while (k<comm_length)and(byte_mem[p+k]=byte_mem[q+k]) do incr(k);
+ if k=comm_length then Incr(p)(comm_length);
+ end;
+k:=byte_ptr-p; {total length}
+if k>255 then
+ begin k:=255; q:=p+255-comm_length; {at most 255 bytes}
+ end;
+out_one(k); out_packet(new_packet); flush_packet;
+for r:=p to q-1 do out_one(bo(byte_mem[r]));
+
+@ These are the additional local variables (if any) needed for |do_bop|;
+the variables |@!i| and |@!j| are already declared.
+
+@<OUT: Declare additional local variables |do_bop|@>=
+var
+
+@ And here is the device dependent code for |do_bop|.
+
+@<OUT: Process a |bop|@>=
+out_one(bop); incr(out_pages);
+for i:=0 to 9 do out_four(count[i]);
+out_four(out_back); out_back:=out_loc-45;
+out_fnt:=invalid_font;
+
+@ These are the local variables (if any) needed for |do_eop|.
+
+@<OUT: Declare local variables (if any) for |do_eop|@>=
+
+@ And here is the device dependent code for |do_eop|.
+
+@<OUT: Process an |eop|@>=
+out_one(eop);
+
+@ These are the local variables (if any) needed for |do_push|.
+
+@<OUT: Declare local variables (if any) for |do_push|@>=
+
+@ And here is the device dependent code for |do_push|.
+
+@<OUT: Process a |push|@>=
+if stack_ptr>out_stack then out_stack:=stack_ptr;
+out_one(push);
+
+@ These are the local variables (if any) needed for |do_pop|.
+
+@<OUT: Declare local variables (if any) for |do_pop|@>=
+
+@ And here is the device dependent code for |do_pop|.
+
+@<OUT: Process a |pop|@>=
+out_one(pop);
+
+@ These are the additional local variables (if any) needed for |do_xxx|;
+the variable |@!p|, the pointer to the packet containing the special
+string, is already declared.
+
+@<OUT: Declare additional local variables for |do_xxx|@>=
+var
+
+@ And here is the device dependent code for |do_xxx|.
+
+@<OUT: Process an |xxx|@>=
+out_unsigned(xxx1,pckt_length(p)); out_packet(p);
+
+@ These are the local variables (if any) needed for |do_right|.
+
+@<OUT: Declare local variables (if any) for |do_right|@>=
+
+@ And here is the device dependent code for |do_right|.
+
+@<OUT: Process a |right| or |w| or |x|@>=
+if cur_class<right_cl then out_one(cur_cmd) {|w0| or |x0|}
+else out_signed(dvi_right_cmd[cur_class],cur_parm); {|right|, |w|, or |x|}
+
+@ Here we update the |out_max_h| value.
+
+@<OUT: Move right@>=
+if abs(cur_h)>out_max_h then out_max_h:=abs(cur_h);
+
+@ These are the local variables (if any) needed for |do_down|.
+
+@<OUT: Declare local variables (if any) for |do_down|@>=
+
+@ And here is the device dependent code for |do_down|.
+
+@<OUT: Process a |down| or |y| or |z|@>=
+if cur_class<down_cl then out_one(cur_cmd) {|y0| or |z0|}
+else out_signed(dvi_down_cmd[cur_class],cur_parm); {|down|, |y|, or |z|}
+
+@ Here we update the |out_max_v| value.
+
+@<OUT: Move down@>=
+if abs(cur_v)>out_max_v then out_max_v:=abs(cur_v);
+
+@ These are the local variables (if any) needed for |do_width|.
+
+@<OUT: Declare local variables (if any) for |do_width|@>=
+
+@ And here is the device dependent code for |do_width|.
+
+@<OUT: Typeset a |width|@>=
+out_one(set_rule);
+out_four(width_dimen); out_four(cur_h_dimen);
+
+@ These are the additional local variables (if any) needed for |do_rule|;
+the variable |@!visible| is already declared.
+
+@<OUT: Declare additional local variables |do_rule|@>=
+var
+
+@ And here is the device dependent code for |do_rule|.
+
+@<OUT: Typeset a visible |rule|@>=
+out_one(dvi_rule_cmd[cur_upd]);
+out_four(cur_v_dimen); out_four(cur_h_dimen);
+
+@ @<OUT: Typeset an invisible |rule|@>=
+@<OUT: Typeset a visible |rule|@>
+
+@ These are the additional local variables (if any) needed for |do_font|;
+the variable |@!p| is already declared.
+
+@<OUT: Declare additional local variables for |do_font|@>=
+var
+
+@ And here is the device dependent code for |do_font|; if the \.{VF} file
+for a font could not be found, we simply assume this must be a real font.
+
+@<OUT: Look for a font file before trying to read the \.{VF} file;
+ if found |goto done|@>=
+
+@ @<OUT: Look for a font file after trying to read the \.{VF} file@>=
+if(out_nf>=max_fonts) then overflow(str_fonts,max_fonts);
+print('OUT: font ',cur_fnt:1); d_print(' => ',out_nf:1);
+print_font(cur_fnt);
+d_print(' at ',font_scaled(cur_fnt):1,' DVI units'); print_ln('.');
+font_type(cur_fnt):=out_font_type; font_font(cur_fnt):=out_nf;
+out_fnts[out_nf]:=cur_fnt; incr(out_nf);
+out_fnt_def(cur_fnt);
+
+@ And here is some device dependent code used before each character.
+
+@<OUT: Prepare to use font |cur_fnt|@>=
+
+@ These are the local variables (if any) needed for |do_char|.
+
+@<OUT: Declare local variables (if any) for |do_char|@>=
+
+@ And here is the device dependent code for |do_char|.
+
+@<OUT: Typeset a |char|@>=
+@!debug if font_type(cur_fnt)<>out_font_type then confusion(str_fonts);
+gubed @;
+if cur_fnt<>out_fnt then
+ begin out_unsigned(fnt1,font_font(cur_fnt)); out_fnt:=cur_fnt;
+ end;
+out_char(cur_upd,cur_ext,cur_res);
+
+@ If the program terminates in the middle of a page, we write as many
+|pop|s as necessary and one |eop|.
+
+@<OUT: Finish incomplete page@>=
+begin while stack_ptr>0 do
+ begin out_one(pop); decr(stack_ptr);
+ end;
+ out_one(eop);
+end
+
+@ If the output file has been started, we write the postamble; in
+addition we print the number of bytes and pages written to |out_file|.
+
+@<OUT: Finish output file(s)@>=
+if out_loc>0 then
+ begin @<OUT: Write the postamble@>;
+ k:=7-((out_loc-1) mod 4); {the number of |dvi_pad| bytes}
+ while k>0 do
+ begin out_one(dvi_pad); decr(k);
+ end;
+ print('OUT file: ',out_loc:1,' bytes, ',out_pages:1,' page');
+ if out_pages<>1 then print('s');
+ end
+else print('OUT file: no output');
+print_ln(' written.');
+if out_pages=0 then mark_harmless;
+
+@ Here we simply write the values accumulated during the \.{DVI} output.
+
+@<OUT: Write the postamble@>=
+out_one(post); out_four(out_back); out_back:=out_loc-5;@/
+out_four(dvi_num); out_four(dvi_den); out_four(out_mag);@/
+out_four(out_max_v); out_four(out_max_h);@/
+out_one(out_stack div @"100); out_one(out_stack mod @"100);@/
+out_one(out_pages div @"100); out_one(out_pages mod @"100);@/
+k:=out_nf;
+while k>0 do
+ begin decr(k); out_fnt_def(out_fnts[k]);
+ end;
+out_one(post_post); out_four(out_back);@/
+out_one(dvi_id)
+
+@ Here we could print more memory usage statistics; this possibility is,
+however, not used for \.{DVIcopy}.
+
+@<Print more memory usage statistics@>=
+
+@* System-dependent changes.
+This section should be replaced, if necessary, by changes to the program
+that are necessary to make \.{DVIcopy} work at a particular installation.
+It is usually best to design your change file so that all changes to
+previous sections preserve the section numbering; then everybody's version
+will be consistent with the printed program. More extensive changes,
+which introduce new sections, can be inserted here; then only the index
+itself will get a new section number.
+@^system dependencies@>
+
+@* Index.
+Pointers to error messages appear here together with the section numbers
+where each ident\-i\-fier is used.
diff --git a/obsolete/dviware/dvicopy/read.me b/obsolete/dviware/dvicopy/read.me
new file mode 100644
index 0000000000..056e38ab3f
--- /dev/null
+++ b/obsolete/dviware/dvicopy/read.me
@@ -0,0 +1,11 @@
+DVICOPY is a utility program that allows one to take a DVI file that references
+composite fonts (VF) and convert it into a DVI file that does not contain such
+references. It also serves as a basis for writing DVI drivers (much like
+DVItype).
+
+Change files are in progress for MS-DOS, CMS, VMS, and WEB2C and will be
+placed in this directory when available.
+
+The following files are currently available:
+
+dvicopy.web The WEB source for DVICOPY.
diff --git a/obsolete/dviware/dvipdfmx/README b/obsolete/dviware/dvipdfmx/README
new file mode 100644
index 0000000000..c1c405203f
--- /dev/null
+++ b/obsolete/dviware/dvipdfmx/README
@@ -0,0 +1,5 @@
+Development of dvipdfmx now takes place within the TeX Live framework, and
+it is no longer available as a separate package. For download, support, and
+other information, please see http://tug.org/tex-live.
+
+
diff --git a/obsolete/dviware/dvipdfmx/dvipdfmx.txt b/obsolete/dviware/dvipdfmx/dvipdfmx.txt
new file mode 100644
index 0000000000..71026f02ce
--- /dev/null
+++ b/obsolete/dviware/dvipdfmx/dvipdfmx.txt
@@ -0,0 +1,502 @@
+$Header: /home/cvsroot/dvipdfmx/README,v 1.27 2005/06/27 09:04:52 hirata Exp $
+
+The dvipdfmx Project
+====================
+
+Last modified: April 20, 2005
+
+
+Copyright (C) 2002-2004 by Jin-Hwan Cho and Shunsaku Hirata,
+the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+
+Contents
+--------
+
+1. Introduction
+
+2. Installation
+
+ 2.1. Compiling and Installation
+
+ 2.2. TeX Directory Structure (TDS)
+
+ 2.3. Auxiliary Files
+
+3. CJK Support
+
+ 3.1. Quick Test of Installation
+
+ 3.2. CJK-LaTeX and HLaTeX
+
+ 3.3. Omega and Other Extended TeX
+
+ 3.4. Vertical Typesetting
+
+4. Unicode Support
+
+ 4.1. Unicode Support in General
+
+ 4.2. ToUnicode CMap Support
+
+ 4.3. OpenType Support and Unicode
+
+ 4.4. Type1 Font Support and Unicode
+
+5. Graphics and Image Format
+
+ 5.1. Supported Graphics File Format
+
+ 5.2. Graphics Extension
+
+ 5.3. Using External Programs for Format Conversion
+
+6. DVI Specials
+
+ 6.1. Compatibility
+
+ 6.2. Additions to Dvipdfm's pdf: Special
+
+7. Font Mapping
+
+8. Incompatible Changes From Dvipdfm
+
+9. Other Improvement Over Dvipdfm
+
+10. Font Licensing and Embedding
+
+
+
+1. Introduction
+ ------------
+
+ The dvipdfmx (formerly dvipdfm-cjk) project provides an eXtended version
+ of the dvipdfm, a DVI to PDF translator developed by Mark A. Wicks.
+
+ The primary goal of this project is to support multi-byte character
+ encodings and large character sets for East Asian languages. The secondary
+ goal is to support as many features as pdfTeX developed by Han The Thanh.
+
+ This project is a combined work of the dvipdfm-jpn project by Shunsaku
+ Hirata and its modified one, dvipdfm-kor, by Jin-Hwan Cho.
+
+
+2. Installation
+ -----------------------
+
+ Typical usage and installation steps are not different from the original dvipdfm.
+ Please refer documents from dvipdfm distribution for detailed instruction on how
+ to install and how to use dvipdfm.
+
+
+2.1. Compiling and Installation
+
+
+ If you have obtained older version, please use latest version unless you have a
+ clear reason to choose older versions. The latest snapshot of dvipdfmx source is
+ available at:
+
+ http://project.ktug.or.kr/dvipdfmx/snapshot/
+
+ And the CVS repository for this project can be obtained through anonymous CVS
+ access with the following command:
+
+ cvs -d:pserver:anonymous@cvs.ktug.or.kr:/home/cvsroot login
+ cvs -d:pserver:anonymous@cvs.ktug.or.kr:/home/cvsroot co dvipdfmx
+
+ When prompted for a password, simply press the Enter key.
+
+
+ The kpathsea library is required to compile and install dvipdfmx in UNIX or
+ UNIX-like platforms. It is usually included for most of TeX distributions.
+ If you already have installed dvipdfm (the original) by yourself, you should
+ already have kpathsea library and it's headers. And zlib library is highly
+ recommended as dvipdfmx can't compress data without this.
+
+
+ Before starting things, you must check the location of your TeX installation.
+ If other TeX related programs are installed under, e.g., '/usr/local/TeX/bin',
+ you should specify directory '/usr/local/TeX' as an for ./configure script as
+
+ ./configure --prefix=/usr/local/TeX --with-kpathsea=/usr/local/TeX
+
+ If you are using libpaper to handle paper sizes for various program, you can
+ use --with-paper option to ./configure. The location of libpaper library can
+ be specified with this option as
+
+ --with-paper=DIR
+
+ Please note thath dvipdfmx uses JIS paper size for B-series paper instead of
+ ISO's one for historical reason. (too late to change the default behavior)
+ The most easiest way to fix this is to use libpaper if you already have that,
+ otherwise define ISO_PAPERSIZE macro at compilation time.
+
+ Dvipdfmx requires libpng library available from
+
+ http://www.libpng.org/pub/png/libpng.html
+
+ to read PNG format images. To tell dvipdfmx the location of libpng header
+ and library, use configure option
+
+ --with-png=DIR
+
+ After you have finished ./configure, just type
+
+ make && make install
+
+ then dvipdfmx will be installed under the directory specified by the --prefix
+ option to ./configure script. After you have successfully installed dvipdfmx,
+ you may need to install various auxiliary files and slightly adjust location
+ of files or configuration. Amount of additional files and modification depends
+ on your environment, and briefly described in the sections follows.
+
+
+2.2. TeX Directory Structure (TDS)
+
+
+ If your TeX installation is conforming with TDS version 1.1 described in
+
+ http://www.tug.org/ftp/tex/tds-1.1/
+
+ , then you'll need to adjust your dvipdfmx installtion. This also applies when
+ you have updated programs without modifying existing platform independent files
+ (files in texmf directory). Dvipdfmx installs few files in addition to dvipdfmx
+ program itself, dvipdfmx.cnf, cid-x.map and others, but it currently does not
+ choose installation directory as appropriate for TDS 1.1.
+
+ If your 'kpsewhich' program recognizes '.sfd' file format, i.e.,
+
+ kpsewhich --show-path --format=.sfd
+
+ does not answer as 'unknown format', then you should move several files under
+ appropriate locations or should modify texmf.cnf as follows:
+
+ * Subfont Definition (SFD) Files
+
+ Recommended location of SFD files (.sfd) is
+
+ $TEXMF/fonts/sfd/
+
+ and environmental variable for specifying additional search path for this
+ file format files is
+
+ SFDFONTS
+
+ . To make those files visible to dvipdfmx under TDS 1.1 installation, you
+ must move all .sfd files to the directory mentioned above or set SFDFONTS
+ variable in texmf.cnf. As some programs may not be updated to follow this
+ convention yet, it is recommended to preserve old installation directory.
+ If you have .sfd files under "$TEXMF/dvipdfm/", please do not use that,
+ please move all files to the directory mentioned above.
+
+ * PostScript CMap Resources
+
+ Recommended location of CMap files (no suffix or with suffix .cmap) is
+
+ $TEXMF/fonts/cmap/
+
+ and environmental variable for adding extra search path for this format files
+ is
+
+ CMAPFONTS
+
+ You may want to set CMAPFONTS to include GhostScript's Resource path, e.g.,
+
+ /usr/share/ghostscript/Resource/CMap//
+
+ in your texmf.cnf file as this resource can be used by various programs that
+ manipulates PS/PDF files. Dvipdfmx installs few additional files into the
+ directory "$TEXMF/dvipdfm/CMap", please move this files to the directory for
+ CMap files. But please note that file "Adobe-Identity-UCS2" is not meaningful
+ to other programs at all, so you should place at least this file in different
+ location than CMap files. (Or you can just remove this unless you see problems
+ in copy-and-pasting text from dvipdfmx output PDF.)
+
+ * Font Mapping Files
+
+ Suggested place for dvipdfm's font mapping files (.map) is
+
+ $TEXMF/fonts/map/dvipdfm/
+
+ and environmental variable for this format files is
+
+ TEXFONTMAPS
+
+ For files containing dvipdfmx extension to dvipdfm format, place them into
+
+ $TEXMF/fonts/map/dvipdfmx/
+
+ instead of sub-directory 'dvipdfm'.
+
+ * OpenType Fonts
+
+ Appropriate place for OpenType font with PostScript outline (.otf) is
+
+ $TEXMF/fonts/opentype/supplier/typeface/
+
+ where 'supplier' and 'typeface' should be replaced with font's supplier and
+ typeface identifier strings.
+
+
+2.3. Auxiliary Files
+
+
+ 1) CMap PostScript Resources
+
+ Dvipdfmx internally identifies glyphs in a font with identifier represented
+ as numbers ranging from 0 to 65535. CMap PostScript Resources defines how the
+ input character codes are translated to those ID's (CID). CID's should be
+ uniquely assigned to every glyphs contained in a collection of glyphs. Adobe
+ has defined several "character collection"s; Adobe-GB1 (Simplified Chinese),
+ Adobe-CNS1 (Traditional Chinese), Adobe-Japan1 (Japanese), and Adobe-Korea1
+ (Korean), which contains much of glyphs necessary for publishing for each
+ languages. Details on Adobe's character collections can be found at Adobe's
+ developer site:
+
+ http://partners.adobe.com/public/developer/font/index.html
+
+ Please install CMap resource files under the directory
+
+ ${TEXMF}/fonts/cmap
+
+ , or set CMAPFONTS variable to point the directory containing CMap resource
+ in texmf.cnf. If your TeX installation does not conforming TDS 1.1, then you
+ should set CMAPINPUTS variable to make those files visible to dvipdfmx. For
+ examples,
+
+ CMAPINPUTS= .;$TEXMF/fonts/cmap//
+
+ Adobe's "CMaps for PDF 1.4 CJK Fonts" are available from:
+
+ http://partners.adobe.com/public/developer/acrobat/index_advanced.html
+
+ or
+
+ ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/adobe/
+
+ You can find a short explanation of each CMap files in cid2code.txt contained
+ in the archive files found at the above FTP site.
+
+
+ 2) SubFont Definition Files
+
+ .....
+
+
+ 3) Adobe Glyph List and ToUnicode Mapping Files
+
+ The Adobe glyph list (AGL) file describes correspondence between PostScript
+ glyph names (e.g., AE, Aacute, ...) and it's Unicode character sequences.
+ Most features described in the section "Unicode Support" requires this file.
+
+ Dvipdfmx looks for file "glyphlist.txt" when conversion from PostScript glyph
+ names to Unicode is necessary. This conversion is done in various situations;
+ when creating ToUnicode CMap for 8bit encoded fonts, finding glyph description
+ from TrueType/OpenType fonts supporting Unicode when the font itself does not
+ provide the mapping from PostScript glyph names to glyph indices (version 2.0
+ "post" table), and when encoding "unicode" is specified for Type 1 font.
+
+ The "glyphlist.txt" file written by Adobe is found at
+
+ http://partners.adobe.com/asn/tech/type/glyphlist.txt
+
+ You should place file "glyphlist.txt" in a directory shown by
+
+ kpsewhich --progname=dvipdfm --show-path="other text files"
+
+ Please check kpathsea library can find this file by 'kpsewhich' command:
+
+ kpsewhich --progname=dvipdfm --format="other text files" glyphlist.txt
+
+ The 'progname' is not dvipdfmx but dvipdfm here.
+
+ ToUnicode mapping is similar to glyph list file but describes correspondence
+ between CID numbers and Unicode values. The content of this file look like a
+ CMap files and is contained in "CMaps for PDF 1.4 CJK Fonts" from Adobe (see
+ "CMap PostScript Resources" above). This file is required to support TrueType
+ font (including OpenType fonts with TrueType outline). Those files should be
+ installed same directory as ordinary CMap files.
+
+
+3. CJK Support
+
+3.1. Quick Test of Installation
+
+3.2. CJK-LaTeX and HLaTeX
+
+3.3. Omega and Other Extended TeX
+
+
+4. Unicode Support
+
+4.1. Unicode Support in General
+
+4.2. ToUnicode CMap Support
+
+4.3. OpenType Support and Unicode
+
+4.4. Type1 Font Support and Unicode
+
+
+5. Graphics and Image Format
+
+5.1. Supported Graphics File Format
+
+5.2. Graphics Extension
+
+5.3. Using External Programs for Format Conversion
+
+
+6. DVI Specials
+
+6.1. Compatibility
+
+6.2. Additions to Dvipdfm's pdf: Special
+
+
+7. Font Mapping
+
+
+7.1. Options for CJK Font
+
+ Few options are available in dvipdfmx (for CID-keyed fonts) in addition
+ to the original dvipdfm.
+
+
+ 1) TTC Index
+
+ You can specify TrueType Collection index number with :n: option in front
+ of TrueType font name.
+
+ min10 H :1:mincho
+
+ In this example, the option :1: tells dvipdfmx to select TrueType font #1
+ from TrueType collection font "mincho.ttc".
+
+
+ 2) No-embed Switch
+
+ It is possible to block embedding glyph data with the character `!'
+ in front of the font name in the font mapping file.
+
+ This feature reduces the size of the final PDF output, but the PDF file
+ may not be viewed exactly in other systems on which appropriate fonts
+ are not installed.
+
+ Use of this option is not recommended for fonts that contains unusual
+ characters (and characters having different width from default value).
+ Please note that glyph metric information is not written in the output
+ PDF file for TrueType fonts without embedding. It will be treated as
+ fixed-pitch with all widths equal to the default value (will be fixed
+ someday).
+
+
+ 3) Stylistic Variants
+
+ Keywords ",Bold", ",Italic", and ",BoldItalic" can be used to create
+ synthetic bold, italic, and bolditalic style variants from other font
+ using PDF viewer's (or OS's) function.
+
+ jbtmo@UKS@ UniKSCms-UCS2-H :0:!batang,Italic
+ jbtb@Unicode@ Identity-H !batang/UCS,Bold
+
+ Availability of this feature highly depends on the implementation of PDF
+ viewers. This feature is not supported for embedded fonts in the most of
+ PDF viewers, like Adobe Acrobat Reader and GNU Ghostscript.
+
+ Notice that this option automatically disable font embedding.
+
+
+
+8. Incompatible Changes From Dvipdfm
+
+
+
+9. Other Improvement Over Dvipdfm
+
+
+9.1. Encryption
+
+
+9.2. Font
+
+
+
+10. Font Licensing and Embedding
+
+ In OpenType format, information regarding how the font should be treated
+ when creating documents can be recorded. Dvipdfmx uses this information
+ to decide whether embedding font into the document is permitted.
+
+ This font embedding information is indicated by a flag called as "fsType"
+ flag; each bit representing different restrictions on font embedding.
+ If multiple flag bits are set in fsType, the least restrictive license
+ granted takes precedence in dvipdfmx. The fsType flag bits recognized by
+ dvipdfmx is as follows:
+
+ * Installable embedding
+
+ All font with this type of license can be embedded.
+
+ * Editable embedding
+
+ All font with this type of license can be embedded.
+
+ * Embedding for Preview & Print only
+
+ Dvipdfmx give the following warning message for fonts with this
+ type of license:
+
+ This document contains `Preview & Print' only licensed font
+
+ For the font with this type of licensing, font embedding is allowed
+ solely for the purpose of (on-screen) viewing and/or printing the
+ document; further editing of the document or extracting an embedded
+ font data for other purpose is not allowed. To ensure this condition,
+ you must at least protect your document with non-empty password.
+
+ All other flags are treated as more restrictive license than any of the
+ above flags and treated as "No embedding allowed"; e.g., if both of the
+ editable-embedding flag and unrecognized license flag is set, the font
+ is treated as editable-embedding allowed, however, if only unrecognized
+ flags are set, the font is not embedded.
+
+ Embedding flags are preserved in embedded font if the font is embedded
+ as a TrueType font or a CIDFontType 2 CIDFont. For all font embedded as
+ a PostScript font (CFF, CIDFontType 0 CIDFont), they are not preserved.
+ Only /Copyright and /Notice in the FontInfo dictionary are preserved in
+ this case.
+
+ Some font vendors put different embedding restrictions for different
+ condition; e.g., font embedding might be not permitted for commercial
+ materials unless you acquire "commercial license" separately.
+ Please read EULA carefully before making decision on font usage.
+
+
+ Adobe provide a font licensing FAQ and a list of embedding permissions
+ for Adobe Type Library fonts:
+
+ http://www.adobe.com/type/browser/legal/
+
+ For Japanese font in general, embedding permission tend to be somewhat
+ restrictive. Japanese users should read the statement regarding font
+ embedding from Japan Typography Association (in Japanese):
+
+ http://www.typo.or.jp/info/morals/moral4.html
+
+
+
diff --git a/obsolete/dviware/dvips/README b/obsolete/dviware/dvips/README
new file mode 100644
index 0000000000..d575443f93
--- /dev/null
+++ b/obsolete/dviware/dvips/README
@@ -0,0 +1,7 @@
+dvips, by Tomas Rokicki, is the principal DVI-to-PostScript translator.
+
+Development now takes place within the TeX Live framework, and it is no
+longer available as a separate package. For download, support, and
+other information, please see http://tug.org/tex-live.
+
+
diff --git a/obsolete/dviware/tkdvi/ChangeLog-0.1-0.2 b/obsolete/dviware/tkdvi/ChangeLog-0.1-0.2
new file mode 100644
index 0000000000..06148bea62
--- /dev/null
+++ b/obsolete/dviware/tkdvi/ChangeLog-0.1-0.2
@@ -0,0 +1,70 @@
+1999-06-18 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * Released version 0.2.
+
+ * lib/browser.tcl, lib/pagesel.tcl: Made sure the current page
+ is highlighted in the page selector even after a DVI file
+ reload.
+
+ * dvi/dviFile.c: Fixed reference count bug which resulted in
+ files not being closed properly when opened multiple times.
+
+ * lib/browser.tcl: Browser monster fix: Made measuring device
+ appear only in non-overview display modes. Fixed bug relating to
+ measuring device in scrolled canvas. Added keyboard shortcuts to
+ switch between display modes. Fixed wrap-around bug in paging
+ via keyboard and/or page selector arrow buttons where pages
+ would appear multiple times in non-single display modes. Changed
+ arrow buttons/keyboard scroll increment to scroll 16 pages in
+ overview mode.
+
+1999-06-16 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * configure.in: Bumped version number to 0.2 in preparation for
+ release.
+
+ * tkdvi.in: Obtain program version number from configure.in.
+
+1999-06-15 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * Fixed segmentation fault during de-allocation of PK fonts,
+ which was due to uninitialized *charInfoPtr entries.
+ (dvi/fontPK.c)
+
+ * Fixed bug where fonts would not be changed during a DVI file
+ reload. Now a DVI file carries a `generation number' which
+ counts the reloads, and this is checked during the reloading
+ operation to free and re-read the fonts if necessary.
+ (dvi/dvi.h, dvi/dviFile.c, dvi/image.c)
+
+1999-06-13 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * Prototype virtual font implementation. (touched lots of files
+ in dvi subdirectory)
+
+1999-06-14 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * Fixed error where it would not be possible to `make dist' in
+ a separate build directory -- the tests and test dvi files
+ would be looked for below the current directory rather than
+ $(srcdir). (Makefile.am)
+
+1999-06-12 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * Made build environment libtool-free, in favor of the Tcl
+ build information from tclConfig.sh. (configure.in,
+ dvi/Makefile.am)
+
+1999-06-11 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * Quoted the message in the 4-byte data type #error directive.
+ Thanks to Oliver Pust for pointing this out. (dvi/dvi.h)
+
+1999-06-10 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * Added configuration option `--with-kpathseainc=DIR' and extended
+ include path guessing conditionals to cope better with teTeX
+ being installed with differing `prefix' and `exec-prefix'.
+ Thanks to Jan Braun for helping to debug this. (configure.in,
+ dvi/Makefile.am, dvi/findFont.c, dvi/init.c)
+
diff --git a/obsolete/dviware/tkdvi/ChangeLog-0.2-0.3 b/obsolete/dviware/tkdvi/ChangeLog-0.2-0.3
new file mode 100644
index 0000000000..6d4e25ca49
--- /dev/null
+++ b/obsolete/dviware/tkdvi/ChangeLog-0.2-0.3
@@ -0,0 +1,198 @@
+2000-07-07 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * Released version 0.3.
+
+ * doc/tkdvi.1, doc/tkdvi::browser.3tcl: Improved man pages.
+
+ * Makefile.in: Improved man page installation procedure. Got rid
+ of Makefile in doc/ subdirectory.
+
+ * tkdvi.in: Added `-pr' (present) command line option. Options
+ which are not specially handled will be passed through to the
+ initial DVI window.
+
+ * dvi/Makefile.in, lib/Makefile.in: Installation subdirectories
+ now contain program's version number.
+
+ * Makefile.in, dvi/Makefile.in, lib/Makefile.in: Don't echo
+ file names when copying stuff to distribution directory.
+
+ * dvi/pkgIndex.tcl.in, dvi/Makefile.in: Fix pkgIndex.tcl so that
+ library is picked up either from current directory or from
+ directory above. Make sure that pkgIndex.tcl is created when
+ library has been built.
+
+ * dvi/configure.in: Make sure configure script looks at tkConfig.sh
+ as well as tclConfig.sh (which was a stupid oversight).
+
+ * dvi/image.c: Removed spurious initialization of masterPtr->layer
+ in image instance command.
+
+ * dvi/image.c: Hopefully fixed backward compatibility problems
+ with image type (esp. createProc) for good. Tk_InitImageArgs()
+ in Tcl/Tk 8.3.1 is broken.
+
+ * lib/tkdvi.tcl: Fix bug where internal widget counter for name
+ generation would not be incremented on `clone window'.
+
+ * lib/browser.tcl: Add check for <Destroy> event to quit program
+ when last DVI window is closed, unless the Tcl variable
+ tkdvi::browser::lastCloseExits is zero.
+
+ * lib/browser.tcl: Use (patched) tk_optionMenu widget instead of
+ home-grown button w/menu.
+
+ * lib/browser.tcl: Added `measureUnit' configuration option.
+
+ * lib/browser.tcl: Make sure `-toplevel' option isn't passed to
+ configure method when widget is created. (This is handled
+ specially beforehand.)
+
+ * lib/browser.tcl: Reintroduced reload-on-expose and layering.
+
+ * lib/browser.tcl: Fixed bugs around button 3.
+
+ * lib/browser.tcl: Added various key bindings, menu accelerators
+ and menu traversal keys.
+
+ * lib/tkdvi.ad: Added accelerators and menu traversal keys.
+ Removed obsolete `Options' menu.
+
+ * lib/menu.tcl: Added support for menu traversal keys and
+ accelerators.
+
+ * lib/browser.tcl: Made the General Preferences dialog work.
+
+ * lib/browser.tcl: Fixed a focus problem with presentations in
+ full-screen mode.
+
+ * lib/browser.tcl, lib/tkdvi.tcl: Added support for cloning a
+ window as well as opening a new file in a new window.
+
+ * lib/browser.tcl: Fixed various small bugs in
+ tkdvi::browser::Opopen; added option to specify a file name
+ rather than open a file selector box.
+
+2000-06-29 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * dvi/configure.in: Fixed bug in determination of `top_builddir'.
+
+ * dvi/dvi.h, dvi/dviFile.c, dvi/dviCFTcl.c: Added C-level and
+ Tcl-level APIs for access to DVI file comment.
+
+ * dvi/dviCFTcl.c, dvi/dviFontTcl.c, dvi/dviInterpTcl.c,
+ dvi/dviTcl.c, dvi/image.c: Added calls to Tcl_InitStubs() and
+ Tk_InitStubs() as appropriate.
+
+ * dvi/image.c: Fixed Tcl_Obj API for image type as per Jan
+ Nijtmans' suggestions.
+
+ * dvi/dviFontTcl.c, dvi/font.c, dvi/image.c: Added initial
+ support for obtaining document font lists.
+
+ * dvi/image.c: Added more paper formats.
+
+ * dvi/image.c: Re-enabled font reloading on document change.
+
+ * lib/browser.tcl: Completely new implementation as a
+ `megawidget'. Various new features such as free-hand drawing
+ on top of a DVI page, cross-hair rulers for checking alignment,
+ initial support for source specials (not quite working yet),
+ optional menu bar and tool bar, etc. Generally revamped look
+ and feel to be more like Acrobat Reader rather than gv.
+ Configuration through X resources is now possible.
+
+ * lib/pagesel.tcl: Completely new implementation as a
+ `megawidget'.
+
+2000-05-27 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * dvi/image.c: Changed image procedures to Tcl_Obj API for
+ compatibility with Tk 8.3.
+
+ * dvi/dviCFTcl.c: Fixed segmentation fault due to
+ non-reconstruction of Dvi_Code structure after file reloading.
+
+2000-05-26 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * dvi/dviCFTcl.c: Added support for `$dviCode configure',
+ `$dviCode findanchor' and `$dvicode info anchors'.
+
+ * dvi/dviCode.c: Added support for registering anchors during
+ pre-scan.
+
+ * dvi/dviFile.c: Fixed bug where `generation' member of Dvi_File
+ structure would not be initialized.
+
+ * lib/browser.tcl: Finished support for bookmarks and file
+ information à la PDF. Reinstated reloading code.
+
+2000-05-18 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * dvi/dviCFTcl.c, dvi/dviFontTcl.c, dvi/dviInterpTcl.c,
+ dvi/image.c: Replaced hard-coded version numbers in package
+ dependencies.
+
+ * dvi/dviFile.c, dvi/dviInterp.c, dvi/font.c, dvi/fontPK.c,
+ dvi/fontTFM.c: Tightened up datatypes on memory
+ allocation/deallocation calls to remove compiler warnings.
+
+ * dvi/image.c: Added Tk_ImagePostScriptProc member to DviImageType
+ for Tcl 8.2 compatibility.
+
+ * Replaced Automake setup by more Tcl-like approach. This
+ simplifies the make process considerably.
+
+2000-02-15 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * dvi/dviOps.h: Changed DVI opcodes from #define to enum.
+
+ * dvi/image.c: Added Tcl command callbacks for moving to/leaving
+ page (options `-precommand' and `-postcommand').
+
+ * dvi/image.c: Draft colour support (doesn't work quite right).
+
+ * dvi/image.c: Added configuration option synonyms `-bg', `-fg',
+ and `-gray' for consistency to other Tk widgets.
+
+ * dvi/image.c: Fixed bitmap shrinking bug.
+
+ * lib/tkdvi.ad: Added menu items for info, bookmarks, and
+ display modes menu.
+
+1999-09-01 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * tkdvi.in: Revised Tcl-level API for DVI browser.
+
+ * dvi/dviFontTcl.c, dvi/dviFont.c: Made generic font searching
+ code Tcl-independent; put Tcl glue into separate file.
+
+ * dvi/dviFile.c, dvi/dviCode.c, dvi/dviCFTcl.c, dvi/dviInterp.c,
+ dvi/dviInterpTcl.c: Divided DVI code handling in file-specific
+ and general code parts. This makes it possible (in theory) to
+ have DVI code generated on the fly, in addition to separating
+ the two layers of functionality better. Improved separation
+ between Tcl-independent DVI file handling and Tcl glue
+ layer. Revised C-level API for consistency. Introduced callback
+ function for file errors so dviFile.c functions no longer need a
+ Tcl interpreter.
+
+ * lib/browser.tcl: Adapted to new Tcl-level API.
+
+ * lib/browser.tcl: Added pop-up-from-overview feature, full-screen
+ display and more flexible display modes.
+
+ * lib/pagesel.tcl: Adapted to new Tcl-level API.
+
+ * lib/pagesel.tcl: Fixed selector painting bug.
+
+1999-06-24 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>
+
+ * dvi/dviInterp.c, dvi/image.c: Revised handling of \special{}
+ commands.
+
+ * lib/browser.tcl: Added scanning on mouse button 2.
+
+ * lib/browser.tcl: Support for `layered' DVI files.
+
+ * lib/browser.tcl: Added `p' and `n' shortcuts for paging.
diff --git a/obsolete/dviware/tkdvi/README b/obsolete/dviware/tkdvi/README
new file mode 100644
index 0000000000..112e3ab6a5
--- /dev/null
+++ b/obsolete/dviware/tkdvi/README
@@ -0,0 +1,167 @@
+TKDVI, A DVI PREVIEWER BASED ON TCL/TK
+======================================
+
+This is TkDVI, a DVI previewer built with the Tcl/Tk toolkit. The
+previewer is built around a Tk extension, `dvi', which implements an
+`image type' for displaying pages from DVI files (or DVI code in
+general).
+
+This README file corresponds to TkDVI 0.3, an alpha release.
+
+
+Features
+--------
+Here are the basic features of the `dvi' Tk extension:
+
+* Implements re-usable Tk `image type'. DVI material can occur
+ wherever Tk allows images, e.g., on a canvas (which is the most
+ sensible place), but also in labels, buttons etc.
+* Supports multiple windows displaying multiple pages from multiple
+ DVI files simultaneously.
+* All DVI files share the same fonts (if resolution etc. allows).
+* Supports fonts in PK format. (Virtual font support is forthcoming;
+ in the meantime dvicopy can be used to de-reference virtual fonts
+ in DVI files.) The standard Kpathsea library is used to locate
+ (and make) fonts.
+* Supports arbitrary (integer-factor) image shrinking as in xdvi.
+* Supports anti-aliasing as in xdvi.
+* Supports simple uses of colour.
+* Comes with an (incomplete) self-test suite.
+
+Here are the basic features of the TkDVI previewer:
+
+* Multiple DVI files.
+* Multiple DVI file windows.
+* Each DVI file window supports various display modes:
+ - `Single Page' as in xdvi
+ - `Two-page spread': Two facing pages, like a book.
+ - `16-page overview': Sixteen reduced pages at the same time, great
+ for looking at page breaks and floats.
+ - Full-screen mode for presentations.
+* `Magnification glass' as in xdvi.
+* `gv'-style page selector.
+* PDF-style document info (experimental).
+* PDF-style bookmarks when used with `hyperref' LaTeX extension
+ (experimental)
+* `Layering' of DVI material for presentations, fill-in-the-blanks etc.
+ (experimental)
+* Automatic reload of changed DVI files on Expose events as in xdvi.
+ This updates all windows that the DVI file is displayed in
+ (regardless of whether they are currently being exposed or not).
+* Can be easily adapted, reconfigured or extended in Tcl.
+
+The most notable omissions to date are:
+
+* No support for EPS graphics inclusions.
+
+As of now there is little or no documentation for most of the
+experimental features. Most of the \special commands supported by
+TkDVI are explained in doc/README.specials. See the testdvi/
+subdirectory for some examples of TeX input and output.
+
+
+Use and Distribution
+--------------------
+TkDVI is copyrighted © by Anselm Lingnau
+<lingnau@tm.informatik.uni-frankfurt.de>.
+
+TkDVI is NOT in the public domain but released as `free software'
+under the same license as Tcl/Tk, meaning that you can use it for
+whatever you want and also give away (possibly modified) copies to all
+your relations, friends, and enemies (depending on how you like the
+program). See the file COPYING for details.
+
+If you do make modifications or extensions of general interest, I
+would appreciate hearing about this. I'd be happy to include your
+contributions in the general distribution as long as their licensing
+doesn't interfere with the rest of the distribution (e.g., I can't
+integrate GPL patches into the main code base because that would
+`infect' the rest of TkDVI with the GPL -- I'd be happy to include
+such patches in a `DIY' corner of the distribution, though.).
+
+TkDVI uses the Kpathsea library by Karl Berry, which is licensed
+unter the LGPL. Due to its size, Kpathsea is not distributed with
+TkDVI but can be obtained separately.
+
+
+Documentation and Other Resources
+---------------------------------
+There is some documentation in the `doc' subdirectory of the
+distribution. As usual, this could be vastly improved.
+
+TkDVI is available from
+
+ ftp://ftp.tm.informatik.uni-frankfurt.de/pub/dist/tkdvi/
+
+The current version is always available as `tkdvi-current.tar.gz',
+which is a symbolic link to the real file, which will be called
+something like `tkdvi-0.3.tar.gz'.
+
+There is a World-Wide Web page dedicated to TkDVI at
+
+ http://www.tm.informatik.uni-frankfurt.de/~lingnau/tkdvi/
+
+There are two mailing lists about TkDVI:
+
+ tkdvi-announce@tm.informatik.uni-frankfurt.de
+
+ This low-volume mailing list carries announcements of general
+ interest to TkDVI users, such as announcements of new releases or
+ significant patches. (This list is moderated by me.)
+
+ tkdvi-users@tm.informatik.uni-frankfurt.de
+
+ This is a mailing list for general discussion about TkDVI, its
+ use, its advantages and disadvantages, bugs, features etc.
+ Everybody can post to this list. Traffic from tkdvi-announce
+ also appears here.
+
+You can subscribe to either of these lists by sending a message with a
+`Subject:' header of `subscribe' to
+
+ tkdvi-announce-request@tm.informatik.uni-frankfurt.de or
+ tkdvi-users-request@tm.informatik.uni-frankfurt.de ,
+
+respectively. You will be asked to confirm your subscription; just
+follow the directions and everything should be fine and dandy.
+
+Bugs can also be reported to
+
+ tkdvi-bugs@tm.informatik.uni-frankfurt.de
+
+Users of Debian GNU/Linux may feel free to use the Debian bug tracking
+system.
+
+
+Supported Platforms
+-------------------
+TkDVI has been tested on the following platforms:
+
+ Debian GNU/Linux 2.2 (Tcl/Tk 8.2.3, gcc 2.9)
+ - Should run on other comparable Linuxes as well
+
+Success stories, failure reports, patches etc. for other environments
+are most welcome.
+
+
+Installation
+------------
+Installation is described in the file INSTALL in the same directory.
+
+
+History
+-------
+I have been working on this program off and on since early 1994, even
+to the extent of giving talks on the software at DANTE conferences (in
+Münster 1994 and Oldenburg 1998). The 1994 version was based on Tk 3.6
+and implemented a full-blown DVI widget. Some code was released for
+this, but it was too incomplete and buggy to be generally useful.
+After Tk 4.0 came out, featuring the new image subsystem, I decided to
+re-implement my DVI stuff as an image type instead of a widget, in
+order to be able to use Tk canvas features in conjunction with DVI
+material rather than having to reimplement the canvas from scratch for
+the purposes of the DVI widget. Due to other distractions, I didn't
+have much time for this but finished a working version in time for the
+DANTE conference in February 1998. Since then, the code has matured
+somewhat, and the current code base seems solid enough to release as
+an alpha version.
diff --git a/obsolete/dviware/tkdvi/tkdvi-0.1-conf.patch b/obsolete/dviware/tkdvi/tkdvi-0.1-conf.patch
new file mode 100644
index 0000000000..2dee93e653
--- /dev/null
+++ b/obsolete/dviware/tkdvi/tkdvi-0.1-conf.patch
@@ -0,0 +1,863 @@
+Index: configure.in
+===================================================================
+RCS file: /usr/local/cvsroot/tkdvi/configure.in,v
+retrieving revision 1.1.1.1
+retrieving revision 1.3
+diff -u -r1.1.1.1 -r1.3
+--- configure.in 1999/06/10 12:36:50 1.1.1.1
++++ configure.in 1999/06/10 17:05:15 1.3
+@@ -1,4 +1,6 @@
++dnl Configure.in script for TkDVI.
+ dnl Process this file with autoconf to produce a configure script.
++dnl $Id: configure.in,v 1.3 1999/06/10 17:05:15 lingnau Exp $
+ AC_INIT(dvi/dviInt.h)
+ AM_INIT_AUTOMAKE(tkdvi, 0.1)
+
+@@ -114,17 +116,25 @@
+ AC_MSG_RESULT(Using kpathsea library in $kpathsea_libdir)
+ AC_SUBST(kpathsea_libdir)
+
++kpathsea_includedir=/usr/include
++AC_ARG_WITH(kpathseainc,
++ [ --with-kpathseainc=DIR 'kpathsea/proginit.h' is in DIR],
++ kpathsea_includedir=$withval)
+ AC_MSG_CHECKING(for Kpathsea include files)
+-if test -f /usr/include/kpathsea/proginit.h; then
+- kpathsea_includedir=/usr/include/kpathsea
++if test -f $kpathsea_includedir/kpathsea/proginit.h; then
++ true # all's well in the world
++elif test -f /usr/include/kpathsea/proginit.h; then
++ kpathsea_includedir=/usr/include
+ elif test -f $kpathsea_libdir/../kpathsea/proginit.h; then
+- kpathsea_includedir=`cd $kpathsea_libdir/../kpathsea; pwd`
++ kpathsea_includedir=`cd $kpathsea_libdir/..; pwd`
+ elif test -f $kpathsea_libdir/../../kpathsea/proginit.h; then
+- kpathsea_includedir=`cd $kpathsea_libdir/../../kpathsea; pwd`
++ kpathsea_includedir=`cd $kpathsea_libdir/../..; pwd`
+ elif test -f $kpathsea_libdir/../include/kpathsea/proginit.h; then
+- kpathsea_includedir=`cd $kpathsea_libdir/../include/kpathsea; pwd`
++ kpathsea_includedir=`cd $kpathsea_libdir/../include; pwd`
++elif test -f $kpathsea_libdir/../../include/kpathsea/proginit.h; then
++ kpathsea_includedir=`cd $kpathsea_libdir/../../include; pwd`
+ fi
+-if test ! -f $kpathsea_includedir/proginit.h; then
++if test ! -f $kpathsea_includedir/kpathsea/proginit.h; then
+ AC_MSG_ERROR(Couldn't find Kpathsea include files)
+ fi
+ AC_MSG_RESULT(in $kpathsea_includedir)
+Index: dvi/Makefile.am
+===================================================================
+RCS file: /usr/local/cvsroot/tkdvi/dvi/Makefile.am,v
+retrieving revision 1.1.1.1
+retrieving revision 1.3
+diff -u -r1.1.1.1 -r1.3
+--- dvi/Makefile.am 1999/06/10 12:36:50 1.1.1.1
++++ dvi/Makefile.am 1999/06/10 17:31:33 1.3
+@@ -3,7 +3,7 @@
+ # Makefile for `dvi' subdirectory of TkDVI.
+ # Copyright © 1999 Anselm Lingnau <lingnau@tm.informatik.uni-frankfurt.de>.
+ # See file COPYING for conditions on use and distribution.
+-# $Id: Makefile.am,v 1.1.1.1 1999/06/10 12:36:50 lingnau Exp $
++# $Id: Makefile.am,v 1.3 1999/06/10 17:31:33 lingnau Exp $
+
+ AUTOMAKE_OPTIONS = foreign
+
+@@ -24,7 +24,8 @@
+ fontPK.c fontTFM.c init.c misc.c image.c
+ libdvi_la_LIBADD = -lkpathsea
+
+-INCLUDES = -I$(kpathsea_includedir) -I$(tcl_includedir) -I$(tk_includedir)
++INCLUDES = -I$(kpathsea_includedir) -I$(kpathsea_includedir)/kpathsea \
++ -I$(tcl_includedir) -I$(tk_includedir)
+
+ # We need to use wish here because otherwise the Tk symbols in the
+ # extension cannot be resolved.
+Index: dvi/findFont.c
+===================================================================
+RCS file: /usr/local/cvsroot/tkdvi/dvi/findFont.c,v
+retrieving revision 1.1.1.1
+retrieving revision 1.2
+diff -u -r1.1.1.1 -r1.2
+--- dvi/findFont.c 1999/06/10 12:36:50 1.1.1.1
++++ dvi/findFont.c 1999/06/10 17:05:36 1.2
+@@ -10,14 +10,14 @@
+ #define WITH_KPATHSEA 1
+ #if WITH_KPATHSEA
+ #include <stdio.h> /* for FILE */
+-#include "proginit.h"
+-#include "tex-glyph.h"
++#include "kpathsea/proginit.h"
++#include "kpathsea/tex-glyph.h"
+ #endif
+
+ #include "dviInt.h"
+
+ #ifndef lint
+-static char rcsid[] VAR_UNUSED = "$Id: findFont.c,v 1.1.1.1 1999/06/10 12:36:50 lingnau Exp $";
++static char rcsid[] VAR_UNUSED = "$Id: findFont.c,v 1.2 1999/06/10 17:05:36 lingnau Exp $";
+ #endif /* lint */
+
+ int dvi_tfm_files_only = 0;
+Index: dvi/init.c
+===================================================================
+RCS file: /usr/local/cvsroot/tkdvi/dvi/init.c,v
+retrieving revision 1.1.1.1
+retrieving revision 1.2
+diff -u -r1.1.1.1 -r1.2
+--- dvi/init.c 1999/06/10 12:36:50 1.1.1.1
++++ dvi/init.c 1999/06/10 17:05:37 1.2
+@@ -12,11 +12,11 @@
+ */
+
+ #include <string.h>
+-#include "kpathsea.h"
++#include "kpathsea/kpathsea.h"
+ #include "dviInt.h"
+
+ #ifndef lint
+-static char rcsid[] VAR_UNUSED = "$Id: init.c,v 1.1.1.1 1999/06/10 12:36:50 lingnau Exp $";
++static char rcsid[] VAR_UNUSED = "$Id: init.c,v 1.2 1999/06/10 17:05:37 lingnau Exp $";
+ #endif /* lint */
+
+ typedef struct DviFileCookie {
+--- configure.old Thu Jun 10 14:36:50 1999
++++ configure Thu Jun 10 19:18:35 1999
+@@ -28,6 +28,8 @@
+ ac_help="$ac_help
+ --with-kpathsea=DIR use kpathsearch from DIR"
+ ac_help="$ac_help
++ --with-kpathseainc=DIR 'kpathsea/proginit.h' is in DIR"
++ac_help="$ac_help
+ --enable-debug enable debugging and regression tests"
+
+ # Initialize some variables set by options.
+@@ -570,7 +572,7 @@
+ # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+ # ./install, which can be erroneously created by make from ./install.sh.
+ echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+-echo "configure:574: checking for a BSD compatible install" >&5
++echo "configure:576: checking for a BSD compatible install" >&5
+ if test -z "$INSTALL"; then
+ if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+@@ -623,7 +625,7 @@
+ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+ echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
+-echo "configure:627: checking whether build environment is sane" >&5
++echo "configure:629: checking whether build environment is sane" >&5
+ # Just in case
+ sleep 1
+ echo timestamp > conftestfile
+@@ -680,7 +682,7 @@
+ test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+ echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+-echo "configure:684: checking whether ${MAKE-make} sets \${MAKE}" >&5
++echo "configure:686: checking whether ${MAKE-make} sets \${MAKE}" >&5
+ set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+@@ -726,7 +728,7 @@
+
+ missing_dir=`cd $ac_aux_dir && pwd`
+ echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
+-echo "configure:730: checking for working aclocal" >&5
++echo "configure:732: checking for working aclocal" >&5
+ # Run test in a subshell; some versions of sh will print an error if
+ # an executable is not found, even if stderr is redirected.
+ # Redirect stdin to placate older versions of autoconf. Sigh.
+@@ -739,7 +741,7 @@
+ fi
+
+ echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
+-echo "configure:743: checking for working autoconf" >&5
++echo "configure:745: checking for working autoconf" >&5
+ # Run test in a subshell; some versions of sh will print an error if
+ # an executable is not found, even if stderr is redirected.
+ # Redirect stdin to placate older versions of autoconf. Sigh.
+@@ -752,7 +754,7 @@
+ fi
+
+ echo $ac_n "checking for working automake""... $ac_c" 1>&6
+-echo "configure:756: checking for working automake" >&5
++echo "configure:758: checking for working automake" >&5
+ # Run test in a subshell; some versions of sh will print an error if
+ # an executable is not found, even if stderr is redirected.
+ # Redirect stdin to placate older versions of autoconf. Sigh.
+@@ -765,7 +767,7 @@
+ fi
+
+ echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
+-echo "configure:769: checking for working autoheader" >&5
++echo "configure:771: checking for working autoheader" >&5
+ # Run test in a subshell; some versions of sh will print an error if
+ # an executable is not found, even if stderr is redirected.
+ # Redirect stdin to placate older versions of autoconf. Sigh.
+@@ -778,7 +780,7 @@
+ fi
+
+ echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
+-echo "configure:782: checking for working makeinfo" >&5
++echo "configure:784: checking for working makeinfo" >&5
+ # Run test in a subshell; some versions of sh will print an error if
+ # an executable is not found, even if stderr is redirected.
+ # Redirect stdin to placate older versions of autoconf. Sigh.
+@@ -845,7 +847,7 @@
+ fi
+
+ echo $ac_n "checking host system type""... $ac_c" 1>&6
+-echo "configure:849: checking host system type" >&5
++echo "configure:851: checking host system type" >&5
+
+ host_alias=$host
+ case "$host_alias" in
+@@ -868,7 +870,7 @@
+ # Extract the first word of "ranlib", so it can be a program name with args.
+ set dummy ranlib; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:872: checking for $ac_word" >&5
++echo "configure:874: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -898,7 +900,7 @@
+ # Extract the first word of "gcc", so it can be a program name with args.
+ set dummy gcc; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:902: checking for $ac_word" >&5
++echo "configure:904: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -928,7 +930,7 @@
+ # Extract the first word of "cc", so it can be a program name with args.
+ set dummy cc; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:932: checking for $ac_word" >&5
++echo "configure:934: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -979,7 +981,7 @@
+ # Extract the first word of "cl", so it can be a program name with args.
+ set dummy cl; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:983: checking for $ac_word" >&5
++echo "configure:985: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1011,7 +1013,7 @@
+ fi
+
+ echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+-echo "configure:1015: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
++echo "configure:1017: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ ac_ext=c
+ # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+@@ -1022,12 +1024,12 @@
+
+ cat > conftest.$ac_ext << EOF
+
+-#line 1026 "configure"
++#line 1028 "configure"
+ #include "confdefs.h"
+
+ main(){return(0);}
+ EOF
+-if { (eval echo configure:1031: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:1033: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+@@ -1053,12 +1055,12 @@
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+ fi
+ echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+-echo "configure:1057: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
++echo "configure:1059: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+ echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+ cross_compiling=$ac_cv_prog_cc_cross
+
+ echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+-echo "configure:1062: checking whether we are using GNU C" >&5
++echo "configure:1064: checking whether we are using GNU C" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1067,7 +1069,7 @@
+ yes;
+ #endif
+ EOF
+-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1071: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
++if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1073: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+ else
+ ac_cv_prog_gcc=no
+@@ -1086,7 +1088,7 @@
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+-echo "configure:1090: checking whether ${CC-cc} accepts -g" >&5
++echo "configure:1092: checking whether ${CC-cc} accepts -g" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1130,7 +1132,7 @@
+ if test "$ac_cv_prog_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+-echo "configure:1134: checking for ld used by GCC" >&5
++echo "configure:1136: checking for ld used by GCC" >&5
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+@@ -1148,10 +1150,10 @@
+ esac
+ elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+-echo "configure:1152: checking for GNU ld" >&5
++echo "configure:1154: checking for GNU ld" >&5
+ else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+-echo "configure:1155: checking for non-GNU ld" >&5
++echo "configure:1157: checking for non-GNU ld" >&5
+ fi
+ if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+@@ -1187,7 +1189,7 @@
+ test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+
+ echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+-echo "configure:1191: checking if the linker ($LD) is GNU ld" >&5
++echo "configure:1193: checking if the linker ($LD) is GNU ld" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1203,7 +1205,7 @@
+
+
+ echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+-echo "configure:1207: checking for BSD-compatible nm" >&5
++echo "configure:1209: checking for BSD-compatible nm" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1240,7 +1242,7 @@
+
+
+ echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+-echo "configure:1244: checking whether ln -s works" >&5
++echo "configure:1246: checking whether ln -s works" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1276,8 +1278,8 @@
+ case "$host" in
+ *-*-irix6*)
+ # Find out which ABI we are using.
+- echo '#line 1280 "configure"' > conftest.$ac_ext
+- if { (eval echo configure:1281: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++ echo '#line 1282 "configure"' > conftest.$ac_ext
++ if { (eval echo configure:1283: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ case "`/usr/bin/file conftest.o`" in
+ *32-bit*)
+ LD="${LD-ld} -32"
+@@ -1318,7 +1320,7 @@
+ # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+ # ./install, which can be erroneously created by make from ./install.sh.
+ echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+-echo "configure:1322: checking for a BSD compatible install" >&5
++echo "configure:1324: checking for a BSD compatible install" >&5
+ if test -z "$INSTALL"; then
+ if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+@@ -1371,7 +1373,7 @@
+ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+ echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+-echo "configure:1375: checking whether ${MAKE-make} sets \${MAKE}" >&5
++echo "configure:1377: checking whether ${MAKE-make} sets \${MAKE}" >&5
+ set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+@@ -1399,12 +1401,12 @@
+
+
+ echo $ac_n "checking for labs""... $ac_c" 1>&6
+-echo "configure:1403: checking for labs" >&5
++echo "configure:1405: checking for labs" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_labs'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 1408 "configure"
++#line 1410 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char labs(); below. */
+@@ -1427,7 +1429,7 @@
+
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1431: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:1433: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_labs=yes"
+ else
+@@ -1464,7 +1466,7 @@
+
+
+ echo $ac_n "checking Tcl include file""... $ac_c" 1>&6
+-echo "configure:1468: checking Tcl include file" >&5
++echo "configure:1470: checking Tcl include file" >&5
+ tcl_includedir=
+ for ac_dir in $includedir $oldincludedir \
+ $tcl_libdir $tcl_libdir/.. $tcl_libdir/../..; do
+@@ -1492,7 +1494,7 @@
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1496: checking for $ac_word" >&5
++echo "configure:1498: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_TCLSH'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1552,7 +1554,7 @@
+
+
+ echo $ac_n "checking Tk include file""... $ac_c" 1>&6
+-echo "configure:1556: checking Tk include file" >&5
++echo "configure:1558: checking Tk include file" >&5
+ tk_includedir=
+ for ac_dir in $includedir $oldincludedir \
+ $tk_libdir $tk_libdir/.. $tk_libdir/../..; do
+@@ -1583,7 +1585,7 @@
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+-echo "configure:1587: checking for $ac_word" >&5
++echo "configure:1589: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_WISH'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -1648,18 +1650,29 @@
+ echo "$ac_t""Using kpathsea library in $kpathsea_libdir" 1>&6
+
+
++kpathsea_includedir=/usr/include
++# Check whether --with-kpathseainc or --without-kpathseainc was given.
++if test "${with_kpathseainc+set}" = set; then
++ withval="$with_kpathseainc"
++ kpathsea_includedir=$withval
++fi
++
+ echo $ac_n "checking for Kpathsea include files""... $ac_c" 1>&6
+-echo "configure:1653: checking for Kpathsea include files" >&5
+-if test -f /usr/include/kpathsea/proginit.h; then
+- kpathsea_includedir=/usr/include/kpathsea
++echo "configure:1662: checking for Kpathsea include files" >&5
++if test -f $kpathsea_includedir/kpathsea/proginit.h; then
++ true # all's well in the world
++elif test -f /usr/include/kpathsea/proginit.h; then
++ kpathsea_includedir=/usr/include
+ elif test -f $kpathsea_libdir/../kpathsea/proginit.h; then
+- kpathsea_includedir=`cd $kpathsea_libdir/../kpathsea; pwd`
++ kpathsea_includedir=`cd $kpathsea_libdir/..; pwd`
+ elif test -f $kpathsea_libdir/../../kpathsea/proginit.h; then
+- kpathsea_includedir=`cd $kpathsea_libdir/../../kpathsea; pwd`
++ kpathsea_includedir=`cd $kpathsea_libdir/../..; pwd`
+ elif test -f $kpathsea_libdir/../include/kpathsea/proginit.h; then
+- kpathsea_includedir=`cd $kpathsea_libdir/../include/kpathsea; pwd`
++ kpathsea_includedir=`cd $kpathsea_libdir/../include; pwd`
++elif test -f $kpathsea_libdir/../../include/kpathsea/proginit.h; then
++ kpathsea_includedir=`cd $kpathsea_libdir/../../include; pwd`
+ fi
+-if test ! -f $kpathsea_includedir/proginit.h; then
++if test ! -f $kpathsea_includedir/kpathsea/proginit.h; then
+ { echo "configure: error: Couldn't find Kpathsea include files" 1>&2; exit 1; }
+ fi
+ echo "$ac_t""in $kpathsea_includedir" 1>&6
+@@ -1681,7 +1694,7 @@
+
+
+ echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+-echo "configure:1685: checking how to run the C preprocessor" >&5
++echo "configure:1698: checking how to run the C preprocessor" >&5
+ # On Suns, sometimes $CPP names a directory.
+ if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+@@ -1696,13 +1709,13 @@
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+-#line 1700 "configure"
++#line 1713 "configure"
+ #include "confdefs.h"
+ #include <assert.h>
+ Syntax Error
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:1706: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1719: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ :
+@@ -1713,13 +1726,13 @@
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+-#line 1717 "configure"
++#line 1730 "configure"
+ #include "confdefs.h"
+ #include <assert.h>
+ Syntax Error
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:1723: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1736: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ :
+@@ -1730,13 +1743,13 @@
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+-#line 1734 "configure"
++#line 1747 "configure"
+ #include "confdefs.h"
+ #include <assert.h>
+ Syntax Error
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:1740: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1753: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ :
+@@ -1761,12 +1774,12 @@
+ echo "$ac_t""$CPP" 1>&6
+
+ echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+-echo "configure:1765: checking for ANSI C header files" >&5
++echo "configure:1778: checking for ANSI C header files" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 1770 "configure"
++#line 1783 "configure"
+ #include "confdefs.h"
+ #include <stdlib.h>
+ #include <stdarg.h>
+@@ -1774,7 +1787,7 @@
+ #include <float.h>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:1778: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1791: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+@@ -1791,7 +1804,7 @@
+ if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat > conftest.$ac_ext <<EOF
+-#line 1795 "configure"
++#line 1808 "configure"
+ #include "confdefs.h"
+ #include <string.h>
+ EOF
+@@ -1809,7 +1822,7 @@
+ if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat > conftest.$ac_ext <<EOF
+-#line 1813 "configure"
++#line 1826 "configure"
+ #include "confdefs.h"
+ #include <stdlib.h>
+ EOF
+@@ -1830,7 +1843,7 @@
+ :
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 1834 "configure"
++#line 1847 "configure"
+ #include "confdefs.h"
+ #include <ctype.h>
+ #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+@@ -1841,7 +1854,7 @@
+ exit (0); }
+
+ EOF
+-if { (eval echo configure:1845: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
++if { (eval echo configure:1858: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ :
+ else
+@@ -1868,17 +1881,17 @@
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+-echo "configure:1872: checking for $ac_hdr" >&5
++echo "configure:1885: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 1877 "configure"
++#line 1890 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:1882: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:1895: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+@@ -1906,12 +1919,12 @@
+
+
+ echo $ac_n "checking for working const""... $ac_c" 1>&6
+-echo "configure:1910: checking for working const" >&5
++echo "configure:1923: checking for working const" >&5
+ if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 1915 "configure"
++#line 1928 "configure"
+ #include "confdefs.h"
+
+ int main() {
+@@ -1960,7 +1973,7 @@
+
+ ; return 0; }
+ EOF
+-if { (eval echo configure:1964: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++if { (eval echo configure:1977: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+ else
+@@ -1981,12 +1994,12 @@
+ fi
+
+ echo $ac_n "checking for off_t""... $ac_c" 1>&6
+-echo "configure:1985: checking for off_t" >&5
++echo "configure:1998: checking for off_t" >&5
+ if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 1990 "configure"
++#line 2003 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #if STDC_HEADERS
+@@ -2014,12 +2027,12 @@
+ fi
+
+ echo $ac_n "checking for size_t""... $ac_c" 1>&6
+-echo "configure:2018: checking for size_t" >&5
++echo "configure:2031: checking for size_t" >&5
+ if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 2023 "configure"
++#line 2036 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #if STDC_HEADERS
+@@ -2047,12 +2060,12 @@
+ fi
+
+ echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
+-echo "configure:2051: checking whether stat file-mode macros are broken" >&5
++echo "configure:2064: checking whether stat file-mode macros are broken" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 2056 "configure"
++#line 2069 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/stat.h>
+@@ -2103,7 +2116,7 @@
+ fi
+
+ echo $ac_n "checking size of int""... $ac_c" 1>&6
+-echo "configure:2107: checking size of int" >&5
++echo "configure:2120: checking size of int" >&5
+ if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -2111,7 +2124,7 @@
+ ac_cv_sizeof_int=4
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 2115 "configure"
++#line 2128 "configure"
+ #include "confdefs.h"
+ #include <stdio.h>
+ main()
+@@ -2122,7 +2135,7 @@
+ exit(0);
+ }
+ EOF
+-if { (eval echo configure:2126: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
++if { (eval echo configure:2139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ ac_cv_sizeof_int=`cat conftestval`
+ else
+@@ -2142,7 +2155,7 @@
+
+
+ echo $ac_n "checking size of long""... $ac_c" 1>&6
+-echo "configure:2146: checking size of long" >&5
++echo "configure:2159: checking size of long" >&5
+ if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -2150,7 +2163,7 @@
+ ac_cv_sizeof_long=4
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 2154 "configure"
++#line 2167 "configure"
+ #include "confdefs.h"
+ #include <stdio.h>
+ main()
+@@ -2161,7 +2174,7 @@
+ exit(0);
+ }
+ EOF
+-if { (eval echo configure:2165: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
++if { (eval echo configure:2178: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ ac_cv_sizeof_long=`cat conftestval`
+ else
+@@ -2183,12 +2196,12 @@
+
+
+ echo $ac_n "checking for working attribute""... $ac_c" 1>&6
+-echo "configure:2187: checking for working attribute" >&5
++echo "configure:2200: checking for working attribute" >&5
+ if eval "test \"`echo '$''{'ac_cv_c_attribute'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 2192 "configure"
++#line 2205 "configure"
+ #include "confdefs.h"
+
+ int main() {
+@@ -2197,7 +2210,7 @@
+
+ ; return 0; }
+ EOF
+-if { (eval echo configure:2201: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
++if { (eval echo configure:2214: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_attribute=yes
+ else
+@@ -2222,17 +2235,17 @@
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+-echo "configure:2226: checking for $ac_hdr" >&5
++echo "configure:2239: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 2231 "configure"
++#line 2244 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+-{ (eval echo configure:2236: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++{ (eval echo configure:2249: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+@@ -2261,12 +2274,12 @@
+ for ac_func in getpagesize
+ do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+-echo "configure:2265: checking for $ac_func" >&5
++echo "configure:2278: checking for $ac_func" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 2270 "configure"
++#line 2283 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+@@ -2289,7 +2302,7 @@
+
+ ; return 0; }
+ EOF
+-if { (eval echo configure:2293: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:2306: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+ else
+@@ -2314,7 +2327,7 @@
+ done
+
+ echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+-echo "configure:2318: checking for working mmap" >&5
++echo "configure:2331: checking for working mmap" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+@@ -2322,7 +2335,7 @@
+ ac_cv_func_mmap_fixed_mapped=no
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 2326 "configure"
++#line 2339 "configure"
+ #include "confdefs.h"
+
+ /* Thanks to Mike Haertel and Jim Avera for this test.
+@@ -2462,7 +2475,7 @@
+ }
+
+ EOF
+-if { (eval echo configure:2466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
++if { (eval echo configure:2479: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ ac_cv_func_mmap_fixed_mapped=yes
+ else
+@@ -2487,12 +2500,12 @@
+ for ac_func in strtol strtoul
+ do
+ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+-echo "configure:2491: checking for $ac_func" >&5
++echo "configure:2504: checking for $ac_func" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+-#line 2496 "configure"
++#line 2509 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+@@ -2515,7 +2528,7 @@
+
+ ; return 0; }
+ EOF
+-if { (eval echo configure:2519: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++if { (eval echo configure:2532: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+ else
diff --git a/obsolete/dviware/tkdvi/tkdvi-0.3.1-gamma.patch b/obsolete/dviware/tkdvi/tkdvi-0.3.1-gamma.patch
new file mode 100644
index 0000000000..4eb495235a
--- /dev/null
+++ b/obsolete/dviware/tkdvi/tkdvi-0.3.1-gamma.patch
@@ -0,0 +1,261 @@
+Index: dvi/dvi.h
+===================================================================
+RCS file: /usr/local/cvsroot/tkdvi/dvi/dvi.h,v
+retrieving revision 1.7
+diff -u -r1.7 dvi.h
+--- dvi/dvi.h 2000/06/29 10:54:42 1.7
++++ dvi/dvi.h 2000/07/14 10:21:47
+@@ -228,18 +228,24 @@
+ S32 *tfmWidthPtr,
+ S32 *pixelWidthPtr));
+ typedef int (Dvi_FontCloseProc) _ANSI_ARGS_((struct Dvi_Font *dviFont));
++typedef int (Dvi_FontIterateCallbackProc)
++ _ANSI_ARGS_((struct Dvi_Font *dviFont, S32 i, Dvi_Glyph *glyphPtr));
++typedef int (Dvi_FontIterateProc) _ANSI_ARGS_((struct Dvi_Font *dviFont,
++ Dvi_FontIterateCallbackProc *));
+
+ typedef struct Dvi_FontTypeDesc {
+ char *name;
+ Dvi_FontLoadProc *loadProc;
+ Dvi_FontGlyphProc *glyphProc;
+ Dvi_FontCloseProc *closeProc;
++ Dvi_FontIterateProc *iterateProc;
+ } Dvi_FontTypeDesc;
+
+ EXTERN int Dvi_CreateFontType _ANSI_ARGS_((Dvi_FontType type, char *name,
+ Dvi_FontLoadProc *loadProc,
+ Dvi_FontGlyphProc *glyphProc,
+- Dvi_FontCloseProc *closeProc));
++ Dvi_FontCloseProc *closeProc,
++ Dvi_FontIterateProc *iterateProc));
+ EXTERN int Dvi_CreateFontType_PK _ANSI_ARGS_((void));
+ EXTERN int Dvi_CreateFontType_VF _ANSI_ARGS_((void));
+ EXTERN int Dvi_CreateFontType_TFM _ANSI_ARGS_((void));
+@@ -282,6 +288,8 @@
+ S32 character,
+ S32 *tfmWidthPtr,
+ S32 *pixelWidthPtr));
++EXTERN int Dvi_FontIterate _ANSI_ARGS_((Dvi_FontIterateCallbackProc *));
++
+ #ifdef DVI_DEBUG
+ EXTERN Tcl_Obj * Dvi_FontDump _ANSI_ARGS_((Tcl_Interp *interp,
+ Dvi_Font *dviFont));
+Index: dvi/font.c
+===================================================================
+RCS file: /usr/local/cvsroot/tkdvi/dvi/font.c,v
+retrieving revision 1.4
+diff -u -r1.4 font.c
+--- dvi/font.c 2000/06/29 11:01:38 1.4
++++ dvi/font.c 2000/07/14 10:21:47
+@@ -57,17 +57,20 @@
+ */
+
+ int
+-Dvi_CreateFontType (type, name, loadProc, glyphProc, closeProc)
++Dvi_CreateFontType (type, name, loadProc, glyphProc, closeProc,
++ iterateProc)
+ Dvi_FontType type;
+ char *name;
+ Dvi_FontLoadProc *loadProc;
+ Dvi_FontGlyphProc *glyphProc;
+ Dvi_FontCloseProc *closeProc;
++ Dvi_FontIterateProc *iterateProc;
+ {
+ fontTypes[type].name = name;
+ fontTypes[type].loadProc = loadProc;
+ fontTypes[type].glyphProc = glyphProc;
+ fontTypes[type].closeProc = closeProc;
++ fontTypes[type].iterateProc = iterateProc;
+ fontTypeCount++;
+
+ return TCL_OK;
+@@ -405,6 +408,26 @@
+ fontHeadPtr = headPtr;
+
+ return headPtr;
++}
++
++int
++Dvi_FontIterate(callbackProc)
++ Dvi_FontIterateCallbackProc *callbackProc;
++{
++ FontHead *headPtr;
++ Dvi_Font *fontPtr;
++
++ for (headPtr = fontHeadPtr; headPtr != 0; headPtr = headPtr->nextPtr) {
++ for (fontPtr = headPtr->fonts; fontPtr; fontPtr = fontPtr->nextPtr) {
++ Dvi_FontIterateProc *iterateProc
++ = fontTypes[fontPtr->type].iterateProc;
++
++ if (iterateProc != 0) {
++ (* iterateProc)(fontPtr, callbackProc);
++ }
++ }
++ }
++ return 1;
+ }
+
+ /*
+Index: dvi/fontPK.c
+===================================================================
+RCS file: /usr/local/cvsroot/tkdvi/dvi/fontPK.c,v
+retrieving revision 1.3
+diff -u -r1.3 fontPK.c
+--- dvi/fontPK.c 2000/05/18 12:50:32 1.3
++++ dvi/fontPK.c 2000/07/14 10:21:47
+@@ -62,6 +62,8 @@
+ static Dvi_Glyph *PkRunCount _ANSI_ARGS_((U8 *codePtr));
+
+ static int PkClose _ANSI_ARGS_((Dvi_Font *dviFont));
++static int PkIterate _ANSI_ARGS_((Dvi_Font *dviFont,
++ Dvi_FontIterateCallbackProc *callbackProc));
+
+ /*
+ * ------------------------------------------------------------------------
+@@ -83,7 +85,8 @@
+ int
+ Dvi_CreateFontType_PK ()
+ {
+- return Dvi_CreateFontType(dvi_font_pk, "pk", PkLoad, PkGlyph, PkClose);
++ return Dvi_CreateFontType(dvi_font_pk, "pk", PkLoad, PkGlyph, PkClose,
++ PkIterate);
+ }
+
+ static int
+@@ -622,4 +625,27 @@
+ }
+ ckfree((char *)charInfoPtr);
+ return TCL_OK;
++}
++
++static int
++PkIterate(dviFont, callback)
++ Dvi_Font *dviFont;
++ Dvi_FontIterateCallbackProc callback;
++{
++ PkInfo *infoPtr = (PkInfo *)dviFont->fontData;
++ PkCharInfo *charInfoPtr;
++ S32 i;
++
++ if (infoPtr == (PkInfo *)0) {
++ return 0;
++ }
++
++ charInfoPtr = infoPtr->charInfoPtr;
++ for (i = infoPtr->minChar; i <= infoPtr->maxChar; i++) {
++ if (charInfoPtr[i - infoPtr->minChar].glyphPtr) {
++ (* callback)(dviFont, i,
++ charInfoPtr[i - infoPtr->minChar].glyphPtr);
++ }
++ }
++ return 1;
+ }
+Index: dvi/image.c
+===================================================================
+RCS file: /usr/local/cvsroot/tkdvi/dvi/image.c,v
+retrieving revision 1.12
+diff -u -r1.12 image.c
+--- dvi/image.c 2000/07/07 08:00:36 1.12
++++ dvi/image.c 2000/07/14 10:21:47
+@@ -263,6 +263,8 @@
+ static int RenderFontDef _ANSI_ARGS_((ClientData, Dvi_Interp *,
+ Dvi_FontList **, S32, U32, U32,
+ U32, size_t, char *, Dvi_FontDefMode));
++
++static int ReleaseShrunkenGlyph _ANSI_ARGS_((Dvi_Font *, S32, Dvi_Glyph *));
+
+ /*
+ * This is a fixed version of the Tk_InitImageArgs function from the
+@@ -768,6 +770,17 @@
+ return TCL_OK;
+ }
+
++static int
++ReleaseShrunkenGlyph (junk0, junk1, glyphPtr)
++ Dvi_Font *junk0;
++ S32 junk1;
++ Dvi_Glyph *glyphPtr;
++{
++ XDestroyImage((XImage *)(glyphPtr->shrinkGlyphPtr));
++ glyphPtr->shrinkGlyphPtr = 0;
++ glyphPtr->shrink = 0;
++}
++
+ static ColorContext *
+ FindColorContext (instancePtr, fgUid, bgUid)
+ DviInstance *instancePtr;
+@@ -837,6 +850,8 @@
+
+ colorContextPtr->nextPtr = instancePtr->colorCachePtr;
+ instancePtr->colorCachePtr = colorContextPtr;
++
++ Dvi_FontIterate(ReleaseShrunkenGlyph);
+
+ return colorContextPtr;
+ }
+Index: lib/browser.tcl
+===================================================================
+RCS file: /usr/local/cvsroot/tkdvi/lib/browser.tcl,v
+retrieving revision 1.12
+diff -u -r1.12 browser.tcl
+--- lib/browser.tcl 2000/07/07 09:02:32 1.12
++++ lib/browser.tcl 2000/07/14 10:21:47
+@@ -31,6 +31,7 @@
+ measureunit {MeasureUnit cm}
+ sourcespecials {SourceSpecials 0}
+ freehandcolor {FreehandColor red}
++ gamma {Gamma 1.2}
+ }
+
+ foreach {option cv} [array get Options] {
+@@ -59,7 +60,10 @@
+ [namespace code [list Images $name -1]]
+ trace variable Configure($name-shrink) w \
+ [namespace code [list Images $name -1]]
+-
++
++ trace variable Configure($name-gamma) w \
++ [namespace code [list Images $name -1]]
++
+ trace variable Configure($name-titleformat) w \
+ [namespace code [list TitleFormat $name]]
+
+@@ -378,6 +382,7 @@
+
+ set State($name-$key,i) [::image create dvi -file $State($name-code) \
+ -shrink $shrink -size $Configure($name-size) \
++ -gamma $Configure($name-gamma) \
+ -specialcommand \
+ [namespace code [list SpecialCmd $name $key %x %y %c %s]] \
+ -precommand [namespace code [list PreCmd $name $key %p]] \
+@@ -1283,6 +1288,7 @@
+
+ set Dialog($name-defaultmode) [option get $name mode Mode]
+ set Dialog($name-measureunit) $Configure($name-measureunit)
++ set Dialog($name-gamma) $Configure($name-gamma)
+
+ label $p.layout-l -text {Default Display Mode: } -anchor e
+ eval OptionMenu $p.layout-m \
+@@ -1298,6 +1304,14 @@
+ grid $p.unit-m -row $row -column 1 -sticky we -padx 2 -pady 2
+ incr row
+
++ label $p.gamma-l -text {Gamma value:} -anchor e
++ scale $p.gamma-s -orient horizontal -length 80 -resolution 0.1 \
++ -showvalue true -from 0 -to 5 -tickinterval 0 \
++ -variable tkdvi::browser::Dialog($name-gamma)
++ grid $p.gamma-l -row $row -column 0 -sticky e -ipadx 5 -ipady 5
++ grid $p.gamma-s -row $row -column 1 -sticky we -padx 2 -pady 2
++ incr row
++
+ frame $p.sep -relief sunken -borderwidth 1 -height 2
+ grid $p.sep -row $row -column 0 -columnspan 2 -sticky we
+ incr row
+@@ -1319,6 +1333,7 @@
+ variable Dialog
+
+ set Configure($name-measureunit) $Dialog($name-measureunit)
++ set Configure($name-gamma) $Dialog($name-gamma)
+ option add *TkDVIBrowser.mode $Dialog($name-defaultmode) interactive
+
+ if {$quit} {
diff --git a/obsolete/dviware/tkdvi/tkdvi-et99.pdf b/obsolete/dviware/tkdvi/tkdvi-et99.pdf
new file mode 100644
index 0000000000..321cd4f77e
--- /dev/null
+++ b/obsolete/dviware/tkdvi/tkdvi-et99.pdf
Binary files differ
diff --git a/obsolete/dviware/tkdvi/tkdvi-etcl2K.pdf b/obsolete/dviware/tkdvi/tkdvi-etcl2K.pdf
new file mode 100644
index 0000000000..c1b7974a61
--- /dev/null
+++ b/obsolete/dviware/tkdvi/tkdvi-etcl2K.pdf
Binary files differ
diff --git a/obsolete/dviware/tkdvi/tkdvi_0.2-1.diff.gz b/obsolete/dviware/tkdvi/tkdvi_0.2-1.diff.gz
new file mode 100644
index 0000000000..2be149aa63
--- /dev/null
+++ b/obsolete/dviware/tkdvi/tkdvi_0.2-1.diff.gz
Binary files differ
diff --git a/obsolete/dviware/tkdvi/tkdvi_0.2-1.dsc b/obsolete/dviware/tkdvi/tkdvi_0.2-1.dsc
new file mode 100644
index 0000000000..c7efa4f3c7
--- /dev/null
+++ b/obsolete/dviware/tkdvi/tkdvi_0.2-1.dsc
@@ -0,0 +1,22 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+
+Source: tkdvi
+Version: 0.2-1
+Binary: tkdvi
+Maintainer: Anselm Lingnau <lingnau@debian.org>
+Architecture: any
+Standards-Version: 2.4.0.0
+Files:
+ cd8eacadfb41a1b4d4cfd918ac49089f 137239 tkdvi_0.2.orig.tar.gz
+ 7b6eeb891531376e8cb22865baabf05f 4636 tkdvi_0.2-1.diff.gz
+
+-----BEGIN PGP SIGNATURE-----
+Version: 2.6.3ia
+Charset: noconv
+
+iQCVAwUBN2pGWkkVMVUvHxy9AQGPYgQA1WL2CNyBgLKixGFHfiuaUwEWVgnNz3Hh
+X6r91Ha82YseUvcOsm9Obgl3zmUdbmDWPrDyB6dwEsVZeFbghonO51k8ScRM92rd
+bWXv3Skd5cdIuupalYLjw5CGq2q8ketjSHn2952NYn6YnVIJ51atN2LQnjhhfCaa
+1Zt11n7i7v4=
+=vG/Z
+-----END PGP SIGNATURE-----