[alt.sources] dviselect

montnaro@sprite.crd.ge.com (Skip Montanaro) (11/14/89)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 6)."
# Contents:  Makefile Makefile.orig dviselect.1 dviselect.c
#   dviselect.c.orig h lib
# Wrapped by montnaro@sprite on Sat Nov 11 17:13:26 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(1356 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
XDESTDIR=
XCFLAGS=	-O -I./h
XMAKE=	make
X
XBINDIR	= $(HOME)/.commands
XIPRBIN  = /usr/local
XMANDIR	= $(HOME)/.man
X
XCSRCS	= dviselect.c
XSRCS	= $(CSRCS) dviselect.1
X
Xdefault: dviselect lib/lib.a
X
Xsrc:	$(SRCS)
X	@echo Done
X
Xclean:
X	cd lib; $(MAKE) $(MFLAGS) clean
X	-rm -f core *.o dviselect imagen1 dviselect.shar*
X
Xinst-dviselect: dviselect dviselect.1
X	install -s dviselect ${BINDIR}/dviselect
X	-install -c -m 444 dviselect.1 ${MANDIR}/man1/dviselect.1
X
Xdviselect: dviselect.o lib/lib.a
X	${CC} ${CFLAGS} -o dviselect dviselect.o lib/lib.a
X
Xlib/lib.a :
X	cd lib; $(MAKE) $(MFLAGS)
X
Xdvidvi: dvidvi.c
X	$(CC) $(CFLAGS) -o dvidvi dvidvi.c
X
Xdepend:
X	makedepend $(CFLAGS) $(CSRCS)
X
Xshar :
X	$(MAKE) $(MFLAGS) clean
X	shar -n1 -e6 -t "Now do 'make dviselect'"          *  >dviselect.shar.1
X	shar -n2 -e6 -t "Now do 'make dviselect'"        h/*  >dviselect.shar.2
X	shar -n3 -e6 -t "Now do 'make dviselect'" lib/[a-f]*  >dviselect.shar.3
X	shar -n4 -e6 -t "Now do 'make dviselect'" lib/[g-m]*  >dviselect.shar.4
X	shar -n5 -e6 -t "Now do 'make dviselect'" lib/[n-p]*  >dviselect.shar.5
X	shar -n6 -e6 -t "Now do 'make dviselect'" lib/[q-zM]* >dviselect.shar.6
X
X# DO NOT DELETE THIS LINE -- make depend depends on it.
X
Xdviselect.o: ../h/types.h ../h/dvi.h ../h/dviclass.h ../h/dvicodes.h
Xdviselect.o: ../h/fio.h ../h/search.h /usr/include/stdio.h
Xdviselect.o: /usr/include/ctype.h
END_OF_Makefile
if test 1356 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
chmod +x Makefile
# end of overwriting check
fi
if test -f Makefile.orig -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile.orig\"
else
echo shar: Extracting \"Makefile.orig\" \(820 characters\)
sed "s/^X//" >Makefile.orig <<'END_OF_Makefile.orig'
XDESTDIR=
XCFLAGS=	-O -I../h
XMAKE=	make
X
XBINDIR	= $(HOME)/.commands
XIPRBIN  = /usr/local
XMANDIR	= $(HOME)/.man
X
XCSRCS	= dviselect.c
XSRCS	= $(CSRCS) dviselect.1
X
Xdefault: all
X
X$(SRCS):;	co -q $@
X
Xsrc:	$(SRCS)
X	@echo Done
X
Xclean:
X	-ci -q $(SRCS)
X	-rm core *.o dviselect imagen1
X
Xinst-dviselect: dviselect dviselect.1
X	install -s dviselect ${BINDIR}/dviselect
X	-install -c -m 444 dviselect.1 ${MANDIR}/man1/dviselect.1
X
Xdviselect: dviselect.o ../lib/lib.a
X	${CC} ${CFLAGS} -o dviselect dviselect.o ../lib/lib.a
X
Xdvidvi: dvidvi.c
X	$(CC) $(CFLAGS) -o dvidvi dvidvi.c
X
Xdepend:
X	makedepend $(CFLAGS) $(CSRCS)
X
X# DO NOT DELETE THIS LINE -- make depend depends on it.
X
Xdviselect.o: ../h/types.h ../h/dvi.h ../h/dviclass.h ../h/dvicodes.h
Xdviselect.o: ../h/fio.h ../h/search.h /usr/include/stdio.h
Xdviselect.o: /usr/include/ctype.h
END_OF_Makefile.orig
if test 820 -ne `wc -c <Makefile.orig`; then
    echo shar: \"Makefile.orig\" unpacked with wrong size!
fi
chmod +x Makefile.orig
# end of overwriting check
fi
if test -f dviselect.1 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dviselect.1\"
else
echo shar: Extracting \"dviselect.1\" \(3897 characters\)
sed "s/^X//" >dviselect.1 <<'END_OF_dviselect.1'
X.TH DVISELECT 1
X.SH NAME
Xdviselect \- extract pages from DVI files
X.SH SYNOPSIS
X.B dviselect
X[
X.B \-s
X] [
X.B \-i
X.I infile
X] [
X.B \-o
X.I outfile
X]
X.I "list of pages"
X[
X.I infile
X[
X.I outfile
X] ]
X.SH DESCRIPTION
X.I Dviselect
Xselects pages from a DVI file produced by TeX, creating a new DVI
Xfile usable by any of TeX's conversion program (e.g., iptex), or even
Xby dviselect itself.
X.PP
XA
X.I range
Xis a string of the form
X.I first:last
Xwhere both
X.I first
Xand
X.I last
Xare optional numeric strings, with negative numbers indicated by
Xa leading underscore character ``_''.  If both
X.I first
Xand
X.I last
Xare omitted, the colon may also be omitted, or may be replaced
Xwith an asterisk ``*''.  A
X.I page range
Xis a list of ranges separated by periods.  A
X.I "list of pages"
Xis described by a set of page ranges separated by commas and/or white space.
X.PP
X.I Dviselect
Xactually looks at the ten
X.I count
Xvariables that TeX writes; the first of these (\ecount0) is the
Xpage number, with \ecount1 through \ecount9 having varied uses
Xdepending on which macro packages are in use.  (Typically \ecount1
Xis a chapter or section number.)  A page is included in
X.IR dviselect 's
Xoutput if all its \ecount values are within any one of the ranges
Xlisted on the command line.  For example, the command
X``dviselect *.1,35:''
Xmight select everything in chapter 1, as well as pages 35 and up.
X``dviselect 10:30'' would select pages 10 through 30 (inclusive).
X``:43'' means everything up to and including page 43 (including
Xnegative-numbered pages).
XIf a Table of Contents has negative page numbers, ``:_1'' will select it.
X``*.4 .........1'' might
Xmean everything in every chapter 4 and an index, presuming \ecount9
Xwas set to 1 in the index.  (``*'' must be quoted from the shell;
Xthe null string is more convenient to use, if harder to read.)
X.PP
XInstead of \ecount values,
X.I dviselect
Xcan also select by ``absolute page number'', where the first page
Xis page 1, the second page 2, and so forth.  Absolute page numbers
Xare indicated by a leading equal sign ``=''.  Ranges of absolute
Xpages are also allowed: ``dviselect =3:7'' will extract the third
Xthrough seventh pages.  Dot separators are not legal in absolute
Xranges, and there are no negative absolute page numbers.
X.PP
XMore precisely, an asterisk or a null string implies no limit;
Xan equal sign means absolute pages rather than \ecounts;
Xa leading colon means everything up to and including the given page; a
Xtrailing colon means everything from the given page on; and
Xa period indicates that the next \ecount should be examined.
XIf fewer than 10 ranges are specified, the remaining \ecounts
Xare left unrestricted (that is, ``1:5'' and ``1:5.*'' are equivalent).
XA single number \fIn\fP is treated as if it were the range \fIn:n\fP.
XAn arbitrary number of page selectors may be given, separated by commas
Xor whitespace; a page is selected if any of the selectors matches
Xits \ecounts or absolute page number.
X.PP
XDviselect normally prints the page numbers of the pages selected; the
X.I \-s
Xoption suppresses this.
X.SH AUTHOR
XChris Torek, University of Maryland
X.SH "SEE ALSO"
Xdvipr(1), iptex(1), tex(1), \fIThe TeXbook\fP
X.SH BUGS
XA leading ``-'' ought to be allowed for negative numbers, but it
Xis currently used as a synonym for ``:'', for backwards compatibility.
X.PP
XSection or subsection selection will sometimes fail, for the DVI
Xfile lists only the \ecount values that were active when the page
Xended.  Clever macro packages can alleviate this by making use of
Xother ``free'' \ecount registers.  Chapters normally begin on new
Xpages, and do not suffer from this particular problem.
X.PP
X.I Dviselect
Xdoes not adjust the parameters in the postamble; however, since these
Xvalues are normally used only to size certain structures in the output
Xconversion programs, and the parameters never need to be adjusted upward,
Xthis has not proven to be a problem.
END_OF_dviselect.1
if test 3897 -ne `wc -c <dviselect.1`; then
    echo shar: \"dviselect.1\" unpacked with wrong size!
fi
chmod +x dviselect.1
# end of overwriting check
fi
if test -f dviselect.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dviselect.c\"
else
echo shar: Extracting \"dviselect.c\" \(22215 characters\)
sed "s/^X//" >dviselect.c <<'END_OF_dviselect.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/utilities/RCS/dviselect.c,v 1.3 87/12/06 12:27:33 grunwald Exp $";
X#endif
X
X/*
X * DVI page selection program
X *
X * Reads DVI version 2 files and selects pages, writing a new DVI
X * file.  The new DVI file is technically correct, though we do not
X * adjust the tallest and widest page values, nor the DVI stack size.
X * This is all right since the values will never become too small,
X * but it might be nice to fix them up.  Perhaps someday . . . .
X */
X
X#include "types.h"
X#include "dvi.h"
X#include "dviclass.h"
X#include "dvicodes.h"
X#include "fio.h"
X#include "search.h"
X#include <stdio.h>
X#include <ctype.h>
X
Xchar  *ProgName;
Xextern int   errno;
Xextern char *optarg;
Xextern int   optind;
X
X/* Globals */
Xchar	serrbuf[BUFSIZ];	/* buffer for stderr */
X
X/*
X * We will try to keep output lines shorter than MAXCOL characters.
X */
X#define MAXCOL	75
X
X/*
X * We use the following structure to keep track of fonts we have seen.
X * The final DVI file lists only the fonts it uses.
X */
Xstruct fontinfo {
X	i32	fi_newindex;	/* font number in output file */
X	int	fi_reallyused;	/* true => used on a page we copied */
X	i32	fi_checksum;	/* the checksum */
X	i32	fi_mag;		/* the magnification */
X	i32	fi_designsize;	/* the design size */
X	short	fi_n1;		/* the name header length */
X	short	fi_n2;		/* the name body length */
X	char	*fi_name;	/* the name itself */
X};
X
X/*
X * We need to remember which pages the user would like.  We build a linked
X * list that allows us to decide (for any given page) whether it should
X * be included in the output file.  Each page has ten \count variables
X * associated with it.  We put a bound on the values allowed for each, and
X * keep a linked list of alternatives should any be outside the allowed
X * range.  For example, `dviselect *.3,10-15' would generate a two-element
X * page list, with the first allowing any value for \count0 (and \counts 2 to
X * 9) but \count1 restricted to the range 3-3, and the second restricting
X * \count0 to the range 10-15 but leaving \counts 1 to 9 unrestrained.
X *
X * In case no bound is specified, the `nol' or `noh' flag is set (so that
X * we need not fix some `large' number as a maximum value).
X *
X * We also allow `absolute' page references, where the first page is
X * page 1, the second 2, and so forth.  These are specified with an
X * equal sign: `dviselect =4:10' picks up the fourth through tenth
X * sequential pages, irrespective of \count values.
X */
Xstruct pagesel {
X	i32	ps_low;		/* lower bound */
X	int	ps_nol;		/* true iff no lower bound */
X	i32	ps_high;	/* upper bound */
X	int	ps_noh;		/* true iff no upper bound */
X};
Xstruct pagelist {
X	struct	pagelist *pl_alt;	/* next in a series of alternates */
X	int	pl_len;			/* number of ranges to check */
X	int	pl_abs;			/* true iff absolute page ref */
X	struct	pagesel pl_pages[10];	/* one for each \count variable */
X};
X
Xint	SFlag;			/* true => -s, silent operation */
X
Xstruct	search *FontFinder;	/* maps from input indicies to fontinfo */
Xi32	NextOutputFontIndex;	/* generates output indicies */
Xi32	CurrentFontIndex;	/* current (old) index in input */
Xi32	OutputFontIndex;	/* current (new) index in ouput */
X
Xstruct	pagelist *PageList;	/* the list of allowed pages */
X
XFILE	*inf;			/* the input DVI file */
XFILE	*outf;			/* the output DVI file */
X
Xint	ExpectBOP;		/* true => BOP ok */
Xint	ExpectEOP;		/* true => EOP ok */
X
Xlong	StartOfLastPage;	/* The file position just before we started
X				   the last page (this is later written to
X				   the output file as the previous page
X				   pointer). */
Xlong	CurrentPosition;	/* The current position of the file */
X
Xint	UseThisPage;		/* true => current page is selected */
X
Xi32	InputPageNumber;	/* current absolute page in old DVI file */
Xint	NumberOfOutputPages;	/* number of pages in new DVI file */
X
Xi32	Numerator;		/* numerator from DVI file */
Xi32	Denominator;		/* denominator from DVI file */
Xi32	DVIMag;			/* magnification from DVI file */
X
Xi32	Count[10];		/* the 10 \count variables */
X
X/* save some string space: we use this a lot */
Xchar	writeerr[] = "error writing DVI file";
X
Xchar	*malloc(), *realloc(), *sprintf();
X
X/*
X * lint gets rather confused with the current definitions of getc and putc,
X * so we redefine them here (#if lint).  This should really be in the
X * standard I/O library, but I am not about to go change it now!
X */
X#ifdef lint
X#undef putc
X#undef getc
X#define putc(c,f) (*(f)->_ptr++ = (unsigned) (c))
X#define getc(f)   (*(f)->_ptr++)
X#endif
X
X/*
X * Return true iff the 10 \counts are one of the desired output pages.
X */
XDesiredPageP()
X{
X	register struct pagelist *pl;
X
X	for (pl = PageList; pl != NULL; pl = pl->pl_alt) {
X		register struct pagesel *ps = pl->pl_pages;
X		register int i;
X		register i32 *pagep;
X
X		pagep = pl->pl_abs ? &InputPageNumber : &Count[0];
X		for (i = 0; i < pl->pl_len; i++, ps++, pagep++)
X			if (!ps->ps_nol && *pagep < ps->ps_low ||
X			    !ps->ps_noh && *pagep > ps->ps_high)
X				break;	/* not within bounds */
X		if (i >= pl->pl_len)
X			return (1);	/* success */
X	}
X	return (0);
X}
X
X/*
X * Print a message to stderr, with an optional leading space, and handling
X * long line wraps.
X */
Xmessage(space, str, len)
X	int space;
X	register char *str;
X	register int len;
X{
X	static int beenhere;
X	static int col;
X
X	if (!beenhere)
X		space = 0, beenhere++;
X	if (len == 0)
X		len = strlen(str);
X	col += len;
X	if (space) {
X		if (col >= MAXCOL)
X			(void) putc('\n', stderr), col = len;
X		else
X			(void) putc(' ', stderr), col++;
X	}
X	while (--len >= 0)
X		(void) putc(*str++, stderr);
X	(void) fflush(stderr);
X}
X
X/*
X * Start a page (process a DVI_BOP).
X */
XBeginPage()
X{
X	register i32 *i;
X
X	if (!ExpectBOP)
X		GripeUnexpectedOp("BOP");
X	ExpectBOP = 0;
X	ExpectEOP++;		/* set the new "expect" state */
X
X	OutputFontIndex = -1;	/* new page requires respecifying font */
X	InputPageNumber++;	/* count it */
X	for (i = Count; i < &Count[10]; i++)
X		fGetLong(inf, *i);
X	(void) GetLong(inf);	/* previous page pointer */
X
X	if ((UseThisPage = DesiredPageP()) == 0)
X		return;
X
X	(void) putc(DVI_BOP, outf);
X	for (i = Count; i < &Count[10]; i++)
X		PutLong(outf, *i);
X	PutLong(outf, StartOfLastPage);
X	if (ferror(outf))
X		error(1, errno, writeerr);
X
X	StartOfLastPage = CurrentPosition;
X	CurrentPosition += 45;	/* we just wrote this much */
X
X	if (!SFlag) {		/* write nice page usage messages */
X		register int z = 0;
X		register int mlen = 0;
X		char msg[80];
X
X		(void) sprintf(msg, "[%d", Count[0]);
X		mlen = strlen(msg);
X		for (i = &Count[1]; i < &Count[10]; i++) {
X			if (*i == 0) {
X				z++;
X				continue;
X			}
X			while (--z >= 0)
X				msg[mlen++] = '.', msg[mlen++] = '0';
X			z = 0;
X			(void) sprintf(msg + mlen, ".%d", *i);
X			mlen += strlen(msg + mlen);
X		}
X		message(1, msg, mlen);
X	}
X}
X
X/*
X * End a page (process a DVI_EOP).
X */
XEndPage()
X{
X	if (!ExpectEOP)
X		GripeUnexpectedOp("EOP");
X	ExpectEOP = 0;
X	ExpectBOP++;
X
X	if (!UseThisPage)
X		return;
X
X	if (!SFlag)
X		message(0, "]", 1);
X
X	putc(DVI_EOP, outf);
X	if (ferror(outf))
X		error(1, errno, writeerr);
X	CurrentPosition++;
X	NumberOfOutputPages++;
X}
X
X/*
X * For each of the fonts used in the new DVI file, write out a definition.
X */
X/* ARGSUSED */
XPostAmbleFontEnumerator(addr, key)
X	char *addr;
X	i32 key;
X{
X
X	if (((struct fontinfo *) addr)->fi_reallyused)
X		WriteFont((struct fontinfo *) addr);
X}
X
XHandlePostAmble()
X{
X	register i32 c;
X
X	(void) GetLong(inf);	/* previous page pointer */
X	if (GetLong(inf) != Numerator)
X		GripeMismatchedValue("numerator");
X	if (GetLong(inf) != Denominator)
X		GripeMismatchedValue("denominator");
X	if (GetLong(inf) != DVIMag)
X		GripeMismatchedValue("\\magfactor");
X
X	putc(DVI_POST, outf);
X	PutLong(outf, StartOfLastPage);
X	PutLong(outf, Numerator);
X	PutLong(outf, Denominator);
X	PutLong(outf, DVIMag);
X	c = GetLong(inf);
X	PutLong(outf, c);	/* tallest page height */
X	c = GetLong(inf);
X	PutLong(outf, c);	/* widest page width */
X	c = GetWord(inf);
X	PutWord(outf, c);	/* DVI stack size */
X	PutWord(outf, NumberOfOutputPages);
X	StartOfLastPage = CurrentPosition;	/* point at post */
X	CurrentPosition += 29;	/* count all those `put's */
X#ifdef notdef
X	(void) GetWord(inf);	/* skip original number of pages */
X#endif
X
X	/*
X	 * just ignore all the incoming font definitions; we are done with
X	 * input file 
X	 */
X
X	/*
X	 * run through the FontFinder table and dump definitions for the
X	 * fonts we have used. 
X	 */
X	SEnumerate(FontFinder, PostAmbleFontEnumerator);
X
X	putc(DVI_POSTPOST, outf);
X	PutLong(outf, StartOfLastPage);	/* actually start of postamble */
X	putc(DVI_VERSION, outf);
X	putc(DVI_FILLER, outf);
X	putc(DVI_FILLER, outf);
X	putc(DVI_FILLER, outf);
X	putc(DVI_FILLER, outf);
X	CurrentPosition += 10;
X	while (CurrentPosition & 3)
X		putc(DVI_FILLER, outf), CurrentPosition++;
X	if (ferror(outf))
X		error(1, errno, writeerr);
X}
X
X/*
X * Write a font definition to the output file
X */
XWriteFont(fi)
X	register struct fontinfo *fi;
X{
X	register int l;
X	register char *s;
X
X	if (fi->fi_newindex < 256) {
X		putc(DVI_FNTDEF1, outf);
X		putc(fi->fi_newindex, outf);
X		CurrentPosition += 2;
X	} else if (fi->fi_newindex < 65536) {
X		putc(DVI_FNTDEF2, outf);
X		PutWord(outf, fi->fi_newindex);
X		CurrentPosition += 3;
X	} else if (fi->fi_newindex < 16777216) {
X		putc(DVI_FNTDEF3, outf);
X		Put3Byte(outf, fi->fi_newindex);
X		CurrentPosition += 4;
X	} else {
X		putc(DVI_FNTDEF4, outf);
X		PutLong(outf, fi->fi_newindex);
X		CurrentPosition += 5;
X	}
X	PutLong(outf, fi->fi_checksum);
X	PutLong(outf, fi->fi_mag);
X	PutLong(outf, fi->fi_designsize);
X	putc(fi->fi_n1, outf);
X	putc(fi->fi_n2, outf);
X	l = fi->fi_n1 + fi->fi_n2;
X	CurrentPosition += 14 + l;
X	s = fi->fi_name;
X	while (--l >= 0)
X		putc(*s, outf), s++;
X}
X
X/*
X * Handle the preamble.  Someday we should update the comment field.
X */
XHandlePreAmble()
X{
X	register int n, c;
X
X	if (GetByte(inf) != Sign8(DVI_PRE))
X		GripeMissingOp("PRE");
X	if (GetByte(inf) != Sign8(DVI_VERSION))
X		GripeMismatchedValue("DVI version number");
X	Numerator = GetLong(inf);
X	Denominator = GetLong(inf);
X	DVIMag = GetLong(inf);
X	putc(DVI_PRE, outf);
X	putc(DVI_VERSION, outf);
X	PutLong(outf, Numerator);
X	PutLong(outf, Denominator);
X	PutLong(outf, DVIMag);
X
X	n = UnSign8(GetByte(inf));
X	CurrentPosition = 15 + n;	/* well, almost */
X	putc(n, outf);
X	while (--n >= 0) {
X		c = GetByte(inf);
X		putc(c, outf);	/* never trust a macro, I always say */
X	}
X}
X
Xmain(argc, argv)
X	int argc;
X	register char **argv;
X{
X	register int c;
X	register char *s;
X	char *inname = NULL, *outname = NULL;
X
X	ProgName = *argv;
X	setbuf(stderr, serrbuf);
X
X	while ((c = getopt(argc, argv, "i:o:s")) != EOF) {
X		switch (c) {
X
X		case 's':	/* silent */
X			SFlag++;
X			break;
X
X		case 'i':
X			if (inname != NULL)
X				goto usage;
X			inname = optarg;
X			break;
X
X		case 'o':
X			if (outname != NULL)
X				goto usage;
X			outname = optarg;
X			break;
X
X		case '?':
Xusage:
X			fprintf(stderr, "\
XUsage: %s [-s] [-i infile] [-o outfile] pages [...] [infile [outfile]]\n",
X				ProgName);
X			(void) fflush(stderr);
X			exit(1);
X		}
X	}
X
X	while (optind < argc) {
X		s = argv[optind++];
X		c = *s;
X		if (!isalpha(c) && c != '/') {
X			if (ParsePages(s))
X				goto usage;
X		} else if (inname == NULL)
X			inname = s;
X		else if (outname == NULL)
X			outname = s;
X		else
X			goto usage;
X	}
X	if (PageList == NULL)
X		goto usage;
X	if (inname == NULL)
X		inf = stdin;
X	else if ((inf = fopen(inname, "r")) == 0)
X		error(1, errno, "cannot read %s", inname);
X	if (outname == NULL)
X		outf = stdout;
X	else if ((outf = fopen(outname, "w")) == 0)
X		error(1, errno, "cannot write %s", outname);
X
X	if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0)
X		error(1, 0, "cannot create font finder (out of memory?)");
X
X	ExpectBOP++;
X	StartOfLastPage = -1;
X	HandlePreAmble();
X	HandleDVIFile();
X	HandlePostAmble();
X	if (!SFlag)
X		fprintf(stderr, "\nWrote %d pages, %d bytes\n",
X			NumberOfOutputPages, CurrentPosition);
X	if (NumberOfOutputPages == 0)
X	  exit(1);
X	else
X	  exit(0);
X}
X
Xstruct pagelist *
XInstallPL(ps, n, absolute)
X	register struct pagesel *ps;
X	register int n;
X	int absolute;
X{
X	register struct pagelist *pl;
X
X	pl = (struct pagelist *) malloc(sizeof *pl);
X	if (pl == NULL)
X		GripeOutOfMemory(sizeof *pl, "page list");
X	pl->pl_alt = PageList;
X	PageList = pl;
X	pl->pl_len = n;
X	while (--n >= 0)
X		pl->pl_pages[n] = ps[n];
X	pl->pl_abs = absolute;
X}
X
X/*
X * Parse a string representing a list of pages.  Return 0 iff ok.  As a
X * side effect, the page selection(s) is (are) prepended to PageList.
X */
XParsePages(s)
X	register char *s;
X{
X	register struct pagesel *ps;
X	register int c;		/* current character */
X	register i32 n;		/* current numeric value */
X	register int innumber;	/* true => gathering a number */
X	int i;			/* next index in page select list */
X	int range;		/* true => saw a range indicator */
X	int negative;		/* true => number being built is negative */
X	int absolute;		/* true => absolute, not \count */
X	struct pagesel pagesel[10];
X
X#define white(x) ((x) == ' ' || (x) == '\t' || (x) == ',')
X
X	range = 0;
X	innumber = 0;
X	absolute = 0;
X	i = 0;
X	ps = pagesel;
X	/*
X	 * Talk about ad hoc!  (Not to mention convoluted.)
X	 */
X	for (;;) {
X		c = *s++;
X		if (i == 0 && !innumber && !range) {
X			/* nothing special going on */
X			if (c == 0)
X				return 0;
X			if (white(c))
X				continue;
X		}
X		if (c == '_') {
X			/* kludge: should be '-' for negatives */
X			if (innumber || absolute)
X				return (-1);
X			innumber++;
X			negative = 1;
X			n = 0;
X			continue;
X		}
X		if (c == '=') {
X			/* absolute page */
X			if (innumber || range || i > 0)
X				return (-1);
X			absolute++;
X			/*
X			 * Setting innumber means that there is always
X			 * a lower bound, but this is all right since
X			 * `=:4' is treated as if it were `=0:4'.  As
X			 * there are no negative absolute page numbers,
X			 * this selects pages 1:4, which is the proper
X			 * action.
X			 */
X			innumber++;
X			negative = 0;
X			n = 0;
X			continue;
X		}
X		if (isdigit(c)) {
X			/* accumulate numeric value */
X			if (!innumber) {
X				innumber++;
X				negative = 0;
X				n = c - '0';
X				continue;
X			}
X			n *= 10;
X			n += negative ? '0' - c : c - '0';
X			continue;
X		}
X		if (c == '-' || c == ':') {
X			/* here is a range */
X			if (range)
X				return (-1);
X			if (innumber) {	/* have a lower bound */
X				ps->ps_low = n;
X				ps->ps_nol = 0;
X			} else
X				ps->ps_nol = 1;
X			range++;
X			innumber = 0;
X			continue;
X		}
X		if (c == '*') {
X			/* no lower bound, no upper bound */
X			c = *s++;
X			if (innumber || range || i >= 10 ||
X			    (c && c != '.' && !white(c)))
X				return (-1);
X			ps->ps_nol = 1;
X			ps->ps_noh = 1;
X			goto finishnum;
X		}
X		if (c == 0 || c == '.' || white(c)) {
X			/* end of this range */
X			if (i >= 10)
X				return (-1);
X			if (!innumber) {	/* no upper bound */
X				ps->ps_noh = 1;
X				if (!range)	/* no lower bound either */
X					ps->ps_nol = 1;
X			} else {		/* have an upper bound */
X				ps->ps_high = n;
X				ps->ps_noh = 0;
X				if (!range) {
X					/* no range => lower bound == upper */
X					ps->ps_low = ps->ps_high;
X					ps->ps_nol = 0;
X				}
X			}
Xfinishnum:
X			i++;
X			if (c == '.') {
X				if (absolute)
X					return (-1);
X				ps++;
X			} else {
X				InstallPL(pagesel, i, absolute);
X				ps = pagesel;
X				i = 0;
X				absolute = 0;
X			}
X			if (c == 0)
X				return (0);
X			range = 0;
X			innumber = 0;
X			continue;
X		}
X		/* illegal character */
X		return (-1);
X	}
X#undef white
X}
X
X/*
X * Handle a font definition.
X */
XHandleFontDef(index)
X	i32 index;
X{
X	register struct fontinfo *fi;
X	register int i;
X	register char *s;
X	int def = S_CREATE | S_EXCL;
X
X	if ((fi = (struct fontinfo *) SSearch(FontFinder, index, &def)) == 0)
X		if (def & S_COLL)
X			error(1, 0, "font %d already defined", index);
X		else
X			error(1, 0, "cannot stash font %d (out of memory?)",
X				index);
X	fi->fi_reallyused = 0;
X	fi->fi_checksum = GetLong(inf);
X	fi->fi_mag = GetLong(inf);
X	fi->fi_designsize = GetLong(inf);
X	fi->fi_n1 = UnSign8(GetByte(inf));
X	fi->fi_n2 = UnSign8(GetByte(inf));
X	i = fi->fi_n1 + fi->fi_n2;
X	if ((s = malloc((unsigned) i)) == 0)
X		GripeOutOfMemory(i, "font name");
X	fi->fi_name = s;
X	while (--i >= 0)
X		*s++ = GetByte(inf);
X}
X
X/*
X * Handle a \special.
X */
XHandleSpecial(c, l, p)
X	int c;
X	register int l;
X	register i32 p;
X{
X	register int i;
X
X	if (UseThisPage) {
X		putc(c, outf);
X		switch (l) {
X
X		case DPL_UNS1:
X			putc(p, outf);
X			CurrentPosition += 2;
X			break;
X
X		case DPL_UNS2:
X			PutWord(outf, p);
X			CurrentPosition += 3;
X			break;
X
X		case DPL_UNS3:
X			Put3Byte(outf, p);
X			CurrentPosition += 4;
X			break;
X
X		case DPL_SGN4:
X			PutLong(outf, p);
X			CurrentPosition += 5;
X			break;
X
X		default:
X			panic("HandleSpecial l=%d", l);
X			/* NOTREACHED */
X		}
X		CurrentPosition += p;
X		while (--p >= 0) {
X			i = getc(inf);
X			putc(i, outf);
X		}
X		if (feof(inf))
X			error(1, 0, "unexpected EOF");
X		if (ferror(outf))
X			error(1, errno, writeerr);
X	} else
X		while (--p >= 0)
X			(void) getc(inf);
X}
X
XReallyUseFont()
X{
X	register struct fontinfo *fi;
X	int look = S_LOOKUP;
X
X	fi = (struct fontinfo *) SSearch(FontFinder, CurrentFontIndex, &look);
X	if (fi == 0)
X		error(1, 0, "index %d not in font table!", CurrentFontIndex);
X	if (fi->fi_reallyused == 0) {
X		fi->fi_reallyused++;
X		fi->fi_newindex = NextOutputFontIndex++;
X		WriteFont(fi);
X	}
X	if (fi->fi_newindex != OutputFontIndex) {
X		PutFontSelector(fi->fi_newindex);
X		OutputFontIndex = fi->fi_newindex;
X	}
X}
X
X/*
X * Write a font selection command to the output file
X */
XPutFontSelector(index)
X	i32 index;
X{
X
X	if (index < 64) {
X		putc(index + DVI_FNTNUM0, outf);
X		CurrentPosition++;
X	} else if (index < 256) {
X		putc(DVI_FNT1, outf);
X		putc(index, outf);
X		CurrentPosition += 2;
X	} else if (index < 65536) {
X		putc(DVI_FNT2, outf);
X		PutWord(outf, index);
X		CurrentPosition += 3;
X	} else if (index < 16777216) {
X		putc(DVI_FNT3, outf);
X		Put3Byte(outf, index);
X		CurrentPosition += 4;
X	} else {
X		putc(DVI_FNT4, outf);
X		PutLong(outf, index);
X		CurrentPosition += 5;
X	}
X}
X
X/*
X * The following table describes the length (in bytes) of each of the DVI
X * commands that we can simply copy, starting with DVI_SET1 (128).
X */
Xchar	oplen[128] = {
X	0, 0, 0, 0,		/* DVI_SET1 .. DVI_SET4 */
X	9,			/* DVI_SETRULE */
X	0, 0, 0, 0,		/* DVI_PUT1 .. DVI_PUT4 */
X	9,			/* DVI_PUTRULE */
X	1,			/* DVI_NOP */
X	0,			/* DVI_BOP */
X	0,			/* DVI_EOP */
X	1,			/* DVI_PUSH */
X	1,			/* DVI_POP */
X	2, 3, 4, 5,		/* DVI_RIGHT1 .. DVI_RIGHT4 */
X	1,			/* DVI_W0 */
X	2, 3, 4, 5,		/* DVI_W1 .. DVI_W4 */
X	1,			/* DVI_X0 */
X	2, 3, 4, 5,		/* DVI_X1 .. DVI_X4 */
X	2, 3, 4, 5,		/* DVI_DOWN1 .. DVI_DOWN4 */
X	1,			/* DVI_Y0 */
X	2, 3, 4, 5,		/* DVI_Y1 .. DVI_Y4 */
X	1,			/* DVI_Z0 */
X	2, 3, 4, 5,		/* DVI_Z1 .. DVI_Z4 */
X	0,			/* DVI_FNTNUM0 (171) */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 172 .. 179 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 180 .. 187 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 188 .. 195 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 196 .. 203 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 204 .. 211 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 212 .. 219 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 220 .. 227 */
X	0, 0, 0, 0, 0, 0, 0,	/* 228 .. 234 */
X	0, 0, 0, 0,		/* DVI_FNT1 .. DVI_FNT4 */
X	0, 0, 0, 0,		/* DVI_XXX1 .. DVI_XXX4 */
X	0, 0, 0, 0,		/* DVI_FNTDEF1 .. DVI_FNTDEF4 */
X	0,			/* DVI_PRE */
X	0,			/* DVI_POST */
X	0,			/* DVI_POSTPOST */
X	0, 0, 0, 0, 0, 0,	/* 250 .. 255 */
X};
X
X/*
X * Here we read the input DVI file and write relevant pages to the
X * output DVI file. We also keep track of font changes, handle font
X * definitions, and perform some other housekeeping.
X */
XHandleDVIFile()
X{
X	register int c, l;
X	register i32 p;
X	register int CurrentFontOK = 0;
X
X	/* Only way out is via "return" statement */
X	for (;;) {
X		c = getc(inf);	/* getc() returns unsigned values */
X		if (DVI_IsChar(c)) {
X			/*
X			 * Copy chars, note font usage, but ignore if
X			 * page is not interesting.
X			 */
X			if (!UseThisPage)
X				continue;
X			if (!CurrentFontOK) {
X				ReallyUseFont();
X				CurrentFontOK++;
X			}
X			putc(c, outf);
X			CurrentPosition++;
X			continue;
X		}
X		if (DVI_IsFont(c)) {	/* note font change */
X			CurrentFontIndex = c - DVI_FNTNUM0;
X			CurrentFontOK = 0;
X			continue;
X		}
X		if ((l = (oplen - 128)[c]) != 0) {	/* simple copy */
X			if (!UseThisPage) {
X				while (--l > 0)
X					(void) getc(inf);
X				continue;
X			}
X			CurrentPosition += l;
X			putc(c, outf);
X			while (--l > 0) {
X				c = getc(inf);
X				putc(c, outf);
X			}
X			if (ferror(outf))
X				error(1, errno, writeerr);
X			continue;
X		}
X		if ((l = DVI_OpLen(c)) != 0) {
X			/*
X			 * Handle other generics.
X			 * N.B.: there should only be unsigned parameters
X			 * here (save SGN4), for commands with negative
X			 * parameters have been taken care of above.
X			 */
X			switch (l) {
X
X			case DPL_UNS1:
X				p = getc(inf);
X				break;
X
X			case DPL_UNS2:
X				fGetWord(inf, p);
X				break;
X
X			case DPL_UNS3:
X				fGet3Byte(inf, p);
X				break;
X
X			case DPL_SGN4:
X				fGetLong(inf, p);
X				break;
X
X			default:
X				panic("HandleDVIFile l=%d", l);
X			}
X
X			/*
X			 * Now that we have the parameter, perform the
X			 * command.
X			 */
X			switch (DVI_DT(c)) {
X
X			case DT_SET:
X			case DT_PUT:
X				if (!UseThisPage)
X					continue;
X				if (!CurrentFontOK) {
X					ReallyUseFont();
X					CurrentFontOK++;
X				}
X				putc(c, outf);
X				switch (l) {
X
X				case DPL_UNS1:
X					putc(p, outf);
X					CurrentPosition += 2;
X					continue;
X
X				case DPL_UNS2:
X					PutWord(outf, p);
X					CurrentPosition += 3;
X					continue;
X
X				case DPL_UNS3:
X					Put3Byte(outf, p);
X					CurrentPosition += 4;
X					continue;
X
X				case DPL_SGN4:
X					PutLong(outf, p);
X					CurrentPosition += 5;
X					continue;
X				}
X
X			case DT_FNT:
X				CurrentFontIndex = p;
X				CurrentFontOK = 0;
X				continue;
X
X			case DT_XXX:
X				HandleSpecial(c, l, p);
X				continue;
X
X			case DT_FNTDEF:
X				HandleFontDef(p);
X				continue;
X
X			default:
X				panic("HandleDVIFile DVI_DT(%d)=%d",
X				      c, DVI_DT(c));
X			}
X			continue;
X		}
X
X		switch (c) {	/* handle the few remaining cases */
X
X		case DVI_BOP:
X			BeginPage();
X			CurrentFontOK = 0;
X			break;
X
X		case DVI_EOP:
X			EndPage();
X			break;
X
X		case DVI_PRE:
X			GripeUnexpectedOp("PRE");
X			/* NOTREACHED */
X
X		case DVI_POST:
X			return;
X
X		case DVI_POSTPOST:
X			GripeUnexpectedOp("POSTPOST");
X			/* NOTREACHED */
X
X		default:
X			GripeUndefinedOp(c);
X			/* NOTREACHED */
X		}
X	}
X}
END_OF_dviselect.c
if test 22215 -ne `wc -c <dviselect.c`; then
    echo shar: \"dviselect.c\" unpacked with wrong size!
