diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /obsolete/dviware |
Initial commit
Diffstat (limited to 'obsolete/dviware')
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(®s, ®s); /* 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(®s, ®s); /* 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 Binary files differnew file mode 100644 index 0000000000..321cd4f77e --- /dev/null +++ b/obsolete/dviware/tkdvi/tkdvi-et99.pdf diff --git a/obsolete/dviware/tkdvi/tkdvi-etcl2K.pdf b/obsolete/dviware/tkdvi/tkdvi-etcl2K.pdf Binary files differnew file mode 100644 index 0000000000..c1b7974a61 --- /dev/null +++ b/obsolete/dviware/tkdvi/tkdvi-etcl2K.pdf diff --git a/obsolete/dviware/tkdvi/tkdvi_0.2-1.diff.gz b/obsolete/dviware/tkdvi/tkdvi_0.2-1.diff.gz Binary files differnew file mode 100644 index 0000000000..2be149aa63 --- /dev/null +++ b/obsolete/dviware/tkdvi/tkdvi_0.2-1.diff.gz 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----- |