[alt.sources] dvibook

ajcd@cs.ed.ac.uk (Angus Duggan) (05/22/91)

Can't remember if I've posted this before; this program rearranges TeX's DVI
files into signature ordering, for printing books and booklets. It uses Chris
Torek's DVI library (I have version 2.16.1), available in the SeeTeX
distribution (look around for a local ftp site for this, or ask Dirk Grunwald
(grunwald@edu.colorado.foobar) where to find it.

#! /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 1)."
# Contents:  Imakefile dvibook.c dvibook.man
# Wrapped by ajcd@davaar on Thu Apr 18 20:34:18 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Imakefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Imakefile\"
else
echo shar: Extracting \"Imakefile\" \(608 characters\)
sed "s/^X//" >Imakefile <<'END_OF_Imakefile'
XOBJS	=dvibook.o
XSRCS	=dvibook.c
X
X      LIBTEXROOT= ../
X      LIBTEXSRC	= ../libtex
X         LIBTEX	= $(LIBTEXSRC)/libtex.a
X      DEPLIBTEX	= $(LIBTEX)
X        DEPLIBS = $(DEPLIBTEX) XawClientDepLibs
XLOCAL_LIBRARIES = $(LIBTEX)
X
X        DEFINES = -I$(LIBTEXROOT)
X
XFILES	=Imakefile dvibook.man Makefile.raw $(SRCS)
X
Xall: dvibook
X
XNormalProgramTarget(dvibook,$(OBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),$(SYSLIBS))
XInstallProgram(dvibook, $(BINDIR))
XInstallManPage(dvibook,$(MANDIR))
XDependTarget()
XTagsTarget()
X
Xtar:
X	cd ../..;\
X	for file in $(FILES); \
X	do \
X	  tar rf $(TARFILE) $(PRODUCT)/Dvibook/$$file; \
X	done
END_OF_Imakefile
if test 608 -ne `wc -c <Imakefile`; then
    echo shar: \"Imakefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dvibook.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dvibook.c\"
else
echo shar: Extracting \"dvibook.c\" \(19274 characters\)
sed "s/^X//" >dvibook.c <<'END_OF_dvibook.c'
X/*
X * Copyright (c) 1987, 1989 University of Maryland
X * Department of Computer Science.  All rights reserved.
X * 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: /usr/src/local/tex/local/mctex/dvi/RCS/dviselect.c,v 3.1 89/08/22 17:16:13 chris Exp $";
X#endif
X
X/*
X * DVI page rearrangement program
X *
X * Reads DVI version 2 files and rearranges pages into signatures,
X * writing a new DVI file.
X */
X
X#include "libtex/types.h"
X#include "libtex/dviclass.h"
X#include "libtex/dvicodes.h"
X#include "libtex/error.h"
X#include "libtex/fio.h"
X#include "libtex/gripes.h"
X#include "libtex/search.h"
X#include <stdio.h>
X#include <ctype.h>
X#include "libtex/seek.h"
X
X#define white(x) ((x) == ' ' || (x) == '\t' || (x) == ',')
X
X#define MAXDVIPAGES 1000 /* max (absolute) pages in DVI file */
X
Xchar  *ProgName;
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
Xint     Signature;              /* #pages per signature (multiple of 4) */
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
Xchar	*DVIFileName;		/* name of input DVI file */
XFILE	*inf;			/* the input file itself */
XFILE	*outf;			/* the output DVI file */
X
Xlong	StartOfPage[MAXDVIPAGES];	/* The file positions of the
X					   input pages */
X
Xlong	StartOfLastPage;	/* The file position just before we
X				   started the last page */
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();
X/*
X * You may get lint warnings about sprintf's return value.
X * Older versions of 4BSD have `char *sprintf()'.  ANSI and
X * SysV use `int sprintf()'; so ignore the warnings.
X */
X
X/*
X * Lint gets somewhat confused over putc.
X */
X#ifdef lint
X#undef putc
X#ifdef ultrix /* grr */
X#define putc(c, f) fputc((char)(c), f)
X#else
X#define putc(c, f) fputc((int)(c), f)
X#endif
X#endif
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	OutputFontIndex = -1;	/* new page requires respecifying font */
X	for (i = Count; i < &Count[10]; i++)
X		fGetLong(inf, *i);
X	(void) GetLong(inf);	/* previous page pointer */
X
X	if (!UseThisPage)
X		return;
X
X	putbyte(outf, DVI_BOP);
X	for (i = Count; i < &Count[10]; i++)
X		PutLong(outf, *i);
X	PutLong(outf, StartOfLastPage);
X	if (ferror(outf))
X		error(1, -1, 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, "[%ld", (long)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, ".%ld", (long)*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
X	if (!UseThisPage)
X		return;
X	if (!SFlag)
X		message(0, "]", 1);
X	putbyte(outf, DVI_EOP);
X	if (ferror(outf))
X		error(1, -1, 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 */
Xvoid
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("\\magnification");
X
X	putbyte(outf, DVI_POST);
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	putbyte(outf, DVI_POSTPOST);
X	PutLong(outf, StartOfLastPage);	/* actually start of postamble */
X	putbyte(outf, DVI_VERSION);
X	putbyte(outf, DVI_FILLER);
X	putbyte(outf, DVI_FILLER);
X	putbyte(outf, DVI_FILLER);
X	putbyte(outf, DVI_FILLER);
X	CurrentPosition += 10;
X	while (CurrentPosition & 3) {
X		putbyte(outf, DVI_FILLER);
X		CurrentPosition++;
X	}
X	if (ferror(outf))
X		error(1, -1, 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		putbyte(outf, DVI_FNTDEF1);
X		putbyte(outf, fi->fi_newindex);
X		CurrentPosition += 2;
X	} else if (fi->fi_newindex < 65536) {
X		putbyte(outf, DVI_FNTDEF2);
X		PutWord(outf, fi->fi_newindex);
X		CurrentPosition += 3;
X	} else if (fi->fi_newindex < 16777216) {
X		putbyte(outf, DVI_FNTDEF3);
X		Put3Byte(outf, fi->fi_newindex);
X		CurrentPosition += 4;
X	} else {
X		putbyte(outf, DVI_FNTDEF4);
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	putbyte(outf, fi->fi_n1);
X	putbyte(outf, fi->fi_n2);
X	l = fi->fi_n1 + fi->fi_n2;
X	CurrentPosition += 14 + l;
X	s = fi->fi_name;
X	while (--l >= 0)
X		putbyte(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	c = getc(inf);
X	if (c == EOF)
X		GripeUnexpectedDVIEOF();
X	if (c != DVI_PRE)
X		GripeMissingOp("PRE");
X	if (getc(inf) != DVI_VERSION)
X		error(1, 0, "%s is not a DVI version %d file",
X		    DVIFileName, DVI_VERSION);
X	Numerator = GetLong(inf);
X	Denominator = GetLong(inf);
X	DVIMag = GetLong(inf);
X	putbyte(outf, DVI_PRE);
X	putbyte(outf, DVI_VERSION);
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	putbyte(outf, n);
X	while (--n >= 0) {
X		c = GetByte(inf);
X		putbyte(outf, c);
X	}
X}
X
Xmain(argc, argv)
X	int argc;
X	register char **argv;
X{
X	register int c;
X	register char *s;
X	char *outname = NULL;
X
X	Signature = 0;
X
X	ProgName = *argv;
X	setbuf(stderr, serrbuf);
X
X	while ((c = getopt(argc, argv, "i:o:s:q")) != EOF) {
X		switch (c) {
X
X		case 'q':	/* silent */
X			SFlag++;
X			break;
X
X		case 'i':
X			if (DVIFileName != NULL)
X				goto usage;
X			DVIFileName = optarg;
X			break;
X
X		case 'o':
X			if (outname != NULL)
X				goto usage;
X			outname = optarg;
X			break;
X
X		case 's':
X			if (Signature != 0)
X				goto usage;
X			Signature = atoi(optarg);
X			if (Signature <= 0)
X			   error(1, -1, "-s parameter must be > 0");
X			if (Signature % 4 != 0)
X			   error(1, -1,
X				 "-s parameter must be a multiple of 4");
X			break;
X
X		case '?':
Xusage:
X			(void) fprintf(stderr, "\
XUsage: %s [-s signature] [-q] [-i infile] [-o outfile] [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 (DVIFileName == NULL)
X			DVIFileName = s;
X		else if (outname == NULL)
X			outname = s;
X		else
X			goto usage;
X	}
X	if (DVIFileName == NULL) {
X		DVIFileName = "`stdin'";
X		inf = stdin;
X	} else if ((inf = fopen(DVIFileName, "r")) == 0)
X		error(1, -1, "cannot read %s", DVIFileName);
X	if (outname == NULL)
X		outf = stdout;
X	else if ((outf = fopen(outname, "w")) == 0)
X		error(1, -1, "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	/* copy inf to TEMP file if not seekable */
X	if ((inf = SeekFile(inf)) == NULL) {
X	        error(1, 0, "can't seek file");
X	}
X	InputPageNumber = 0;
X	StartOfLastPage = -1;
X	HandlePreAmble();
X	ScanDVIFile();
X	HandleDVIFile();
X	HandlePostAmble();
X	if (!SFlag)
X		(void) fprintf(stderr, "\nWrote %d page%s, %ld bytes\n",
X		    NumberOfOutputPages, NumberOfOutputPages == 1 ? "" : "s",
X		    (long)CurrentPosition);
X	exit(0);
X	/* NOTREACHED */
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 (!UseThisPage) {
X		if ((fi = (struct fontinfo *)SSearch(FontFinder, index, &def)) == 0)
X			if (def & S_COLL)
X				error(1, 0, "font %ld already defined", (long)index);
X			else
X				error(1, 0, "cannot stash font %ld (out of memory?)",
X					(long)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	} else {
X	        (void) GetLong(inf);
X	        (void) GetLong(inf);
X	        (void) GetLong(inf);
X		i = UnSign8(GetByte(inf));
X		i += UnSign8(GetByte(inf));
X		while (--i >= 0)
X			(void) GetByte(inf);
X	}
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		putbyte(outf, c);
X		switch (l) {
X
X		case DPL_UNS1:
X			putbyte(outf, p);
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			putbyte(outf, i);
X		}
X		if (feof(inf))
X			GripeUnexpectedDVIEOF();
X		if (ferror(outf))
X			error(1, -1, 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 == NULL)
X		error(1, 0, "DVI file requested font %ld without defining it",
X		    (long)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		putbyte(outf, index + DVI_FNTNUM0);
X		CurrentPosition++;
X	} else if (index < 256) {
X		putbyte(outf, DVI_FNT1);
X		putbyte(outf, index);
X		CurrentPosition += 2;
X	} else if (index < 65536) {
X		putbyte(outf, DVI_FNT2);
X		PutWord(outf, index);
X		CurrentPosition += 3;
X	} else if (index < 16777216) {
X		putbyte(outf, DVI_FNT3);
X		Put3Byte(outf, index);
X		CurrentPosition += 4;
X	} else {
X		putbyte(outf, DVI_FNT4);
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 scan the input DVI file and record pointers to the pages.
X */
XScanDVIFile()
X{
X	UseThisPage = 0;
X
X	StartOfPage[InputPageNumber] = ftell(inf);
X	while (HandlePage()) {  /* scan DVI file */
X	        StartOfPage[++InputPageNumber] = ftell(inf);
X	}
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        int CurrentPage, ActualPage, MaxPage;
X
X	UseThisPage = 1;
X
X	MaxPage = InputPageNumber + (4-InputPageNumber%4)%4;
X
X	if (!Signature)
X	        Signature = MaxPage;
X	for (CurrentPage = 0; CurrentPage < MaxPage; CurrentPage++) {
X	        ActualPage = CurrentPage - CurrentPage%Signature;
X	        switch (CurrentPage%4) {
X		case 0:
X		case 3:
X		   ActualPage += Signature-1-(CurrentPage%Signature)/2;
X		   break;
X		case 1:
X		case 2:
X		   ActualPage += (CurrentPage%Signature)/2;
X		   break;
X		}
X	        if (ActualPage < InputPageNumber) {
X		        if (fseek(inf, StartOfPage[ActualPage], 0) == -1)
X		               error(1, -1,
X				     "can't seek page %d", ActualPage+1);
X		        HandlePage();
X		} else
X    	                PutEmptyPage();
X	}
X	if (fseek(inf, StartOfPage[InputPageNumber]+1, 0) == -1)
X	        error(1, -1, "can't seek last page");
X}
X
Xint
XHandlePage()
X{
X	register int c, l;
X	register i32 p;
X	register int CurrentFontOK = 0;
X	int doingpage = 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			putbyte(outf, c);
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 (c == EOF)
X			GripeUnexpectedDVIEOF();
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			putbyte(outf, c);
X			while (--l > 0) {
X				c = getc(inf);
X				putbyte(outf, c);
X			}
X			if (ferror(outf))
X				error(1, -1, 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				putbyte(outf, c);
X				switch (l) {
X
X				case DPL_UNS1:
X					putbyte(outf, p);
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			if (doingpage)
X				GripeUnexpectedOp("BOP (during page)");
X			BeginPage();
X			doingpage = 1;
X			break;
X
X		case DVI_EOP:
X			if (!doingpage)
X				GripeUnexpectedOp("EOP (outside page)");
X			EndPage();
X			doingpage = 0;
X			return(1);
X
X		case DVI_PRE:
X			GripeUnexpectedOp("PRE");
X			/* NOTREACHED */
X
X		case DVI_POST:
X			if (doingpage)
X				GripeUnexpectedOp("POST (inside page)");
X			return(0);
X
X		case DVI_POSTPOST:
X			GripeUnexpectedOp("POSTPOST");
X			/* NOTREACHED */
X
X		default:
X			GripeUndefinedOp(c);
X			/* NOTREACHED */
X		}
X	}
X}
X
X/* write an empty page to fill out space */
XPutEmptyPage()
X{
X        int i;
X
X	putbyte(outf, DVI_BOP);
X	PutLong(outf, -1L);
X	for (i = 1; i < 10; i++)     /* set all sub counts to 0 */
X		PutLong(outf, 0L);
X	PutLong(outf, StartOfLastPage);
X	putbyte(outf, DVI_EOP);
X	if (!SFlag) {		/* write nice page usage messages */
X		char *msg = "[*]";
X		message(1, msg, strlen(msg));
X	}
X	if (ferror(outf))
X		error(1, -1, writeerr);
X
X	StartOfLastPage = CurrentPosition;
X	CurrentPosition += 46;	/* we just wrote this much */
X	NumberOfOutputPages++;
X}
END_OF_dvibook.c
if test 19274 -ne `wc -c <dvibook.c`; then
    echo shar: \"dvibook.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dvibook.man -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dvibook.man\"
else
echo shar: Extracting \"dvibook.man\" \(1308 characters\)
sed "s/^X//" >dvibook.man <<'END_OF_dvibook.man'
X.TH DVIBOOK 1
X.SH NAME
Xdvibook \- rearrange pages in DVI file into signatures
X.SH SYNOPSIS
X.B dvibook
X[
X.B \-q
X] [
X.B \-s\fI<num>
X] [
X.B \-i
X.I infile
X] [
X.B \-o
X.I outfile
X]
X[
X.I infile
X[
X.I outfile
X] ]
X.SH DESCRIPTION
X.I Dvibook
Xrearranges pages from a DVI file produced by TeX into ``signatures'' for
Xprinting books or booklets, creating a new DVI file
Xusable by any of the TeX conversion programs.
X.PP
XThe
X.I \-s
Xoption selects the size of signature which will be used. The signature size is
Xthe number of sides which will be folded and bound together; the number given
Xshould be a multiple of four. The default is to use one signature for the
Xwhole file. Extra blank sides will be added if the file does not contain a
Xmultiple of four pages.
X.PP
XDvibook normally prints the page numbers of the pages rearranged; the
X.I \-q
Xoption suppresses this.
X.SH AUTHOR
XAngus Duggan, from dviselect(1), by
XChris Torek, University of Maryland
X.SH "SEE ALSO"
Xdviconcat(1), dviselect(1), latex(1), tex(1)
X.br
X.I "MC-TeX User's Guide"
X.br
X.I "The TeXbook"
X.I Dvibook
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_dvibook.man
if test 1308 -ne `wc -c <dvibook.man`; then
    echo shar: \"dvibook.man\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 1 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

a.
-- 
Angus Duggan, Department of Computer Science,	| I'm pink, therefore I'm Spam.
University of Edinburgh, JCMB,			| JANET:  ajcd@uk.ac.ed.lfcs
The King's Buildings, Mayfield Road,		| VOICE:  (UK) 031 650 5126
Edinburgh, EH9 3JZ, Scotland.	| OR:  ajcd%lfcs.ed.ac.uk@nsfnet-relay.ac.uk