fi
chmod +x dviselect.c
# end of overwriting check
fi
if test -f dviselect.c.orig -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dviselect.c.orig\"
else
echo shar: Extracting \"dviselect.c.orig\" \(22164 characters\)
sed "s/^X//" >dviselect.c.orig <<'END_OF_dviselect.c.orig'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/utilities/RCS/dviselect.c,v 1.3 87/12/06 12:27:33 grunwald Exp $";
X#endif
X
X/*
X * DVI page selection program
X *
X * Reads DVI version 2 files and selects pages, writing a new DVI
X * file.  The new DVI file is technically correct, though we do not
X * adjust the tallest and widest page values, nor the DVI stack size.
X * This is all right since the values will never become too small,
X * but it might be nice to fix them up.  Perhaps someday . . . .
X */
X
X#include "types.h"
X#include "dvi.h"
X#include "dviclass.h"
X#include "dvicodes.h"
X#include "fio.h"
X#include "search.h"
X#include <stdio.h>
X#include <ctype.h>
X
Xchar  *ProgName;
Xextern int   errno;
Xextern char *optarg;
Xextern int   optind;
X
X/* Globals */
Xchar	serrbuf[BUFSIZ];	/* buffer for stderr */
X
X/*
X * We will try to keep output lines shorter than MAXCOL characters.
X */
X#define MAXCOL	75
X
X/*
X * We use the following structure to keep track of fonts we have seen.
X * The final DVI file lists only the fonts it uses.
X */
Xstruct fontinfo {
X	i32	fi_newindex;	/* font number in output file */
X	int	fi_reallyused;	/* true => used on a page we copied */
X	i32	fi_checksum;	/* the checksum */
X	i32	fi_mag;		/* the magnification */
X	i32	fi_designsize;	/* the design size */
X	short	fi_n1;		/* the name header length */
X	short	fi_n2;		/* the name body length */
X	char	*fi_name;	/* the name itself */
X};
X
X/*
X * We need to remember which pages the user would like.  We build a linked
X * list that allows us to decide (for any given page) whether it should
X * be included in the output file.  Each page has ten \count variables
X * associated with it.  We put a bound on the values allowed for each, and
X * keep a linked list of alternatives should any be outside the allowed
X * range.  For example, `dviselect *.3,10-15' would generate a two-element
X * page list, with the first allowing any value for \count0 (and \counts 2 to
X * 9) but \count1 restricted to the range 3-3, and the second restricting
X * \count0 to the range 10-15 but leaving \counts 1 to 9 unrestrained.
X *
X * In case no bound is specified, the `nol' or `noh' flag is set (so that
X * we need not fix some `large' number as a maximum value).
X *
X * We also allow `absolute' page references, where the first page is
X * page 1, the second 2, and so forth.  These are specified with an
X * equal sign: `dviselect =4:10' picks up the fourth through tenth
X * sequential pages, irrespective of \count values.
X */
Xstruct pagesel {
X	i32	ps_low;		/* lower bound */
X	int	ps_nol;		/* true iff no lower bound */
X	i32	ps_high;	/* upper bound */
X	int	ps_noh;		/* true iff no upper bound */
X};
Xstruct pagelist {
X	struct	pagelist *pl_alt;	/* next in a series of alternates */
X	int	pl_len;			/* number of ranges to check */
X	int	pl_abs;			/* true iff absolute page ref */
X	struct	pagesel pl_pages[10];	/* one for each \count variable */
X};
X
Xint	SFlag;			/* true => -s, silent operation */
X
Xstruct	search *FontFinder;	/* maps from input indicies to fontinfo */
Xi32	NextOutputFontIndex;	/* generates output indicies */
Xi32	CurrentFontIndex;	/* current (old) index in input */
Xi32	OutputFontIndex;	/* current (new) index in ouput */
X
Xstruct	pagelist *PageList;	/* the list of allowed pages */
X
XFILE	*inf;			/* the input DVI file */
XFILE	*outf;			/* the output DVI file */
X
Xint	ExpectBOP;		/* true => BOP ok */
Xint	ExpectEOP;		/* true => EOP ok */
X
Xlong	StartOfLastPage;	/* The file position just before we started
X				   the last page (this is later written to
X				   the output file as the previous page
X				   pointer). */
Xlong	CurrentPosition;	/* The current position of the file */
X
Xint	UseThisPage;		/* true => current page is selected */
X
Xi32	InputPageNumber;	/* current absolute page in old DVI file */
Xint	NumberOfOutputPages;	/* number of pages in new DVI file */
X
Xi32	Numerator;		/* numerator from DVI file */
Xi32	Denominator;		/* denominator from DVI file */
Xi32	DVIMag;			/* magnification from DVI file */
X
Xi32	Count[10];		/* the 10 \count variables */
X
X/* save some string space: we use this a lot */
Xchar	writeerr[] = "error writing DVI file";
X
Xchar	*malloc(), *realloc(), *sprintf();
X
X/*
X * lint gets rather confused with the current definitions of getc and putc,
X * so we redefine them here (#if lint).  This should really be in the
X * standard I/O library, but I am not about to go change it now!
X */
X#ifdef lint
X#undef putc
X#undef getc
X#define putc(c,f) (*(f)->_ptr++ = (unsigned) (c))
X#define getc(f)   (*(f)->_ptr++)
X#endif
X
X/*
X * Return true iff the 10 \counts are one of the desired output pages.
X */
XDesiredPageP()
X{
X	register struct pagelist *pl;
X
X	for (pl = PageList; pl != NULL; pl = pl->pl_alt) {
X		register struct pagesel *ps = pl->pl_pages;
X		register int i;
X		register i32 *pagep;
X
X		pagep = pl->pl_abs ? &InputPageNumber : &Count[0];
X		for (i = 0; i < pl->pl_len; i++, ps++, pagep++)
X			if (!ps->ps_nol && *pagep < ps->ps_low ||
X			    !ps->ps_noh && *pagep > ps->ps_high)
X				break;	/* not within bounds */
X		if (i >= pl->pl_len)
X			return (1);	/* success */
X	}
X	return (0);
X}
X
X/*
X * Print a message to stderr, with an optional leading space, and handling
X * long line wraps.
X */
Xmessage(space, str, len)
X	int space;
X	register char *str;
X	register int len;
X{
X	static int beenhere;
X	static int col;
X
X	if (!beenhere)
X		space = 0, beenhere++;
X	if (len == 0)
X		len = strlen(str);
X	col += len;
X	if (space) {
X		if (col >= MAXCOL)
X			(void) putc('\n', stderr), col = len;
X		else
X			(void) putc(' ', stderr), col++;
X	}
X	while (--len >= 0)
X		(void) putc(*str++, stderr);
X	(void) fflush(stderr);
X}
X
X/*
X * Start a page (process a DVI_BOP).
X */
XBeginPage()
X{
X	register i32 *i;
X
X	if (!ExpectBOP)
X		GripeUnexpectedOp("BOP");
X	ExpectBOP = 0;
X	ExpectEOP++;		/* set the new "expect" state */
X
X	OutputFontIndex = -1;	/* new page requires respecifying font */
X	InputPageNumber++;	/* count it */
X	for (i = Count; i < &Count[10]; i++)
X		fGetLong(inf, *i);
X	(void) GetLong(inf);	/* previous page pointer */
X
X	if ((UseThisPage = DesiredPageP()) == 0)
X		return;
X
X	(void) putc(DVI_BOP, outf);
X	for (i = Count; i < &Count[10]; i++)
X		PutLong(outf, *i);
X	PutLong(outf, StartOfLastPage);
X	if (ferror(outf))
X		error(1, errno, writeerr);
X
X	StartOfLastPage = CurrentPosition;
X	CurrentPosition += 45;	/* we just wrote this much */
X
X	if (!SFlag) {		/* write nice page usage messages */
X		register int z = 0;
X		register int mlen = 0;
X		char msg[80];
X
X		(void) sprintf(msg, "[%d", Count[0]);
X		mlen = strlen(msg);
X		for (i = &Count[1]; i < &Count[10]; i++) {
X			if (*i == 0) {
X				z++;
X				continue;
X			}
X			while (--z >= 0)
X				msg[mlen++] = '.', msg[mlen++] = '0';
X			z = 0;
X			(void) sprintf(msg + mlen, ".%d", *i);
X			mlen += strlen(msg + mlen);
X		}
X		message(1, msg, mlen);
X	}
X}
X
X/*
X * End a page (process a DVI_EOP).
X */
XEndPage()
X{
X	if (!ExpectEOP)
X		GripeUnexpectedOp("EOP");
X	ExpectEOP = 0;
X	ExpectBOP++;
X
X	if (!UseThisPage)
X		return;
X
X	if (!SFlag)
X		message(0, "]", 1);
X
X	putc(DVI_EOP, outf);
X	if (ferror(outf))
X		error(1, errno, writeerr);
X	CurrentPosition++;
X	NumberOfOutputPages++;
X}
X
X/*
X * For each of the fonts used in the new DVI file, write out a definition.
X */
X/* ARGSUSED */
XPostAmbleFontEnumerator(addr, key)
X	char *addr;
X	i32 key;
X{
X
X	if (((struct fontinfo *) addr)->fi_reallyused)
X		WriteFont((struct fontinfo *) addr);
X}
X
XHandlePostAmble()
X{
X	register i32 c;
X
X	(void) GetLong(inf);	/* previous page pointer */
X	if (GetLong(inf) != Numerator)
X		GripeMismatchedValue("numerator");
X	if (GetLong(inf) != Denominator)
X		GripeMismatchedValue("denominator");
X	if (GetLong(inf) != DVIMag)
X		GripeMismatchedValue("\\magfactor");
X
X	putc(DVI_POST, outf);
X	PutLong(outf, StartOfLastPage);
X	PutLong(outf, Numerator);
X	PutLong(outf, Denominator);
X	PutLong(outf, DVIMag);
X	c = GetLong(inf);
X	PutLong(outf, c);	/* tallest page height */
X	c = GetLong(inf);
X	PutLong(outf, c);	/* widest page width */
X	c = GetWord(inf);
X	PutWord(outf, c);	/* DVI stack size */
X	PutWord(outf, NumberOfOutputPages);
X	StartOfLastPage = CurrentPosition;	/* point at post */
X	CurrentPosition += 29;	/* count all those `put's */
X#ifdef notdef
X	(void) GetWord(inf);	/* skip original number of pages */
X#endif
X
X	/*
X	 * just ignore all the incoming font definitions; we are done with
X	 * input file 
X	 */
X
X	/*
X	 * run through the FontFinder table and dump definitions for the
X	 * fonts we have used. 
X	 */
X	SEnumerate(FontFinder, PostAmbleFontEnumerator);
X
X	putc(DVI_POSTPOST, outf);
X	PutLong(outf, StartOfLastPage);	/* actually start of postamble */
X	putc(DVI_VERSION, outf);
X	putc(DVI_FILLER, outf);
X	putc(DVI_FILLER, outf);
X	putc(DVI_FILLER, outf);
X	putc(DVI_FILLER, outf);
X	CurrentPosition += 10;
X	while (CurrentPosition & 3)
X		putc(DVI_FILLER, outf), CurrentPosition++;
X	if (ferror(outf))
X		error(1, errno, writeerr);
X}
X
X/*
X * Write a font definition to the output file
X */
XWriteFont(fi)
X	register struct fontinfo *fi;
X{
X	register int l;
X	register char *s;
X
X	if (fi->fi_newindex < 256) {
X		putc(DVI_FNTDEF1, outf);
X		putc(fi->fi_newindex, outf);
X		CurrentPosition += 2;
X	} else if (fi->fi_newindex < 65536) {
X		putc(DVI_FNTDEF2, outf);
X		PutWord(outf, fi->fi_newindex);
X		CurrentPosition += 3;
X	} else if (fi->fi_newindex < 16777216) {
X		putc(DVI_FNTDEF3, outf);
X		Put3Byte(outf, fi->fi_newindex);
X		CurrentPosition += 4;
X	} else {
X		putc(DVI_FNTDEF4, outf);
X		PutLong(outf, fi->fi_newindex);
X		CurrentPosition += 5;
X	}
X	PutLong(outf, fi->fi_checksum);
X	PutLong(outf, fi->fi_mag);
X	PutLong(outf, fi->fi_designsize);
X	putc(fi->fi_n1, outf);
X	putc(fi->fi_n2, outf);
X	l = fi->fi_n1 + fi->fi_n2;
X	CurrentPosition += 14 + l;
X	s = fi->fi_name;
X	while (--l >= 0)
X		putc(*s, outf), s++;
X}
X
X/*
X * Handle the preamble.  Someday we should update the comment field.
X */
XHandlePreAmble()
X{
X	register int n, c;
X
X	if (GetByte(inf) != Sign8(DVI_PRE))
X		GripeMissingOp("PRE");
X	if (GetByte(inf) != Sign8(DVI_VERSION))
X		GripeMismatchedValue("DVI version number");
X	Numerator = GetLong(inf);
X	Denominator = GetLong(inf);
X	DVIMag = GetLong(inf);
X	putc(DVI_PRE, outf);
X	putc(DVI_VERSION, outf);
X	PutLong(outf, Numerator);
X	PutLong(outf, Denominator);
X	PutLong(outf, DVIMag);
X
X	n = UnSign8(GetByte(inf));
X	CurrentPosition = 15 + n;	/* well, almost */
X	putc(n, outf);
X	while (--n >= 0) {
X		c = GetByte(inf);
X		putc(c, outf);	/* never trust a macro, I always say */
X	}
X}
X
Xmain(argc, argv)
X	int argc;
X	register char **argv;
X{
X	register int c;
X	register char *s;
X	char *inname = NULL, *outname = NULL;
X
X	ProgName = *argv;
X	setbuf(stderr, serrbuf);
X
X	while ((c = getopt(argc, argv, "i:o:s")) != EOF) {
X		switch (c) {
X
X		case 's':	/* silent */
X			SFlag++;
X			break;
X
X		case 'i':
X			if (inname != NULL)
X				goto usage;
X			inname = optarg;
X			break;
X
X		case 'o':
X			if (outname != NULL)
X				goto usage;
X			outname = optarg;
X			break;
X
X		case '?':
Xusage:
X			fprintf(stderr, "\
XUsage: %s [-s] [-i infile] [-o outfile] pages [...] [infile [outfile]]\n",
X				ProgName);
X			(void) fflush(stderr);
X			exit(1);
X		}
X	}
X
X	while (optind < argc) {
X		s = argv[optind++];
X		c = *s;
X		if (!isalpha(c) && c != '/') {
X			if (ParsePages(s))
X				goto usage;
X		} else if (inname == NULL)
X			inname = s;
X		else if (outname == NULL)
X			outname = s;
X		else
X			goto usage;
X	}
X	if (PageList == NULL)
X		goto usage;
X	if (inname == NULL)
X		inf = stdin;
X	else if ((inf = fopen(inname, "r")) == 0)
X		error(1, errno, "cannot read %s", inname);
X	if (outname == NULL)
X		outf = stdout;
X	else if ((outf = fopen(outname, "w")) == 0)
X		error(1, errno, "cannot write %s", outname);
X
X	if ((FontFinder = SCreate(sizeof(struct fontinfo))) == 0)
X		error(1, 0, "cannot create font finder (out of memory?)");
X
X	ExpectBOP++;
X	StartOfLastPage = -1;
X	HandlePreAmble();
X	HandleDVIFile();
X	HandlePostAmble();
X	if (!SFlag)
X		fprintf(stderr, "\nWrote %d pages, %d bytes\n",
X			NumberOfOutputPages, CurrentPosition);
X	exit(0);
X}
X
Xstruct pagelist *
XInstallPL(ps, n, absolute)
X	register struct pagesel *ps;
X	register int n;
X	int absolute;
X{
X	register struct pagelist *pl;
X
X	pl = (struct pagelist *) malloc(sizeof *pl);
X	if (pl == NULL)
X		GripeOutOfMemory(sizeof *pl, "page list");
X	pl->pl_alt = PageList;
X	PageList = pl;
X	pl->pl_len = n;
X	while (--n >= 0)
X		pl->pl_pages[n] = ps[n];
X	pl->pl_abs = absolute;
X}
X
X/*
X * Parse a string representing a list of pages.  Return 0 iff ok.  As a
X * side effect, the page selection(s) is (are) prepended to PageList.
X */
XParsePages(s)
X	register char *s;
X{
X	register struct pagesel *ps;
X	register int c;		/* current character */
X	register i32 n;		/* current numeric value */
X	register int innumber;	/* true => gathering a number */
X	int i;			/* next index in page select list */
X	int range;		/* true => saw a range indicator */
X	int negative;		/* true => number being built is negative */
X	int absolute;		/* true => absolute, not \count */
X	struct pagesel pagesel[10];
X
X#define white(x) ((x) == ' ' || (x) == '\t' || (x) == ',')
X
X	range = 0;
X	innumber = 0;
X	absolute = 0;
X	i = 0;
X	ps = pagesel;
X	/*
X	 * Talk about ad hoc!  (Not to mention convoluted.)
X	 */
X	for (;;) {
X		c = *s++;
X		if (i == 0 && !innumber && !range) {
X			/* nothing special going on */
X			if (c == 0)
X				return 0;
X			if (white(c))
X				continue;
X		}
X		if (c == '_') {
X			/* kludge: should be '-' for negatives */
X			if (innumber || absolute)
X				return (-1);
X			innumber++;
X			negative = 1;
X			n = 0;
X			continue;
X		}
X		if (c == '=') {
X			/* absolute page */
X			if (innumber || range || i > 0)
X				return (-1);
X			absolute++;
X			/*
X			 * Setting innumber means that there is always
X			 * a lower bound, but this is all right since
X			 * `=:4' is treated as if it were `=0:4'.  As
X			 * there are no negative absolute page numbers,
X			 * this selects pages 1:4, which is the proper
X			 * action.
X			 */
X			innumber++;
X			negative = 0;
X			n = 0;
X			continue;
X		}
X		if (isdigit(c)) {
X			/* accumulate numeric value */
X			if (!innumber) {
X				innumber++;
X				negative = 0;
X				n = c - '0';
X				continue;
X			}
X			n *= 10;
X			n += negative ? '0' - c : c - '0';
X			continue;
X		}
X		if (c == '-' || c == ':') {
X			/* here is a range */
X			if (range)
X				return (-1);
X			if (innumber) {	/* have a lower bound */
X				ps->ps_low = n;
X				ps->ps_nol = 0;
X			} else
X				ps->ps_nol = 1;
X			range++;
X			innumber = 0;
X			continue;
X		}
X		if (c == '*') {
X			/* no lower bound, no upper bound */
X			c = *s++;
X			if (innumber || range || i >= 10 ||
X			    (c && c != '.' && !white(c)))
X				return (-1);
X			ps->ps_nol = 1;
X			ps->ps_noh = 1;
X			goto finishnum;
X		}
X		if (c == 0 || c == '.' || white(c)) {
X			/* end of this range */
X			if (i >= 10)
X				return (-1);
X			if (!innumber) {	/* no upper bound */
X				ps->ps_noh = 1;
X				if (!range)	/* no lower bound either */
X					ps->ps_nol = 1;
X			} else {		/* have an upper bound */
X				ps->ps_high = n;
X				ps->ps_noh = 0;
X				if (!range) {
X					/* no range => lower bound == upper */
X					ps->ps_low = ps->ps_high;
X					ps->ps_nol = 0;
X				}
X			}
Xfinishnum:
X			i++;
X			if (c == '.') {
X				if (absolute)
X					return (-1);
X				ps++;
X			} else {
X				InstallPL(pagesel, i, absolute);
X				ps = pagesel;
X				i = 0;
X				absolute = 0;
X			}
X			if (c == 0)
X				return (0);
X			range = 0;
X			innumber = 0;
X			continue;
X		}
X		/* illegal character */
X		return (-1);
X	}
X#undef white
X}
X
X/*
X * Handle a font definition.
X */
XHandleFontDef(index)
X	i32 index;
X{
X	register struct fontinfo *fi;
X	register int i;
X	register char *s;
X	int def = S_CREATE | S_EXCL;
X
X	if ((fi = (struct fontinfo *) SSearch(FontFinder, index, &def)) == 0)
X		if (def & S_COLL)
X			error(1, 0, "font %d already defined", index);
X		else
X			error(1, 0, "cannot stash font %d (out of memory?)",
X				index);
X	fi->fi_reallyused = 0;
X	fi->fi_checksum = GetLong(inf);
X	fi->fi_mag = GetLong(inf);
X	fi->fi_designsize = GetLong(inf);
X	fi->fi_n1 = UnSign8(GetByte(inf));
X	fi->fi_n2 = UnSign8(GetByte(inf));
X	i = fi->fi_n1 + fi->fi_n2;
X	if ((s = malloc((unsigned) i)) == 0)
X		GripeOutOfMemory(i, "font name");
X	fi->fi_name = s;
X	while (--i >= 0)
X		*s++ = GetByte(inf);
X}
X
X/*
X * Handle a \special.
X */
XHandleSpecial(c, l, p)
X	int c;
X	register int l;
X	register i32 p;
X{
X	register int i;
X
X	if (UseThisPage) {
X		putc(c, outf);
X		switch (l) {
X
X		case DPL_UNS1:
X			putc(p, outf);
X			CurrentPosition += 2;
X			break;
X
X		case DPL_UNS2:
X			PutWord(outf, p);
X			CurrentPosition += 3;
X			break;
X
X		case DPL_UNS3:
X			Put3Byte(outf, p);
X			CurrentPosition += 4;
X			break;
X
X		case DPL_SGN4:
X			PutLong(outf, p);
X			CurrentPosition += 5;
X			break;
X
X		default:
X			panic("HandleSpecial l=%d", l);
X			/* NOTREACHED */
X		}
X		CurrentPosition += p;
X		while (--p >= 0) {
X			i = getc(inf);
X			putc(i, outf);
X		}
X		if (feof(inf))
X			error(1, 0, "unexpected EOF");
X		if (ferror(outf))
X			error(1, errno, writeerr);
X	} else
X		while (--p >= 0)
X			(void) getc(inf);
X}
X
XReallyUseFont()
X{
X	register struct fontinfo *fi;
X	int look = S_LOOKUP;
X
X	fi = (struct fontinfo *) SSearch(FontFinder, CurrentFontIndex, &look);
X	if (fi == 0)
X		error(1, 0, "index %d not in font table!", CurrentFontIndex);
X	if (fi->fi_reallyused == 0) {
X		fi->fi_reallyused++;
X		fi->fi_newindex = NextOutputFontIndex++;
X		WriteFont(fi);
X	}
X	if (fi->fi_newindex != OutputFontIndex) {
X		PutFontSelector(fi->fi_newindex);
X		OutputFontIndex = fi->fi_newindex;
X	}
X}
X
X/*
X * Write a font selection command to the output file
X */
XPutFontSelector(index)
X	i32 index;
X{
X
X	if (index < 64) {
X		putc(index + DVI_FNTNUM0, outf);
X		CurrentPosition++;
X	} else if (index < 256) {
X		putc(DVI_FNT1, outf);
X		putc(index, outf);
X		CurrentPosition += 2;
X	} else if (index < 65536) {
X		putc(DVI_FNT2, outf);
X		PutWord(outf, index);
X		CurrentPosition += 3;
X	} else if (index < 16777216) {
X		putc(DVI_FNT3, outf);
X		Put3Byte(outf, index);
X		CurrentPosition += 4;
X	} else {
X		putc(DVI_FNT4, outf);
X		PutLong(outf, index);
X		CurrentPosition += 5;
X	}
X}
X
X/*
X * The following table describes the length (in bytes) of each of the DVI
X * commands that we can simply copy, starting with DVI_SET1 (128).
X */
Xchar	oplen[128] = {
X	0, 0, 0, 0,		/* DVI_SET1 .. DVI_SET4 */
X	9,			/* DVI_SETRULE */
X	0, 0, 0, 0,		/* DVI_PUT1 .. DVI_PUT4 */
X	9,			/* DVI_PUTRULE */
X	1,			/* DVI_NOP */
X	0,			/* DVI_BOP */
X	0,			/* DVI_EOP */
X	1,			/* DVI_PUSH */
X	1,			/* DVI_POP */
X	2, 3, 4, 5,		/* DVI_RIGHT1 .. DVI_RIGHT4 */
X	1,			/* DVI_W0 */
X	2, 3, 4, 5,		/* DVI_W1 .. DVI_W4 */
X	1,			/* DVI_X0 */
X	2, 3, 4, 5,		/* DVI_X1 .. DVI_X4 */
X	2, 3, 4, 5,		/* DVI_DOWN1 .. DVI_DOWN4 */
X	1,			/* DVI_Y0 */
X	2, 3, 4, 5,		/* DVI_Y1 .. DVI_Y4 */
X	1,			/* DVI_Z0 */
X	2, 3, 4, 5,		/* DVI_Z1 .. DVI_Z4 */
X	0,			/* DVI_FNTNUM0 (171) */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 172 .. 179 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 180 .. 187 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 188 .. 195 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 196 .. 203 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 204 .. 211 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 212 .. 219 */
X	0, 0, 0, 0, 0, 0, 0, 0,	/* 220 .. 227 */
X	0, 0, 0, 0, 0, 0, 0,	/* 228 .. 234 */
X	0, 0, 0, 0,		/* DVI_FNT1 .. DVI_FNT4 */
X	0, 0, 0, 0,		/* DVI_XXX1 .. DVI_XXX4 */
X	0, 0, 0, 0,		/* DVI_FNTDEF1 .. DVI_FNTDEF4 */
X	0,			/* DVI_PRE */
X	0,			/* DVI_POST */
X	0,			/* DVI_POSTPOST */
X	0, 0, 0, 0, 0, 0,	/* 250 .. 255 */
X};
X
X/*
X * Here we read the input DVI file and write relevant pages to the
X * output DVI file. We also keep track of font changes, handle font
X * definitions, and perform some other housekeeping.
X */
XHandleDVIFile()
X{
X	register int c, l;
X	register i32 p;
X	register int CurrentFontOK = 0;
X
X	/* Only way out is via "return" statement */
X	for (;;) {
X		c = getc(inf);	/* getc() returns unsigned values */
X		if (DVI_IsChar(c)) {
X			/*
X			 * Copy chars, note font usage, but ignore if
X			 * page is not interesting.
X			 */
X			if (!UseThisPage)
X				continue;
X			if (!CurrentFontOK) {
X				ReallyUseFont();
X				CurrentFontOK++;
X			}
X			putc(c, outf);
X			CurrentPosition++;
X			continue;
X		}
X		if (DVI_IsFont(c)) {	/* note font change */
X			CurrentFontIndex = c - DVI_FNTNUM0;
X			CurrentFontOK = 0;
X			continue;
X		}
X		if ((l = (oplen - 128)[c]) != 0) {	/* simple copy */
X			if (!UseThisPage) {
X				while (--l > 0)
X					(void) getc(inf);
X				continue;
X			}
X			CurrentPosition += l;
X			putc(c, outf);
X			while (--l > 0) {
X				c = getc(inf);
X				putc(c, outf);
X			}
X			if (ferror(outf))
X				error(1, errno, writeerr);
X			continue;
X		}
X		if ((l = DVI_OpLen(c)) != 0) {
X			/*
X			 * Handle other generics.
X			 * N.B.: there should only be unsigned parameters
X			 * here (save SGN4), for commands with negative
X			 * parameters have been taken care of above.
X			 */
X			switch (l) {
X
X			case DPL_UNS1:
X				p = getc(inf);
X				break;
X
X			case DPL_UNS2:
X				fGetWord(inf, p);
X				break;
X
X			case DPL_UNS3:
X				fGet3Byte(inf, p);
X				break;
X
X			case DPL_SGN4:
X				fGetLong(inf, p);
X				break;
X
X			default:
X				panic("HandleDVIFile l=%d", l);
X			}
X
X			/*
X			 * Now that we have the parameter, perform the
X			 * command.
X			 */
X			switch (DVI_DT(c)) {
X
X			case DT_SET:
X			case DT_PUT:
X				if (!UseThisPage)
X					continue;
X				if (!CurrentFontOK) {
X					ReallyUseFont();
X					CurrentFontOK++;
X				}
X				putc(c, outf);
X				switch (l) {
X
X				case DPL_UNS1:
X					putc(p, outf);
X					CurrentPosition += 2;
X					continue;
X
X				case DPL_UNS2:
X					PutWord(outf, p);
X					CurrentPosition += 3;
X					continue;
X
X				case DPL_UNS3:
X					Put3Byte(outf, p);
X					CurrentPosition += 4;
X					continue;
X
X				case DPL_SGN4:
X					PutLong(outf, p);
X					CurrentPosition += 5;
X					continue;
X				}
X
X			case DT_FNT:
X				CurrentFontIndex = p;
X				CurrentFontOK = 0;
X				continue;
X
X			case DT_XXX:
X				HandleSpecial(c, l, p);
X				continue;
X
X			case DT_FNTDEF:
X				HandleFontDef(p);
X				continue;
X
X			default:
X				panic("HandleDVIFile DVI_DT(%d)=%d",
X				      c, DVI_DT(c));
X			}
X			continue;
X		}
X
X		switch (c) {	/* handle the few remaining cases */
X
X		case DVI_BOP:
X			BeginPage();
X			CurrentFontOK = 0;
X			break;
X
X		case DVI_EOP:
X			EndPage();
X			break;
X
X		case DVI_PRE:
X			GripeUnexpectedOp("PRE");
X			/* NOTREACHED */
X
X		case DVI_POST:
X			return;
X
X		case DVI_POSTPOST:
X			GripeUnexpectedOp("POSTPOST");
X			/* NOTREACHED */
X
X		default:
X			GripeUndefinedOp(c);
X			/* NOTREACHED */
X		}
X	}
X}
END_OF_dviselect.c.orig
if test 22164 -ne `wc -c <dviselect.c.orig`; then
    echo shar: \"dviselect.c.orig\" unpacked with wrong size!
fi
chmod +x dviselect.c.orig
# end of overwriting check
fi
if test ! -d h ; then
    echo shar: Creating directory \"h\"
    mkdir h
fi
if test ! -d lib ; then
    echo shar: Creating directory \"lib\"
    mkdir lib
fi
echo shar: End of archive 1 \(of 6\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    echo "Now do 'make dviselect'"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--
Skip Montanaro (montanaro@crdgw1.ge.com)

montnaro@sprite.crd.ge.com (Skip Montanaro) (11/14/89)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 6)."
# Contents:  h/Makefile h/README h/conv.h h/convstruct.h h/dvi.h
#   h/dviclass.h h/dvicodes.h h/dvistruct.h h/fio.h h/font.h
#   h/gfclass.h h/gfcodes.h h/imPcodes.h h/imagen.h h/num.h
#   h/postamble.h h/search.h h/tfm.h h/types.h
# Wrapped by montnaro@sprite on Sat Nov 11 17:13:28 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f h/Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/Makefile\"
else
echo shar: Extracting \"h/Makefile\" \(271 characters\)
sed "s/^X//" >h/Makefile <<'END_OF_h/Makefile'
XHDR	=arith.h binding.h box.h conv.h dvi.h dviclass.h dvicodes.h \
X	error.h fio.h font.h gfclass.h gfcodes.h imPcodes.h imagen.h \
X	io.h num.h postamble.h search.h str.h tfm.h types.h verser.h
X
Xgoal:
X	@echo Nothing to make here
X
X$(HDR):
X	co -q $@
X
Xhdr:	$(HDR)
X	@echo Done
END_OF_h/Makefile
if test 271 -ne `wc -c <h/Makefile`; then
    echo shar: \"h/Makefile\" unpacked with wrong size!
fi
chmod +x h/Makefile
# end of overwriting check
fi
if test -f h/README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/README\"
else
echo shar: Extracting \"h/README\" \(36 characters\)
sed "s/^X//" >h/README <<'END_OF_h/README'
XThis directory is for header files.
END_OF_h/README
if test 36 -ne `wc -c <h/README`; then
    echo shar: \"h/README\" unpacked with wrong size!
fi
chmod +x h/README
# end of overwriting check
fi
if test -f h/conv.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/conv.h\"
else
echo shar: Extracting \"h/conv.h\" \(3295 characters\)
sed "s/^X//" >h/conv.h <<'END_OF_h/conv.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * Conversions.  Conversion factors convert between values in scaled
X * points and values in device-dependenent units.  The results of all
X * conversions are rounded to the nearest integral value, of type (i32).
X */
X
X/*
X * This is now done using `double' values, but may be changed to
X * fixed-point or some other `fast' method, as long as the results
X * are consistent and reasonably accurate.  The structure `conversion'
X * holds the conversion-method-dependent quantities; the macros
X * fromSP and toSP apply the conversion to a value.  (Note that
X * fromSP and toSP need not be macros, but should be fast.)
X *
X * SetConversion sets the (single, global) conversion factor.
X * If a driver needs special conversions, there is another routine,
X * CSetConversion that sets a specific conversion, and cfromSP and
X * ctoSP to apply these.
X *
X * IS USING DOTS PER INCH SUFFICIENT?  (Pixels per point might be better.)
X *
X * Note that it is necessary to set the global conversion factor before
X * using any fonts.
X */
X
Xtypedef struct conversion {
X	double	c_fromsp;	/* multiplier to convert from scaled points */
X	double	c_tosp;		/* multiplier to convert to scaled points:
X				   could divide by c_fromsp, but this should
X				   be faster and more accurate */
X	double	c_mag;		/* the magnification this conversion
X				   represents; mainly for GetFont() */
X	double	c_dpi;		/* dpi (should be pixels per point?) */
X} Conv;
X
X/*
X * In order to do this, we need to round properly.  The compilers I
X * have tend to generate very poor code for this.  The following is
X * intended to help them out.  Smarter compilers can do better, but
X * if they are smart enough, they will realise that the variables
X * here are not used anywhere else, and discard them.  (For a compiler
X * to do this given separate compliation, `static' is a must.)
X */
X
X#ifdef lint			/* or a smart compiler */
X
X#define	ROUND(f) ((i32) ((f) < 0.0 ? (f) - 0.5 : (f) + 0.5))
X#define	CEIL(f)	((double) (i32) (f) < (f) ? (i32) (f) + 1 : (i32) (f))
X
X#else
X
Xstatic double _half = 0.5;
Xstatic double _zero = 0.0;
Xstatic double _d;
X
X#define	ROUND(f) ((i32) (_d = (f), _d < _zero ? _d - _half : _d + _half))
X
X#ifdef NEGATIVE_FLOAT_ROUNDS_TO_NEGATIVE_INFINITY
X
X#define	CEIL(f)  (-(i32) -(f))
X
X#else /* we will assume that floating to integer truncates */
X
Xstatic i32 _i;
X
X#define	CEIL(f)	 (_i = _d = (f), _i < _d ? _i + 1 : _i)
X
X#endif /* round towards negative infinity */
X
X#endif /* lint */
X
X#define	SetConversion(dpi, usermag, num, denom, dvimag)	\
X	CSetConversion(&Conversion, dpi, usermag, num, denom, dvimag)
X
X#define	cfromSP(c, v)	ROUND((c)->c_fromsp * (v))
X#define	ctoSP(c, v)	ROUND((c)->c_tosp * (v))
X
X#define	fromSP(v)	cfromSP(&Conversion, v)
X#define	toSP(v)		ctoSP(&Conversion, v)
X
X/*
X * Conversions for rules are a bit different: we must round up, rather
X * than off.  ConvRule applies the global conversion value for a rule
X * value (height or width); CConvRule applies a specific conversion.
X */
X
X#define	CConvRule(c, v)	CEIL((c)->c_fromsp * (v))
X#define	ConvRule(v)	CConvRule(&Conversion, v)
X
Xvoid	CSetConversion();
END_OF_h/conv.h
if test 3295 -ne `wc -c <h/conv.h`; then
    echo shar: \"h/conv.h\" unpacked with wrong size!
fi
chmod +x h/conv.h
# end of overwriting check
fi
if test -f h/convstruct.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/convstruct.h\"
else
echo shar: Extracting \"h/convstruct.h\" \(400 characters\)
sed "s/^X//" >h/convstruct.h <<'END_OF_h/convstruct.h'
Xtypedef struct conversion {
X	double	c_fromsp;	/* multiplier to convert from scaled points */
X	double	c_tosp;		/* multiplier to convert to scaled points:
X				   could divide by c_fromsp, but this should
X				   be faster and more accurate */
X	double	c_mag;		/* the magnification this conversion
X				   represents; mainly for GetFont() */
X	double	c_dpi;		/* dpi (should be pixels per point?) */
X} Conv;
END_OF_h/convstruct.h
if test 400 -ne `wc -c <h/convstruct.h`; then
    echo shar: \"h/convstruct.h\" unpacked with wrong size!
fi
chmod +x h/convstruct.h
# end of overwriting check
fi
if test -f h/dvi.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/dvi.h\"
else
echo shar: Extracting \"h/dvi.h\" \(876 characters\)
sed "s/^X//" >h/dvi.h <<'END_OF_h/dvi.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/* DVI file info */
X
X/*
X * Units of distance are stored in scaled points, but we can convert to
X * units of 10^-7 meters by multiplying by the numbers in the preamble.
X */
X
X/* the structure of the stack used to hold the values (h,v,w,x,y,z) */
X
Xtypedef struct dvi_stack {
X	i32	h;		/* the saved h */
X	i32	v;		/* the saved v */
X	i32	w;		/* etc */
X	i32	x;
X	i32	y;
X	i32	z;
X} DviStack;
X
Xextern DviStack dvi_current;	/* the current values of h, v, etc */
Xextern int	dvi_f;			/* the current font */
X
X#define dvi_h dvi_current.h
X#define dvi_v dvi_current.v
X#define dvi_w dvi_current.w
X#define dvi_x dvi_current.x
X#define dvi_y dvi_current.y
X#define dvi_z dvi_current.z
END_OF_h/dvi.h
if test 876 -ne `wc -c <h/dvi.h`; then
    echo shar: \"h/dvi.h\" unpacked with wrong size!
fi
chmod +x h/dvi.h
# end of overwriting check
fi
if test -f h/dviclass.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/dviclass.h\"
else
echo shar: Extracting \"h/dviclass.h\" \(1662 characters\)
sed "s/^X//" >h/dviclass.h <<'END_OF_h/dviclass.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * Macros to convert DVI opcodes to (hopefully) simpler values.
X */
X
X/*
X * Large range types.
X */
X#define DVI_IsChar(code) ((code) < 128)
X#define DVI_IsFont(code) ((code) >= 171 && (code) < 235)
X
X/*
X * Symbolic names for generic types (for things with parameters).
X * These are obtained via the macro DVI_DT(int c), where 0 <= c <= 255.
X */
X#define	DT_CHAR		 0
X#define DT_SET		 1
X#define	DT_SETRULE	 2
X#define DT_PUT		 3
X#define	DT_PUTRULE	 4
X#define	DT_NOP		 5
X#define	DT_BOP		 6
X#define	DT_EOP		 7
X#define	DT_PUSH		 8
X#define	DT_POP		 9
X#define DT_RIGHT	10
X#define DT_W0		11
X#define	DT_W		12
X#define	DT_X0		13
X#define DT_X		14
X#define DT_DOWN		15
X#define	DT_Y0		16
X#define DT_Y		17
X#define	DT_Z0		18
X#define DT_Z		19
X#define	DT_FNTNUM	20
X#define DT_FNT		21
X#define DT_XXX		22
X#define DT_FNTDEF	23
X#define	DT_PRE		24
X#define	DT_POST		25
X#define	DT_POSTPOST	26
X#define	DT_UNDEF	27
X
X/*
X * Symbolic names for parameter lengths, obtained via the macro
X * DVL_OpLen(int c).
X *
X * N.B.: older drivers may assume that 0 => none, 1-4 => 1-4 bytes
X * and 5-7 => unsigned version of 1-4---so DO NOT change these values!
X */
X#define	DPL_NONE	0
X#define	DPL_SGN1	1
X#define	DPL_SGN2	2
X#define	DPL_SGN3	3
X#define	DPL_SGN4	4
X#define	DPL_UNS1	5
X#define	DPL_UNS2	6
X#define	DPL_UNS3	7
X/* there are no unsigned four byte parameters */
X
X#define DVI_OpLen(code)  (dvi_oplen[code])
X#define DVI_DT(code)	 (dvi_dt[code])
Xextern char dvi_oplen[];
Xextern char dvi_dt[];
END_OF_h/dviclass.h
if test 1662 -ne `wc -c <h/dviclass.h`; then
    echo shar: \"h/dviclass.h\" unpacked with wrong size!
fi
chmod +x h/dviclass.h
# end of overwriting check
fi
if test -f h/dvicodes.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/dvicodes.h\"
else
echo shar: Extracting \"h/dvicodes.h\" \(2554 characters\)
sed "s/^X//" >h/dvicodes.h <<'END_OF_h/dvicodes.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/* DVI opcodes */
X
X#define DVI_VERSION	2	/* version number that should appear in
X				   pre- and post-ambles */
X
X#define DVI_SET1	128	/* set character, 1 byte param */
X#define DVI_SET2	129	/* set character, 2 byte param */
X#define DVI_SET3	130	/* set character, 3 byte param */
X#define DVI_SET4	131	/* set character, 4 byte param */
X#define DVI_SETRULE	132	/* set a rule */
X#define DVI_PUT1	133	/* put char, don't move right */
X#define DVI_PUT2	134	/* put char, 2 byte */
X#define DVI_PUT3	135	/* etc */
X#define DVI_PUT4	136
X#define DVI_PUTRULE	137	/* put rule, don't move right */
X#define DVI_NOP		138	/* no-op */
X#define DVI_BOP		139	/* begin page */
X#define DVI_EOP		140	/* end page */
X#define DVI_PUSH	141	/* push h,v,w,x,y,z */
X#define DVI_POP		142	/* pop  h,v,w,x,y,z */
X#define DVI_RIGHT1	143	/* move right, 1 byte signed param */
X#define DVI_RIGHT2	144	/* move right, 2 byte signed param */
X#define DVI_RIGHT3	145	/* etc */
X#define DVI_RIGHT4	146
X#define DVI_W0		147	/* h += w */
X#define DVI_W1		148	/* w = 1 byte signed param, h += w */
X#define DVI_W2		149	/* w = 2 byte etc, h += w */
X#define DVI_W3		150
X#define DVI_W4		151
X#define DVI_X0		152	/* like DVI_W0 but for x */
X#define DVI_X1		153	/* etc */
X#define DVI_X2		154
X#define DVI_X3		155
X#define DVI_X4		156
X#define DVI_DOWN1	157	/* v += 1 byte signed param */
X#define DVI_DOWN2	158	/* v += 2 byte signed param */
X#define DVI_DOWN3	159	/* etc */
X#define DVI_DOWN4	160
X#define DVI_Y0		161	/* y = 1 byte signed param, v += y */
X#define DVI_Y1		162	/* etc */
X#define DVI_Y2		163
X#define DVI_Y3		164
X#define DVI_Y4		165
X#define DVI_Z0		166	/* z = 1 byte signed param, v += z */
X#define DVI_Z1		167	/* etc */
X#define DVI_Z2		168
X#define DVI_Z3		169
X#define DVI_Z4		170
X#define DVI_FNTNUM0	171
X
X#define DVI_FNT1	235	/* select font, 1 byte param */
X#define DVI_FNT2	236	/* etc */
X#define DVI_FNT3	237
X#define DVI_FNT4	238
X#define DVI_XXX1	239	/* for \special: if length < 256 */
X#define DVI_XXX2	240	/* etc */
X#define DVI_XXX3	241
X#define DVI_XXX4	242
X#define DVI_FNTDEF1	243	/* Define font, 1 byte param (0 to 63) */
X#define DVI_FNTDEF2	244	/* etc */
X#define DVI_FNTDEF3	245
X#define DVI_FNTDEF4	246
X#define DVI_PRE		247	/* preamble */
X#define DVI_POST	248	/* postamble */
X#define DVI_POSTPOST	249	/* end of postamble */
X#define DVI_FILLER	223	/* filler bytes at end of dvi file */
END_OF_h/dvicodes.h
if test 2554 -ne `wc -c <h/dvicodes.h`; then
    echo shar: \"h/dvicodes.h\" unpacked with wrong size!
fi
chmod +x h/dvicodes.h
# end of overwriting check
fi
if test -f h/dvistruct.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/dvistruct.h\"
else
echo shar: Extracting \"h/dvistruct.h\" \(595 characters\)
sed "s/^X//" >h/dvistruct.h <<'END_OF_h/dvistruct.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/* DVI file info */
X
X/*
X * Units of distance are stored in scaled points, but we can convert to
X * units of 10^-7 meters by multiplying by the numbers in the preamble.
X */
X
X/* the structure of the stack used to hold the values (h,v,w,x,y,z) */
Xtypedef struct dvi_stack {
X	i32	h;		/* the saved h */
X	i32	v;		/* the saved v */
X	i32	w;		/* etc */
X	i32	x;
X	i32	y;
X	i32	z;
X} DviStack;
END_OF_h/dvistruct.h
if test 595 -ne `wc -c <h/dvistruct.h`; then
    echo shar: \"h/dvistruct.h\" unpacked with wrong size!
fi
chmod +x h/dvistruct.h
# end of overwriting check
fi
if test -f h/fio.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/fio.h\"
else
echo shar: Extracting \"h/fio.h\" \(1456 characters\)
sed "s/^X//" >h/fio.h <<'END_OF_h/fio.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * File I/O: numbers.
X *
X * We deal in fixed format numbers and (FILE *)s here.
X * For pointer I/O, see pio.h.
X *
X * N.B.: These do the `wrong thing' at EOF.  It is imperative
X * that the caller add appropriate `if (feof(fp))' statements.
X */
X
X/*
X * Get one unsigned byte.  Note that this is a proper expression.
X * The reset have more limited contexts, and are therefore OddLy
X * CapItaliseD.
X */
X#define	fgetbyte(fp)	(getc(fp))
X
X/*
X * Get a two-byte unsigned integer, a three-byte unsigned integer,
X * or a four-byte signed integer.
X */
X#define fGetWord(fp, r)	((r)  = getc(fp) << 8,  (r) |= getc(fp))
X#define fGet3Byte(fp,r) ((r)  = getc(fp) << 16, (r) |= getc(fp) << 8, \
X			 (r) |= getc(fp))
X#define fGetLong(fp, r)	((r)  = getc(fp) << 24, (r) |= getc(fp) << 16, \
X			 (r) |= getc(fp) << 8,  (r) |= getc(fp))
X
X/*
X * Fast I/O write (and regular write) macros.
X */
X#define	putbyte(fp, r)	(putc((r), fp))
X
X#define PutWord(fp, r)	(putc((r) >> 8,  fp), putc((r), fp))
X#define Put3Byte(fp, r)	(putc((r) >> 16, fp), putc((r) >> 8, fp), \
X			 putc((r), fp))
X#define PutLong(fp, r)	(putc((r) >> 24, fp), putc((r) >> 16, fp), \
X			 putc((r) >> 8, fp),  putc((r), fp))
X
X/*
X * Function types
X */
Xi32	GetByte(), GetWord(), Get3Byte(), GetLong();
END_OF_h/fio.h
if test 1456 -ne `wc -c <h/fio.h`; then
    echo shar: \"h/fio.h\" unpacked with wrong size!
fi
chmod +x h/fio.h
# end of overwriting check
fi
if test -f h/font.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/font.h\"
else
echo shar: Extracting \"h/font.h\" \(7100 characters\)
sed "s/^X//" >h/font.h <<'END_OF_h/font.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * Font file information, readers, etc.
X */
X
X#ifndef _CTEX_TYPES_
X#include "types.h"
X#endif
X
X/*
X * First, font independent information: per glyph info, and per font
X * info.
X */
Xstruct glyph {
X	short	g_flags;	/* see below */
X	/*
X	 * The following cannot be used with GetRasterlessFont
X	 */
X	short	g_rotation;	/* see below */
X	char	*g_raster;	/* raster, if known */
X	/*
X	 * These, however, do come with rasterless fonts,
X	 * even though they relate only to the raster.
X	 */
X	i32	g_height;	/* height of bounding box */
X	i32	g_width;	/* width of bounding box */
X	i32	g_yorigin;	/* y origin (>= 0 -> within box) */
X	i32	g_xorigin;	/* x origin (>= 0 -> within box) */
X	/*
X	 * This of course comes with every font.
X	 */
X	i32	g_rawtfmwidth;	/* the tfmwidth as read from the file */
X	i32	g_tfmwidth;	/* width in scaled points (not FIXes!) */
X	i32	g_xescapement;	/* x escapement (`chardx') */
X	i32	g_yescapement;	/* y escapement (`chardy') */
X	/*
X	 * This is provided purely for DVI to device conversion programs.
X	 */
X	int	g_pixwidth;	/* width in pixels */
X	/*
X	 * Mainly for internal use, index is the glyph index within the
X	 * font.  That is, f->f_gly[i]->g_index == i.
X	 */
X	int	g_index;	/* character index */
X	/*
X	 * g_details and g_integer are purely for the font reading
X	 * subroutines to use however they will.  g_next makes lists
X	 * of glyphs while the glyphs are free.
X	 */
X	union {			/* various options */
X		char	*g_details;	/* details: arbitrary */
X		i32	g_integer;	/* 32 bit integer */
X		struct	glyph *g_next;	/* linked list */
X	} g_un;
X};
X
X/*
X * Glyph flags.
X */
X#define	GF_VALID	0x0001	/* glyph is `real' */
X#define	GF_USR0		0x0100	/* reserved to user code */
X#define	GF_USR1		0x0200	/* reserved to user code */
X#define	GF_USR2		0x0400	/* reserved to user code */
X#define	GF_USR3		0x0800	/* reserved to user code */
X
X/*
X * Rotations are in quarter-pi steps, counterclockwise of course.
X * This order must be maintained; see rotate.c.
X */
X#define	ROT_NORM	0		/* no rotation: `normal' position */
X#define	ROT_LEFT	1		/* 1/4 turn counterclockwise */
X#define	ROT_DOWN	2		/* 1/2 turn, i.e., upside-down */
X#define	ROT_RIGHT	3		/* 3/4 turn ccw, or 1/4 turn cw */
X
Xstruct font {
X	int	f_flags;	/* see below */
X	struct	fontops *f_ops;	/* operations */
X	/*
X	 * f_details is provided for font reading subroutines.
X	 * It is intended to be cast to a pointer to a structure
X	 * that is allocated by those routines, and used to keep
X	 * track of whatever information those routines need to
X	 * determine glyph boxes and (if asked for) rasters.
X	 */
X	char	*f_details;	/* type dependent stuff */
X	/*
X	 * f_path is the full pathname to the font file, filled in
X	 * by GetFont and GetRasterlessFont.  Note that since we
X	 * hold on to the path until the font is freed, it should be
X	 * possible to cache glyph accesses on memory-poor machines.
X	 */
X	char	*f_path;	/* font file pathname */
X	/*
X	 * f_dvimag and f_dvidsz are the magnification and design size
X	 * values from the DVI file.  f_font and f_scaled correspond to
X	 * TeX's idea of the proper name for the font (e.g., `cmr10',
X	 * `cmbx10 scaled 1440').  (Note that f_scaled is just the
X	 * ratio of f_dvimag and f_dvidsz; you could save a bit of memory
X	 * by eliminating it and altering the routine Font_TeXName()).
X	 * f_checksum should be set by the font reading routines to
X	 * the font checksum.  If the value is nonzero, it will be
X	 * compared to the checksum in the DVI file.
X	 */
X	i32	f_dvimag;	/* magnification from DVI file */
X	i32	f_dvidsz;	/* design size from DVI file */
X	char	*f_font;	/* TeX's name for the font */
X	int	f_scaled;	/* the ratio of dvimag to dvidsz, x1000 */
X	i32	f_design_size;
X	i32	f_checksum;	/* font checksum, or 0 */
X	i32	f_hppp;		/* horizontal pixels per point */
X	i32	f_vppp;		/* vertical pixels per point */
X	/*
X	 * f_lowch and f_highch bound the region in which f_gly
X	 * indicies are valid.  Specificially, f_gly[i] may be
X	 * read or written if and only if i is in the half-open
X	 * interval [f_lowch..f_highch).  f_gly is an array of
X	 * pointers to glyph structures.  The structures themselves
X	 * are not allocated until requested.
X	 *
X	 * f_glybase is the actual return from malloc(), since it
X	 * is theoretically possible for f_gly-f_lowch to become
X	 * NULL.
X	 */
X	int	f_lowch;	/* first character */
X	int	f_highch;	/* last character, plus 1 */
X	struct	glyph **f_gly;	/* glyphs */
X	struct	glyph **f_glybase;
X};
X
X/*
X * Font flags.
X */
X#define	FF_RASTERS	0x0001	/* font has rasters */
X#define	FF_USR0		0x0100	/* reserved to user code */
X#define	FF_USR1		0x0200	/* reserved to user code */
X#define	FF_USR2		0x0400	/* reserved to user code */
X#define	FF_USR3		0x0800	/* reserved to user code */
X
X/*
X * Operations on fonts.
X *
X * The `fo_dpitomag' field is used as a multiplier for a desired
X * resolution in dots per inch.  The result of the multiplication
X * is converted to a font name by multipying by 1000.0 and rounding.
X * The idea is that PXL files will have a multiplier of 5.0, and
X * others will have a multiplier of 1.0.  This suffices for the
X * present, at any rate; in the future, this field may be replaced
X * with something more general.
X *
X * N.B.: more operations may be added as they are discovered to be
X * useful.
X */
Xstruct	fontops {
X	char	*fo_name;		/* name, e.g., "gf" */
X	double	fo_dpitomag;		/* multiplier */
X	int	(*fo_read)();		/* open and read the font itself */
X	int	(*fo_getgly)();		/* obtain specified glyphs (range) */
X#ifdef notdef
X	int	(*fo_freegly)();	/* release specified glyphs */
X#endif
X	int	(*fo_rasterise)();	/* rasterise specified glyphs */
X	int	(*fo_freefont)();	/* discard font (free details) */
X	struct	fontops *fo_next;	/* purely for font.c */
X};
X
X/*
X * Return a pointer to the glyph information for character `c' in
X * font `f'.
X */
X#define	GLYPH(f, c) \
X	((c) < (f)->f_lowch || (c) >= (f)->f_highch ? (struct glyph *) 0 : \
X	 ((f)->f_gly[c] ? (f)->f_gly[c] : GetGlyph(f, c)))
X
X/*
X * True iff glyph `g' is valid.  Useful for checking return values
X * from GLYPH().
X */
X#define	GVALID(g)	((g) && ((g)->g_flags & GF_VALID))
X
X/*
X * True iff glyph g has a raster.
X */
X#define	HASRASTER(g)	((g)->g_height || (g)->g_width)
X
X/*
X * Return a pointer to the raster information for glyph `g' in font
X * `f' at rotation `r'.
X */
X#define	RASTER(g, f, r)	((g)->g_rotation == (r) && (g)->g_raster ? \
X			 (g)->g_raster : GetRaster(g, f, r))
X
X/*
X * Function types.
X */
Xstruct	font *GetFont(), *GetRasterlessFont();
Xstruct	glyph *GetGlyph();
Xchar	*GetRaster();
Xvoid	FreeFont();
Xvoid	FreeGlyph();
Xvoid	FreeRaster();
Xchar	*Font_TeXName();
Xdouble	DMagFactor();		/* from magfactor.c */
X
X/*
X * Normally from stdio.h
X */
X#ifndef NULL
X#define	NULL	0
X#endif
X
X/*
X * The following environment variable overrides the default font
X * configuration file.  That default is used when fontinit() is not
X * called, or is passed a null pointer.
X */
X#define	CONFENV	"TEXFONTDESC"
END_OF_h/font.h
if test 7100 -ne `wc -c <h/font.h`; then
    echo shar: \"h/font.h\" unpacked with wrong size!
fi
chmod +x h/font.h
# end of overwriting check
fi
if test -f h/gfclass.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/gfclass.h\"
else
echo shar: Extracting \"h/gfclass.h\" \(1730 characters\)
sed "s/^X//" >h/gfclass.h <<'END_OF_h/gfclass.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * GF classification codes
X */
X
X/*
X * Predicate for simple paint commands.  This is presumably the most
X * common GF operation; it may be profitable to check for this before
X * switching out on the command type.
X */
X#define	GF_IsPaint(c)	((c) < 64)
X
X/*
X * Symbolic names for command `types', as returned by the macro
X * GT_TYPE(int c).
X */
X#define GT_PAINT0	0	/* paint without parameter */
X#define	GT_PAINT	1	/* paint with parameter */
X#define GT_BOC		2	/* long BOC */
X#define	GT_BOC1		3	/* short BOC */
X#define GT_EOC		4	/* EOC */
X#define GT_SKIP0	5	/* parameterless SKIP */
X#define	GT_SKIP		6	/* parmeterised SKIP */
X#define GT_NEW_ROW	7	/* NEW_ROW_n */
X#define GT_XXX		8	/* XXXn */
X#define GT_YYY		9	/* YYY */
X#define	GT_NOP		10	/* no op */
X#define GT_CHAR_LOC	11	/* CHAR_LOC */
X#define	GT_CHAR_LOC0	12	/* abbreviated CHAR_LOC */
X#define	GT_PRE		13
X#define	GT_POST		14
X#define	GT_POSTPOST	15
X#define	GT_UNDEF	16
X
X/*
X * Symbolic names for parameter lengths, obtained via the macro
X * GT_OpLen(int c).
X */
X#define	GPL_NONE	0	/* no parameter, or too complex */
X#define	GPL_UNS1	1	/* one one-byte parameter in 0..255 */
X#define	GPL_UNS2	2	/* one two-byte parameter in 0..65535 */
X#define	GPL_UNS3	3	/* one three-byte parameter in 0..16777215 */
X#define	GPL_SGN4	4	/* one four-byte signed parameter */
X/*
X * there are no unsigned four byte parameters, and no shorter signed
X * parameters
X */
X
X#define GF_OpLen(code)	(gf_oplen[code])
X#define GF_TYPE(code)	(gf_gt[code])
Xextern char gf_oplen[];
Xextern char gf_gt[];
END_OF_h/gfclass.h
if test 1730 -ne `wc -c <h/gfclass.h`; then
    echo shar: \"h/gfclass.h\" unpacked with wrong size!
fi
chmod +x h/gfclass.h
# end of overwriting check
fi
if test -f h/gfcodes.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/gfcodes.h\"
else
echo shar: Extracting \"h/gfcodes.h\" \(1732 characters\)
sed "s/^X//" >h/gfcodes.h <<'END_OF_h/gfcodes.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * GF (generic font) opcodes.
X */
X
X#define	GF_PAINT_0	0	/* paint with `d' = 0 */
X				/* ... through PAINT_63, d = 63 */
X#define	GF_PAINT1	64	/* paint, with a one-byte parameter */
X#define	GF_PAINT2	65	/* paint, with a two-byte parameter */
X#define	GF_PAINT3	66	/* paint, with a three-byte parameter */
X#define	GF_BOC		67	/* beginning of character */
X#define	GF_BOC1		68	/* compressed form of BOC */
X#define	GF_EOC		69	/* end of character */
X#define	GF_SKIP0	70	/* finish this row, begin next with white */
X#define	GF_SKIP1	71	/* finish row, one byte parameter */
X#define	GF_SKIP2	72
X#define	GF_SKIP3	73
X#define	GF_NEW_ROW_0	74	/* begin a new row, ready to blacken */
X#define	GF_NEW_ROW_1	75	/* begin a new row, but one col. from left */
X				/* through GF_NEW_ROW_164 */
X#define	GF_XXX1		239	/* special (interpreter dependent) command */
X#define	GF_XXX2		240	/* like XXX1, but two byte length parameter */
X#define	GF_XXX3		241
X#define	GF_XXX4		242
X#define	GF_YYY		243	/* takes four byte parameter, otherwise nop */
X				/* (generated by METAFONT for numspecial) */
X#define	GF_NOP		244	/* no op */
X#define	GF_CHAR_LOC	245	/* character locator */
X#define	GF_CHAR_LOC0	246	/* abbreviated form of CHAR_LOC */
X#define	GF_PRE		247	/* introduces preamble */
X#define	GF_POST		248	/* introduces postamble */
X#define	GF_POSTPOST	249	/* marks end of postamble */
X
X				/* codes 250 through 255 are undefined */
X
X#define	GF_ID		131	/* identifies this revision of GF */
X
X#define GF_FILLER	223	/* filler bytes at end of GF file */
END_OF_h/gfcodes.h
if test 1732 -ne `wc -c <h/gfcodes.h`; then
    echo shar: \"h/gfcodes.h\" unpacked with wrong size!
fi
chmod +x h/gfcodes.h
# end of overwriting check
fi
if test -f h/imPcodes.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/imPcodes.h\"
else
echo shar: Extracting \"h/imPcodes.h\" \(2346 characters\)
sed "s/^X//" >h/imPcodes.h <<'END_OF_h/imPcodes.h'
X/* imPRESS command codes */
X
X#define	imP_SP		128	/* advance one space */
X#define imP_SP1		129	/* advance one space plus 1 pixel */
X
X#define imP_OLD_MMOVE   130
X#define imP_Forw	131	/* one pixel forward */
X#define imP_Backw	132	/* one pixel backward */
X#define imP_MMove	133	/* move in main advance dir. */
X#define imP_SMove	134	/* move in secondary advance dir. */
X#define imP_SetHAbs	135	/* set absolute H pos */
X#define imP_SetHRel	136	/* set relative H pos */
X#define imP_SetVAbs	137	/* set absolute V pos */
X#define imP_SetVRel	138	/* set relative V pos */
X
X/*
X *	rephrase for imagen1-special.c
X */
X#define imP_SET_ABS_H	135	/* set absolute H pos */
X#define imP_SET_REL_H	136	/* set relative H pos */
X#define imP_SET_ABS_V	137	/* set absolute V pos */
X#define imP_SET_REL_V	138	/* set relative V pos */
X
X#define CIRC_ARC	150
X#define ELLIPSE_ARC	151
X#define CIRC_SEGM	160
X
X#define imSRULE		192
X#define imP_Rule	193	/* print a rule */
X
X#define imP_SET_HPOS	195
X#define imP_SET_VPOS	196
X#define imP_CRLF	197	/* move to begin. of line */
X#define imP_SGLY	198
X
X#define imP_DefGlyph	199	/* define a glyph */
X
X#define imP_BGLY	199	/* for imagen1-special.c */
X
X#define imP_DelGlyph	200	/* mark a glyph for deletion */
X#define imP_DELC	201
X#define imP_DELF	202
X
X#define imP_SetHVSystem	205	/* set the H/V coordinate system */
X#define imP_SET_HV_SYSTEM	205	/* for imagen1-special.c */
X
X#define imP_SetAdvDirs	206	/* set the advance directions */
X#define imP_SetFamily	207	/* use this particular family */
X#define imP_SetILSpace	208	/* set the interline spacing */
X#define imP_SetBOL	209	/* define the beginning of line */
X#define imP_SetSP	210	/* define the space between words */
X
X#define imP_CreateFam	211	/* define a family table */
X#define imP_PUSH	211	/* for imagen1-special.c */
X#define imP_POP		212
X
X#define imP_Page	213	/* go to (0,0) */
X#define imP_SET_PUSH_MASK	214
X
X#define imP_EndPage	219	/* print the current page */
X
X#define imP_CREATE_FAMILY_TABLE 221
X#define imP_CREATE_MAP	222
X
X#define SET_PUM		225
X
X#define imP_CREATE_PATH	230
X#define imP_SET_TEXTURE	231
X#define imP_SET_PEN	232
X#define imP_FILL_PATH	233
X#define imP_DRAW_PATH	234
X#define imP_BITMAP	235
X#define imP_SET_MAGN	236
X
X
X#define imP_ForceDel	240	/* force glyph deletion */
X
X#define imP_DEFINE_MACRO	242
X#define imP_EXEC_MACRO		243
X#define imP_EOF		255	/* end of document */
END_OF_h/imPcodes.h
if test 2346 -ne `wc -c <h/imPcodes.h`; then
    echo shar: \"h/imPcodes.h\" unpacked with wrong size!
fi
chmod +x h/imPcodes.h
# end of overwriting check
fi
if test -f h/imagen.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/imagen.h\"
else
echo shar: Extracting \"h/imagen.h\" \(777 characters\)
sed "s/^X//" >h/imagen.h <<'END_OF_h/imagen.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/* imagen globals */
X
X/* Accounting: */
X#ifndef ACCOUNT_FILE
X/*
X#define ACCOUNT_FILE "/usr/adm/imagen_acct"/* if defined, the name of the
X					      imagen page accounting file */
X#endif	ACCOUNT_FILE
X
X#define MaxImFamily	128	/* hardware limitation on font family index */
X#define DefaultDPI	300	/* 300 for Imagen 8/300, 240 for Imprint-10 */
X
X#define DefaultMaxDrift	3	/* default value for MaxDrift */
X
X/* Default margins, in dots */
X/* CRUFT ALERT: depending on DPI variable */
X#define DefaultTopMargin   (DPI)	/* 1" margins */
X#define DefaultLeftMargin  (DPI)
END_OF_h/imagen.h
if test 777 -ne `wc -c <h/imagen.h`; then
    echo shar: \"h/imagen.h\" unpacked with wrong size!
fi
chmod +x h/imagen.h
# end of overwriting check
fi
if test -f h/num.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/num.h\"
else
echo shar: Extracting \"h/num.h\" \(1123 characters\)
sed "s/^X//" >h/num.h <<'END_OF_h/num.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * Pointer I/O: numbers.
X *
X * We deal in fixed format numbers and pointers here.
X * For file I/O, see fio.h.
X */
X
X/*
X * Get one unsigned byte.  Note that this is a proper expression.
X * The rest have more limited contexts, and are therefore OddLy
X * CapItaliseD.
X */
X#define	pgetbyte(p)	UnSign8(*(p)++)
X
X/*
X * Get a two-byte unsigned integer, a three-byte unsigned integer,
X * or a four-byte signed integer.
X */
X#define	pGetWord(p, r) ((r)  = UnSign8(*(p)++) << 8, \
X			(r) |= UnSign8(*(p)++))
X#define	pGet3Byte(p,r) ((r)  = UnSign8(*(p)++) << 16, \
X			(r) |= UnSign8(*(p)++) << 8, \
X			(r) |= UnSign8(*(p)++))
X#define	pGetLong(p, r) ((r)  = UnSign8(*(p)++) << 24, \
X			(r) |= UnSign8(*(p)++) << 16, \
X			(r) |= UnSign8(*(p)++) << 8, \
X			(r) |= UnSign8(*(p)++))
X
X/*
X * ADD pputbyte, pPutWord, pPut3Byte, pPutLong HERE IF THEY PROVE
X * USEFUL.  (But then must consider changing PutWord &c in fio.h.)
X */
END_OF_h/num.h
if test 1123 -ne `wc -c <h/num.h`; then
    echo shar: \"h/num.h\" unpacked with wrong size!
fi
chmod +x h/num.h
# end of overwriting check
fi
if test -f h/postamble.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/postamble.h\"
else
echo shar: Extracting \"h/postamble.h\" \(1895 characters\)
sed "s/^X//" >h/postamble.h <<'END_OF_h/postamble.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/* Definitions for ScanPostAmble */
X
X/*
X * ScanPostAmble reads the postamble of a DVI file from the (stdio)
X * file specified in its first argument.  It is handed two pointers to
X * functions.  The first (ScanPostAmble's second argument) is called
X * after the header information has been read, and given a pointer to a
X * PostAmbleInfo structure.  It is the job of this function to extract the
X * required information from this structure (which is deallocated when
X * ScanPostAmble returns).
X *
X * The second function is called once for each font definition occurring in
X * the postamble, and is given a pointer to a PostAmbleFont structure.  This
X * function should do whatever the device needs to read the actual font.
X *
X * If the DVI file appears malformed, ScanPostAmble will print an error
X * message and exit.  (Drastic, perhaps, but effective.)
X */
X
Xstruct PostAmbleInfo {
X	i32	pai_PrevPagePointer;	/* previous page pointer */
X	i32	pai_Numerator;		/* numerator from dvi file */
X	i32	pai_Denominator;	/* denominator from dvi file*/
X	i32	pai_DVIMag;		/* \magnification */
X	i32	pai_TallestPageHeight;	/* height of tallest page */
X	i32	pai_WidestPageWidth;	/* width of widest page */
X	int	pai_DVIStackSize;	/* DVI stack size required */
X	int	pai_NumberOfPages;	/* total number of pages in DVI file */
X};
X
Xstruct PostAmbleFont {
X	char	*paf_name;		/* name of font (null terminated) */
X	int 	paf_n1;			/* length of first part of name */
X	int 	paf_n2;			/* length of second part of name */
X	i32 	paf_DVIFontIndex;	/* font index number */
X	i32 	paf_DVIChecksum;	/* checksum from DVI file */
X	i32 	paf_DVIMag;		/* "at size" */
X	i32 	paf_DVIDesignSize;	/* design size of font */
X};
END_OF_h/postamble.h
if test 1895 -ne `wc -c <h/postamble.h`; then
    echo shar: \"h/postamble.h\" unpacked with wrong size!
fi
chmod +x h/postamble.h
# end of overwriting check
fi
if test -f h/search.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/search.h\"
else
echo shar: Extracting \"h/search.h\" \(1279 characters\)
sed "s/^X//" >h/search.h <<'END_OF_h/search.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/* search structures and routines for 32-bit key, arbitrary data */
X
Xstruct search {
X	unsigned s_dsize;	/* data object size (includes key size) */
X	unsigned s_space;	/* space left (in terms of objects) */
X	unsigned s_n;		/* number of objects in the table */
X	char	*s_data;	/* data area */
X};
X
X/* returns a pointer to the search table (for future search/installs) */
Xstruct	search *SCreate();	/* create a search table */
X
X/* returns a pointer to the data object found or created */
Xchar	*SSearch();		/* search for a data object */
X
X/* the third argument to SSearch controls operation as follows: */
X#define	S_LOOKUP	0x00	/* pseudo flag */
X#define	S_CREATE	0x01	/* create object if not found */
X#define	S_EXCL		0x02	/* complain if already exists */
X
X/* in addition, it is modified before return to hold status: */
X#define	S_COLL		0x04	/* collision (occurs iff S_EXCL set) */
X#define	S_FOUND		0x08	/* found (occurs iff existed already) */
X#define	S_NEW		0x10	/* created (occurs iff S_CREATE && !S_EXCL) */
X#define	S_ERROR		0x20	/* problem creating (out of memory) */
END_OF_h/search.h
if test 1279 -ne `wc -c <h/search.h`; then
    echo shar: \"h/search.h\" unpacked with wrong size!
fi
chmod +x h/search.h
# end of overwriting check
fi
if test -f h/tfm.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/tfm.h\"
else
echo shar: Extracting \"h/tfm.h\" \(2711 characters\)
sed "s/^X//" >h/tfm.h <<'END_OF_h/tfm.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * TFM file information.
X */
X
X/*
X * TFM files start with a series of unsigned 16 bit integers.  We
X * read this into the structure `tfm_header'.  These are type i32
X * so that they may be used as integer quantities without concern
X * as to sign extension.
X */
Xstruct tfmheader {
X	i32	th_lf;		/* length of the file (16 bit words) */
X	i32	th_lh;		/* length of the header data (words) */
X	i32	th_bc;		/* beginning character */
X	i32	th_ec;		/* ending character (inclusive) */
X	i32	th_nw;		/* number of words in width table */
X	i32	th_nh;		/* number of words in height table */
X	i32	th_nd;		/* number of words in depth table */
X	i32	th_ni;		/* words in italic correction table */
X	i32	th_nl;		/* words in ligature/kern table */
X	i32	th_nk;		/* words in kern table */
X	i32	th_ne;		/* words in extensible character table */
X	i32	th_np;		/* number of font parameter words */
X};
X
X/*
X * The remainder of the TFM file comprises the following information,
X * all of which are 32 bit quantities:
X *
X * header:	array [0..lh-1] of stuff
X * char_info:	array [bc..ec] of char_info_word
X * width:	array [0..nw-1] of fix_word
X * height:	array [0..nh-1] of fix_word
X * depth:	array [0..nd-1] of fix_word
X * italic:	array [0..ni-1] of fix_word
X * lig_kern:	array [0..nl-1] of lig_kern_command
X * kern:	array [0..ne-1] of extensible_recipie
X * param:	array [0..np-1] of fix_word
X */
X
X/*
X * A char_info_word is built of four unsigned eight-bit quantities.  The first
X * is an index into the width table (this saves 24 bits for every
X * character that has the same width as another character).  The
X * second is a composite height and depth index.  The third is a
X * composite italic index and tag, and the fourth is a remainder.
X *
X * XXX needs explaining
X */
Xstruct char_info_word {
X	char	ci_width;	/* width index */
X	char	ci_h_d;		/* height and depth index */
X	char	ci_i_t;		/* italic index and tag */
X	char	ci_remainder;	/* ??? */
X};
X
X/*
X * These macros split up h_and_d and i_and_t values.
X */
X#define	T_CI_H(ci) (((ci)->ci_h_d >> 4) & 0xf)
X#define	T_CI_D(ci) ((ci)->ci_h_d & 0xf)
X#define	T_CI_I(ci) (((ci)->ci_i_t >> 2) & 0x3f)
X#define	T_CI_T(ci) ((ci)->ci_i_t & 3)
X
X/*
X * This structure contains everything one might need to know about
X * a TFM file at run-time.
X *
X * XXX incomplete, or wrong, as yet
X */
Xstruct tfmdata {
X	struct	tfmheader t_hdr;	/* full header */
X	struct	char_info_word *t_ci;	/* char info */
X	i32	*t_width;		/* widths table */
X	i32	*t_height;		/* heights */
X	i32	*t_depth;		/* depths */
X};
END_OF_h/tfm.h
if test 2711 -ne `wc -c <h/tfm.h`; then
    echo shar: \"h/tfm.h\" unpacked with wrong size!
fi
chmod +x h/tfm.h
# end of overwriting check
fi
if test -f h/types.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"h/types.h\"
else
echo shar: Extracting \"h/types.h\" \(1282 characters\)
sed "s/^X//" >h/types.h <<'END_OF_h/types.h'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * C-TeX types (system dependent).
X */
X
X#ifndef _CTEX_TYPES_
X#define _CTEX_TYPES_
X
X/* a 16 bit integer (signed) */
Xtypedef short i16;
X
X/* a 32 bit integer (signed) */
Xtypedef long i32;
X
X/* macros to sign extend quantities that are less than 32 bits long */
X#if defined(u3b) || defined(u3b2) || defined(u3b5) || defined(ibm03)
X#define Sign8(n)	((n) & (1 << 7) ? ((n) | 0xffffff00) : (n))
X#define Sign16(n)	((i32) (short) (n))
X#define Sign24(n)	((n) & (1 << 23) ? ((n) | 0xff000000) : (n))
X#else
X#if defined(sun) || defined(hp300)
X/* Sun mishandles (int)(char)(constant), but this subterfuge works: */
X#define Sign8(n)	((i32) (char) (int) (n))
X#else
X#define Sign8(n)	((i32) (char) (n))
X#endif /* sun */
X#define Sign16(n)	((i32) (short) (n))
X#define Sign24(n)	(((n) << 8) >> 8)
X#endif /* u3b || u3b2 || u3b5 */
X
X/* macros to truncate quantites that are signed but shouldn't be */
X#define UnSign8(n)	((n) & 0xff)
X#define UnSign16(n)	((n) & 0xffff)
X#define UnSign24(n)	((n) & 0xffffff)
X
X/* note that we never have unsigned 32 bit integers */
X
X#endif /* _CTEX_TYPES_ */
END_OF_h/types.h
if test 1282 -ne `wc -c <h/types.h`; then
    echo shar: \"h/types.h\" unpacked with wrong size!
fi
chmod +x h/types.h
# end of overwriting check
fi
echo shar: End of archive 2 \(of 6\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    echo "Now do 'make dviselect'"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--
Skip Montanaro (montanaro@crdgw1.ge.com)

montnaro@sprite.crd.ge.com (Skip Montanaro) (11/14/89)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 6)."
# Contents:  lib/conv.c lib/dviclass.c lib/error.c lib/findpost.c
#   lib/fio.c lib/font.c lib/font_subr.c
# Wrapped by montnaro@sprite on Sat Nov 11 17:13:29 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f lib/conv.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/conv.c\"
else
echo shar: Extracting \"lib/conv.c\" \(1325 characters\)
sed "s/^X//" >lib/conv.c <<'END_OF_lib/conv.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/conv.c,v 1.3 89/02/13 14:30:55 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * Conversions.
X */
X
X#include "types.h"
X#include "conv.h"
X
XConv Conversion;
X
Xdouble	DMagFactor();
X
X/*
X * Set a conversion (possibly the global conversion).
X */
Xvoid
XCSetConversion(c, dpi, usermag, num, denom, dvimag)
X	register struct conversion *c;
X	int dpi, usermag;
X	i32 num, denom, dvimag;
X{
X	double ddpi = dpi;
X
X	c->c_mag = DMagFactor((int) dvimag) * DMagFactor(usermag);
X	c->c_dpi = ddpi;
X
X	/*
X	 * The conversion facture is figured as follows:  there are exactly
X	 * num/denom DVI units per decimicron, and 254000 decimicrons per
X	 * inch, and dpi pixels per inch.  Then we have to adjust this by
X	 * the stated magnification. 
X	 */
X	c->c_fromsp = (num / 254000.0) * (ddpi / denom) * c->c_mag;
X
X	/*
X	 * c->c_tosp is 1/c->c_fromsp, but we will invert the expression
X	 * above in the hopes of some extra accuracy.
X	 *
X	 * IS THIS ANY GOOD?  I NEED A NUMERICAL ANALYST!
X	 */
X	c->c_tosp = (254000.0 / num) * (denom / ddpi) * (1.0 / c->c_mag);
X}
END_OF_lib/conv.c
if test 1325 -ne `wc -c <lib/conv.c`; then
    echo shar: \"lib/conv.c\" unpacked with wrong size!
fi
chmod +x lib/conv.c
# end of overwriting check
fi
if test -f lib/dviclass.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/dviclass.c\"
else
echo shar: Extracting \"lib/dviclass.c\" \(3242 characters\)
sed "s/^X//" >lib/dviclass.c <<'END_OF_lib/dviclass.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/dviclass.c,v 1.3 89/02/13 14:30:57 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * dviclass - DVI code classification tables.
X */
X
X#include "dviclass.h"
X
X/* shorthand---in lowercase for contrast (read on!) */
X#define	four(x)		x, x, x, x
X#define	six(x)		four(x), x, x
X#define	sixteen(x)	four(x), four(x), four(x), four(x)
X#define	sixty_four(x)	sixteen(x), sixteen(x), sixteen(x), sixteen(x)
X#define	one_twenty_eight(x)	sixty_four(x), sixty_four(x)
X
X/*
X * This table contains the byte length of the single operand, or DPL_NONE
X * if no operand, or if it cannot be decoded this way.
X *
X * The sequences UNS1, UNS2, UNS3, SGN4 (`SEQ_U') and SGN1, SGN2, SGN3,
X * SGN4 (`SEQ_S') are rather common, and so we define macros for these.
X */
X#define	SEQ_U	DPL_UNS1, DPL_UNS2, DPL_UNS3, DPL_SGN4
X#define	SEQ_S	DPL_SGN1, DPL_SGN2, DPL_SGN3, DPL_SGN4
X
Xchar dvi_oplen[256] = {
X	one_twenty_eight(DPL_NONE),
X				/* characters 0 through 127 */
X	SEQ_U,			/* DVI_SET1 through DVI_SET4 */
X	DPL_NONE,		/* DVI_SETRULE */
X	SEQ_U,			/* DVI_PUT1 through DVI_PUT4 */
X	DPL_NONE,		/* DVI_PUTRULE */
X	DPL_NONE,		/* DVI_NOP */
X	DPL_NONE,		/* DVI_BOP */
X	DPL_NONE,		/* DVI_EOP */
X	DPL_NONE,		/* DVI_PUSH */
X	DPL_NONE,		/* DVI_POP */
X	SEQ_S,			/* DVI_RIGHT1 through DVI_RIGHT4 */
X	DPL_NONE,		/* DVI_W0 */
X	SEQ_S,			/* DVI_W1 through DVI_W4 */
X	DPL_NONE,		/* DVI_X0 */
X	SEQ_S,			/* DVI_X1 through DVI_X4 */
X	SEQ_S,			/* DVI_DOWN1 through DVI_DOWN4 */
X	DPL_NONE,		/* DVI_Y0 */
X	SEQ_S,			/* DVI_Y1 through DVI_Y4 */
X	DPL_NONE,		/* DVI_Z0 */
X	SEQ_S,			/* DVI_Z1 through DVI_Z4 */
X	sixty_four(DPL_NONE),	/* DVI_FNTNUM0 through DVI_FNTNUM63 */
X	SEQ_U,			/* DVI_FNT1 through DVI_FNT4 */
X	SEQ_U,			/* DVI_XXX1 through DVI_XXX4 */
X	SEQ_U,			/* DVI_FNTDEF1 through DVI_FNTDEF4 */
X	DPL_NONE,		/* DVI_PRE */
X	DPL_NONE,		/* DVI_POST */
X	DPL_NONE,		/* DVI_POSTPOST */
X	six(DPL_NONE)		/* 250 through 255 */
X};
X
Xchar dvi_dt[256] = {
X	one_twenty_eight(DT_CHAR),
X				/* characters 0 through 127 */
X	four(DT_SET),		/* DVI_SET1 through DVI_SET4 */
X	DT_SETRULE,		/* DVI_SETRULE */
X	four(DT_PUT),		/* DVI_PUT1 through DVI_PUT4 */
X	DT_PUTRULE,		/* DVI_PUTRULE */
X	DT_NOP,			/* DVI_NOP */
X	DT_BOP,			/* DVI_BOP */
X	DT_EOP,			/* DVI_EOP */
X	DT_PUSH,		/* DVI_PUSH */
X	DT_POP,			/* DVI_POP */
X	four(DT_RIGHT),		/* DVI_RIGHT1 through DVI_RIGHT4 */
X	DT_W0,			/* DVI_W0 */
X	four(DT_W),		/* DVI_W1 through DVI_W4 */
X	DT_X0,			/* DVI_X0 */
X	four(DT_X),		/* DVI_X1 through DVI_X4 */
X	four(DT_DOWN),		/* DVI_DOWN1 through DVI_DOWN4 */
X	DT_Y0,			/* DVI_Y0 */
X	four(DT_Y),		/* DVI_Y1 through DVI_Y4 */
X	DT_Z0,			/* DVI_Z0 */
X	four(DT_Z),		/* DVI_Z1 through DVI_Z4 */
X	sixty_four(DT_FNTNUM),	/* DVI_FNTNUM0 through DVI_FNTNUM63 */
X	four(DT_FNT),		/* DVI_FNT1 through DVI_FNT4 */
X	four(DT_XXX),		/* DVI_XXX1 through DVI_XXX4 */
X	four(DT_FNTDEF),	/* DVI_FNTDEF1 through DVI_FNTDEF4 */
X	DT_PRE,			/* DVI_PRE */
X	DT_POST,		/* DVI_POST */
X	DT_POSTPOST,		/* DVI_POSTPOST */
X	six(DT_UNDEF)		/* 250 through 255 */
X};
END_OF_lib/dviclass.c
if test 3242 -ne `wc -c <lib/dviclass.c`; then
    echo shar: \"lib/dviclass.c\" unpacked with wrong size!
fi
chmod +x lib/dviclass.c
# end of overwriting check
fi
if test -f lib/error.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/error.c\"
else
echo shar: Extracting \"lib/error.c\" \(2104 characters\)
sed "s/^X//" >lib/error.c <<'END_OF_lib/error.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/error.c,v 1.3 89/02/13 14:30:59 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * Print an error message with an optional system error number, and
X * optionally quit.
X *
X * THIS CODE IS SYSTEM DEPENDENT UNLESS varargs WORKS WITH vprintf
X * OR _doprnt.  It should work properly under System V using vprintf.
X * (If you have vprintf, define HAVE_VPRINTF.)
X */
X
X#include <stdio.h>
X#include <varargs.h>
X
X#ifdef lint
X
X/* VARARGS3 ARGSUSED */
Xerror(quit, e, fmt) int quit, e; char *fmt; {;}
X
X/* VARARGS1 ARGSUSED */
Xpanic(fmt) char *fmt; { exit(1); /* NOTREACHED */ }
X
X#else lint
X
Xextern char *ProgName;
Xextern int errno;
Xextern char *sys_errlist[];
Xextern int sys_nerr;
X
Xerror(va_alist)
X	va_dcl
X{
X	va_list l;
X	int quit, e;
X	char *fmt;
X
X	(void) fflush(stdout);	/* sync error messages */
X	(void) fprintf(stderr, "%s: ", ProgName);
X	va_start(l);
X	/* pick up the constant arguments: quit, errno, printf format */
X	quit = va_arg(l, int);
X	e = va_arg(l, int);
X	if (e < 0)
X		e = errno;
X	fmt = va_arg(l, char *);
X#if defined(sys5) || defined(HAVE_VPRINTF)
X	(void) vfprintf(stderr, fmt, l);
X#else
X	_doprnt(fmt, l, stderr);
X#endif
X	va_end(l);
X	if (e) {
X		if (e < sys_nerr)
X			(void) fprintf(stderr, ": %s", sys_errlist[e]);
X		else
X			(void) fprintf(stderr, ": Unknown error code %d", e);
X	}
X	(void) putc('\n', stderr);
X	(void) fflush(stderr);	/* just in case */
X	if (quit)
X		exit(quit);
X}
X
Xpanic(va_alist)
X	va_dcl
X{
X	va_list l;
X	char *fmt;
X
X	(void) fflush(stdout);
X	(void) fprintf(stderr, "%s: panic: ", ProgName);
X	va_start(l);
X	/* pick up the constant argument: printf format */
X	fmt = va_arg(l, char *);
X#if defined(sys5) || defined(HAVE_VPRINTF)
X	(void) vfprintf(stderr, fmt, l);
X#else
X	_doprnt(fmt, l, stderr);
X#endif
X	va_end(l);
X	(void) putc('\n', stderr);
X	(void) fflush(stderr);
X	abort();
X}
X
X#endif /* lint */
END_OF_lib/error.c
if test 2104 -ne `wc -c <lib/error.c`; then
    echo shar: \"lib/error.c\" unpacked with wrong size!
fi
chmod +x lib/error.c
# end of overwriting check
fi
if test -f lib/findpost.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/findpost.c\"
else
echo shar: Extracting \"lib/findpost.c\" \(3945 characters\)
sed "s/^X//" >lib/findpost.c <<'END_OF_lib/findpost.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/findpost.c,v 1.4 89/02/13 14:31:00 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * FindPostAmble - Find the postamble of a DVI file.
X *
X * N.B.: This routine assumes that ftell() returns byte offsets,
X * not magic cookies.
X */
X
X#include <stdio.h>
X#include "types.h"
X#include "dvicodes.h"
X#include "fio.h"
X
X/*
X * I am making the assumption that 530 bytes will always be enough
X * to find the end of the DVI file.  12 should suffice, as there
X * should be at most seven DVI_FILLER bytes, preceded by the version
X * number, preceded by the four byte postamble pointer; but at least
X * one VMS TeX must pad to a full `sector'.
X */
X/*
X * The above is not correct.  The DVItype program, as authoritative on
X * DVI format, states regarding postambles:
X *
X *	The [last] byte is followed by four or more bytes that are all
X *	equal to the decimal number 223 (i.e., 337 in octal). TeX puts
X *	out four to seven of these trailing bytes, until the total length
X *	of the file is a multiple of four bytes, since this works out
X *	best on machines that pack four bytes per word; but any number
X *	of 223's is allowed, as long as there are at least four of them.
X *
X * Thus assuming "at most seven DVI_FILLER bytes" is wrong.  In fact,
X * PC-TeX seems to put out liberal amounts of DVI_FILLER at the end.
X *
X * The original code was efficient, but had to assume a certain
X * number of bytes.  Since the postamble is only read once anyway,
X * efficiency is not really a consideration.  Plus, like I always
X * say, it's better to get the right answer slowly than the wrong
X * answer fast....
X *
X * Vahe Sarkissian, UCLA Math. Sci., 4/13/88.
X */
X
X#ifdef ORIGINAL_CODE
X#ifdef vms
X#define POSTSIZE	530	/* make only VMS pay for its errors; */
X#else
X#define POSTSIZE	16	/* others get to use something reasonable */
X#endif
X
Xlong	ftell();
X
XFindPostAmble(f)
X	register FILE *f;
X{
X	register long offset;
X	register char *p;
X	register int i;
X	register i32 n;
X	char postbuf[POSTSIZE];
X
X	/*
X	 * Avoid fseek'ing beyond beginning of file; it may
X	 * give odd results.
X	 */
X	fseek(f, 0L, 2);		/* seek to end */
X	offset = ftell(f) - POSTSIZE;	/* and compute where to go next */
X	if (offset < 0L)		/* but make sure it is positive */
X		offset = 0L;
X	fseek(f, offset, 0);
X	p = postbuf;
X	for (i = 0; i < POSTSIZE; i++) {
X		*p++ = getc(f);
X		if (feof(f)) {
X			p--;
X			break;
X		}
X	}
X
X	/*
X	 * Now search backwards for the VERSION byte.  The postamble
X	 * pointer will be four bytes behind that.
X	 */
X	while (--i >= 0) {
X		if (UnSign8(*--p) == DVI_VERSION)
X			goto foundit;
X		if (UnSign8(*p) != DVI_FILLER)
X			break;
X	}
X	return (-1);		/* cannot find postamble ptr */
X
Xfoundit:
X	/*
X	 * Change offset from the position at the beginning of postbuf
X	 * to the position of the VERSION byte, and seek to four bytes
X	 * before that.  Then get a long and use its value to seek to
X	 * the postamble itself.
X	 */
X	offset += p - postbuf;
X	fseek(f, offset - 4L, 0);
X	fGetLong(f, n);
X	offset = n;
X	fseek(f, offset, 0);
X	return (0);		/* success */
X}
X
X#else !ORIGINAL_CODE
X
XFindPostAmble(f)
X	register FILE *f;
X{
X	register long offset;
X	register i32 n;
X	
X	offset = -4;	/* At least four bytes of DVI_FILLER must be present. */
X	do {
X		offset -= 1;
X		(void) fseek(f, offset, 2);
X		n = fgetbyte(f);
X	} while (n == DVI_FILLER);
X
X	if (n != DVI_VERSION)
X		return (-1);	/* Bad version of DVI file */
X	
X	/*
X	 * Position file four bytes before DVI_VERSION byte,
X	 * and read a long.  Use that long to seek to the
X	 * beginning of the postamble itself.
X	 */
X	offset -= 4;
X	(void) fseek(f, offset, 2);
X	fGetLong(f, n);
X	offset = n;
X	(void) fseek(f, offset, 0);
X	return (0);		/* success */
X}
X#endif ORIGINAL_CODE
END_OF_lib/findpost.c
if test 3945 -ne `wc -c <lib/findpost.c`; then
    echo shar: \"lib/findpost.c\" unpacked with wrong size!
fi
chmod +x lib/findpost.c
# end of overwriting check
fi
if test -f lib/fio.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/fio.c\"
else
echo shar: Extracting \"lib/fio.c\" \(965 characters\)
sed "s/^X//" >lib/fio.c <<'END_OF_lib/fio.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/fio.c,v 1.3 89/02/13 14:31:01 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * File I/O subroutines for getting bytes, words, 3bytes, and longwords.
X */
X
X#include <stdio.h>
X#include "types.h"
X#include "fio.h"
X
Xstatic char eofmsg[] = "unexpected EOF";
X
X/* for symmetry: */
X#define	fGetByte(fp, r)	((r) = getc(fp))
X#define	Sign32(i)	(i)
X
X#define make(name, func, signextend) \
Xi32 \
Xname(fp) \
X	register FILE *fp; \
X{ \
X	register i32 n; \
X \
X	func(fp, n); \
X	if (feof(fp)) \
X		error(1, 0, eofmsg); \
X	return (signextend(n)); \
X}
X
Xmake(GetByte,  fGetByte,  Sign8)
Xmake(GetWord,  fGetWord,  Sign16)
Xmake(Get3Byte, fGet3Byte, Sign24)
Xmake(GetLong,  fGetLong,  Sign32)
END_OF_lib/fio.c
if test 965 -ne `wc -c <lib/fio.c`; then
    echo shar: \"lib/fio.c\" unpacked with wrong size!
fi
chmod +x lib/fio.c
# end of overwriting check
fi
if test -f lib/font.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/font.c\"
else
echo shar: Extracting \"lib/font.c\" \(9825 characters\)
sed "s/^X//" >lib/font.c <<'END_OF_lib/font.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/font.c,v 1.6 89/02/13 14:31:02 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * Routines for working with fonts.  In particular, the configuration
X * dependent code is here.
X *
X * Specific fonts (GF, PXL, etc.) have functions in separate files.
X */
X
X#include <stdio.h>
X#include <errno.h>
X#include <sys/file.h>
X#include "types.h"
X#include "conv.h"
X#include "font.h"
X
X/*
X * Define the default configuration file.
X * Also define the maximum path name length.
X */
X#ifndef FONTDESC
X	you need to define FONTDESC in the compile line
X#endif
X
X#define	PATHLEN	1024
X
X/*
X * A font configuration.  The font list is ordered.
X *
X * A specifier is typically a particular print engine, since
X * different engines need slightly different fonts.
X */
Xstruct fontconf {
X	struct	fontconf *fc_next;
X	struct	fontops *fc_ops;
X	char	*fc_path;	/* path, with metacharacters */
X	char	*fc_spec;	/* specifier */
X	int	fc_slop;	/* slop value */
X};
X
X/*
X * EQ is a fast way to check for string equivalence.
X */
X#define	EQ(a, b) (*(a) == *(b) && strcmp(a, b) == 0)
X
X/*
X * Private variables.
X */
Xstatic	int didinit;		/* true => initialised already */
Xstatic	char *cfname;		/* config file name, for errors */
Xstatic	int cfline;		/* config file line, likewise */
Xstatic	struct fontops *fontops;/* font operations code: list head */
Xstatic	struct fontconf *fonts;	/* font list */
Xstatic	struct fontconf **nextfc;/* used during initialisation */
Xstatic	char spec_any[] = "*";	/* the `anything' specifier */
X
X/*
X * Imports.
X */
Xextern	int errno;
Xchar	*getenv(), *malloc(), *strsave();
X#ifndef sys5
Xchar	*sprintf();
X#endif
X
Xstatic readconf();
Xstatic setfont();
Xstatic badcf();
Xstatic struct font *getafont();	/* get a font and optional rasters */
X
X/*
X * Here, alas, we know about all the kinds of fonts.
X * This also means that every DVI interpreter pulls in
X * the full set of font manipulation routines.
X *
X * PERHAPS THIS SHOULD BE CONFIGURABLE.
X */
X#define	ADDFONT(x) { \
X	extern struct fontops x; \
X	x.fo_next = fontops; \
X	fontops = &x; \
X}
X
Xfontinit(file)
X	char *file;
X{
X
X	if (didinit) {
X		/*
X		 * Could free the old configuration and fire up
X		 * a new one, but for now . . .
X		 */
X		error(1, 0, "attempt to reinit fonts");
X		/* NOTREACHED */
X	}
X	didinit++;
X	ADDFONT(boxops);
X	ADDFONT(blankops);
X	ADDFONT(invisops);
X	ADDFONT(pxlops);
X	ADDFONT(pkops);
X	ADDFONT(gfops);
X	nextfc = &fonts;
X	if (file == NULL)
X		if ((file = getenv(CONFENV)) == NULL)
X			file = FONTDESC;
X	readconf(file);
X}
X
X/*
X * A proto resembles a fontspec (indeed, it is a prototype
X * fontspec) but is not quite the same.  It is used to gather
X * the information needed per fontspec before allocating
X * the fontspec itself.
X */
Xstruct proto {
X	char	*p_type;
X	char	*p_spec;
X	char	*p_slop;
X	char	*p_path;
X};
X
X/*
X * Read the named configuration file.  The file is split into
X * lines, and lines are split into words; if the first word is
X * "font", this is a fontconf, and we read the remainder of the
X * words and make a fontconf entry.
X */
Xstatic
Xreadconf(name)
X	char *name;
X{
X	register FILE *f;	/* config file */
X	register char **p;	/* pointer into word vector */
X	register int c;
X	char line[1024];	/* input line */
X	char *v[100];		/* word vector */
X	struct proto proto;	/* prototype fontconf */
X
X#define GETWORD(x, ifnone) \
X	if (--c <= 0) \
X		badcf(ifnone); \
X	else \
X		(x) = *p++
X
X	if ((f = fopen(name, "r")) == NULL)
X		error(1, errno, "cannot read font configuration file \"%s\"",
X			name);
X	cfname = name;
X	cfline = 0;
X	while (fgets(line, sizeof (line), f) != NULL) {
X		cfline++;
X		if ((c = strlen(line)) > 0) {
X			if (line[--c] != '\n')
X				badcf("line too long");
X			line[c] = 0;
X		}
X		if ((c = split(line, v, sizeof (v) / sizeof (*v))) < 0)
X			badcf("too many words");
X		p = v;
X		/* skip things that are not fonts */
X		if (c == 0 || !EQ(*p, "font"))
X			continue;
X		p++;
X		GETWORD(proto.p_type, "missing font typename");
X		GETWORD(proto.p_spec, "missing font spec (engine)");
X		GETWORD(proto.p_slop, "missing slop value");
X		GETWORD(proto.p_path, "need pathname");
X		(void) setfont(&proto);
X	}
X}
X
X/*
X * Find a font's operations, given its name.
X */
Xstatic struct fontops *
Xfindops(name)
X	register char *name;
X{
X	register struct fontops *fo;
X
X	for (fo = fontops; fo != NULL; fo = fo->fo_next)
X		if (EQ(fo->fo_name, name))
X			return (fo);
X	return (NULL);
X}
X
X/*
X * Turn a prototype fontconf into a real one.
X */
Xstatic int
Xsetfont(p)
X	register struct proto *p;
X{
X	register struct fontconf *fc;
X	struct fontops *ops = findops(p->p_type);
X
X	if (ops == NULL) {
X		error(0, 0,
X			"\"%s\", line %d: unknown font type \"%s\" ignored",
X			cfname, cfline, p->p_type);
X		return (-1);
X	}
X	if ((fc = (struct fontconf *) malloc(sizeof (*fc))) == NULL)
X		error(1, errno,
X			"out of memory for font configuration (sorry)");
X	fc->fc_ops = ops;
X	fc->fc_next = NULL;
X	fc->fc_path = strsave(p->p_path);
X	fc->fc_spec = EQ(p->p_spec, spec_any) ? NULL : strsave(p->p_spec);
X	fc->fc_slop = atoi(p->p_slop);
X	if (fc->fc_slop < 1)	/* quietly enforce proper slops */
X		fc->fc_slop = 1;
X	*nextfc = fc;
X	nextfc = &fc->fc_next;
X	return (0);
X}
X
X/*
X * Complain about a problem in the configuration file.
X */
Xstatic
Xbadcf(why)
X	char *why;
X{
X
X	error(1, 0, "\"%s\", line %d: %s", cfname, cfline, why);
X	/* NOTREACHED */
X}
X
X/*
X * Turn a prototype path, name, and magnification into a full
X * path.
X */
Xstatic
Xpave(result, proto, name, mag)
X	char *result, *proto, *name;
X	int mag;
X{
X	register int c;
X	register char *s, *d, *p;
X	char num[30];
X
X	d = result;
X	p = proto;
X	s = NULL;
X	num[0] = 0;		/* will need changing for other bases */
X
X	while (p != NULL) {
X		/*
X		 * If sourcing from s, take its next character, and
X		 * insert it directly.  Otherwise take the next path
X		 * character and interpret it.
X		 */
X		if (s != NULL) {
X			if ((c = *s++) == 0) {
X				s = NULL;
X				continue;
X			}
X			goto put;
X		}
X		if ((c = *p++) == 0)
X			p = NULL;
X		if (c != '%')
X			goto put;
X
X		switch (c = *p++) {
X
X		case 'f':
X		case 'n':
X		case 's':
X			s = name;
X			continue;
X
X		case 'd':
X		case 'm':
X			if (num[0] == 0)
X				(void) sprintf(num, "%d", mag);
X			s = num;
X			continue;
X
X		case 0:
X			c = '%';
X			p--;
X			/* FALLTHROUGH */
X		}
Xput:
X		if (d - result >= PATHLEN)
X			error(1, 0, "font path `%s' too long (sorry)", proto);
X		*d++ = c;
X	}
X}
X
X
X/*
X * Given a font name and size, return the first font that fits, along
X * with its name (via fname).  If we cannot find such a font, we set
X * *fname to point to a `canonical' example font name, unless there are
X * are no fonts for the device, in which case we set *fname to NULL.
X */
Xstruct font *
XGetFont(nm, dvimag, dvidsz, dev, fname)
X	char *nm;
X	i32 dvimag, dvidsz;
X	char *dev, **fname;
X{
X
X	return (getafont(nm, dvimag, dvidsz, dev, fname, 1));
X}
X
X/*
X * Same as GetFont, but caller promises never to ask for rasters.
X */
Xstruct font *
XGetRasterlessFont(nm, dvimag, dvidsz, dev, fname)
X	char *nm;
X	i32 dvimag, dvidsz;
X	char *dev, **fname;
X{
X
X	return (getafont(nm, dvimag, dvidsz, dev, fname, 0));
X}
X
X/*
X * NEED TO THINK ABOUT gf NAMING CONVENTIONS HERE: ARE THEY LIKE pxl?
X * WHAT ABOUT OTHERS?
X */
Xstatic struct font *
Xgetafont(nm, dvimag, dvidsz, dev, fname, wantrast)
X	char *nm;
X	i32 dvimag, dvidsz;
X	char *dev, **fname;
X	int wantrast;
X{
X	register int slop, fmag;
X	register struct font *f;
X	register struct fontconf *fc;
X	register char *path;
X	static char firstpath[PATHLEN], laterpath[PATHLEN];
X	double mag;
X	int scaled;
X
X	extern Conv Conversion;
X
X	if (!didinit)
X		fontinit((char *) NULL);
X
X	/*
X	 * The equation below means, approximately, `the font is
X	 * magnified by the ratio of the actual size dvimag to the
X	 * design size dvidsz, and then further scaled by the
X	 * global magnification.'  We multiply this by the printer's
X	 * resolution in dots per inch, then use the per-font
X	 * conversion factor to convert a dots-per-inch value to
X	 * a font name `%m' magnification (extension).
X	 */
X	mag = (double) dvimag / (double) dvidsz;
X	scaled = mag * 1000.0 + 0.5;
X	mag *= Conversion.c_mag * Conversion.c_dpi;
X
X	path = firstpath;
X	for (fc = fonts; fc != NULL; fc = fc->fc_next) {
X		if (dev != NULL && fc->fc_spec != NULL &&
X		    !EQ(dev, fc->fc_spec))
X			continue;
X		fmag = mag * fc->fc_ops->fo_dpitomag + 0.5;
X		for (slop = 0; slop < fc->fc_slop; slop++) {
X			pave(path, fc->fc_path, nm, fmag + slop);
X			if (access(path, R_OK) == 0)
X				goto found;
X
X
X			/* if someone could explain this, I'd appreicate it.
X			   On ultrix 2.2, checking R_OK on a RO filesyste
X			   fails, with the following errno. Why? */
X
X			if ( errno == EROFS ) {
X			  goto found;
X			}
X
X			if (slop) {
X				pave(path, fc->fc_path, nm, fmag - slop);
X				if (access(path, R_OK) == 0)
X					goto found;
X				if ( errno == EROFS ) {
X				  goto found;
X				}
X			}
X			path = laterpath;
X		}
X	}
X
X	/* not found */
X	if (path == firstpath) {	/* never got to try any paths */
X		*fname = NULL;
X		errno = ENXIO;
X	} else {
X		*fname = firstpath;
X		errno = ENOENT;
X	}
X	return (NULL);
X
Xfound:
X	*fname = path;
X
X	/* allocate space for the per-font info, and read it in */
X	f = (struct font *) malloc(sizeof (struct font));
X	if (f == NULL)
X		return (NULL);
X	f->f_flags = wantrast ? FF_RASTERS : 0;
X	f->f_ops = fc->fc_ops;
X	f->f_path = strsave(path);
X	f->f_font = strsave(nm);
X	f->f_dvimag = dvimag;
X	f->f_dvidsz = dvidsz;
X	f->f_scaled = scaled;
X	f->f_checksum = 0;	/* in case the font reader cannot get one */
X	errno = 0;
X	if ((*f->f_ops->fo_read)(f)) {
X		int e = errno;	/* paranoid */
X
X		free(f->f_path); f -> f_path = 0;
X		free(f->f_font); f -> f_font = 0;
X		free((char *) f); f = 0;
X		errno = e;
X		return (NULL);
X	}
X	return (f);
X}
END_OF_lib/font.c
if test 9825 -ne `wc -c <lib/font.c`; then
    echo shar: \"lib/font.c\" unpacked with wrong size!
fi
chmod +x lib/font.c
# end of overwriting check
fi
if test -f lib/font_subr.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/font_subr.c\"
else
echo shar: Extracting \"lib/font_subr.c\" \(4984 characters\)
sed "s/^X//" >lib/font_subr.c <<'END_OF_lib/font_subr.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/font_subr.c,v 1.5 89/02/13 14:31:04 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * Subroutines common to all fonts.
X */
X
X#include "font.h"
X
Xstatic struct glyph *freeglyphs;
X
Xchar	*malloc();
Xextern	errno;
X
X/*
X * Set up the font structures to note that a font has glyphs in
X * the half-open interval [low, high).
X *
X * SHOULD I ALLOW ADDITIONS TO THE RANGE VIA SUBSEQUENT CALLS TO
X * FontHasGlyphs?
X */
XFontHasGlyphs(f, low, high)
X	register struct font *f;
X	register int low, high;
X{
X	register struct glyph **gp;
X
X	/* record bounds */
X	f->f_lowch = low;
X	f->f_highch = high;
X
X	/*
X	 * Allocate space for all the glyph pointers, and set
X	 * them all to NULL.
X	 */
X	if (low >= high)	/* no glyphs */
X		gp = NULL;
X	else {
X		gp = (struct glyph **) malloc((unsigned) (high - low) *
X			sizeof (*gp));
X		if (gp == NULL)
X			return (-1);
X	}
X	f->f_glybase = gp;
X	f->f_gly = gp - low;
X	while (++low <= high)
X		*gp++ = NULL;
X	return (0);
X}
X
X/*
X * AllocGlyph allocates a new glyph.  ReleaseGlyph puts one onto the free
X * list.  We maintain a local list of free glyphs.
X */
X#define ReleaseGlyph(g)	\
X	((g)->g_un.g_next = freeglyphs, freeglyphs = (g))
X
Xstatic struct glyph *
XAllocGlyph(n)
X	int n;
X{
X	register struct glyph *g;
X	register int i;
X
X	if ((g = freeglyphs) == NULL) {
X		g = (struct glyph *) malloc((unsigned) (128 * sizeof (*g)));
X		if (g == NULL)
X			error(1, errno, "out of glyph memory");
X		g += (i = 128);
X		while (--i >= 0) {
X			g--;
X			ReleaseGlyph(g);
X		}
X	}
X	freeglyphs = g->g_un.g_next;
X	g->g_flags = 0;
X	g->g_raster = NULL;
X	g->g_index = n;
X	return (g);
X}
X
X/*
X * Free one glyph.
X */
Xvoid
XFreeGlyph(f, n)
X	struct font *f;
X	register int n;
X{
X	register struct glyph *g;
X
X	if (n < f->f_lowch || n >= f->f_highch)
X		return;
X#ifdef notdef
X	(*f->f_ops->fo_freegly)(f, n, n);
X#endif
X	if ((g = f->f_gly[n]) == NULL)
X		return;
X	if (g->g_raster != NULL) {
X		free(g->g_raster); g -> g_raster = 0;
X	      }
X	ReleaseGlyph(g);
X}
X
X/*
X * Free a font.
X */
Xvoid
XFreeFont(f)
X	register struct font *f;
X{
X	register struct glyph *g;
X	register int i;
X
X#ifdef notdef
X	(*f->f_ops->fo_freegly)(f, f->f_lowch, f->f_highch);
X#endif
X	for (i = f->f_lowch; i < f->f_highch; i++) {
X		if ((g = f->f_gly[i]) == NULL)
X			continue;
X		if (g->g_raster != NULL) {
X			free(g->g_raster); g -> g_raster = 0;
X		      }
X		ReleaseGlyph(g);
X	}
X	if (f->f_glybase != NULL) {
X		free((char *) f->f_glybase); g -> g_raster = 0;
X	      }
X	(*f->f_ops->fo_freefont)(f);
X	free(f->f_path); f -> f_path = 0;
X	free(f->f_font); f -> f_font = 0;
X	free((char *) f); f = 0;
X}
X
X/*
X * Get glyph `c' in font `f'.  We pull in a few adjacent glyphs here
X * under the (perhaps naive) assumption that things will go faster
X * that way.
X *
X * TODO:
X *	try different adjacency values
X *	make adjacency a font attribute? (or an op)
X */
X#define	ADJ	8		/* must be a power of 2 */
X#define	GET_ADJ(c, l, h) ((h) = ADJ + ((l) = (c) & ~(ADJ - 1)))
X
Xstruct glyph *
XGetGlyph(f, c)
X	register struct font *f;
X	int c;
X{
X	register int i, h, l;
X
X	GET_ADJ(c, l, h);
X	if (l < f->f_lowch)
X		l = f->f_lowch;
X	if (h > f->f_highch)
X		h = f->f_highch;
X	if (l >= h)
X		return (NULL);
X	for (i = l; i < h; i++)
X		if (f->f_gly[i] == NULL)
X			f->f_gly[i] = AllocGlyph(i);
X
X	if ((*f->f_ops->fo_getgly)(f, l, h)) {
X		/*
X		 * I do not know what to do about this just yet, so:
X		 */
X		panic("getgly fails and I am confused ... help!");
X	}
X
X	/*
X	 * Apply the appropriate scale factor to the TFM widths.
X	 * This makes them come out in scaled points, instead of FIXes.
X	 */
X	ScaleGlyphs(f, l, h);	/* ??? */
X
X	return (f->f_gly[c]);
X}
X
X/*
X * Get the raster for glyph g in font f at rotation r.
X */
Xchar *
XGetRaster(g, f, r)
X	register struct glyph *g;
X	register struct font *f;
X	int r;
X{
X	int l, h;
X
X	/* abort if caller did not ask for rasters in advance */
X	if ((f->f_flags & FF_RASTERS) == 0)
X		panic("GetRaster(%s)", f->f_path);
X
X	/*
X	 * If there is no raster, get one.  Blank characters,
X	 * however, never have rasters.
X	 */
X	if (g->g_raster == NULL) {
X		if (!HASRASTER(g))
X			return (NULL);
X		/*
X		 * THE FOLLOWING DEPENDS ON THE ADJACENCY MATCHING THAT IN
X		 * GetGlyph() ABOVE.
X		 */
X		GET_ADJ(g->g_index, l, h);
X		if (l < f->f_lowch)
X			l = f->f_lowch;
X		if (h > f->f_highch)
X			h = f->f_highch;
X		if ((*f->f_ops->fo_rasterise)(f, l, h))
X			error(1, 0, "rasterise fails (out of memory?)");
X	}
X	if (g->g_rotation != r)
X		SetRotation(g, r);
X	return (g->g_raster);
X}
X
X/*
X * Return a TeX-style font name, including scale factor.
X * SHOULD I BOTHER WITH \magstep STYLE NAMES?
X */
Xchar *
XFont_TeXName(f)
X	register struct font *f;
X{
X	static char result[200];
X
X	if (f->f_scaled == 1000)
X		return (f->f_font);
X	sprintf(result, "%s scaled %d", f->f_font, f->f_scaled);
X	return (result);
X}
END_OF_lib/font_subr.c
if test 4984 -ne `wc -c <lib/font_subr.c`; then
    echo shar: \"lib/font_subr.c\" unpacked with wrong size!
fi
chmod +x lib/font_subr.c
# end of overwriting check
fi
echo shar: End of archive 3 \(of 6\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    echo "Now do 'make dviselect'"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--
Skip Montanaro (montanaro@crdgw1.ge.com)

montnaro@sprite.crd.ge.com (Skip Montanaro) (11/14/89)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 4 (of 6)."
# Contents:  lib/getopt.c lib/gfclass.c lib/gffont.c lib/gripes.c
#   lib/magfactor.c
# Wrapped by montnaro@sprite on Sat Nov 11 17:13:31 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f lib/getopt.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/getopt.c\"
else
echo shar: Extracting \"lib/getopt.c\" \(1380 characters\)
sed "s/^X//" >lib/getopt.c <<'END_OF_lib/getopt.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * getopt - get option letter from argv
X * (From Henry Spencer @ U of Toronto Zoology, slightly edited)
X */
X
X#include <stdio.h>
X
Xchar	*optarg;	/* Global argument pointer. */
Xint	optind;		/* Global argv index. */
X
Xstatic char *scan;	/* Private scan pointer. */
X
Xextern char *index();
X
Xint
Xgetopt(argc, argv, optstring)
X	register int argc;
X	register char **argv;
X	char *optstring;
X{
X	register int c;
X	register char *place;
X
X	optarg = NULL;
X	if (scan == NULL || *scan == 0) {
X		if (optind == 0)
X			optind++;
X		if (optind >= argc || argv[optind][0] != '-' ||
X		    argv[optind][1] == 0)
X			return (EOF);
X		if (strcmp(argv[optind], "--") == 0) {
X			optind++;
X			return (EOF);
X		}
X		scan = argv[optind] + 1;
X		optind++;
X	}
X	c = *scan++;
X	place = index(optstring, c);
X
X	if (place == NULL || c == ':') {
X		fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
X		return ('?');
X	}
X	place++;
X	if (*place == ':') {
X		if (*scan != '\0') {
X			optarg = scan;
X			scan = NULL;
X		} else {
X			if (optind >= argc) {
X				fprintf(stderr,
X					"%s: missing argument after -%c\n",
X					argv[0], c);
X				return ('?');
X			}
X			optarg = argv[optind];
X			optind++;
X		}
X	}
X	return (c);
X}
END_OF_lib/getopt.c
if test 1380 -ne `wc -c <lib/getopt.c`; then
    echo shar: \"lib/getopt.c\" unpacked with wrong size!
fi
chmod +x lib/getopt.c
# end of overwriting check
fi
if test -f lib/gfclass.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/gfclass.c\"
else
echo shar: Extracting \"lib/gfclass.c\" \(2408 characters\)
sed "s/^X//" >lib/gfclass.c <<'END_OF_lib/gfclass.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/gfclass.c,v 1.3 89/02/13 14:31:07 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * gfclass - GF code classification tables.
X */
X
X#include "gfclass.h"
X
X/* shorthand---in lowercase for contrast (read on!) */
X#define	three(x)	x, x, x
X#define	four(x)		x, x, x, x
X#define	five(x)		four(x), x
X#define	six(x)		four(x), x, x
X#define	eight(x)	four(x), four(x)
X#define	sixteen(x)	eight(x), eight(x)
X#define	thirty_two(x)	sixteen(x), sixteen(x)
X#define	sixty_four(x)	thirty_two(x), thirty_two(x)
X#define	one_twenty_eight(x) sixty_four(x), sixty_four(x)
X#define	one_sixty_five(x) one_twenty_eight(x), thirty_two(x), five(x)
X
X/*
X * Length of the single (or first) operand, if any.
X */
Xchar gf_oplen[256] = {
X	sixty_four(GPL_NONE),	/* GF_PAINT_0 through GF_PAINT_63 */
X	GPL_UNS1,		/* GF_PAINT1 */
X	GPL_UNS2,		/* GF_PAINT2 */
X	GPL_UNS3,		/* GF_PAINT3 */
X	GPL_NONE,		/* GF_BOC */
X	GPL_NONE,		/* GF_BOC1 */
X	GPL_NONE,		/* GF_EOC */
X	GPL_NONE,		/* GF_SKIP0 */
X	GPL_UNS1,		/* GF_SKIP1 */
X	GPL_UNS2,		/* GF_SKIP2 */
X	GPL_UNS3,		/* GF_SKIP3 */
X	one_sixty_five(GPL_NONE),/* GF_NEW_ROW_0 through GF_NEW_ROW_164 */
X	GPL_UNS1,		/* GF_XXX1 */
X	GPL_UNS2,		/* GF_XXX2 */
X	GPL_UNS3,		/* GF_XXX3 */
X	GPL_SGN4,		/* GF_XXX4 */
X	GPL_SGN4,		/* GF_YYY */
X	GPL_NONE,		/* GF_NOP */
X	GPL_NONE,		/* GF_CHAR_LOC */
X	GPL_NONE,		/* GF_CHAR_LOC0 */
X	GPL_NONE,		/* GF_PRE */
X	GPL_NONE,		/* GF_POST */
X	GPL_NONE,		/* GF_POSTPOST */
X	six(GPL_NONE)		/* 250 through 255 */
X};
X
X/*
X * Types of the various opcodes.
X */
Xchar gf_gt[256] = {
X	sixty_four(GT_PAINT0),	/* GF_PAINT_0 through GF_PAINT_63 */
X	three(GT_PAINT),	/* GF_PAINT1 through GF_PAINT3 */
X	GT_BOC,			/* GF_BOC */
X	GT_BOC1,		/* GF_BOC1 */
X	GT_EOC,			/* GF_EOC */
X	GT_SKIP0,		/* GF_SKIP0 */
X	three(GT_SKIP),		/* GF_SKIP1 through GF_SKIP3 */
X	one_sixty_five(GT_NEW_ROW),/* GF_NEW_ROW_0 throgh GF_NEW_ROW_164 */
X	four(GT_XXX),		/* GF_XXX1 through GF_XXX4 */
X	GT_YYY,			/* GF_YYY */
X	GT_NOP,			/* GF_NOP */
X	GT_CHAR_LOC,		/* GF_CHAR_LOC */
X	GT_CHAR_LOC0,		/* GF_CHAR_LOC0 */
X	GT_PRE,			/* GF_PRE */
X	GT_POST,		/* GF_POST */
X	GT_POSTPOST,		/* GF_POSTPOST */
X	six(GT_UNDEF)		/* 250 through 255 */
X};
END_OF_lib/gfclass.c
if test 2408 -ne `wc -c <lib/gfclass.c`; then
    echo shar: \"lib/gfclass.c\" unpacked with wrong size!
fi
chmod +x lib/gfclass.c
# end of overwriting check
fi
if test -f lib/gffont.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/gffont.c\"
else
echo shar: Extracting \"lib/gffont.c\" \(22029 characters\)
sed "s/^X//" >lib/gffont.c <<'END_OF_lib/gffont.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/gffont.c,v 1.4 89/02/13 14:31:08 grunwald Exp Locker: grunwald $";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "types.h"
X#include "font.h"
X#include "gfcodes.h"
X#include "gfclass.h"
X#include "num.h"
X
X/*
X * GF font operations.
X *
X * GF files may be compact, but this code surely is not!
X *
X * TODO:
X *	think about fonts with characters outside [0..255]
X *	find some way to free gf body when done
X */
X
Xstatic gf_read();
Xstatic gf_getgly();
Xstatic gf_rasterise();
Xstatic gf_freefont();
X
Xstruct	fontops gfops =
X	{ "gf", 1.0, gf_read, gf_getgly, gf_rasterise, gf_freefont };
X
X/*
X * Local info.
X */
X
X/*
X * A bounding box.  The names follow those in the GF documentation.
X */
Xstruct bounds {
X	i32	min_m, max_m;	/* min and max `m' (colunm) values */
X	i32	min_n, max_n;	/* min and max `n' (row) values */
X};
X
X/*
X * char_loc is one `character locator' from a GF file, save for the
X * `character residue', which we need not.
X */
Xstruct char_loc {
X	i32	cl_dx;		/* x escapement (scaled pixels) */
X	i32	cl_dy;		/* y escapement (scaled pixels) */
X	i32	cl_w;		/* TFM width */
X	i32	cl_p;		/* pointer to BOC (or specials) */
X};
X
X/*
X * GF details include:
X *  ->	the main body of the GF file (all bytes save pre- and post-amble);
X *  ->	global box boundaries;
X * and	character locators, addressed by `character residue'.  Empty
X *	slots are indicated by a -1 `pointer'.
X */
Xstruct gf_details {
X	char	*gd_body;		/* GF body */
X	char	*gd_base;		/* == gd_body - preamble_size */
X	struct	bounds gd_gb;		/* global boundaries */
X	struct	char_loc gd_cl[256];	/* character locators */
X};
X
X/*
X * Get the gf_details from font f.
X */
X#define	ftogd(f) ((struct gf_details *) (f)->f_details)
X
Xextern	int errno;
Xchar	*malloc(), *copyit();
X
Xstatic int gf_read();
Xstatic int gf_read();
Xstatic int gf_rasterise();
Xstatic int gf_freefont();
X
X/*
X * I am making the assumption that 530 bytes will always be enough
X * to find the end of the GF file.  12 should suffice, as there
X * should be at most seven GF_FILLER bytes, preceded by the GF ID,
X * preceded by the four byte postamble pointer; but at least one
X * VMS TeX pads pads DVI files to a full `sector', so I am assuming
X * it may do the same to GF files.
X */
X#ifdef vms
X#define	POSTSIZE	530	/* make only VMS pay for its ways; */
X#else
X#define	POSTSIZE	16	/* others get to use something reasonable */
X#endif
X
X/*
X * Find the GF postamble.  Store the offsets of the POST and POSTPOST
X * opcodes through postp and postpostp.
X */
Xstatic
XfindGFpostamble(fd, postp, postpostp)
X	int fd;
X	long *postp, *postpostp;
X{
X	register long offset;
X	register char *p;
X	register int i;
X	register i32 n;
X	char postbuf[POSTSIZE];
X
X	/*
X	 * Avoid lseek()ing beyond beginning of file; it may give odd
X	 * results.  Read the last POSTSIZE bytes (or however many we
X	 * can get).
X	 */
X	offset = lseek(fd, 0L, 2) - (long) POSTSIZE;
X	if (offset < 0L)
X		offset = 0L;
X	(void) lseek(fd, offset, 0);
X	i = read(fd, postbuf, POSTSIZE);
X	if (i <= 0)
X		return (-1);
X	p = &postbuf[i];
X	i -= 4;			/* account for the pointer in advance */
X
X	/*
X	 * Now search backwards for the GF_ID byte.  The postamble
X	 * pointer will be four bytes behind that.
X	 */
X	while (--i >= 0) {
X		if (UnSign8(*--p) == GF_ID)
X			goto foundit;
X		if (UnSign8(*p) != GF_FILLER)
X			break;
X	}
X	return (-1);		/* cannot find postamble ptr */
X
Xfoundit:
X	/*
X	 * Store the (presumed) position of the POSTPOST byte, which
X	 * is i-1 bytes beyond `offset'.
X	 */
X	*postpostp = offset + i - 1;
X
X	/*
X	 * Read out the postamble pointer and seek to the postamble,
X	 * also saving the offset.
X	 */
X	p -= 4;
X	pGetLong(p, n);
X	*postp = offset = n;
X	(void) lseek(fd, offset, 0);
X	return (0);		/* made it */
X}
X
X/*
X * Read a GF file.
X */
Xstatic int
Xgf_read(f)
X	register struct font *f;
X{
X	register struct gf_details *gd;
X	register char *p;
X	register struct char_loc *cl;
X	register int i;
X	int fd, presize, postsize, bodysize, firstc, lastc;
X	char *postamble;
X	long postaddr, postpostaddr;
X	i32 lasteoc;
X	char *problem = NULL;
X	struct stat st;
X	char b[4];
X	int saverr;
X
X	if ((fd = open(f->f_path, 0)) < 0)
X		return (-1);
X	gd = NULL;		/* prepare for failure */
X	postamble = NULL;
X
X	/*
X	 * The file had best be at least 50 bytes long.  A
X	 * `completely empty' GF file might consist of a PRE, a GF_ID,
X	 * no comment (one zero byte), then: POST, pointer to last
X	 * EOC, design size, checksum, hppp, vppp, min_m, max_m,
X	 * min_n, max_n, POSTPOST, pointer to POST, GF_ID, and four
X	 * FILLERs.
X	 */
X	(void) fstat(fd, &st);
X	if (st.st_size < 50) {	/* too small to be a GF file */
X		problem = "file is too short";
X		goto fail;
X	}
X
X	/*
X	 * Read the very beginning and pick up the preamble size.
X	 */
X	if (read(fd, b, 4) != 4)
X		goto fail;
X	if (UnSign8(b[0]) != GF_PRE) {
X		problem = "file does not begin with PRE";
X		goto fail;
X	}
X	i = UnSign8(b[1]);
X	if (i != GF_ID)
X		error(0, 0, "Warning: strange GF id (%d) in \"%s\"", i,
X			f->f_path);
X	presize = 3 + UnSign8(b[2]);
X
X	/*
X	 * Find the postamble, allocate space, and read it in.
X	 */
X	if (findGFpostamble(fd, &postaddr, &postpostaddr)) {
X		problem = "cannot find postamble";
X		goto fail;
X	}
X	postsize = postpostaddr - postaddr + 1;
X	if ((p = malloc(postsize)) == NULL)
X		goto fail;
X	if (read(fd, p, postsize) != postsize)
X		goto fail;
X	postamble = p;
X	
X	/*
X	 * Make sure we found it.
X	 */
X	if (pgetbyte(p) != GF_POST) {
X		problem = "no GF_POST at postamble";
X		goto fail;
X	}
X
X	/*
X	 * Looks okay.  Allocate detail space and poke through the postamble.
X	 */
X	if ((gd = (struct gf_details *) malloc(sizeof (*gd))) == NULL)
X		goto fail;
X	gd->gd_body = NULL;
X
X	pGetLong(p, lasteoc);	/* actually one past last EOC */
X	pGetLong(p, f -> f_design_size );
X	pGetLong(p, f->f_checksum);
X	pGetLong(p, f -> f_hppp);
X	pGetLong(p, f -> f_vppp);
X
X	pGetLong(p, gd->gd_gb.min_m);
X	pGetLong(p, gd->gd_gb.max_m);
X	pGetLong(p, gd->gd_gb.min_n);
X	pGetLong(p, gd->gd_gb.max_n);
X
X	/*
X	 * Zap all the character locators, then read those that are
X	 * defined in the postamble.  Remember the first and last
X	 * characters so that we know which glyphs are defined.  Lastc
X	 * is actually the last-plus-one'th character.
X	 */
X	for (cl = gd->gd_cl, i = 256; --i >= 0; cl++)
X		cl->cl_p = -1;
X	firstc = 256;
X	lastc = 0;
X	for (;;) {
X		i32 dx, dy;
X
X		switch (pgetbyte(p)) {
X
X		case GF_CHAR_LOC:
X			i = pgetbyte(p);
X			pGetLong(p, dx);
X			pGetLong(p, dy);
X			goto merge;
X
X		case GF_CHAR_LOC0:
X			i = pgetbyte(p);
X			dx = ((i32) pgetbyte(p)) << 16;
X			dy = 0;
Xmerge:
X			if (i < firstc)
X				firstc = i;
X			if (i >= lastc)
X				lastc = i + 1;
X			cl = &gd->gd_cl[i];
X			cl->cl_dx = dx;
X			cl->cl_dy = dy;
X			pGetLong(p, cl->cl_w);
X			pGetLong(p, cl->cl_p);
X			break;
X
X		case GF_POSTPOST:
X			goto done;
X
X		default:
X			error(0, 0, "I do not understand %d here",
X				UnSign8(p[-1]));
X			problem = "unexpected opcode in postamble";
X			goto fail;
X		}
X	}
Xdone:
X	free(postamble);
X	postamble = NULL;	/* all done with it */
X
X	/*
X	 * Alas, we need the instructions whether or not we need
X	 * the rasters, since the raster bounding box information
X	 * can only be properly determined by converting the rasters.
X	 * Compute the size of the main body of the GF file, then
X	 * read it in.
X	 */
X	bodysize = lasteoc - presize;
X	if ((gd->gd_body = malloc(bodysize + 1)) == NULL)
X		goto fail;
X	(void) lseek(fd, (long) presize, 0);
X	if (read(fd, gd->gd_body, bodysize) != bodysize)
X		goto fail;
X	/*
X	 * The next byte might be a special, so we just
X	 * arbitrarily stuff in a POST.
X	 */
X	gd->gd_body[bodysize] = GF_POST;
X	gd->gd_base = gd->gd_body - presize;
X
X	f->f_details = (char *) gd;
X	if (FontHasGlyphs(f, firstc, lastc))
X		goto fail2;
X	(void) close(fd);
X	return (0);
X
Xfail:
X	if (problem == NULL)
X		error(0, errno, "trouble reading \"%s\"", f->f_path);
X	else
X		error(0, 0, "%s\n\t(are you sure \"%s\" is a GF file?)",
X			problem, f->f_path);
X	errno = 0;
Xfail2:
X	saverr = errno;
X	if (postamble != NULL) {
X		free(postamble); postamble = 0;
X	      }
X	if (gd != NULL) {
X		if (gd->gd_body != NULL) {
X			free(gd->gd_body); gd -> gd_body = 0;
X		      }
X		free((char *) gd); gd = 0;
X	}
X	(void) close(fd);
X	errno = saverr;
X	return (-1);
X}
X
X/*
X * Some global variables, used while building rasters.  (These are
X * referenced also in copyit(), so must be global.  Fortunately, no
X * one yet requires the font routines to be re-entrant.)
X */
Xstatic char *buildraster;	/* raster being built */
Xstatic int buildsize;		/* size of buildraster (bytes) */
X
Xstatic struct bounds tempb;	/* bounds used during buildraster */
Xstatic struct bounds ob;	/* observed bounds */
X
X/*
X * Bit tables: `left' and `right' bits.  lbits[b] has all the bits
X * that are to the left of bit b set; rbits[b] has all the bits
X * that are to the right of bit b set, as well as bit b itself.
X */
Xstatic char lbits[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
Xstatic char rbits[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
X
X/*
X * The magic address `nullraster' is known in getgly() as a valid
X * but empty raster, and changed there to NULL.  A NULL return from
X * drawchar indicates failure; we need something to distinguish the
X * empty raster.
X */
Xstatic char nullraster[1];
X
X/*
X * `Inline functions':
X *  ->	convert a bit number to a byte number (round down);
X *  ->	convert a number of bits to a number of bytes (round up);
X * and	convert a bit to a bit index.
X */
X#define btoby(b) ((b) >> 3)
X#define	btonb(b) (((b) + 7) >> 3)
X#define	btobi(b) ((b) & 7)
X
X/*
X * Helper function for getgly: build the raster, and compute its
X * minimal bounding box.  Called with `p' pointing past the backpointer
X * field of the BOC command (i.e., at min_m or del_m).  `abbrev' is true
X * iff this was a BOC1.  `globalb' are the global bounds from the GF file,
X * whose name is pointed to by gfname.
X */
Xstatic char *
Xdrawchar(p, abbrev, globalb, gfname)
X	register char *p;
X	int abbrev;
X	struct bounds globalb;
X	char *gfname;
X{
X	register i32 m;		/* m register (column) */
X	register char *colp;	/* pointer to byte corresponding to m */
X	register int c;		/* temporary */
X	register i32 i;		/* temporary */
X	register int black;	/* true when paint_switch==black */
X	register i32 n;		/* n register (row) */
X	int stride;		/* multiplier to convert linear to 2d array */
X	int wrotethisrow;	/* true iff we wrote in the current row */
X	char *virtrast;		/* virtual origin version of buildraster */
X	int mustcopy;		/* true if we must copy the built raster */
X	struct bounds gb;	/* bounds from the GF file */
X
X	/* get the bounds */
X	if (abbrev) {
X		c = pgetbyte(p);/* del_m */
X		gb.min_m = (gb.max_m = pgetbyte(p)) - c;
X		c = pgetbyte(p);/* del_n */
X		gb.min_n = (gb.max_n = pgetbyte(p)) - c;
X	} else {
X		pGetLong(p, gb.min_m);
X		pGetLong(p, gb.max_m);
X		pGetLong(p, gb.min_n);
X		pGetLong(p, gb.max_n);
X	}
X
X	/*
X	 * Trim the GF bounds according to the global bounds.  We
X	 * use the trimmed values to allocate the build space.
X	 */
X	tempb = gb;
X#define	GB_ADJ(field, cmp) \
X	if (tempb.field cmp globalb.field) \
X		tempb.field = globalb.field
X	GB_ADJ(min_m, <);
X	GB_ADJ(max_m, >);
X	GB_ADJ(min_n, <);
X	GB_ADJ(max_n, >);
X#undef GB_ADJ
X
X	/*
X	 * Compute the distance between rows (the number of bytes per
X	 * column), then make sure there is room in the build space
X	 * for [min_n..max_n] of these, possibly by allocating a new raster.
X	 */
X	stride = btonb(tempb.max_m - tempb.min_m + 1);
X	c = stride * (tempb.max_n - tempb.min_n + 1);
X	if (c <= 0)		/* completely empty character */
X		return (nullraster);
X	if (c > buildsize) {
X		if (buildraster != NULL) {
X			free(buildraster); buildraster = 0;
X		      }
X		if ((buildraster = malloc(c)) == NULL) {
X			buildsize = 0;
X			return (NULL);
X		}
X		buildsize = c;
X	}
X
X	/*
X	 * If we are using an old raster that is too big, remember to
X	 * scrunch it down later.
X	 */
X	mustcopy = buildsize > c;
X
X	/* clear the raster to white */
X	bzero(buildraster, c);
X
X	/*
X	 * Make a virtual origin raster pointer.  The virtual origin is
X	 * where raster[0][0] is, whether or not there is a raster[0][0].
X	 * Normally, this would be
X	 *	&buildraster[-gb.min_n * stride - btoby(gb.min_m)],
X	 * but it is complicated by two things.  Firstly, we would like
X	 * n==max_n to be the bottommost point in the raster (low
X	 * addresses), and n==min_n to be the topmost (high addresses).
X	 * In other words, we need to reflect the n (Y) values about
X	 * the X axis: negate them.  Secondly, the raster we create
X	 * must be `flush left'.  That is, somewhere along its rows,
X	 * bit 0x80 must be set at the left edge of one of its columns.
X	 * We need to subtract away the minimum bit index before
X	 * calculating bit values.  This cannot really be done in
X	 * advance, since we cannot address bits directly.
X	 */
X	virtrast = &buildraster[gb.max_n * stride];
X
X	/*
X	 * Set up the bounds-trimming variables.  The observed m bounds
X	 * are kept offset by gb.min_m until we finish drawing the
X	 * character.
X	 */
X	ob.min_m = tempb.max_m - gb.min_m + 1;
X	ob.max_m = tempb.min_m - gb.min_m - 1;
X	ob.min_n = tempb.max_n + 1;
X	ob.max_n = tempb.min_n - 1;
X	wrotethisrow = 0;
X
X#define FIX_N_BOUNDS() { \
X	if (wrotethisrow) { \
X		c = -n; /* recall that n is reflected about X axis */ \
X		if (c < ob.min_n) \
X			ob.min_n = c; \
X		if (c > ob.max_n) \
X			ob.max_n = c; \
X		wrotethisrow = 0; \
X	} \
X}
X
X	/*
X	 * Initialise state variables: m = min_m, n = max_n,
X	 * paint_switch = white.
X	 */
X	m = 0;			/* gb.min_m - gb.min_m */
X	n = -gb.max_n;		/* reflected */
X	colp = &virtrast[n * stride];
Xif (colp != buildraster)
Xpanic("gffont drawchar colp != buildraster");
X	black = 0;
X
X	/*
X	 * Now interpret the character.
X	 * `for (;;)' pushes everything off the right edge, alas.
X	 */
Xmore:
X	c = pgetbyte(p);
X	if (GF_IsPaint(c))	/* faster? */
X		goto paint;
X	switch (GF_OpLen(c)) {
X
X	case GPL_NONE:
X		break;
X
X	case GPL_UNS1:
X		i = pgetbyte(p);
X		break;
X
X	case GPL_UNS2:
X		pGetWord(p, i);
X		break;
X
X	case GPL_UNS3:
X		pGet3Byte(p, i);
X		break;
X
X	case GPL_SGN4:
X		pGetLong(p, i);
X		break;
X
X	default:
X		panic("gffont drawchar GF_OpLen(%d) = %d", c, GF_OpLen(c));
X		/* NOTREACHED */
X	}
X
X	switch (GF_TYPE(c)) {
X
X	case GT_PAINT0:
Xpaint:
X		i = c - GF_PAINT_0;
X		/* FALLTHROUGH */
X
X	case GT_PAINT:
X		/*
X		 * Paint `i' bits in the current row at columns [m..m+i).
X		 */
X		if (i && black) {
X			/* remember to adjust n bounds later */
X			wrotethisrow = 1;
X			/* adjust minimum m bound */
X			if (m < ob.min_m)
X				ob.min_m = m;
X
X			/*
X			 * Finish the partial byte at colp.  There are 8-k
X			 * bits to set to finish it, where k is the bit
X			 * index value from m.  If we need to set fewer
X			 * than 8-k bits, set them now and skip the rest
X			 * of this.
X			 */
X			c = 8 - btobi(m);
X			if (i < c) {	/* cannot finish it off */
X				*colp |= UnSign8(lbits[i]) >> btobi(m);
X				m += i;
X			} else {	/* finish it off */
X				*colp++ |= rbits[btobi(m)];
X				i -= c;
X				m += c;
X
X				/*
X				 * Update m to reflect having written the
X				 * remaining i bits, then write them.
X				 * First write all the full bytes, then
X				 * start a partial byte with whatever
X				 * is left over, if anything.
X				 */
X				m += i;
X				i >>= 3;
X				while (--i >= 0)
X					*colp++ = 0xff;
X				*colp |= lbits[btobi(m)];
X			}
X
X			/* adjust maximum m bound */
X			if (m > ob.max_m)
X				ob.max_m = m;
X		} else {
X			/*
X			 * Add the bit index so that we round up whenever
X			 * this fills the partial byte at colp.
X			 */
X			colp += (i + btobi(m)) >> 3;
X			m += i;
X		}
X		black = !black;
X		break;
X
X	case GT_EOC:		/* all done */
X		FIX_N_BOUNDS();
X		goto done;
X
X	case GT_SKIP0:		/* skip no rows */
X		i = 0;
X		/* FALLTHROUGH */
X
X	case GT_SKIP:		/* skip some rows, draw white */
X		m = 0;
X		black = 0;
X		goto skip_or_new_row;
X
X	case GT_NEW_ROW:	/* next row near left col, draw black */
X		m = c - GF_NEW_ROW_0;
X		black = 1;
X		i = 0;			/* n offset is 1: skip no rows */
Xskip_or_new_row:
X		FIX_N_BOUNDS();
X		n += i + 1;		/* += because reflected */
X		colp = &virtrast[n * stride + btoby(m)];
X		break;
X
X	case GT_XXX:		/* special */
X		p += i;
X		break;
X
X	case GT_YYY:		/* numspecial */
X		break;
X
X	case GT_NOP:		/* dull */
X		break;
X
X	case GT_BOC:		/* should not appear */
X	case GT_BOC1:
X	case GT_CHAR_LOC:
X	case GT_CHAR_LOC0:
X	case GT_PRE:
X	case GT_POST:
X	case GT_POSTPOST:
X	case GT_UNDEF:
X		error(0, 0, "unexpected GF opcode %d", c);
X		error(1, 0, "bad GF file \"%s\"", gfname);
X		/* NOTREACHED */
X
X	default:
X		panic("gffont drawchar GF_TYPE(%d) = %d", c, GF_TYPE(c));
X		/* NOTREACHED */
X	}
X	goto more;
X
Xdone:
X	/*
X	 * The observed bounds `m' values are both off by gb.min_m, so
X	 * fix them now.  CONSIDER ADJUSTING n HERE TOO
X	 */
X	ob.min_m += gb.min_m;
X	ob.max_m += gb.min_m;
X
X	/*
X	 * If we used too much memory for the raster, copy it now.
X	 */
X	if (mustcopy || tempb.min_n != ob.min_n || tempb.max_n != ob.max_n ||
X	    btonb(ob.max_m - ob.min_m + 1) != stride)
X		return (copyit());
X
X	/*
X	 * If the left column bounds match, just move the raster in place.
X	 */
X	if (tempb.min_m == ob.min_m) {
X		p = buildraster;
X		buildraster = NULL;
X		buildsize = 0;
X		return (p);
X	}
X
X	/*
X	 * The raster must be copied, but only because it is not
X	 * `left justified'.
X	 *
X	 * CONSIDER DEFERRING THIS PHASE UNTIL THE RASTER IS USED
X	 */
X	return (copyit());
X}
X
X/*
X * Copy the built raster to newly allocated space.
X * We may need to shift all the bits left as well.
X */
Xchar *
Xcopyit()
X{
X	register char *o, *p;
X	register int i, oldoff, newoff;
X	char *n;
X
X	/*
X	 * Compute the observed minimum stride.  If it is zero or negative,
X	 * there is no raster at all, else allocate just enough space
X	 * to hold the new raster.
X	 */
X	newoff = btonb(ob.max_m - ob.min_m + 1);
X	if (newoff <= 0)
X		return (nullraster);
Xif (ob.max_n < ob.min_n)
Xpanic("gffont copyit max_n < min_n");
X	n = malloc((unsigned) (newoff * (ob.max_n - ob.min_n + 1)));
X	if ((p = n) == NULL)
X		return (NULL);
X
X	/*
X	 * Compute the old stride.
X	 */
X	oldoff = btonb(tempb.max_m - tempb.min_m + 1);
Xif (oldoff < newoff)
Xpanic("gffont copyit oldoff < newoff");
X
X	/*
X	 * Point at the old raster, then add the offset to the first
X	 * written row, and then the offset to the first written column.
X	 */
X	o = buildraster;
X	o += (ob.max_n - tempb.max_n) * oldoff;
X	i = ob.min_m - tempb.min_m;
X	o += btoby(i);
X
X	/*
X	 * Now copy each row, doing shifting if required.
X	 */
X	if ((i = btobi(i)) != 0) {	/* must shift, alas */
X		register int r = 8 - i, j, k;
X
X		oldoff -= newoff;
X		for (k = ob.max_n; k >= ob.min_n; k--) {
X			for (j = newoff; --j >= 0;) {
X				*p++ = *o++ << i;
X				p[-1] |= UnSign8(*o) >> r;
X			}
X			o += oldoff;
X		}
X	} else if (oldoff > newoff) {	/* compressing columns */
X		for (i = ob.max_n; i >= ob.min_n; i--) {
X			bcopy(o, p, newoff);
X			o += oldoff;
X			p += newoff;
X		}
X	} else				/* just squeezing out extra rows */
X		bcopy(o, p, newoff * (ob.max_n - ob.min_n + 1));
X
X	/* finally, return the copy */
X	return (n);
X}
X
X/*
X * Obtain the specified range of glyphs.
X */
Xstatic int
Xgf_getgly(f, l, h)
X	register struct font *f;
X	int l, h;
X{
X	register struct glyph *g;
X	register struct char_loc *cl;
X	register char *p;
X	register i32 c;
X	register int i;
X	register i32 thisboc;
X	int abbrev;
X	struct gf_details *gd = ftogd(f);
X
X	/*
X	 * For each glyph, make sure there exists an instance of that
X	 * character residue.  Go find the actual glyph (which may be
X	 * arbitrarily far down a chain of pointers) and get its info.
X	 */
X	for (cl = &gd->gd_cl[i = l]; i < h; i++, cl++) {
X		g = f->f_gly[i];
X		thisboc = cl->cl_p;
X
X		/*
X		 * Screw around locating the character for real.
X		 */
X		while (thisboc != -1) {
X			p = gd->gd_base + thisboc;
Xskip:
X			c = pgetbyte(p);
X			switch (GF_TYPE(c)) {
X
X			case GT_XXX:
X				switch (GF_OpLen(c)) {
X
X				case GPL_UNS1:
X					c = pgetbyte(p);
X					break;
X
X				case GPL_UNS2:
X					pGetWord(p, c);
X					break;
X
X				case GPL_UNS3:
X					pGet3Byte(p, c);
X					break;
X
X				case GPL_SGN4:
X					pGetLong(p, c);
X					break;
X
X				default:
X					panic("gf_getgly GF_OpLen(%d) = %d",
X						c, GF_OpLen(c));
X					/* NOTREACHED */
X				}
X				p += c;
X				goto skip;
X
X			case GT_YYY:
X				p += 4;
X				goto skip;
X
X			case GT_BOC:
X				abbrev = 0;
X				pGetLong(p, c);
X				break;
X
X			case GT_BOC1:
X				abbrev = 1;
X				c = pgetbyte(p);
X				break;
X
X			default:
X				error(0, 0, "GF code %d; I expected BOC", c);
X				error(1, 0, "bad GF file \"%s\"", f->f_path);
X				/* NOTREACHED */
X			}
X			/*
X			 * Found a BOC.  If it is the right character,
X			 * go handle it.
X			 */
X			if (c == i)
X				goto handleit;
X			if ((c & 255) != i) {
X				error(0, 0, "%d != %d mod 256", c, i);
X				error(1, 0, "Bad GF file \"%s\"", f->f_path);
X			}
X			/*
X			 * Follow the backpointer.
X			 */
X			if (abbrev)
X				thisboc = -1;
X			else
X				pGetLong(p, thisboc);
X		}
X
X		/*
X		 * If we get here, the glyph is not valid after all.
X		 */
X		continue;
X	
X		/*
X		 * The glyph is okay.  Set it up.
X		 */
Xhandleit:
X		g->g_flags = GF_VALID;
X		g->g_xescapement = cl->cl_dx;
X		g->g_yescapement = cl->cl_dy;
X		g->g_tfmwidth = cl->cl_w;
X		g -> g_rawtfmwidth = g -> g_tfmwidth;
X		if (!abbrev)
X			p += 4;		/* skip backpointer */
X		if ((p = drawchar(p, abbrev, gd->gd_gb, f->f_path)) == NULL)
X			return (-1);	/* ??? */
X		if (p == nullraster)
X			p = NULL;
X		/* set height &c based on observed bounds */
X		g->g_height = ob.max_n - ob.min_n + 1;
X		g->g_width = ob.max_m - ob.min_m + 1;
X		g->g_yorigin = ob.max_n;
X		g->g_xorigin = -ob.min_m;
X		g->g_raster = p;
X		g->g_rotation = ROT_NORM;
X	}
X	return (0);
X}
X
X/*
X * Obtain rasters for the specified glyphs.  We did this above, while
X * adjusting the bounding boxes, so this routine should never get called.
X */
Xstatic int
Xgf_rasterise(f, l, h)
X	struct font *f;
X	int l, h;
X{
X
X	panic("gf_rasterise(%s, %d, %d)", f->f_path, l, h);
X}
X
X/*
X * Discard the font details.
X */
Xstatic
Xgf_freefont(f)
X	struct font *f;
X{
X	struct gf_details *gd;
X
X	if ((gd = ftogd(f)) != NULL) {
X		free(gd->gd_body); gd -> gd_body = 0;
X		free((char *) gd); gd = 0;
X	}
X}
END_OF_lib/gffont.c
if test 22029 -ne `wc -c <lib/gffont.c`; then
    echo shar: \"lib/gffont.c\" unpacked with wrong size!
fi
chmod +x lib/gffont.c
# end of overwriting check
fi
if test -f lib/gripes.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/gripes.c\"
else
echo shar: Extracting \"lib/gripes.c\" \(3046 characters\)
sed "s/^X//" >lib/gripes.c <<'END_OF_lib/gripes.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/gripes.c,v 1.3 89/02/13 14:31:11 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * Common errors (`gripes').
X */
X
X#include <stdio.h>
X#include "types.h"
X
Xstatic char areyousure[] = "Are you sure this is a DVI file?";
X
Xextern	errno;
X
X/*
X * DVI file requests a font it never defined.
X */
XGripeNoSuchFont(n)
X	i32 n;
X{
X
X	error(0, 0, "DVI file wants font %ld, which it never defined", n);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * DVI file redefines a font.
X */
XGripeFontAlreadyDefined(n)
X	i32 n;
X{
X
X	error(0, 0, "DVI file redefines font %ld", n);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Unexpected DVI opcode.
X */
XGripeUnexpectedOp(s)
X	char *s;
X{
X
X	error(0, 0, "unexpected %s", s);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Missing DVI opcode.
X */
XGripeMissingOp(s)
X	char *s;
X{
X
X	error(0, 0, "missing %s", s);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Cannot find DVI postamble.
X */
XGripeCannotFindPostamble()
X{
X
X	error(0, 0, "cannot find postamble");
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Inconsistent DVI value.
X */
XGripeMismatchedValue(s)
X	char *s;
X{
X
X	error(0, 0, "mismatched %s", s);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Undefined DVI opcode.
X */
XGripeUndefinedOp(n)
X	int n;
X{
X
X	error(0, 0, "undefined DVI opcode %d");
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Cannot allocate memory.
X */
XGripeOutOfMemory(n, why)
X	int n;
X	char *why;
X{
X
X	error(1, errno, "ran out of memory allocating %d bytes for %s",
X		n, why);
X	/* NOTREACHED */
X}
X
X/*
X * Cannot get a font.
X * RETURNS TO CALLER
X */
XGripeCannotGetFont(name, mag, dsz, dev, fullname)
X	char *name;
X	i32 mag, dsz;
X	char *dev, *fullname;
X{
X	int e = errno;
X	char scale[40];
X
X	if (mag == dsz)		/* no scaling */
X		scale[0] = 0;
X	else
X		(void) sprintf(scale, " scaled %d",
X			(int) ((double) mag / (double) dsz * 1000.0 + .5));
X
X	error(0, e, "cannot get font %s%s", name, scale);
X	if (fullname)
X		error(0, 0, "(wanted, e.g., \"%s\")", fullname);
X	else {
X		if (dev)
X			error(1, 0, "(there are no fonts for the %s engine!)",
X				dev);
X		else
X			error(1, 0, "(I cannot find any fonts!)");
X		/* NOTREACHED */
X	}
X}
X
X/*
X * Font checksums do not match.
X * RETURNS TO CALLER
X */
XGripeDifferentChecksums(font, tfmsum, fontsum)
X	char *font;
X	i32 tfmsum, fontsum;
X{
X
X	error(0, 0, "\
XWARNING: TeX and I have different checksums for font\n\
X\t\"%s\"\n\
X\tPlease notify your TeX maintainer\n\
X\t(TFM checksum = 0%o, my checksum = 0%o)",
X		font, tfmsum, fontsum);
X}
X
X/*
X * A font, or several fonts, are missing, so no output.
X */
XGripeMissingFontsPreventOutput(n)
X	int n;
X{
X	static char s[2] = {'s', 0};
X
X	error(1, 0, "%d missing font%s prevent%s output (sorry)", n,
X		n > 1 ? s : &s[1], n == 1 ? s : &s[1]);
X	/* NOTREACHED */
X}
END_OF_lib/gripes.c
if test 3046 -ne `wc -c <lib/gripes.c`; then
    echo shar: \"lib/gripes.c\" unpacked with wrong size!
fi
chmod +x lib/gripes.c
# end of overwriting check
fi
if test -f lib/magfactor.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/magfactor.c\"
else
echo shar: Extracting \"lib/magfactor.c\" \(869 characters\)
sed "s/^X//" >lib/magfactor.c <<'END_OF_lib/magfactor.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * Convert a magnification factor to floating point.  This is used in
X * conjunction with the FONT_SLOP stuff to try to get the file names
X * right, and may also be used by DVI reading programs to get slightly
X * more accurate values for (mag/1000.0).
X */
Xdouble
XDMagFactor(mag)
X	int mag;
X{
X
X	switch (mag) {
X
X	case 1095:		/* stephalf */
X		return (1.095445);
X
X	case 1315:		/* stepihalf */
X		return (1.314534);
X
X	case 2074:		/* stepiv */
X		return (2.0736);
X
X	case 2488:		/* stepv */
X		return (2.48832);
X
X	case 2986:		/* stepiv */
X		return (2.985984);
X
X	default:		/* remaining mags have been ok */
X		return ((double) mag / 1000.);
X	}
X	/* NOTREACHED */
X}
END_OF_lib/magfactor.c
if test 869 -ne `wc -c <lib/magfactor.c`; then
    echo shar: \"lib/magfactor.c\" unpacked with wrong size!
fi
chmod +x lib/magfactor.c
# end of overwriting check
fi
echo shar: End of archive 4 \(of 6\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    echo "Now do 'make dviselect'"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--
Skip Montanaro (montanaro@crdgw1.ge.com)

montnaro@sprite.crd.ge.com (Skip Montanaro) (11/14/89)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 5 (of 6)."
# Contents:  lib/pkfont.c lib/pxlfont.c
# Wrapped by montnaro@sprite on Sat Nov 11 17:13:32 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f lib/pkfont.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/pkfont.c\"
else
echo shar: Extracting \"lib/pkfont.c\" \(18209 characters\)
sed "s/^X//" >lib/pkfont.c <<'END_OF_lib/pkfont.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/pkfont.c,v 1.9 89/02/13 14:31:13 grunwald Exp Locker: grunwald $";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "types.h"
X#include "font.h"
X#include "num.h"
X
X/*
X * PK font operations.
X *
X * The spelling `nybble' is a concession to the authors of the PK format.
X */
X
Xstatic pk_read();
Xstatic scan_characters();
Xstatic pk_getgly();
Xstatic pk_rasterise();
Xstatic pk_freefont();
X
Xstruct	fontops pkops =
X	{ "pk", 1.0, pk_read, pk_getgly, pk_rasterise, pk_freefont };
X
X/*
X * Local info.
X */
X
X/*
X * Commands.
X */
X#define	PK_XXX1		240	/* 1 byte special */
X#define	PK_XXX2		241	/* 2 byte special */
X#define	PK_XXX3		242	/* 3 byte special */
X#define	PK_XXX4		243	/* 4 byte special */
X#define	PK_YYY		244	/* METAFONT numspecial */
X#define	PK_POST		245	/* marks postamble */
X#define	PK_NO_OP	246	/* do nothing */
X#define	PK_PRE		247	/* marks preamble */
X				/* 248..255 undefined */
X#define PK_IsUndef(c)	((c) > PK_PRE)
X
X#define	PK_ID		89	/* marks this brand of PK file */
X
X/*
X * Information about a character packet.
X */
Xstruct cp {
X	char	*cp_packet;	/* the beginning of the packet */
X	int	cp_type;	/* decoded pre type, see below */
X};
X
X#define	CP_SHORT	0	/* short preamble */
X#define	CP_EXT_SHORT	1	/* extended short preamble */
X#define	CP_LONG		2	/* long preamble */
X
X/*
X * The PK details include:
X *  ->	a pointer to the next byte to fetch;
X *  ->	the most recent byte fetched (when we are using nextnyb());
X *  ->	a flag indicating that we have used nybble 0 (bits 4..7) and
X *	should use nybble 1 next;
X *  ->	the base address of the memory allocated for the PK file;
X *  ->	the value of dyn_f (during character translation);
X *  ->	the repeat count (during rasterisation);
X *  ->	the lowest glyph number that is legal;
X *  ->	the highest glyph number that is legal;
X *  ->	glyph instructions for the standard glyphs;
X *  ->	glyph instructions for more (nonstandard) glyphs;
X * and	the number of glyphs left unrasterised.
X */
Xstruct pk_details {
X	char	*pk_ptr;	/* next byte to fetch */
X	int	pk_c;		/* most recent byte fetched, if nybbling */
X	int	pk_1nyb;	/* true => nybble 1 is next (bits 0..3) */
X	char	*pk_base;	/* base of allocated memory */
X	int	pk_dyn_f;	/* the dyn_f value */
X	int	pk_repeat;	/* the repeat count */
X	int	pk_minc;	/* minimum character value */
X	int	pk_maxc;	/* maximum character value */
X#define MAXSTD	256		/* maximum `standard' character value */
X	int	pk_gleft;	/* number of valid glyphs left uninterpreted */
X	struct	cp pk_cpack[MAXSTD];	/* for characters in [0..MAXSTD) */
X	struct	cp *pk_morec;		/* for characters in [MAXSTD..maxc] */
X};
X
X/*
X * Fetch the next byte from the PK file.
X */
X#define	nextbyte(pk) pgetbyte((pk)->pk_ptr)
X
X/*
X * PK packed number encoding.  Nybbles in [1..dyn_f] represent themselves.
X * Values in (dyn_f..13] are two-nybble values, and represent values
X * dyn_f+1 through (13-dyn_f+1)*16+15.  Zero marks a long number; 14 and
X * 15 specify repeat counts instead (which are another packed number).
X * Note that we cannot represent the number zero as a packed number.
X */
X#define	PK_LONGNUM	0	/* a `long number' */
X#define	PK_REPEAT	14	/* set repeat count */
X#define	PK_REPEAT1	15	/* set repeat to 1 */
X
X/*
X * Get the next nybble.  This is an expression rendition of
X *	if (--pk->pk_1nyb < 0) {
X *		pk->pk_1nyb = 1;
X *		pk->pk_c = nextbyte(pk);
X *		return (pk->pk_c >> 4);
X *	} else
X *		return (pk->pk_c & 0xf);
X */
X#define	nextnyb(f) \
X	(--(pk)->pk_1nyb < 0 ? \
X	 ((pk)->pk_1nyb = 1, ((pk)->pk_c = nextbyte(pk)) >> 4) : \
X	 (pk)->pk_c & 0xf)
X
X/*
X * Get the pk_details from font f.
X */
X#define	ftopk(f) ((struct pk_details *) (f)->f_details)
X
Xextern	int errno;
Xchar	*malloc();
X
X/*
X * PK subroutines.
X */
X
X/*
X * Unpack a packed number.
X */
Xstatic int
Xpk_unpack(pk)
X	register struct pk_details *pk;
X{
X	register int i, j;
X
Xtop:
X	if ((i = nextnyb(pk)) == PK_LONGNUM) {
X#if PK_LONGNUM != 0		/* this may be silly, but . . . */
X		i = 0;
X#endif
X		/*
X		 * Expand a long number.  There are one fewer leading
X		 * zeros than there are nonzero digits to obtain, so
X		 * count up the leading zeros, add one, and get that
X		 * many digits.  (The `digits' are hexadecimal values.)
X		 */
X		do {
X			i++;
X		} while ((j = nextnyb(pk)) == 0);
X		while (--i >= 0) {
X			j <<= 4;
X			j += nextnyb(pk);
X		}
X		return (j - 15 + (13 - pk->pk_dyn_f) * 16 + pk->pk_dyn_f);
X	}
X	if (i <= pk->pk_dyn_f)
X		return (i);
X	if (i < PK_REPEAT)
X		return ((i - pk->pk_dyn_f - 1) * 16 + nextnyb(pk) +
X			pk->pk_dyn_f + 1);
X
X	/*
X	 * There is a repeat count, either one or a packed number.
X	 * Get it first, then start over.  (tail recursion)
X	 */
X	if (i == PK_REPEAT)
X		pk->pk_repeat = pk_unpack(pk);
X	else
X		pk->pk_repeat = 1;
X	goto top;
X}
X
X/*
X * Skip over special commands (PK_XXX?, PK_YYY).
X */
Xstatic
Xskip_specials(f)
X	struct font *f;
X{
X	struct pk_details *pk = ftopk(f);
X	register char *p = pk->pk_ptr;
X	register i32 i;
X
X	for (;;) {
X	    int tmp;
X	    tmp = UnSign8(*p);
X	    p++;
X		 switch (tmp) {
X
X		case PK_XXX1:
X			i = UnSign8(*p);
X			p++;
X			p += i;
X			break;
X
X		case PK_XXX2:
X			pGetWord(p, i);
X			p += i;
X			break;
X
X		case PK_XXX3:
X			pGet3Byte(p, i);
X			p += i;
X			break;
X
X		case PK_XXX4:
X			pGetLong(p, i);
X			p += i;
X			break;
X
X		case PK_YYY:
X			p += 4;
X			break;
X
X		case PK_NO_OP:
X			break;
X
X		case PK_PRE:
X			error(1, 0, "unexpected PK_PRE in \"%s\"", f->f_path);
X			break;
X
X		default:
X			p--;
X			if (PK_IsUndef(UnSign8(*p)))
X				error(1, 0, "invalid opcode %d in \"%s\"",
X					f->f_path);
X			pk->pk_ptr = p;
X			return;
X		}
X	}
X}
X
X/*
X * Read a PK file.
X */
Xstatic int
Xpk_read(f)
X	register struct font *f;
X{
X	register struct pk_details *pk;
X	register char *p;
X	int i, fd;
X	struct stat st;
X	char *reason;
X
X	if ((fd = open(f->f_path, 0)) < 0)
X		return (-1);
X	pk = NULL;		/* prepare for failure */
X	reason = NULL;
X	(void) fstat(fd, &st);
X	if (st.st_size < 4) {	/* ??? */
X		reason = "file is too small";
X		goto fail;
X	}
X	if ((pk = (struct pk_details *) malloc(sizeof (*pk))) == NULL)
X		goto fail;
X	pk->pk_morec = NULL;
X	if ((pk->pk_base = malloc(st.st_size)) == NULL)
X		goto fail;
X	if (read(fd, pk->pk_base, st.st_size) != st.st_size)
X		goto fail;
X	pk->pk_ptr = pk->pk_base;
X	if (nextbyte(pk) != PK_PRE) {
X		reason = "file does not begin with PK_PRE";
X		goto fail;
X	}
X	if (nextbyte(pk) != PK_ID) {
X		reason = "bad PK_ID";
X		goto fail;
X	}
X	i = nextbyte(pk);
X	p = pk->pk_ptr + i;	/* skip comment */
X	pGetLong(p, f -> f_design_size);
X	pGetLong(p, f -> f_checksum);
X	pGetLong(p, f -> f_hppp);
X	pGetLong(p, f -> f_vppp);
X	pk->pk_ptr = p;
X/* DEBUG */
X	f->f_details = (char *) pk;
X
X	/* scan the characters, fail if necessary */
X	if (scan_characters(f, &reason))
X		goto fail;
X
X	/* ignore the postamble */
X
X	/* COMPRESS pk->pk_base DATA? */
X
X	if (FontHasGlyphs(f, pk->pk_minc, pk->pk_maxc + 1))
X		goto fail;
X	(void) close(fd);
X	return (0);
X
Xfail:
X	if (reason) {
X		error(0, 0, "%s", reason);
X		error(0, 0, "(are you sure %s is a PK file?)", f->f_path);
X		errno = 0;
X	}
X	if (pk != NULL) {
X		if (pk->pk_base != NULL) {
X			free(pk->pk_base); pk -> pk_base = 0; 
X		      }
X		if (pk->pk_morec != NULL) {
X			free((char *) pk->pk_morec); pk -> pk_morec = 0;
X		      }
X		free((char *) pk); pk = 0;
X	}
X	(void) close(fd);
X	return (-1);
X}
X
X/*
X * Scan through the characters in the PK file, and set the offsets
X * and preamble types for each of the character packets.
X */
Xstatic int
Xscan_characters(f, reason)
X	struct font *f;
X	char **reason;
X{
X	register struct pk_details *pk = ftopk(f);
X	register i32 c, pl;
X  	register char *p;
X  	register struct cp *cp;
X  	int type;
X
X#ifdef lint
X	/* reason will be used someday ... I think */
X	reason = reason;
X#endif
X
X	/* set up the minimisers and the glyph count */
X	pk->pk_minc = 1;
X	pk->pk_maxc = 0;
X	pk->pk_gleft = 0;
X
X	/* mark all character packets as untouched */
X	for (cp = pk->pk_cpack, c = MAXSTD; --c >= 0; cp++)
X		cp->cp_packet = NULL;
X
X  	/*
X  	 * Loop through the packets until we reach a POST, skipping
X 	 * the glyph instructions themselves after each definition,
X 	 * and specials (if any) before each.
X  	 */
X 	for (;; pk->pk_ptr = p + pl) {
X 		skip_specials(f);
X 		p = pk->pk_ptr;
X 		if ((c = pgetbyte(p)) == PK_POST)
X 			break;	/* whoops, done after all */
X
X		/*
X		 * Look at the low three bits to decide preamble size.
X		 * A value of 7 is a `long preamble'; 4, 5, and 6 are
X		 * `extended short preambles'; and 0, 1, 2, and 3 are
X		 * `short preambles'.
X		 *
X		 * We ignore most of the preamble, reading only the
X		 * `packet length' and the character code at this time.
X		 */
X		switch (c & 7) {
X
X		case 7:		/* long */
X			type = CP_LONG;
X			pGetLong(p, pl);
X			pGetLong(p, c);
X			break;
X
X		case 6:
X		case 5:
X		case 4:		/* extended short */
X			type = CP_EXT_SHORT;
X			pGetWord(p, pl);
X			pl += (c & 3) << 16;
X			c = pgetbyte(p);
X			break;
X
X		default:	/* short */
X			type = CP_SHORT;
X			pl = ((c & 3) << 8) + pgetbyte(p);
X			c = pgetbyte(p);
X			break;
X		}
X
X		if (c >= MAXSTD) {
X			/*
X			 * BEGIN XXX - should alloc pk_morec, but is hard
X			 * and not now useful
X			 */
X			error(0, 0, "ignoring character %d in \"%s\"",
X				f->f_path);
X			error(0, 0, "because some darn programmer was lazy!");
X			continue;
X			/* END XXX */
X		} else
X			cp = &pk->pk_cpack[c];
X
X		cp->cp_packet = pk->pk_ptr;
X		cp->cp_type = type;
X
X		/* adjust range */
X		if (c < pk->pk_minc)
X			pk->pk_minc = c;
X		if (c > pk->pk_maxc)
X			pk->pk_maxc = c;
X
X		pk->pk_gleft++;	/* and count the glyph */
X	}
X	return (0);		/* no problems */
X}
X
X/*
X * Obtain the specified range of glyphs.
X */
Xstatic int
Xpk_getgly(f, l, h)
X	register struct font *f;
X	int l, h;
X{
X	register struct pk_details *pk = ftopk(f);
X	register char *p;
X	register struct glyph *g;
X	register int i;
X	register struct cp *cp;
X
X	if (pk == NULL)
X		panic("pk_getgly(%s)", f->f_path);
X	for (i = l; i < h; i++) {
X  		if (i < MAXSTD)
X  			cp = &pk->pk_cpack[i];
X 		else {
X 			if (i > pk->pk_maxc)
X 				panic("pk_getgly(%s, %d)", f->f_path, i);
X  			cp = &pk->pk_morec[i - MAXSTD];
X 		}
X  		p = cp->cp_packet;
X  		if (p == NULL)	/* glyph is not valid */
X			continue;
X		g = f->f_gly[i];
X		p++;		/* skip flag */
X		switch (cp->cp_type) {
X
X		case CP_LONG:
X			p += 8;	/* skip packet len, character code */
X			pGetLong(p, g->g_tfmwidth);
X			g -> g_rawtfmwidth = g -> g_tfmwidth;
X			pGetLong(p, g->g_xescapement);
X			pGetLong(p, g->g_yescapement);
X			pGetLong(p, g->g_width);
X			pGetLong(p, g->g_height);
X			pGetLong(p, g->g_xorigin);
X			pGetLong(p, g->g_yorigin);
X			break;
X
X		case CP_EXT_SHORT:
X			p += 3;	/* skip packet len, character code */
X			pGet3Byte(p, g->g_tfmwidth);
X			g -> g_rawtfmwidth = g -> g_tfmwidth;
X			{ i32 dm; pGetWord(p, dm);
X			g->g_xescapement = dm << 16; }
X			g->g_yescapement = 0;
X			pGetWord(p, g->g_width);
X			pGetWord(p, g->g_height);
X			pGetWord(p, g->g_xorigin);
X			g->g_xorigin = Sign16(g->g_xorigin);
X			pGetWord(p, g->g_yorigin);
X			g->g_yorigin = Sign16(g->g_yorigin);
X			break;
X
X		case CP_SHORT:
X			p += 2;	/* skip packet len, character code */
X			pGet3Byte(p, g->g_tfmwidth);
X			g -> g_rawtfmwidth = g -> g_tfmwidth;
X			g->g_xescapement = pgetbyte(p) << 16;
X			g->g_yescapement = 0;
X			g->g_width = pgetbyte(p);
X			g->g_height = pgetbyte(p);
X			g->g_xorigin = pgetbyte(p);
X			g->g_xorigin = Sign8(g->g_xorigin);
X			g->g_yorigin = pgetbyte(p);
X			g->g_yorigin = Sign8(g->g_yorigin);
X			break;
X		}
X		g->g_flags = GF_VALID;
X		g->g_un.g_details = p;
X	}
X	return (0);
X}
X
X/*
X * Bit masks for pk_rasterise().
X */
Xstatic char bmask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
Xstatic char rbits[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
X
X/*
X * Obtain rasters for the specified glyphs.
X */
Xstatic int
Xpk_rasterise(f, l, h)
X	struct font *f;
X	int l, h;
X{
X	struct pk_details *pk0;
X	struct glyph *g0;
X	char *p0, *rp0;
X	int flag, ii;
X
X	if ((pk0 = ftopk(f)) == NULL)
X		panic("pk_rasterise(%s)", f->f_path);
X	for (ii = l; ii < h; ii++) {
X		{
X			register struct glyph *g;
X			register char *p;
X			register int i;
X
X			g = f->f_gly[i = ii];
X			if ((g->g_flags & GF_VALID) == 0)
X				continue;	/* no glyph */
X			if (!HASRASTER(g))	/* empty raster */
X				goto done;
X
X			/*
X			 * Allocate a raster.
X			 */
X			rp0 = malloc(((g->g_width + 7) >> 3) * g->g_height);
X			if ((g->g_raster = rp0) == NULL)
X				return (-1);/* ??? */
X			g->g_rotation = ROT_NORM;
X
X			/*
X			 * Pick up the flag byte, then start at the real
X			 * packet, which we saved in g_details.
X			 */
X			if (i < MAXSTD)
X				p = pk0->pk_cpack[i].cp_packet;
X			else
X				p = pk0->pk_morec[i - MAXSTD].cp_packet;
X			flag = UnSign8(*p);
X			p0 = g->g_un.g_details;
X			g0 = g;
X		}
X		if ((pk0->pk_dyn_f = flag >> 4) == 14) {
X			register char *p = p0, *rp = rp0;
X			register int j, ls, rs, i, w;
X
X			/*
X			 * Expand a bit-packed representation.
X			 * If we get lucky, it is byte packed and
X			 * we can just copy it over.
X			 */
X			i = g0->g_height;
X			j = g0->g_width;
X			if ((j & 7) == 0) {
X				bcopy(p, rp, i * (j >> 3));
X				goto done;
X			}
X
X			/*
X			 * No such luck.
X			 */
X			w = j;
X			ls = 0;
X			while (--i >= 0) {
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X#ifdef BROKEN_COMPILER_HACKS
X				/* have to work on the compiler someday */
X				rs = ls - 8;
X#else
X				rs = 8 - ls;
X#endif
X				/* know j always != 8 */
X				for (j = w; j > 8; j -= 8) {
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X#ifdef BROKEN_COMPILER_HACKS
X					asm("	movb	(r11)+,r0");
X					asm("	ashl	r8,r0,r0");
X					asm("	movb	r0,(r10)");
X					asm("	movzbl	(r11),r0");
X					asm("	ashl	r7,r0,r0");
X					asm("	bisb2	r0,(r10)+");
X#else
X					*rp = *p << ls;
X					p++;
X					*rp |= UnSign8(*p) >> rs;
X					rp++;
X#endif
X				}
X
X				/*
X				 * We need j more bits; there are rs
X				 * bits available at *p.  Ask for j,
X				 * which gets min(j, rs).
X				 */
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X				  
X#ifdef BROKEN_COMPILER_HACKS
X				/*void*/; /* avoid asm() label botch */
X				asm("	movb	(r11),r0");
X				asm("	ashl	r8,r0,r0");
X				asm("	mcomb	_bmask[r9],r1");
X				asm("	bicb2	r1,r0");
X				asm("	movb	r0,(r10)+");
X#else
X				*rp++ = (*p << ls) & bmask[j];
X#endif
X				/* account for j bits */
X				ls += j; ls &= 7;
X				/* then adjust j based on rs */
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X#ifdef BROKEN_COMPILER_HACKS
X				j += rs;
X#else
X				j -= rs;
X#endif
X				/* still need j more bits */
X				if (j < 0)	/* got them all */
X					continue;
X				p++;
X				if (j == 0)	/* there were just enough */
X					continue;
X				/* take j more bits */
X
X				/* IF THE COMPILER IS BROKEN, FIX IT */
X#ifdef BROKEN_COMPILER_HACKS
X				/*void*/; /* avoid asm() label botch */
X				asm("	mcomb	_bmask[r9],r0");
X				asm("	bicb3	r0,(r11),r0");
X				asm("	movzbl	r0,r0");
X				asm("	ashl	r7,r0,r0");
X				asm("	bisb2	r0,-1(r10)");
X#else
X				rp[-1] |= UnSign8(*p & bmask[j]) >> rs;
X#endif
X			}
X		} else {
X			register struct pk_details *pk = pk0;
X			register int on = flag & 8 ? 0xff : 0;
X			register char *rowp;	/* pointer into this row */
X			register int j;		/* trimmed run count */
X			register int k;		/* misc */
X			register int b;		/* bit index in current col */
X			register int i;		/* run count */
X			register int colsleft;	/* columns left this row */
X			register int rowsleft;	/* rows left */
X			static char *row;	/* a one-row buffer */
X			static int rowsize;	/* and its size in bytes */
X			int wb;			/* row width in bytes */
X
X			wb = (g0->g_width + 7) >> 3;
X			if (rowsize < wb) {	/* get more row space */
X				if (row) {
X				  free(row); row = 0;
X				}
X				/* keep a slop byte */
X				row = malloc((unsigned) (wb + 1));
X				if (row == NULL)
X					return (-1);	/* ??? */
X				rowsize = wb;
X			}
X			bzero(row, wb);
X			rowsleft = g0->g_height;
X			colsleft = g0->g_width;
X			pk->pk_repeat = 0;
X			pk->pk_ptr = p0;
X			pk->pk_1nyb = 0;	/* start on nybble 0 */
X			rowp = row;
X			b = 0;
X			while (rowsleft > 0) {	/* do all rows */
X				/* EXPAND IN LINE? */
X				i = pk_unpack(pk);
X				/*
X				 * Work until the run count is exhausted
X				 * (or at least pretty tired).
X				 *
X				 * (Okay, so the joke is stolen!)
X				 */
X				while ((j = i) > 0) {
X					/*
X					 * If the count is more than the
X					 * rest of this row, trim it down.
X					 */
X					if (j > colsleft)
X						j = colsleft;
X					i -= j;	/* call them done */
X					/*
X					 * We need k=8-b bits to finish
X					 * up the current byte.  If we
X					 * can finish it, do so; the proper
X					 * bits to set are in rbits[k].
X					 */
X					if (j >= (k = 8 - b)) {
X						j -= k;
X						colsleft -= k;
X						*rowp++ |= on & rbits[k];
X						b = 0;
X					}
X					/*
X					 * Set any full bytes.
X					 */
X					while (j >= 8) {
X						*rowp++ = on;
X						j -= 8;
X						colsleft -= 8;
X					}
X					/*
X					 * Finally, begin a new byte, or
X					 * add to the current byte, with
X					 * j more bits.  We know j <= 8-b.
X					 * (If j==0, we may be writing on
X					 * our slop byte, which is why we
X					 * keep one around....)
X					 */
Xif (j > 8-b) panic("pk_rasterise j>8-b");
X					*rowp |= (on & bmask[j]) >> b;
X					colsleft -= j;
X					b += j; b &= 7;
X					if (colsleft == 0) {
X						pk->pk_repeat++;
X						rowsleft -= pk->pk_repeat;
X						while (--pk->pk_repeat >= 0) {
X							bcopy(row, rp0, wb);
X							rp0 += wb;
X						}
Xif (rowsleft == 0 && i) panic("pk_rasterise leftover bits");
X						pk->pk_repeat = 0;
X						rowp = row;
X						colsleft = g0->g_width;
X						bzero(row, wb);
X						b = 0;
X					}
X				}
X				on = 0xff - on;
X			}
X		}
X
Xdone:
X		/*
X		 * Successfully converted another glyph.
X		 */
X		pk0->pk_gleft--;
X	}
X
Xif (pk0->pk_gleft < 0)
Xpanic("%s: gleft==%d", f->f_path, pk0->pk_gleft);
X	if (pk0->pk_gleft == 0) {
X		free(pk0->pk_base); pk0 -> pk_base = 0;
X		if (pk0->pk_morec != NULL) {
X		  free((char *) pk0->pk_morec); pk0 -> pk_morec = 0;
X		}
X		free((char *) pk0); pk0 = 0;
X		f->f_details = NULL;
X	}
X	return (0);
X}
X
X/*
X * Discard the font details.
X */
Xstatic
Xpk_freefont(f)
X	struct font *f;
X{
X	register struct pk_details *pk = ftopk(f);
X
X	if (pk != NULL) {
X		free(pk->pk_base); pk -> pk_base = 0;
X		if (pk->pk_morec != NULL) {
X		  free((char *) pk->pk_morec); (char *) pk->pk_morec = 0;
X		}
X		free((char *) pk); (char *) pk = 0;
X	}
X}
END_OF_lib/pkfont.c
if test 18209 -ne `wc -c <lib/pkfont.c`; then
    echo shar: \"lib/pkfont.c\" unpacked with wrong size!
fi
chmod +x lib/pkfont.c
# end of overwriting check
fi
if test -f lib/pxlfont.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/pxlfont.c\"
else
echo shar: Extracting \"lib/pxlfont.c\" \(6872 characters\)
sed "s/^X//" >lib/pxlfont.c <<'END_OF_lib/pxlfont.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/pxlfont.c,v 1.4 89/02/13 14:31:16 grunwald Exp Locker: grunwald $";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <errno.h>
X#include "types.h"
X#include "font.h"
X#include "fio.h"
X
X/*
X * PXL font operations.
X */
X
Xstatic pxl_read();
Xstatic pxl_getgly();
Xstatic pxl_rasterise();
Xstatic pxl_freefont();
X
X
Xstruct	fontops pxlops =
X	{ "pxl", 5.0, pxl_read, pxl_getgly, pxl_rasterise, pxl_freefont };
X
X/*
X * Local info.
X */
X
X#define	PXLID	1001		/* ID denoting PXL files */
X#define	TAILSIZE (517 * 4)	/* size of pxl tail info */
X
X/*
X * pc describes one PXL character information block.
X */
Xstruct pc {
X	i16	pc_width;	/* character width (pixels) */
X	i16	pc_height;	/* character height (pixels) */
X	i16	pc_xoffset;	/* X offset of reference point */
X	i16	pc_yoffset;	/* Y offset of reference point */
X	i32	pc_rastoff;	/* raster offset */
X	i32	pc_TFMwidth;	/* TFM width (FIXes) */
X};
X
X/*
X * pxl_details are the PXL-specific font details.
X *
X * We keep track of the number of characters converted to internal
X * glyph form, and when all have been done, we discard the now-
X * useless details.
X */
Xstruct pxl_details {
X	int	pd_nconv;	/* number of characters converted */
X	char	*pd_ras;	/* raster space, until converted */
X	struct	pc pd_pc[128];	/* `font directory' */
X};
X
X/*
X * Get the pxl_details from font f.
X */
X#define	ftopd(f) ((struct pxl_details *) (f)->f_details)
X
Xextern	errno;
Xchar	*malloc();
X
X/*
X * Read a PXL file.
X */
Xstatic int
Xpxl_read(f)
X	struct font *f;
X{
X	register struct pxl_details *pd;
X	register FILE *fp;
X	register struct pc *pc;
X	register int i;
X	int fd, saverr;
X	i32 pxlid;
X	struct stat st;
X
X	if ((fd = open(f->f_path, 0)) < 0)
X		return (-1);
X
X	fp = NULL;
X	if ((pd = (struct pxl_details *) malloc(sizeof (*pd))) == 0)
X		goto fail;
X	pd->pd_ras = 0;
X
X	/*
X	 * There should be 4n bytes, with an absolute minimum of TAILSIZE+4
X	 * (+4 for the initial PXLID).
X	 */
X	(void) fstat(fd, &st);
X	if ((st.st_size & 3) != 0 || st.st_size < (TAILSIZE + 4)) {
X		errno = EINVAL;
X		goto fail;
X	}
X
X	/*
X	 * Set up the raster pointer (if we need rasters).
X	 */
X	if (f->f_flags & FF_RASTERS) {
X		i = st.st_size - (TAILSIZE + 4);
X		if (i != 0)  {
X			if ((pd->pd_ras = malloc((unsigned) i)) == 0)
X				goto fail;
X			(void) lseek(fd, 4L, 0);
X			if (read(fd, pd->pd_ras, i) != i)
X				goto fail;
X		}
X	}
X
X	/*
X	 * Read the glyph information.
X	 */
X	errno = 0;		/* try to make errno meaningful */
X	if ((fp = fdopen(fd, "r")) == NULL) {
X		if (errno == 0)
X			errno = EMFILE;
X		goto fail;
X	}
X	(void) fseek(fp, (long) -TAILSIZE, 2);
X	for (i = 128, pc = pd->pd_pc; --i >= 0; pc++) {
X		fGetWord(fp, pc->pc_width);
X		fGetWord(fp, pc->pc_height);
X		fGetWord(fp, pc->pc_xoffset);
X		fGetWord(fp, pc->pc_yoffset);
X		fGetLong(fp, pc->pc_rastoff);
X		fGetLong(fp, pc->pc_TFMwidth);
X	}
X	f->f_checksum = GetLong(fp);
X	(void) GetLong(fp);	/* mag */
X	f -> f_design_size = GetLong(fp);	/* designsize */
X	(void) GetLong(fp);	/* dirpointer */
X	pxlid = GetLong(fp);
X	if (pxlid != PXLID)
X		error(0, 0, "Warning: strange PXL id (%d) in \"%s\"",
X			pxlid, f->f_path);
X
X	f->f_details = (char *) pd;
X	if (FontHasGlyphs(f, 0, 128))
X		goto fail;
X	(void) fclose(fp);
X	pd->pd_nconv = 0;
X	return (0);
X
Xfail:
X	saverr = errno;
X	if (pd) {
X		if (pd->pd_ras) {
X		  free(pd->pd_ras); pd->pd_ras = 0;
X		}
X		free((char *) pd); (char *) pd = 0;
X	}
X	if (fp)
X		(void) fclose(fp);
X	else
X		(void) close(fd);
X	errno = saverr;
X	return (-1);
X}
X
X/*
X * Obtain the specified range of glyphs.
X */
Xstatic int
Xpxl_getgly(f, l, h)
X	register struct font *f;
X	int l;
X	register int h;
X{
X	register struct glyph *g;
X	register struct pc *pc;
X	register int i;
X	struct pxl_details *pd;
X
X	if ((pd = ftopd(f)) == NULL)
X		error(1, 0, "pxl_getgly details==0: cannot happen");
X	/*
X	 * By definition, all 128 glyphs are valid.  Just copy the
X	 * PXL information.
X	 */
X	for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
X		g = f->f_gly[i];
X		g->g_flags = GF_VALID;
X		g->g_height = pc->pc_height;
X		g->g_width = pc->pc_width;
X		g->g_yorigin = pc->pc_yoffset;
X		g->g_xorigin = pc->pc_xoffset;
X		g->g_tfmwidth = pc->pc_TFMwidth;
X		g -> g_rawtfmwidth = g -> g_tfmwidth;
X	}
X	return (0);
X}
X
X/*
X * Helper function for rasterise: return a pointer to a converted
X * (malloc()ed and minimised) raster.
X */
Xstatic char *
Xmakeraster(h, w, rp)
X	register int h, w;
X	register char *rp;
X{
X	register char *cp;
X	register int i, o;
X	char *rv;
X
X	/*
X	 * The height and width values are in bits.  Convert width to
X	 * bytes, rounding up.  The raw raster (at rp) is almost what
X	 * we want, but not quite: it has `extra' bytes at the end of
X	 * each row, to pad out to a multiple of four bytes.
X	 */
X	w = (w + 7) >> 3;
X	o = (4 - w) & 3;	/* offset (number of `extra' bytes) */
X	if ((cp = malloc((unsigned) (h * w))) == NULL)
X		return (NULL);
X	if (o == 0) {
X		/*
X		 * The raster fits exactly; just copy it to the allocated
X		 * memory space.  (We must copy anyway, so that glyphs
X		 * can be freed, e.g., after rotation.)
X		 */
X		bcopy(rp, cp, h * w);
X		return (cp);
X	}
X	rv = cp;
X	while (--h >= 0) {
X		/*
X		 * Copy each row, then skip over the extra stuff.
X		 */
X		for (i = w; --i >= 0;)
X			*cp++ = *rp++;
X		rp += o;
X	}
X	return (rv);
X}
X
X/*
X * Obtain rasters for the specified glyphs.
X */
Xstatic int
Xpxl_rasterise(f, l, h)
X	register struct font *f;
X	int l;
X	register int h;
X{
X	register struct glyph *g;
X	register struct pc *pc;
X	register int i;
X	register struct pxl_details *pd;
X
X	if ((pd = ftopd(f)) == NULL)
X		error(1, 0, "pxl_rasterise details==0: cannot happen");
X	if (pd->pd_ras == NULL)
X		error(1, 0, "pxl_rasterise pd_ras==NULL: cannot happen");
X	for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
X		g = f->f_gly[i];
X		if (pc->pc_rastoff == 0) {
X			/*
X			 * g should not claim a raster, since it has none.
X			 */
X			if (HASRASTER(g))
X				error(1, 0, "bad PXL glyph %d in \"%s\"",
X					g->g_index, f->f_path);
X		} else {
X			g->g_raster = makeraster(pc->pc_height, pc->pc_width,
X				pd->pd_ras + ((pc->pc_rastoff - 1) << 2));
X			if (g->g_raster == NULL)
X				return (-1);	/* ??? */
X			g->g_rotation = ROT_NORM;
X		}
X	}
X
X	/*
X	 * If we have converted all the characters, dump the
X	 * pre-conversion rasters.  In fact, dump everything.
X	 */
X	pd->pd_nconv += h - l;
X	if (pd->pd_nconv == 128) {
X		free(pd->pd_ras); pd->pd_ras = 0;
X		free((char *) pd); (char *) pd = 0;
X		f->f_details = NULL;
X	}
X	return (0);
X}
X
X/*
X * Discard the font details.
X */
Xstatic
Xpxl_freefont(f)
X	struct font *f;
X{
X	struct pxl_details *pd;
X
X	if ((pd = ftopd(f)) != NULL) {
X		if (pd->pd_ras != NULL) {
X		  free(pd->pd_ras); pd->pd_ras = 0;
X		}
X		free((char *) pd); (char *) pd = 0;
X	}
X}
END_OF_lib/pxlfont.c
if test 6872 -ne `wc -c <lib/pxlfont.c`; then
    echo shar: \"lib/pxlfont.c\" unpacked with wrong size!
fi
chmod +x lib/pxlfont.c
# end of overwriting check
fi
echo shar: End of archive 5 \(of 6\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    echo "Now do 'make dviselect'"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--
Skip Montanaro (montanaro@crdgw1.ge.com)

montnaro@sprite.crd.ge.com (Skip Montanaro) (11/14/89)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 6 (of 6)."
# Contents:  lib/Makefile lib/rotate.c lib/scaletfm.c lib/scanpost.c
#   lib/search.c lib/seek.c lib/split.c lib/strsave.c lib/tfm.c
#   lib/tfmfont.c
# Wrapped by montnaro@sprite on Sat Nov 11 17:13:33 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f lib/Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/Makefile\"
else
echo shar: Extracting \"lib/Makefile\" \(3637 characters\)
sed "s/^X//" >lib/Makefile <<'END_OF_lib/Makefile'
X#
X# Copyright (c) 1987 University of Maryland Department of Computer Science.
X# All rights reserved.  Permission to copy for any purpose is hereby granted
X# so long as this copyright notice remains intact.
X#
X# Makefile for ctex/lib (C-TeX library routines)
X#
X# $Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/Makefile,v 1.6 89/02/13 14:31:29 grunwald Exp Locker: grunwald $
X#
XDESTDIR=
X# Alas, -R makes ALL initialised variables read-only, and we cannot
X# use it on font files; hence, FCFLAGS.
XCC=cc
XCFLAGS=	-O -I../h 
XFCFLAGS=-O -I../h
X
X# 4.1BSD Vax:
X#ASSRC=	bcopy.s bzero.s
X#ASOBJ=	bcopy.o bzero.o
X#MISCC=	getopt.c
X#MISCO=	getopt.o
X
X# 4.2BSD Vax:
X#ASSRC=
X#ASOBJ=
X#MISCC=	getopt.c
X#MISCO=	getopt.o
X
X# 4.2BSD Sun:
X#ASSRC=
X#ASOBJ=
X#MISCC=
X#MISCO=
X
X# 4.2BSD Pyramid:
X#ASSRC=
X#ASOBJ=
X#MISCC=	getopt.c
X#MISCO=	getopt.o
X
X# 4.3BSD Vax:
XASSRC=
XASOBJ=
XMISCC=
XMISCO=
X# all
XCSRC=	conv.c dviclass.c error.c findpost.c fio.c font.c font_subr.c \
X	gfclass.c gripes.c magfactor.c rotate.c scaletfm.c scanpost.c \
X	search.c seek.c split.c strsave.c tfm.c ${MISCC}
XCOBJ=	conv.o dviclass.o error.o findpost.o fio.o font.o font_subr.o \
X	gfclass.o gripes.o magfactor.o rotate.o scaletfm.o scanpost.o \
X	search.o seek.o split.o strsave.o tfm.o ${MISCO}
XFSRC=	gffont.c pkfont.c pxlfont.c tfmfont.c
XFOBJ=	gffont.o pkfont.o pxlfont.o tfmfont.o
X
XOBJS=	${COBJ} ${ASOBJ} ${FOBJ}
X
Xall: lib.a
X
Xlib.a: ${OBJS}
X	ar cr lib.a ${OBJS}
X	ranlib lib.a
X
Xsrc: $(CSRC) $(FSRC)
X	@echo Done
X
X# no installation is necessary; this entry is just for standardisation
Xinstall:
X
Xclean:
X	rm -f *.o lib.a
X
X#pxl.o:
X#	${CC} ${CFLAGS} -c -DPXLPATH=\"${PXLPATH}\" pxl.c
X
X# font.o needs to know where to find the font description file
Xfont.o:
X	${CC} ${CFLAGS} -c -DFONTDESC=\"${FONTDESC}\" font.c
X
X# special rules for font objects
X${FOBJ}:
X	${CC} ${FCFLAGS} -c $*.c
X
X# DO NOT DELETE THIS LINE -- make depend uses it
X# DEPENDENCIES MUST END AT END OF FILE
X# IF YOU PUT STUFF HERE IT WILL GO AWAY
X# see make depend above
X# DO NOT DELETE THIS LINE -- make depend depends on it.
X
Xconv.o: ../h/types.h ../h/conv.h
Xdviclass.o: ../h/dviclass.h
Xerror.o: /usr/include/stdio.h /usr/include/varargs.h
Xfindpost.o: /usr/include/stdio.h ../h/types.h ../h/dvicodes.h ../h/fio.h
Xfio.o: /usr/include/stdio.h ../h/types.h ../h/fio.h
Xfont.o: /usr/include/stdio.h /usr/include/errno.h /usr/include/sys/errno.h
Xfont.o: ../h/types.h ../h/conv.h ../h/font.h
Xfont_subr.o: ../h/font.h
Xgetopt.o: /usr/include/stdio.h
Xgfclass.o: ../h/gfclass.h
Xgffont.o: /usr/include/stdio.h /usr/include/sys/types.h
Xgffont.o: /usr/include/sys/stat.h ../h/types.h
Xgffont.o: ../h/font.h ../h/gfcodes.h ../h/gfclass.h ../h/num.h
Xgripes.o: /usr/include/stdio.h ../h/types.h
Xpkfont.o: /usr/include/stdio.h /usr/include/sys/types.h
Xpkfont.o: /usr/include/sys/stat.h ../h/types.h
Xpkfont.o: ../h/font.h ../h/num.h
Xpxlfont.o: /usr/include/stdio.h /usr/include/sys/types.h
Xpxlfont.o: /usr/include/sys/stat.h
Xpxlfont.o: /usr/include/errno.h /usr/include/sys/errno.h ../h/types.h
Xpxlfont.o: ../h/font.h ../h/fio.h
Xrotate.o: ../h/font.h
Xscaletfm.o: ../h/types.h ../h/font.h
Xscanpost.o: /usr/include/stdio.h ../h/types.h ../h/dvicodes.h ../h/fio.h
Xscanpost.o: ../h/postamble.h
Xsearch.o: ../h/types.h ../h/search.h
Xseek.o: /usr/include/stdio.h /usr/include/sys/param.h
Xseek.o: /usr/include/sys/signal.h
Xseek.o: /usr/include/sys/types.h 
Xseek.o: /usr/include/sys/file.h
Xseek.o: /usr/include/sys/stat.h
Xsplit.o: /usr/include/ctype.h
Xtfm.o: /usr/include/stdio.h ../h/types.h ../h/fio.h ../h/tfm.h
Xtfmfont.o: /usr/include/stdio.h /usr/include/sys/types.h
Xtfmfont.o: /usr/include/sys/stat.h ../h/types.h
Xtfmfont.o: ../h/conv.h ../h/font.h ../h/tfm.h
END_OF_lib/Makefile
if test 3637 -ne `wc -c <lib/Makefile`; then
    echo shar: \"lib/Makefile\" unpacked with wrong size!
fi
chmod +x lib/Makefile
# end of overwriting check
fi
if test -f lib/rotate.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/rotate.c\"
else
echo shar: Extracting \"lib/rotate.c\" \(3519 characters\)
sed "s/^X//" >lib/rotate.c <<'END_OF_lib/rotate.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/rotate.c,v 1.4 89/02/13 14:31:18 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * Routines to generate rotated bitmaps given unrotated inputs.
X *
X * The rotated bitmap is indistinguishable from the unrotated one (aside
X * from being rotated of course!).
X */
X
X#include "font.h"
X
Xextern	int errno;
X
Xchar	*malloc();
X
Xstatic RotateClockwise();
X
X/*
X * Rounding, but by powers of two only.
X */
X#define ROUND(n,r) (((n) + ((r) - 1)) & ~((r) - 1))
X
X/*
X * Set the rotation of glyph g to r.
X */
XSetRotation(g, r)
X	register struct glyph *g;
X	int r;
X{
X
X	if (r < ROT_NORM || r > ROT_RIGHT)
X		error(1, 0, "bad rotation value %d", r);
X
X	/*
X	 * The null glyph is trivial to rotate by any amount.
X	 *
X	 * Note that this assumes that any raster has been obtained
X	 * BEFORE calling SetRotation()!
X	 */
X	if (g->g_raster == NULL) {
X		g->g_rotation = r;
X		return;
X	}
X
X	/*
X	 * This is hardly efficient, but it *is* expedient....
X	 */
X	while (g->g_rotation != r) {
X		RotateClockwise(g);
X		g->g_rotation = (g->g_rotation - 1) & 3;
X	}
X}
X
X/*
X * Rotation by 1/4 turn clockwise (from ROT_NORM to ROT_RIGHT, e.g.).
X */
Xstatic
XRotateClockwise(glyph)
X	struct glyph *glyph;
X{
X	register char *nrast;	/* new raster */
X	register char *orast;	/* old raster */
X	register int oheight;	/* old raster height, new raster width */
X	register int owidth;	/* old raster width, new raster height */
X	unsigned int size;	/* size of new raster (in bytes) */
X	int nplus;		/* offset between rows in nrast */
X
X	/*
X	 * First, get a new raster.
X	 */
X	{
X		register struct glyph *g = glyph;
X		register int t;
X
X		oheight = g->g_height;
X		owidth = g->g_width;
X
X		/*
X		 * Offset is (new width) rounded to bytes.
X		 */
X		nplus = ROUND(oheight, 8) >> 3;
X
X		/*
X		 * Size of new raster is (new height) * (new rounded width,
X		 * in bytes).
X		 */
X		size = nplus * owidth;
X		if ((nrast = malloc(size)) == NULL)
X			error(1, errno, "out of memory");
X		bzero(nrast, size);
X
X		/*
X		 * New y origin is old x origin; new x origin is old height
X		 * minus old y origin - 1.
X		 */
X		t = g->g_yorigin;
X		g->g_yorigin = g->g_xorigin;
X		g->g_xorigin = oheight - t - 1;
X
X		/* While we are at it, exchange height & width... */
X		g->g_height = owidth;
X		g->g_width = oheight;
X
X		/* and grab a pointer to the old raster. */
X		orast = g->g_raster;
X	}
X
X	/*
X	 * Now copy bits from the old raster to the new one.  The mapping
X	 * function is
X	 *
X	 *	for i in [0..height)
X	 *		for j in [0..width)
X	 *			new[j, height-i-1] = old[i, j] 
X	 *
X	 * Thus i maps to height-i-1 and (since we have to do our own 2
X	 * dimensional array indexing) j to nplus*j.  We call the mapped
X	 * variables mapi and mapj, and, since we scan sequentially through
X	 * the old raster, can discard the original i and j.
X	 */
X	{
X		register int mapj, c, k, mapi;
X
X		mapi = oheight;
X		owidth *= nplus;
X		while (--mapi >= 0) {
X			k = 7;
X			for (mapj = 0; mapj < owidth; mapj += nplus) {
X				if (++k == 8)	/* get another byte */
X					c = *orast++, k = 0;
X				if (c & 0x80)	/* old[i,j] was set */
X					nrast[mapj + (mapi >> 3)] |=
X						1 << (7 - (mapi & 7));
X				c <<= 1;
X			}
X		}
X	}
X
X	/*
X	 * Finally, free the storage associated with the original raster.
X	 */
X	free(glyph->g_raster); glyph->g_raster = 0;
X	glyph->g_raster = nrast;
X}
END_OF_lib/rotate.c
if test 3519 -ne `wc -c <lib/rotate.c`; then
    echo shar: \"lib/rotate.c\" unpacked with wrong size!
fi
chmod +x lib/rotate.c
# end of overwriting check
fi
if test -f lib/scaletfm.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/scaletfm.c\"
else
echo shar: Extracting \"lib/scaletfm.c\" \(3302 characters\)
sed "s/^X//" >lib/scaletfm.c <<'END_OF_lib/scaletfm.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/scaletfm.c,v 1.3 89/02/13 14:31:19 grunwald Exp Locker: grunwald $";
X#endif
X
X#include "types.h"
X#include "font.h"
X
X/*
X * From DVITYPE.WEB:
X *
X * ``The most important part of in_TFM is the width computation, which
X *   involvles multiplying the relative widths in the TFM file by the scaling
X *   factor in the DVI file.  This fixed-point multiplication must be done with
X *   precisely the same accuracy by all DVI-reading programs, in order to
X *   validate the assumptions made by DVI-writing programs like \TeX 82.
X *
X *   Let us therefore summarize what needs to be done.  Each width in a TFM
X *   file appears as a four-byte quantity called a fix_word.  A fix_word whose
X *   respective bytes are (a,b,c,d) represents the number
X *
X *	   {{ b * 2^{-4} + c * 2^{-12} + d * 2^{-20},        if a = 0;
X *    x = {{
X *	   {{ -16 + b * 2^{-4} + c * 2^{-12} + d * 2^{-20},  if a = 255.
X *
X *   (No other choices of a are allowed, since the magnitude of a TFM dimension
X *   must be less than 16.)  We want to multiply this quantity by the integer
X *   z, which is known to be less than 2^{27}.  Let \alpha = 16z.  If z <
X *   2^{23}, the individual multiplications b * z, c * z, d * z cannot
X *   overflow; otherwise we will divide z by 2, 4, 8, or 16, to obtain a
X *   multiplier less than 2^{23}, and we can compensate for this later.  If z
X *   has thereby been replaced by z' = z/2^e, let \beta = 2^{4-e}; we shall
X *   compute
X *
X *	\lfloor (b + c * 2^{-8} + d * 2^{-16})z' / \beta \rfloor
X *
X *   if a = 0, or the same quantity minus \alpha if a = 255.  This calculation
X *   must be done exactly, for the reasons stated above; the following program
X *   does the job in a system-independent way, assuming that arithmetic is
X *   exact on numbers less than 2^{31} in magnitude.''
X */
X
X/*
X * Scale the single TFM width t by z.
X */
Xi32
XScaleOneWidth(t, z)
X	register i32 t, z;
X{
X	register i32 alpha, log2beta;
X
X	/* First compute \alpha, \beta, and z': */
X	alpha = 16 * z;
X	log2beta = 4;
X	while (z >= (1 << 23)) {
X		z >>= 1;
X		log2beta--;
X	}
X
X	/* The four values 'a', 'b', 'c', and 'd' are fields within t: */
X#define	a	(UnSign8(t >> 24))
X#define	b	(UnSign8(t >> 16))
X#define	c	(UnSign8(t >> 8))
X#define	d	(UnSign8(t))
X	if (t) {
X		t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta;
X		if (a) {
X			if (a != 255)
X				error(0, 0, "bad TFM width! [ScaleOneWidth]");
X			t -= alpha;
X		}
X	}
X	return (t);
X}
X
X/*
X * Scale a set of glyphs [l..h) in font f according to f->f_dvimag.
X */
XScaleGlyphs(f, l, h)
X	register struct font *f;
X	int l, h;
X{
X	register int i;
X	register i32 t, z, alpha, log2beta;
X
X	z = f->f_dvimag;
X	alpha = 16 * z;
X	log2beta = 4;
X	while (z >= (1 << 23)) {
X		z >>= 1;
X		log2beta--;
X	}
X
X	for (i = l; i < h; i++) {
X		if ((t = f->f_gly[i]->g_tfmwidth) == 0)
X			continue;
X		t = (((((d * z) >> 8) + c * z) >> 8) + b * z) >> log2beta;
X		if (a) {
X			if (a != 255)
X				error(0, 0, "\"%s\", glyph %d: bad TFM width",
X					f->f_path, i);
X			t -= alpha;
X		}
X		f->f_gly[i]->g_tfmwidth = t;
X	}
X}
END_OF_lib/scaletfm.c
if test 3302 -ne `wc -c <lib/scaletfm.c`; then
    echo shar: \"lib/scaletfm.c\" unpacked with wrong size!
fi
chmod +x lib/scaletfm.c
# end of overwriting check
fi
if test -f lib/scanpost.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/scanpost.c\"
else
echo shar: Extracting \"lib/scanpost.c\" \(2244 characters\)
sed "s/^X//" >lib/scanpost.c <<'END_OF_lib/scanpost.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/scanpost.c,v 1.3 89/02/13 14:31:20 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * ScanPostAmble - read a DVI postamble.
X */
X
X#include <stdio.h>
X#include "types.h"
X#include "dvicodes.h"
X#include "fio.h"
X#include "postamble.h"
X
XScanPostAmble(f, headerfunc, fontfunc)
X	register FILE *f;
X	int (*headerfunc)();
X	register int (*fontfunc)();
X{
X	register int n;
X	register char *s;
X	char name[512];
X
X	if (FindPostAmble(f)) {
X	  GripeCannotFindPostamble();
X	  return(1);
X	}
X	if (GetByte(f) != Sign8(DVI_POST)) {
X	  GripeMissingOp("POST");
X	  return(1);
X	}
X
X	/* Read the postamble info stuff. */
X	{
X		struct PostAmbleInfo pai;
X		register struct PostAmbleInfo *p = &pai;
X
X		p->pai_PrevPagePointer = GetLong(f);
X		p->pai_Numerator = GetLong(f);
X		p->pai_Denominator = GetLong(f);
X		p->pai_DVIMag = GetLong(f);
X		p->pai_TallestPageHeight = GetLong(f);
X		p->pai_WidestPageWidth = GetLong(f);
X		p->pai_DVIStackSize = GetWord(f);
X		p->pai_NumberOfPages = GetWord(f);
X
X		(*headerfunc)(p);
X	}
X
X	/* Now read all the font definitions. */
X	{
X		struct PostAmbleFont paf;
X		register struct PostAmbleFont *p = &paf;
X
X		for (;;) {
X			switch (UnSign8(getc(f))) {
X
X			case DVI_FNTDEF1:
X				p->paf_DVIFontIndex = UnSign8(getc(f));
X				break;
X
X			case DVI_FNTDEF2:
X				p->paf_DVIFontIndex = UnSign16(GetWord(f));
X				break;
X
X			case DVI_FNTDEF3:
X				p->paf_DVIFontIndex = UnSign24(Get3Byte(f));
X				break;
X
X			case DVI_FNTDEF4:
X				p->paf_DVIFontIndex = GetLong(f);
X				break;
X
X			case DVI_POSTPOST:
X				return(0);
X
X			default:
X				GripeMissingOp("POSTPOST");
X				return(1);
X				/*NOTREACHED*/
X			}
X			p->paf_DVIChecksum = GetLong(f);
X			p->paf_DVIMag = GetLong(f);
X			p->paf_DVIDesignSize = GetLong(f);
X			p->paf_n1 = UnSign8(getc(f));
X			p->paf_n2 = UnSign8(getc(f));
X			p->paf_name = name;	/* never trust people not to
X						   clobber it */
X			n = p->paf_n1 + p->paf_n2;
X			s = name;
X			while (--n >= 0)
X				*s++ = GetByte(f);
X			*s = 0;
X			(*fontfunc)(p);
X		}
X	}
X}
END_OF_lib/scanpost.c
if test 2244 -ne `wc -c <lib/scanpost.c`; then
    echo shar: \"lib/scanpost.c\" unpacked with wrong size!
fi
chmod +x lib/scanpost.c
# end of overwriting check
fi
if test -f lib/search.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/search.c\"
else
echo shar: Extracting \"lib/search.c\" \(4599 characters\)
sed "s/^X//" >lib/search.c <<'END_OF_lib/search.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/search.c,v 1.4 89/02/13 14:31:21 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * Key search routines (for a 32 bit key)
X *
X * SCreate initializes the search control area.
X *
X * SSearch returns the address of the data area (if found or created)
X * or a null pointer (if not).  The last argument controls the disposition
X * in various cases, and is a ``value-result'' parameter.
X *
X * SEnumerate calls the given function on each data object within the
X * search table.  Note that no ordering is specified (though currently
X * it runs in increasing-key-value sequence).
X */
X
X#include "types.h"
X#include "search.h"
X
X#if vax || mc68000 || ns32000 || pyr
X#define	HARD_ALIGNMENT	4
X#else
X#define	HARD_ALIGNMENT	16	/* should suffice for most everyone */
X#endif
X
Xstatic int DOffset;		/* part of alignment code */
X
Xchar	*malloc(), *realloc();
X
Xstruct search *
XSCreate(dsize)
X	register unsigned int dsize;
X{
X	register struct search *s;
X
X	if ((s = (struct search *) malloc(sizeof *s)) == 0)
X		return (0);
X
X	if (DOffset == 0) {
X#ifndef HARD_ALIGNMENT
X		DOffset = sizeof(i32);
X#else
X		DOffset = (sizeof(i32) + HARD_ALIGNMENT - 1) &
X			~(HARD_ALIGNMENT - 1);
X#endif
X	}
X	dsize += DOffset;	/* tack on space for keys */
X
X#ifdef HARD_ALIGNMENT
X	/*
X	 * For machines with strict alignment constraints, it may be
X	 * necessary to align the data at a multiple of some positive power
X	 * of two.  In general, it would suffice to make dsize a power of
X	 * two, but this could be very space-wasteful, so instead we align it
X	 * to HARD_ALIGNMENT.  64 bit machines might ``#define HARD_ALIGNMENT
X	 * 8'', for example.  N.B.:  we assume that HARD_ALIGNMENT is a power
X	 * of two.
X	 */
X
X	dsize = (dsize + HARD_ALIGNMENT - 1) & ~(HARD_ALIGNMENT - 1);
X#endif
X
X	s->s_dsize = dsize;	/* save data object size */
X	s->s_space = 10;	/* initially, room for 10 objects */
X	s->s_n = 0;		/* and none in the table */
X	if ((s->s_data = malloc(s->s_space * dsize)) == 0) {
X		free((char *) s); (char *) s = 0;
X		return (0);
X	}
X	return (s);
X}
X
X/*
X * We actually use a binary search right now - this may change.
X */
Xchar *
XSSearch(s, key, disp)
X	register struct search *s;
X	register i32 key;
X	int *disp;
X{
X	register char *keyaddr;
X	int itemstomove;
X
X	*disp &= S_CREATE | S_EXCL;	/* clear return codes */
X	if (s->s_n) {		/* look for the key */
X		register int h, l, m;
X
X		h = s->s_n - 1;
X		l = 0;
X		while (l <= h) {
X			m = (l + h) >> 1;
X			keyaddr = s->s_data + m * s->s_dsize;
X			if (*(i32 *) keyaddr > key)
X				h = m - 1;
X			else if (*(i32 *) keyaddr < key)
X				l = m + 1;
X			else {	/* found it, now what? */
X				if (*disp & S_EXCL) {
X					*disp |= S_COLL;
X					return (0);	/* collision */
X				}
X				*disp |= S_FOUND;
X				return (keyaddr + DOffset);
X			}
X		}
X		keyaddr = s->s_data + l * s->s_dsize;
X	} else
X		keyaddr = s->s_data;
X
X	/* keyaddr is now where the key should have been found, if anywhere */
X	if ((*disp & S_CREATE) == 0)
X		return (0);	/* not found */
X
X	/* avoid using realloc so as to retain old data if out of memory */
X	if (s->s_space <= 0) {	/* must expand; double it */
X		register char *new;
X
X		if ((new = malloc((s->s_n << 1) * s->s_dsize)) == 0) {
X			*disp |= S_ERROR;	/* no space */
X			return (0);
X		}
X		keyaddr = (keyaddr - s->s_data) + new;	/* relocate */
X		bcopy(s->s_data, new, s->s_n * s->s_dsize);
X		free(s->s_data); s->s_data = 0;
X		s->s_data = new;
X		s->s_space = s->s_n;
X	}
X	/* now move any keyed data that is beyond keyaddr down */
X	itemstomove = s->s_n - (keyaddr - s->s_data) / s->s_dsize;
X	if (itemstomove) {
X#ifndef USE_BCOPY		/* often bcopy doesn't handle overlap */
X		register char *from, *to;
X
X		from = s->s_data + s->s_n * s->s_dsize;
X		to = from + s->s_dsize;
X		while (from > keyaddr)
X			*--to = *--from;
X#else
X		bcopy(keyaddr + s->s_dsize, keyaddr + (s->s_dsize << 1),
X			itemstomove * s->s_dsize);
X#endif
X	}
X	*disp |= S_NEW;
X	s->s_n++;
X	s->s_space--;
X	*(i32 *) keyaddr = key;
X	keyaddr += DOffset;	/* now actually dataaddr */
X	/* the bzero is just a frill... */
X	bzero(keyaddr, s->s_dsize - DOffset);
X	return (keyaddr);
X}
X
X/*
X * Call function `f' for each element in the search table `s'.
X */
XSEnumerate(s, f)
X	register struct search *s;
X	register int (*f)();
X{
X	register int n;
X	register char *p;
X
X	n = s->s_n;
X	p = s->s_data;
X	while (--n >= 0) {
X		(*f)(p + DOffset, *(i32 *) p);
X		p += s->s_dsize;
X	}
X}
END_OF_lib/search.c
if test 4599 -ne `wc -c <lib/search.c`; then
    echo shar: \"lib/search.c\" unpacked with wrong size!
fi
chmod +x lib/search.c
# end of overwriting check
fi
if test -f lib/seek.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/seek.c\"
else
echo shar: Extracting \"lib/seek.c\" \(3044 characters\)
sed "s/^X//" >lib/seek.c <<'END_OF_lib/seek.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/seek.c,v 1.3 89/02/13 14:31:23 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * Seekable is a predicate which returns true iff a Unix fd is seekable.
X *
X * MakeSeekable forces an input stdio file to be seekable, by copying to
X * a temporary file if necessary.
X */
X
X#include <stdio.h>
X#ifdef sys5
X#include <sys/types.h>
X#include <sys/fcntl.h>
X#else
X#include <sys/param.h>
X#endif
X#include <sys/file.h>
X#include <sys/stat.h>
X
Xlong	lseek();
Xchar	*getenv();
X
Xint
XSeekable(fd)
X	int fd;
X{
X
X	return (lseek(fd, 0L, 1) >= 0 && !isatty(fd));
X}
X
X/*
X * We use the despicable trick of unlinking an open temporary file.
X * The alternatives are too painful.  If it becomes necessary to
X * do this another way, however, here is a method suggested by Fred
X * Blonder: fork, and have the parent wait for the child to exit.
X * (The parent must avoid being killed during this phase.)  When
X * the child exits, the parent should then remove the temporary file,
X * then exit with the same status, or send itself the same signal.
X */
Xint
XMakeSeekable(f)
X	register FILE *f;
X{
X	register int tf, n;
X	int mypid, tries, blksize;
X	char *tmpdir;
X#ifdef MAXBSIZE
X	char buf[MAXBSIZE];
X	struct stat st;
X#else
X	char buf[BUFSIZ];
X#endif
X
X	if (Seekable(fileno(f)))
X		return (0);
X
X	if ((tmpdir = getenv("TMPDIR")) == 0)
X		tmpdir = "/tmp";
X
X	/* compose a suitable temporary file name, and get an r/w descriptor */
X	mypid = getpid();
X	n = 0;
X	tries = 0;
X	do {
X		sprintf(buf, "%s/#%d.%d", tmpdir, mypid, n++);
X		(void) unlink(buf);
X#ifdef O_CREAT			/* have three-argument open syscall */
X		tries++;
X		tf = open(buf, O_RDWR | O_CREAT | O_EXCL, 0666);
X#else
X		if (access(buf, 0) == 0) {
X			/*
X			 * Skip existing files.  Note that tf might
X			 * not be set yet.
X			 */
X			tf = -1;
X			continue;
X		}
X		tries++;
X		tf = creat(buf, 0666);
X		if (tf >= 0) {
X			(void) close(tf);
X			tf = open(buf, 2);
X			if (tf < 0)
X				(void) unlink(buf);
X		}
X#endif
X	} while (tf < 0 && tries < 20);
X	if (tf < 0)		/* probably unrecoverable user error */
X		return (-1);
X
X	(void) unlink(buf);
X
X	/* copy from input file to temp file */
X#ifdef MAXBSIZE
X	if (fstat(tf, &st))	/* how can this ever fail? */
X		blksize = MAXBSIZE;
X	else
X		blksize = MIN(MAXBSIZE, st.st_blksize);
X#else
X	blksize = BUFSIZ;
X#endif
X	while ((n = fread(buf, 1, blksize, f)) > 0) {
X		if (write(tf, buf, n) != n) {
X			(void) close(tf);
X			return (-1);
X		}
X	}
X	/* ferror() is broken in Ultrix 1.2; hence the && */
X	if (ferror(f) && !feof(f)) {
X		(void) close(tf);
X		return (-1);
X	}
X
X	/*
X	 * Now switch f to point at the temp file.  Since we hit EOF, there
X	 * is nothing in f's stdio buffers, so we can play a dirty trick: 
X	 */
X	clearerr(f);
X	if (dup2(tf, fileno(f))) {
X		(void) close(tf);
X		return (-1);
X	}
X	(void) close(tf);
X	return (0);
X}
END_OF_lib/seek.c
if test 3044 -ne `wc -c <lib/seek.c`; then
    echo shar: \"lib/seek.c\" unpacked with wrong size!
fi
chmod +x lib/seek.c
# end of overwriting check
fi
if test -f lib/split.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/split.c\"
else
echo shar: Extracting \"lib/split.c\" \(4603 characters\)
sed "s/^X//" >lib/split.c <<'END_OF_lib/split.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/split.c,v 1.3 89/02/13 14:31:24 grunwald Exp Locker: grunwald $";
X#endif
X
X#include <ctype.h>
X
X/*
X * Split a line into an array of words.  This is destructive of
X * the original line; the word pointers point to places within
X * that line.
X *
X * Return the number of words made, or -1 for overflow.
X */
X
X/*
X * The lexical states are much like `sh's, except that we also do
X * C-style backslash-escapes.
X */
Xenum lexstate {
X	S_BLANK,		/* outside a word */
X	S_WORD,			/* inside a word, no quoting */
X	S_SQUOTE,		/* inside a single quote */
X	S_DQUOTE,		/* inside a double quote */
X	S_BKSL0,		/* last char was \ */
X	S_BKSL1,		/* last chars were \, [0-7] */
X	S_BKSL2			/* last chars were \, [0-7][0-7] */
X};
X
Xint
Xsplit(s, w, nw)
X	register char *s, **w;
X	int nw;
X{
X	register int c;
X	register char *canon = s;
X	register int wleft = nw;
X	enum lexstate state, prebkstate;
X
X	/*
X	 * Start out in the `blank' state (outside a word).  Handle
X	 * quotes and things.  Backslashes are handled by saving the
X	 * `pre-backslash' state, doing the backslash, and restoring
X	 * that state at the end of the backslash sequence.
X	 */
X	state = S_BLANK;
X	while ((c = *s++) != 0) {
Xreswitch:
X		switch (state) {
X
X		/*
X		 * Blanks: spaces stay in blank state; anything
X		 * else starts a word.  However, quotes may put
X		 * us into quote states, rather than word states.
X		 */
X		case S_BLANK:
X			if (isspace(c))
X				continue;
X			if (--wleft < 0)
X				return (-1);
X			*w++ = canon;
X			state = S_WORD;
X			/* FALLTHROUGH */
X
X		/*
X		 * In a word.  Spaces take us out (and end the
X		 * current word).  Quotes, however, put us into
X		 * quote states.
X		 */
X		case S_WORD:
X			if (isspace(c)) {
X				*canon++ = 0;
X				state = S_BLANK;
X				break;
X			}
X			if (c == '\'') {
X				state = S_SQUOTE;
X				break;
X			}
X			if (c == '"') {
X				state = S_DQUOTE;
X				break;
X			}
X			if (c == '\\') {
X				prebkstate = S_WORD;
X				state = S_BKSL0;
X				break;
X			}
X			*canon++ = c;
X			break;
X
X		/*
X		 * Inside a single quote, the only special character
X		 * is another single quote.  This matches the Bourne
X		 * shell quoting convention exactly.
X		 */
X		case S_SQUOTE:
X			if (c == '\'')
X				state = S_WORD;
X			else
X				*canon++ = c;
X			break;
X
X		/*
X		 * Inside a double quote, double quotes get us out,
X		 * but backslashes must be interpreted.
X		 */
X		case S_DQUOTE:
X			if (c == '\\') {
X				prebkstate = S_DQUOTE;
X				state = S_BKSL0;
X			} else if (c == '"')
X				state = S_WORD;
X			else
X				*canon++ = c;
X			break;
X
X		/*
X		 * If we are handling a backslash, we will either
X		 * restore the state, or go to BKSL1 state.  In
X		 * the latter case, do not advance the canonicalisation
X		 * pointer, since we might have more octal digits
X		 * to insert.
X		 */
X		case S_BKSL0:
X			state = prebkstate;	/* probably */
X			switch (c) {
X
X			case 'b':
X				*canon++ = '\b';
X				break;
X
X			case 'f':
X				*canon++ = '\f';
X				break;
X
X			case 'n':
X				*canon++ = '\n';
X				break;
X
X			case 'r':
X				*canon++ = '\r';
X				break;
X
X			case 't':
X				*canon++ = '\t';
X				break;
X
X			case '0': case '1': case '2': case '3':
X			case '4': case '5': case '6': case '7':
X				*canon = c - '0';
X				state = S_BKSL1;
X				break;
X
X			default:
X				*canon++ = c;
X				break;
X			}
X			break;
X
X
X		/*
X		 * In BKSL1, we have seen backslash and one octal
X		 * digit.  There may be more (in which case just
X		 * count them on in), or there might be something
X		 * that requires we restore the state and try again.
X		 */
X		case S_BKSL1:
X			switch (c) {
X
X			case '0': case '1': case '2': case '3':
X			case '4': case '5': case '6': case '7':
X				*canon <<= 3;
X				*canon |= c - '0';
X				state = S_BKSL2;
X				break;
X
X			default:
X				canon++;
X				state = prebkstate;
X				goto reswitch;
X			}
X			break;
X
X		/*
X		 * BKSL2 is like BKSL1, except that it cannot
X		 * help but restore the original state, since
X		 * there are no four-character octal sequences.
X		 */
X		case S_BKSL2:
X			state = prebkstate;	/* assuredly */
X			switch (c) {
X
X			case '0': case '1': case '2': case '3':
X			case '4': case '5': case '6': case '7':
X				*canon <<= 3;
X				*canon++ |= c - '0';
X				break;
X
X			default:
X				canon++;
X				goto reswitch;
X			}
X			break;
X		}
X	}
X#ifdef notdef
X	if (state != S_WORD && state != S_BLANK)
X		error(0, 0, "warning: unclosed quote");
X#endif
X	if (state != S_BLANK)
X		*canon = 0;
X	return (nw - wleft);
X}
END_OF_lib/split.c
if test 4603 -ne `wc -c <lib/split.c`; then
    echo shar: \"lib/split.c\" unpacked with wrong size!
fi
chmod +x lib/split.c
# end of overwriting check
fi
if test -f lib/strsave.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/strsave.c\"
else
echo shar: Extracting \"lib/strsave.c\" \(522 characters\)
sed "s/^X//" >lib/strsave.c <<'END_OF_lib/strsave.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * Save a string in managed memory.
X */
X
Xchar	*malloc(), *realloc();
Xextern int errno;
X
Xchar *
Xstrsave(s)
X	register char *s;
X{
X	register int l = strlen(s) + 1;
X	register char *p = malloc((unsigned) l);
X
X	if (p == 0)
X		error(1, errno, "no room for %d bytes of string", l);
X	bcopy(s, p, l);
X	return (p);
X}
END_OF_lib/strsave.c
if test 522 -ne `wc -c <lib/strsave.c`; then
    echo shar: \"lib/strsave.c\" unpacked with wrong size!
fi
chmod +x lib/strsave.c
# end of overwriting check
fi
if test -f lib/tfm.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/tfm.c\"
else
echo shar: Extracting \"lib/tfm.c\" \(2549 characters\)
sed "s/^X//" >lib/tfm.c <<'END_OF_lib/tfm.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/tfm.c,v 1.4 89/02/13 14:31:26 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * TFM file reading routines.
X *
X * TODO:
X *	finish
X */
X
X#include <stdio.h>
X#include "types.h"
X#include "fio.h"
X#include "tfm.h"
X
Xchar	*malloc();
X
X#define	ALLOC(n, type)	((type *) malloc((unsigned) ((n) * sizeof (type))))
X
Xstatic trd_header();
Xstatic trd_ci();
Xstatic trd_fix();
X
Xint
Xreadtfmfile(f, t, stopafterwidth)
X	register FILE *f;
X	register struct tfmdata *t;
X	int stopafterwidth;	/* ??? */
X{
X	i32 nc;
X
X	if (trd_header(f, &t->t_hdr))
X		return (-1);
X	nc = t->t_hdr.th_ec - t->t_hdr.th_bc + 1;
X
X	t->t_ci = NULL;
X	t->t_width = NULL;
X	t->t_height = NULL;
X	t->t_depth = NULL;
X
X	(void) fseek(f, t->t_hdr.th_lh * 4L, 1);	/* XXX */
X
X	if ((t->t_ci = ALLOC(nc, struct char_info_word)) == NULL ||
X	    trd_ci(f, nc, t->t_ci) ||
X	    (t->t_width = ALLOC(t->t_hdr.th_nw, i32)) == NULL ||
X	    trd_fix(f, t->t_hdr.th_nw, t->t_width))
X		goto bad;
X	if (stopafterwidth)
X		return (0);
X	if ((t->t_height = ALLOC(t->t_hdr.th_nh, i32)) == NULL ||
X	    trd_fix(f, t->t_hdr.th_nh, t->t_height) ||
X	    (t->t_depth = ALLOC(t->t_hdr.th_nd, i32)) == NULL ||
X	    trd_fix(f, t->t_hdr.th_nd, t->t_depth))
X		goto bad;
X	return (0);
X	
X      bad:
X	if (t->t_ci != NULL) {
X	  free((char *) t->t_ci); (char *) t->t_ci = 0;
X	}
X	if (t->t_width != NULL) {
X	  free((char *) t->t_width); (char *) t->t_width = 0;
X	}
X	if (t->t_height != NULL) {
X	  free((char *) t->t_height); (char *) t->t_height = 0;
X	}
X	if (t->t_depth != NULL) {
X	  free((char *) t->t_depth); (char *) t->t_depth = 0;
X	}
X	return (-1);
X      }
X
Xstatic int
Xtrd_header(f, th)
X	register FILE *f;
X	register struct tfmheader *th;
X{
X	register i32 *p;
X
X	for (p = &th->th_lf; p <= &th->th_np; p++)
X		fGetWord(f, *p);
X	if (feof(f))
X		return (-1);
X	return (0);
X}
X
Xstatic int
Xtrd_ci(f, nc, ci)
X	register FILE *f;
X	register int nc;
X	register struct char_info_word *ci;
X{
X
X	while (--nc >= 0) {
X		ci->ci_width = fgetbyte(f);
X		ci->ci_h_d = fgetbyte(f);
X		ci->ci_i_t = fgetbyte(f);
X		ci->ci_remainder = fgetbyte(f);
X		ci++;
X	}
X	if (feof(f))
X		return (-1);
X	return (0);
X}
X
Xstatic int
Xtrd_fix(f, nf, p)
X	register FILE *f;
X	register int nf;
X	register i32 *p;
X{
X
X	while (--nf >= 0) {
X		fGetLong(f, *p);
X		p++;
X	}
X	if (feof(f))
X		return (-1);
X	return (0);
X}
END_OF_lib/tfm.c
if test 2549 -ne `wc -c <lib/tfm.c`; then
    echo shar: \"lib/tfm.c\" unpacked with wrong size!
fi
chmod +x lib/tfm.c
# end of overwriting check
fi
if test -f lib/tfmfont.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/tfmfont.c\"
else
echo shar: Extracting \"lib/tfmfont.c\" \(5607 characters\)
sed "s/^X//" >lib/tfmfont.c <<'END_OF_lib/tfmfont.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/tfmfont.c,v 1.5 89/02/13 14:31:27 grunwald Exp Locker: grunwald $";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "types.h"
X#include "conv.h"
X#include "font.h"
X#include "tfm.h"
X
X/*
X * TFM font operations.  This defines three fonts:
X *
X *	box   - prints as little square boxes, outlining what TeX
X *		thinks is the character.
X *	blank - prints as entirely blank.
X *	invis - prints as entirely blank.
X *
X * The first two also complain that no font is available in the
X * requested size; these are intended to be used as a last resort
X * so that users can always print DVI files.  You should configure
X * in exactly one of box or blank.
X *
X * TODO:
X *	base box edge widths on Conversion.c_dpi
X */
X
Xstatic box_read();
Xstatic blank_read();
Xstatic invis_read();
Xstatic do_read();
Xstatic tfm_getgly();
Xstatic tfm_rasterise();
Xstatic tfm_freefont();
X
X	/* magnifications are unused in tfm fonts */
Xstruct	fontops boxops =	/* `boxtops'?  Is this a cereal driver? */
X	{ "box", 0.0, box_read, tfm_getgly, tfm_rasterise, tfm_freefont };
Xstruct	fontops blankops =
X	{ "blank", 0.0, blank_read, tfm_getgly, tfm_rasterise, tfm_freefont };
Xstruct	fontops invisops =
X	{ "invis", 0.0, invis_read, tfm_getgly, tfm_rasterise, tfm_freefont };
X
X/*
X * Local info.
X */
X
Xstruct tfm_details {
X	int	tfm_edge;		/* box edge widths, in pixels */
X	struct	conversion tfm_conv;	/* conv. from scaled pts to pixels */
X	struct	tfmdata tfm_data;	/* the TFM file data */
X};
X
X/*
X * Get the tfm_details from font f.
X */
X#define	ftotfm(f) ((struct tfm_details *) (f)->f_details)
X
Xextern	int errno;
Xchar	*malloc();
X
X/*
X * Read a Box font.
X */
Xstatic int
Xbox_read(f)
X	struct font *f;
X{
X
X	return (do_read(f, 0, 1));
X}
X
X/*
X * Read a Blank font.
X */
Xstatic int
Xblank_read(f)
X	struct font *f;
X{
X
X	return (do_read(f, 1, 1));
X}
X
X/*
X * Read an Invisible font.
X */
Xstatic int
Xinvis_read(f)
X	struct font *f;
X{
X
X	return (do_read(f, 1, 0));
X}
X
X/*
X * Read a TFM font.  It is blank if `blank'; complain if `complain'.
X */
Xstatic int
Xdo_read(f, blank, complain)
X	register struct font *f;
X	int blank, complain;
X{
X	register struct tfm_details *tfm;
X	FILE *fd;
X
X	if ((fd = fopen(f->f_path, "r")) == 0)
X		return (-1);
X	if ((tfm = (struct tfm_details *) malloc(sizeof (*tfm))) == NULL)
X		goto fail;
X	if (readtfmfile(fd, &tfm->tfm_data, blank))
X		goto fail;
X	if (blank)
X		tfm->tfm_edge = 0;
X	else {
X	  extern Conv Conversion;
X
X		tfm->tfm_edge = 2;	/* XXX should be based on dpi */
X		tfm->tfm_conv = Conversion;
X		tfm->tfm_conv.c_fromsp *= DMagFactor(f->f_scaled);
X					/* XXX !data abstraction */
X	}
X	if (FontHasGlyphs(f, tfm->tfm_data.t_hdr.th_bc,
X			  tfm->tfm_data.t_hdr.th_ec + 1))
X		goto fail;
X	f->f_details = (char *) tfm;
X	(void) fclose(fd);
X	if (complain)
X		error(0, 0, "Warning: no font for %s", Font_TeXName(f));
X	return (0);
X
Xfail:
X	(void) fclose(fd);
X	if (tfm != NULL) {
X	  free((char *) tfm); (char *) tfm = 0;
X	}
X	return (-1);
X}
X
X/*
X * Obtain the specified range of glyphs.
X */
Xstatic int
Xtfm_getgly(f, l, h)
X	register struct font *f;
X	int l;
X	register int h;
X{
X	register struct tfm_details *tfm = ftotfm(f);
X	register struct glyph *g;
X	register int i;
X	register struct char_info_word *ci;
X#define	t (&tfm->tfm_data)
X	i32 ScaleOneWidth();
X
X#define ftop(fix) cfromSP(&tfm->tfm_conv, ScaleOneWidth(fix, f->f_dvimag))
X
X	for (i = l; i < h; i++) {
X		ci = &t->t_ci[i - t->t_hdr.th_bc];
X		/* zero widths mark invalid characters */
X		if (ci->ci_width == 0)
X			continue;
X		g = f->f_gly[i];
X		g->g_flags = GF_VALID;
X		g->g_tfmwidth = t->t_width[UnSign8(ci->ci_width)];
X		if (tfm->tfm_edge != 0) {
X			g->g_xorigin = 0;
X			g->g_yorigin = ftop(t->t_height[T_CI_H(ci)]);
X			g->g_width = ftop(g->g_tfmwidth);
X			g->g_height = g->g_yorigin +
X				ftop(t->t_depth[T_CI_D(ci)]);
X		}
X	}
X	return (0);
X#undef t
X}
X
X/*
X * Obtain rasters for the specified glyphs.
X *
X * IGNORES tfm->tfm_edge: 2 HARDCODED FOR NOW
X */
Xstatic int
Xtfm_rasterise(f, l, h)
X	struct font *f;
X	int l, h;
X{
X	register struct glyph *g;
X	register char *p;
X	register int w, j, i;
X	struct tfm_details *tfm = ftotfm(f);
X#define EDGE 2
X
X	if (tfm->tfm_edge == 0)
X		return;
Xif (tfm->tfm_edge != 2) panic("tfm_rasterise");
X	for (i = l; i < h; i++) {
X		g = f->f_gly[i];
X		if ((g->g_flags & GF_VALID) == 0 || !HASRASTER(g))
X			continue;
X		w = (g->g_width + 7) >> 3;
X		p = malloc((unsigned) (g->g_height * w));
X		if (p == NULL)
X			return (-1);
X		g->g_raster = p;
X		g->g_rotation = ROT_NORM;
X		if (g->g_width < 2 * EDGE) {
X			w = 2 * EDGE - g->g_width;
X			for (j = g->g_height; --j >= 0;)
X				*p++ = 0xf0 << w;
X		} else {
X			bzero(p, g->g_height * w);
X			for (j = 0; j < g->g_height;) {
X				if (j < EDGE || j >= g->g_height - EDGE) {
X					register int k = w;
X
X					while (--k > 0)
X						*p++ = 0xff;
X					*p++ = 0xff << ((8 - g->g_width) & 7);
X					j++;
X					continue;
X				}
X				/* the following depends on EDGE==2 */
X				*p = 0xc0;
X				p += w - ((g->g_width & 7) == 1 ? 2 : 1);
X				*p++ |= 0xc0 >> ((g->g_width - EDGE) & 7);
X				if ((g->g_width & 7) == 1)
X					*p++ = 0x80;
X				/* end dependencies */
X				if (++j == EDGE && g->g_height >= 2 * EDGE) {
X					register int n = g->g_height - EDGE;
X
X					p += (n - j) * w;
X					j = n;
X				}
X			}
X		}
X	}
X	return (0);
X}
X
X/*
X * Discard the font details.
X */
Xstatic
Xtfm_freefont(f)
X	struct font *f;
X{
X
X  free(f->f_details); f->f_details = 0;
X}
END_OF_lib/tfmfont.c
if test 5607 -ne `wc -c <lib/tfmfont.c`; then
    echo shar: \"lib/tfmfont.c\" unpacked with wrong size!
fi
chmod +x lib/tfmfont.c
# end of overwriting check
fi
echo shar: End of archive 6 \(of 6\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    echo "Now do 'make dviselect'"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--
Skip Montanaro (montanaro@crdgw1.ge.com)

wabit@cbnewsm.ATT.COM (david.w.mundhenk) (11/18/89)

Isn't it customary to put a short description of the code
somewhere near the beginning of a posting, or is this
something that, if it's not obvious what it is, I wouldn't
know what to do with it? (It isn't obvious, but I'm curious!)

Thanks,

-- 
Dave Mundhenk [...!att!lc15a!doc]
EMAIL: ...!att!lc15a!doc  | "I can't complain but |   /^,
VOICE: (201)-580-4943     |  sometimes I still do"|  /  } _, , , __
#include <std.disclaimer> |  - Joe Walsh          | /_./ (_l |/ <~_