DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T U

⟦6c45d404a⟧ TextFile

    Length: 161680 (0x27790)
    Types: TextFile
    Notes: Uncompressed file

Derivation

└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
    └─⟦037544301⟧ »./DVIware/obsolete/ln01.sh.Z« 
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦037544301⟧ »DVIware/obsolete/ln01.sh.Z« 
                └─⟦this⟧ 

TextFile

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	ln01
# This archive created: Fri Mar 11 15:55:17 1988
export PATH; PATH=/bin:$PATH
if test ! -d 'ln01'
then
	echo shar: creating directory "'ln01'"
	mkdir 'ln01'
fi
echo shar: entering directory "'ln01'"
cd 'ln01'
if test ! -d 'ln01'
then
	echo shar: creating directory "'ln01'"
	mkdir 'ln01'
fi
echo shar: entering directory "'ln01'"
cd 'ln01'
echo shar: extracting "'Makefile'" '(1642 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
#	ln01 driver routines
#
DEBUGFLAGS = -DDEBUG 
LN01sFLAG = -DLN01s
CFLAGS = -O -c $(DEBUGFLAGS)
PFLAGS = -Pln
LDFLAGS = 

all:	pxltoln01 lndvif makelnentry fonttest

SOURCES = pxltoln01.h pxltoln01.c \
		lndvif.h lndvif.c \
		lncmd.h lncode.h lncode.c lnfile.h lnfile.c \
		makelnentry.c fonttest.c cnvt-plain


PTOLNOBJS = pxltoln01.o lnfile.o lncode.o \
		../utilities.o ../pxlfile.o ../dimen.o ../fontcap.o
PTOLNHEADERS = pxltoln01.h lnfile.h lncode.h \
		../utilities.h ../pxlfile.h ../dimen.h ../fontcap.h

pxltoln01:  $(PTOLNHEADERS) $(PTOLNOBJS)
	    cc -o pxltoln01 $(PTOLNOBJS) $(LDFLAGS)

pxltoln01.o:  $(PTOLNHEADERS) pxltoln01.c 
	    cc $(CFLAGS) pxltoln01.c 


LNDVIFHEADERS = ../paths.h lndvif.h ../utilities.h ../dvifile.h ../pxlfile.h \
		../dimen.h ../fontcap.h lncode.h lncmd.h

LNDVIFOBJS = lndvif.o lncode.o \
		../utilities.o ../dimen.o ../dvifile.o ../pxlfile.o ../fontcap.o

lndvif:	    $(LNDVIFHEADERS) $(LNDVIFOBJS)
	    cc -o lndvif $(LNDVIFOBJS) $(LDFLAGS)

lndvif.o:   $(LNDVIFHEADERS) lndvif.c
	    cc $(CFLAGS) $(LN01sFLAG) lndvif.c


lnfile.o:   lncode.h lnfile.h lnfile.c
	    cc $(CFLAGS) lnfile.c

lncode.o:   lncode.h lncode.c
	    cc $(CFLAGS) lncode.c

MLOBJS = makelnentry.o ../utilities.o 
MLHEADERS = ../utilities.h 

makelnentry.o:	$(MLHEADERS) makelnentry.c
	    cc $(CFLAGS) makelnentry.c

makelnentry: $(MLOBJS)
	    cc $(MLOBJS) -o makelnentry $(LDFLAGS)

fonttest:   ../paths.h fonttest.o lncode.o
	    cc -o fonttest fonttest.o lncode.o $(LDFLAGS)

fonttest.o: lncmd.h lncode.h fonttest.c
	    cc $(CFLAGS) fonttest.c

list:
	    lpr -p $(PFLAGS) $(SOURCES) Makefile

clean:  
	    rm -f *.o
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'cnvt-plain'" '(725 characters)'
if test -f 'cnvt-plain'
then
	echo shar: will not over-write existing file "'cnvt-plain'"
else
cat << \SHAR_EOF > 'cnvt-plain'
#  cnvt-plain    	Samuel W. Bent		8/15/84
#    Convert all the plain TeX fonts to LN01 format.  Argument is magnification.

if ($#argv > 0) then
    set magv = ( $argv )
else
    set magv = 1500
endif
set pxl = pxl
set ln = ln
set pxldir = /usr/public/pxlfonts
set lndir = /usr/public/pxlfonts

echo Reading PXL files from $pxldir --- writing LN files in $lndir
foreach mag ( $magv )
foreach font ( amr10 amr7 amr5 ammi10 ammi7 ammi5 ambx10 ambx7 ambx5 \
			amti10 amex10 amsl10 amtt10 \
			amsy10 amsy7 amsy5 )
    if (-e $pxldir/$font.$mag$pxl) then
	echo $font.$mag$pxl "  -->  " $font.$mag$ln
	pxltoln01 $pxldir/$font.$mag$pxl | conv - > $lndir/$font.$mag$ln
    else
	echo "Can't find " $font.$mag$pxl
    endif
end
end
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'fonttest.c'" '(1828 characters)'
if test -f 'fonttest.c'
then
	echo shar: will not over-write existing file "'fonttest.c'"
else
cat << \SHAR_EOF > 'fonttest.c'
/* This ought to print the characters in a TeX ln01 font */

#include <stdio.h>
#include "../paths.h"
#include "lncmd.h"
#include "lncode.h"

#define LMARG	300
#define TMARG	300
#define BASELINE	300

main(argc,argv)
int argc;
char **argv;
{
int ch;
int count;
int i;
FILE *in, *out;
char buf[1024];
char fontfile[200];
char answer[200];
static char ln01[] = LN01DEVICE;
char *output;
int append, summary;
    if (argc>1) output = argv[1];
      else  output = ln01;
    out = fopen(output,"w");
    if (out==NULL) exit(1);

    for (i=1;;++i) {
	fprintf(stderr,"Font file %d? ",i);
	scanf("%s", fontfile);
	if ((in = fopen(fontfile,"r")) == NULL) {
	    fprintf(stderr,"Can't load font %s \n", fontfile);
	    continue;
	    };
	fprintf(out,LN_RESET);
	fprintf(stderr,"  Append? ");
	scanf("%s", answer);
	append = (*answer=='y' || *answer=='Y');
	fprintf(stderr," Summary? ");
	scanf("%s", answer);
	summary = (*answer=='y' || *answer=='Y');
	if (append && summary)		fprintf(out,LN_APPENDFONT_SUMMARY);
	else if (append && !summary)	fprintf(out,LN_APPENDFONT);
	else if (!append && summary)	fprintf(out,LN_LOADFONT_SUMMARY);
	else if (!append && !summary)	fprintf(out,LN_LOADFONT);
	while((count = fread(buf,1,1024,in)) > 0) {
	    fwrite(buf,1,count,out);
	    };
	fclose(in);
	fprintf(out,LN_ENDLOAD, "Font test");
	fprintf(out,LN_RESET);
	fprintf(out,"\033[11m");	/* seclect portrait font */
	fprintf(out,"\033[3300t\33[0;3300r\33[0;2550s");   /* set margins */
	fprintf(out,"\033P1;19}%-20s\33\134", fontfile);  /* select test font*/
	fprintf(out,"\033[19m");
	fprintf(out,"\033[%d`\33[%dd", LMARG, TMARG);
	for (ch=0;ch<128;++ch) {		/* print a table of the font */
	    if (ch%020==0) fprintf(out,"\033[%d`\33[%de", LMARG, BASELINE);
	    fprintf(out,"%c", lncode[ch]);
	    };
	fprintf(out,"\f\033c");
	fflush(out);
	}
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'lncmd.h'" '(1545 characters)'
if test -f 'lncmd.h'
then
	echo shar: will not over-write existing file "'lncmd.h'"
else
cat << \SHAR_EOF > 'lncmd.h'
/* lncmd.h	Samuel W. Bent		8/6/84 */
/* commands for the LN01
 * The commands are control strings for use with printf.  The expected arguments
 * are indicated in the comments.  For example, to move to x-coord 1500,
 * say printf(LN_XABS,1500)
 */

#define LN_LOADFONT	"\033P1;1y"		/* followed by font record */
#define LN_LOADFONT_SUMMARY "\033P1;0y"		/* ... and print summary page */
#define LN_APPENDFONT	"\033P2;1y"		/* append next font record */
#define LN_APPENDFONT_SUMMARY "\033P2;0y"	/* ... and print summary page */
#define LN_ENDLOAD	";%s\033\\"		/* (comment) */
#define LN_NAMEFONT	"\033P1;1%d}%-20.20s\033\\" /* (number,name) */
#define LN_SELECTFONT	"\033[1%dm"		/* (number) */
#define LN_TOPOFFORM	"\033[%dt"		/* (dist to bottom in PXLs) */
#define LN_VMARGINS	"\033[%d;%dr"		/* (top,bottom) from top */
#define LN_HMARGINS	"\033[%d;%ds"		/* (left,right) from left */
#define LN_XABS		"\033[%d`"		/* (x) */
#define LN_XINCR	"\033[%da"		/* (dx) */
#define LN_YABS		"\033[%dd"		/* (y) */
#define LN_YINCR	"\033[%de"		/* (dy) */
#define LN_RULE		"\033[1;%d;%d;%d;%d!|"	/* (upleftx,uplefty,ht,wd) */
#define LN_NEWPAGE	"\014"			/* eject page */
#define LN_TOGGLEOFFSET	"\033[1!}"		/* shift paper stacker */
#define LN_PXLUNIT	"\033[7 I"		/* distance unit is pixel */
#define LN_RESET	"\033c"			/* reset to default state */

#define LN_ASSIGNEDFONTS 10			/* number of font assignment
							slots */
#ifdef LN01s
#define LN_MAXFONTMEM	400000			/* size of font ram */
#else
#define LN_MAXFONTMEM	193608			/* size of font ram */
#endif

SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'lncode.h'" '(209 characters)'
if test -f 'lncode.h'
then
	echo shar: will not over-write existing file "'lncode.h'"
else
cat << \SHAR_EOF > 'lncode.h'
/* lncode.h	Samuel W. Bent		8/6/84  */
/* Definitions for the TeX interface with the LN01
 */

#define LN_XOFFSET	4	/* Assume ref point lies this many pxls
					right of envelope edge */

extern int lncode[];
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'lncode.c'" '(894 characters)'
if test -f 'lncode.c'
then
	echo shar: will not over-write existing file "'lncode.c'"
else
cat << \SHAR_EOF > 'lncode.c'
/* lncode.c	Samuel W. Bent	8/1/84 */

		/* translate 7-bit codes to 8-bit graphic chars */
int lncode[] = {	
	0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
	0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
	0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
	0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
	0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047,
	0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057,
	0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067,
	0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077,
	0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
	0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
	0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
	0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
	0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147,
	0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157,
	0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167,
	0170, 0171, 0172, 0173, 0174, 0175, 0176, 0300};
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'lndvif.c'" '(39597 characters)'
if test -f 'lndvif.c'
then
	echo shar: will not over-write existing file "'lndvif.c'"
else
cat << \SHAR_EOF > 'lndvif.c'
/* lndvif.c	Samuel W. Bent		7/30/84 */
/* This program reads a DVI file (in type 2 format), and prints the
 * document on the LN01.  It is based on Knuth's dvitype.web, version 2.2.
 * The input file is stdin, the output is stdout;  someone (usually the
 * spooler) should arrange for the desired input file and the LN01 to be
 * associated with these file pointers.
 *
 * The general method is to interpret the DVI commands, maintaining the
 * current position in two ways:  (h,v) - in DVI units, and (hh,vv) -
 * in pixels.  After reading a page, sort the characters and rules by
 * their (vv,hh) values, then send commands to the LN01.
 *
 * Because an LN01 font has no provision for a horizontal offset from the
 * left edge of a character envelope to the reference point, all characters
 * assume a standard offset, LN_XOFFSET.  Any character whose offset exceeds
 * this must be repositioned slightly to the left.
 *
 * The LN01 has only enough memory to hold 10 fonts, so any document
 * that uses more causes font loads in the midst of printing.  In
 * addition, this program writes a log file indicating which fonts are
 * loaded.  If the next document to be printed is also a DVI file, perhaps
 * no font load will be needed;  but if it's a troff file, a font load will
 * certainly be necessary.
 *
 * The LN01s has much more memory, and can load fonts incrementally.  There's
 * a different algorithm for selecting and loading fonts that tries to avoid
 * reloading from scratch unless absolutely necessary.
 */

/* #define DEBUG 	/* Also defined in Makefile */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <strings.h>
#include "../paths.h"
#include "lndvif.h"
#include "../utilities.h"
#include "../dimen.h"
#include "../dvifile.h"
#include "../pxlfile.h"
#include "../fontcap.h"
#include "lncmd.h"
#include "lncode.h"
char PGM_NAME[] = "lndvif";
\f



/* Data structures */

char *namearg = NULL;	/* user who asked for printing */
char *hostarg = NULL;	/* where he came from */
char *acctfile = NULL;	/* where to write accounting line */
int PAGE_WIDTH;		/* width of physical page in pixels */
int PAGE_HEIGHT;	/* height of physical page in pixels */
int dviindex, ln01index; /* indices for dvi file and ln01 */
int pxlcapindex;	/* index for PXL file database */
int lncapindex;		/* index for LN file database */
int curpage;		/* sequence number of current page */
PREAMBLE preamble;	/* preamble of current dvi file */
POSTAMBLE postamble;	/* postamble */
POSTPOSTAMBLE postpostamble; /* postpostamble */
bool inpostamble;	/* true when reading postamble */
long f, h,v, w,x, y,z;	/* DVI registers:  font, position, horiz space amounts,
				vert space amounts */
long hh,vv;		/* position in pixels */
STACKITEM stack[MAXSTACKDEPTH]; /* stack for registers */
int top=0;		/* index of first free position in stack */
FONT *fontp;		/* pointer to current font structure */
FONT *fcache[CACHEFONTS];	/* buckets for first few fonts */
FONT *fontptrarray[TABLEFONTS];	/* unordered table for remaining fonts */
int fpalen;			/* first free slot in fontptrarray */
FONT *allfonts[MAX_FONTS];	/* list of all fonts */
int fonts;			/* number of fonts */
FONT *font_to_load[MAX_FONTS];	/* fonts selected for next font load */
FONT *loadedfont[MAX_FONTS];	/* fonts currently loaded in LN01 */
int loadedfonts;		/* number of loaded fonts */
FONT *fontassignment[LN_ASSIGNEDFONTS]; /* assigning fonts in LN01 */
int nrassigned;			/* number of fonts assigned so far */
long time=0;			/* for stamping fonts for LRU reassignment */
long boptime;			/* time of last BOP */
FONT *lnfontp;			/* current LN01 font */
char rulebuffer[RULEBUFFERSIZE]; /* buffer for rule commands */
OUTCHAR outchardata[MAXCHARS];	/* characters to be printed */
OUTCHAR *outchar[MAXCHARS];	/* pointers to characters to be printed */
int ocindex;			/* number of characters printed this page */
int xx,yy;			/* current LN01 position */
int obchars, obrules;		/* number of out of bounds chars and rules */
OUTCHAR *retry[MAXRETRIES];	/* chars to retry (due to negative kerns) */
int retries;			/* number of chars in current line to retry */
int bigcmds;			/* number of commands causing new record */
int flindex;			/* index of font log file */
char fontlog[MAX_FONTS][MAXLINELENGTH];	/* names of currently loaded fonts */
int fontsize[MAX_FONTS];	/* sizes of currently loaded fonts */
int flsize;			/* number of currently loaded fonts */
int last_flsize;		/* number the last time we updated log */
long fontmem;			/* total size of currently loaded fonts */
bool fonts_reloaded=false;	/* true if we reload LN01 fonts */
bool fonts_changed=false;	/* true if we reload or append fonts */
char summary_line[MAXSUMMARYLINES][OUTLINELENGTH+1]; /* summary messages */
int summary_index;
int Vflg;		/* Print progress reports? */
FILE *Vfp = NULL;	/* where to print progress reports */
char *Vfilename = NULL;	/* where to print progress reports */
#ifdef DEBUG
int dflg;		/* debug level */
int Dflg;		/* printing phase debug level */
bool debugmode;		/* true if debugging, so don't load fonts or change
				system-wide environment (font log, etc.) */
char line[OUTLINELENGTH+1]; /* current line, for debugging */
int lineindex;		/* index into line */
#endif
char *fontlogfile;	/* name of font log file */
int needed;		/* number of fonts needed on current page */
long neededmem;		/* total size of fonts needed on current page */
long needed_newmem;	/* size of fonts that are needed but not loaded */
FONT *font_to_load[MAX_FONTS]; /* pointers to fonts to be loaded next */
int fonts_to_load;	/* number of fonts to be loaded */
bool append_new_fonts;	/* true if fonts should be appended */
\f



main(argc,argv)
int argc;
char **argv;
{
    while (--argc) {
	if (**++argv == '-')
	    set_option(&argc,&argv);
	else
	    acctfile = *argv;
	};
#ifdef DEBUG
    debugmode = (dflg!=0 || Dflg!=0);
#endif
    Initialize();
    read_font_log();
    print_dvi_file();
    finish();
}
\f



set_option(argcp,argvp)
int *argcp;
char ***argvp;
{
    switch ((*argvp)[0][1]) {
    case 'x':
	PAGE_WIDTH = atoi(&(*argvp)[0][2]);
	break;
    case 'y':
	PAGE_HEIGHT = atoi(&(*argvp)[0][2]);
	break;
    case 'n':
	if ((*argvp)[0][2]=='\0') {
	    if (*argcp > 1) {
		--*argcp;
		namearg = *++(*argvp);
		};
	    }
	else {
	    namearg = &((*argvp)[0][2]);
	    };
	break;
    case 'h':
	if ((*argvp)[0][2]=='\0') {
	    if ((*argcp) > 1) {
		(*argcp)--;
		hostarg = *++(*argvp);
		};
	    }
	else {
	    hostarg = &((*argvp)[0][2]);
	    };
	break;
    case 'V':	/* verbose -- tell file what's happening */
	++Vflg;
	Vfilename = &((*argvp)[0][2]);
	break;
#ifdef DEBUG
    case 'd':		/* debug */
	++Vflg;			/* implies V */
	if ((*argvp)[0][2]=='\0')
	    dflg = EVERYPAGE;
	else
	    sscanf( &((*argvp)[0][2]), "%d", &dflg);
	break;
    case 'D':		/* debug */
	++Vflg;			/* implies V */
	if ((*argvp)[0][2]=='\0')
	    Dflg = EVERYFONTASSIGN;
	else
	    sscanf( &((*argvp)[0][2]), "%d", &Dflg);
	break;
#endif
    default:
	break;
    }
}

account(who, from, acctfile)
char *who, *from, *acctfile;
{
register FILE *a;
    if (who == NULL || acctfile == NULL)
	    return;
    if (access(acctfile, 02) || (a = fopen(acctfile, "a")) == NULL)
	    return;
/*
 * LN01 accounting is done by the page;
 */
    fprintf(a, "d%6.2f\t", (float) curpage);
    if (from != NULL)
	    fprintf(a, "%s:", from);
    fprintf(a, "%s\n", who);
    fclose(a);
}
\f



Initialize()
{
int i;
    umask(000);			/* allow anyone to write files we create.
				    The only file affected is the font log. */
    InitializeFiles(&dviindex,&ln01index);	/* prime the file pump */
    if ( (lncapindex=OpenFile(LNCAP,"r")) <0)
	Error(2,"Can't open %s",LNCAP);
    set_device_resolution(DEVICE_RES);		/* set resolution */
    for (i=0;i<MAXCHARS;++i) {			/* initialize pointers */
	outchar[i] = &(outchardata[i]);
	};
    if (Vflg) {				/* set up for progress reports */
	if (Vfilename==NULL || Vfilename[0]=='\0') {
	    Vfp = stderr;
	    }
	else {
	    Vfp = fopen(Vfilename,"w");
	    if (Vfp==NULL) Error(2,"Can't open %s",Vfilename);
	    };
	};
    if (PAGE_HEIGHT==0) PAGE_HEIGHT = DEF_PAGE_HEIGHT; /* set page dimensions */
    if (PAGE_WIDTH==0) PAGE_WIDTH = DEF_PAGE_WIDTH;
    set_pagesize(true);
    fontlogfile = FONTLOG;
#ifdef DEBUG
    if (debugmode) fontlogfile = DEBUG_FONTLOG;
    line[0]='[';			/* initialize debug output */
    lineindex = 1;
#endif
}

set_pagesize(reset)
bool reset;
{
    if (reset) printf(LN_RESET);
    printf(LN_SELECTFONT,1);		/* select ROM portrait font to start */
    printf(LN_TOPOFFORM,PAGE_HEIGHT);	/* set page size and margins */
    printf(LN_VMARGINS,0,PAGE_HEIGHT);
    printf(LN_HMARGINS,0,PAGE_WIDTH);
}

print_summary()
{
int i;
#ifdef DEBUG
    if (Dflg>=EVERYFONTLOAD) {
	fprintf(Vfp, "Font usage:\n");
	for (i=0;i<fonts;++i) {
	    fprintf(Vfp,"  %-20s  %5d chars\n", allfonts[i]->truename, allfonts[i]->chars_in_doc);
	    };
	};
#endif
    if (summary_index==0) return;
    printf(LN_RESET);
    printf(LN_SELECTFONT,1);		/* Print summary in portrait ROM */
    printf("Errors encountered in TeX job for %s at %s:\n\n\n",
	    namearg==NULL? "?": namearg, hostarg==NULL? "?" : hostarg);
    for (i=0;i<summary_index;++i) {
	if (Vflg) fprintf(Vfp, "%s\n", summary_line[i]);
	printf("%s\n", summary_line[i]);
	};
    printf(LN_NEWPAGE);
    summary_index = 0;
}

read_font_log()
{
int len, size;
char line[MAXLINELENGTH];
bool sizeOK = true;
    fontmem = 0;
    flindex = OpenFile(fontlogfile,"r");
    if (flindex<0) {			/* no font log, assume memory full */
	fontmem = LN_MAXFONTMEM+1;
	return;
	};
    ReadFromFile(flindex);
#ifdef DEBUG
    if (Dflg>=EVERYFONTLOAD) fprintf(Vfp, "Font log:\n");
#endif
    for (;;) {				/* read line from font log file */
	len = getline(line, MAXLINELENGTH);
	if (len<=0) break;
	size = 0;
	sscanf(line, "%s %d", fontlog[flsize], &size);
	if (size>0) {			/* should always be true */
	    fontsize[flsize] = size;
	    fontmem += fontsize[flsize];
	    }
	else {			/* just in case someone forgot to write size */
	    sizeOK = false;
	    };
#ifdef DEBUG
	if (Dflg>=EVERYFONTLOAD) 
	    fprintf(Vfp,"  %-20s  %6d\n", fontlog[flsize], fontsize[flsize]);
#endif
	++flsize;
	};
    if (!sizeOK) fontmem = LN_MAXFONTMEM+1; /* missing font will cause reload */
#ifdef DEBUG
    if (Dflg>=EVERYFONTLOAD)
	fprintf(Vfp,"  %-20s  %6d\n", "Available", LN_MAXFONTMEM-fontmem);
#endif
    last_flsize = flsize;
    CloseFile(flindex);
    umask(000);			/* make sure daemon can read this file */
    flindex = OpenFile(fontlogfile,"a");	/* prepare for updates */
}

open_font_log()
{
    if (fonts_reloaded) {
	if (flindex>=0) CloseFile(flindex);
	flindex = OpenFile(fontlogfile,"w");
	};
}

write_font_log()
{
int i;
    if (!fonts_changed) return;	/* Don't bother if we didn't change fonts */
    if (flindex<0) return;	/* if no fontlog file, forget it */
    WriteToFile(flindex);
    for (i=(fonts_reloaded? 0 : last_flsize); i<flsize; ++i) {
	putline("%s\t%6d\n", fontlog[i], fontsize[i]);
	};
    last_flsize = flsize;
    Flush();
    fonts_changed = fonts_reloaded = false;
}

#ifdef DEBUG
dump_font_log()
{
int i;
    for (i=0;i<flsize;++i) {
	fprintf(Vfp,"  %s\t%6d\n", fontlog[i], fontsize[i]);
	};
}
#endif
\f



print_dvi_file()
{
int cmd;
long firstpage;
    ReadFromFile(dviindex);
    GotoByte(0);
    do cmd=GetByte(); while (cmd==NOP);
    if (cmd==PRE) {			/* check for preamble and read it */
	inpostamble = false;
	get_preamble(&preamble);
	set_DVI_dimens(preamble.numerator,
		    preamble.denominator, preamble.magnification);
#ifdef DEBUG
	if (dflg>=EVERYAMBLE) dump_preamble(Vfp,&preamble);
#endif
	firstpage = WhereIsRead();
	preload_fonts();		/* read font definitions */
	GotoByte(firstpage);
	}
    else {
	message("Input is apparently not a DVI file --- no preamble.");
	return;
	};
    do {				/* then read the rest of the file */
	cmd = GetByte();
#ifdef DEBUG
	if (dflg>=EVERYCMD) fprintf(Vfp,"cmd(%d)=%d ", WhereIsRead()-1,cmd);
#endif
	switch (cmd) {
	    case BOP:
		++curpage;
		boptime = time++;
		read_page();
		sort_page();
		print_page();
		break;
	    case NOP:
		break;
	    case FNTDEF1:
		define_font(1,false);
		break;
	    case FNTDEF2:
		define_font(2,false);
		break;
	    case FNTDEF3:
		define_font(3,false);
		break;
	    case FNTDEF4:
		define_font(4,false);
		break;
	    case POST:
		inpostamble = true;
		get_postamble(&postamble);
#ifdef DEBUG
		if (dflg>=EVERYAMBLE) dump_postamble(Vfp,&postamble);
#endif
		break;
	    case POSTPOST:
		get_postpostamble(&postpostamble);
#ifdef DEBUG
		if (dflg>=EVERYAMBLE) dump_postpostamble(Vfp,&postpostamble);
#endif
		break;
	    default:
		Error(2,"Bad command (%o) at byte %d", cmd, WhereIsRead()-1);
		break;
	    };
	} while (cmd!=POSTPOST);
}

read_page()
{
int cmd;
long prevpageptr;
#ifdef DEBUG
    if (debugmode) fprintf(Vfp,"Page %d...\n",curpage);
#endif
    Skip(40);			/* Skip count registers */
    prevpageptr = Get4Byte();	/* remember address of previous page */
    h=v= hh=vv= w=x=y=z = 0;
    top = 0;
    ocindex = 0;
    rulebuffer[0] = '\0';
    obchars = obrules = 0;
    do {			/* Command interpreter */
	cmd = GetByte();
#ifdef DEBUG
	if (dflg>=EVERYCMD) fprintf(Vfp, "cmd(%d)=%d ",WhereIsRead()-1,cmd);
#endif
	if (SETCHAR<=cmd && cmd<SET1) {
	    setchar(cmd,true);
	    continue;
	    };
	if (FNTNUM<=cmd && cmd<FNT1) {
	    changefont(cmd-FNTNUM);
	    continue;
	    };
	switch (cmd) {
	    case SET1: 
		setchar(GetByte(), true);
		break;
	    case SET2: 
		setchar(Get2Byte(), true);
		break;
	    case SET3: 
		setchar(Get3Byte(), true);
		break;
	    case SET4: 
		setchar(Get4Byte(), true);
		break;
	    case SETRULE: 
		setrule(true);
		break;
	    case PUT1: 
		setchar(GetByte(), false);
		break;
	    case PUT2: 
		setchar(Get2Byte(), false);
		break;
	    case PUT3: 
		setchar(Get3Byte(), false);
		break;
	    case PUT4: 
		setchar(Get4Byte(), false);
		break;
	    case PUTRULE: 
		setrule(false);
		break;
	    case NOP: 
		break;
	    case BOP: 
		message("BOP in middle of page at byte %d", WhereIsRead()-1);
		break;
	    case EOP: 
#ifdef DEBUG
		if (dflg>=EVERYLINE) dump_line();
#endif
		break;
	    case PUSH: 
		push();
		break;
	    case POP: 
		pop();
		break;
	    case RIGHT1: 
		hmove(GetByte());
		break;
	    case RIGHT2: 
		hmove(Get2Byte());
		break;
	    case RIGHT3: 
		hmove(Get3Byte());
		break;
	    case RIGHT4: 
		hmove(Get4Byte());
		break;
	    case W0: 
		hmove(w);
		break;
	    case W1: 
		w = GetByte();
		hmove(w);
		break;
	    case W2: 
		w = Get2Byte();
		hmove(w);
		break;
	    case W3: 
		w = Get3Byte();
		hmove(w);
		break;
	    case W4: 
		w = Get4Byte();
		hmove(w);
		break;
	    case X0: 
		hmove(x);
		break;
	    case X1: 
		x = GetByte();
		hmove(x);
		break;
	    case X2: 
		x = Get2Byte();
		hmove(x);
		break;
	    case X3: 
		x = Get3Byte();
		hmove(x);
		break;
	    case X4: 
		x = Get4Byte();
		hmove(x);
		break;
	    case DOWN1: 
		vmove(GetByte());
		break;
	    case DOWN2: 
		vmove(Get2Byte());
		break;
	    case DOWN3: 
		vmove(Get3Byte());
		break;
	    case DOWN4: 
		vmove(Get4Byte());
		break;
	    case Y0: 
		vmove(y);
		break;
	    case Y1: 
		y = GetByte();
		vmove(y);
		break;
	    case Y2: 
		y = Get2Byte();
		vmove(y);
		break;
	    case Y3: 
		y = Get3Byte();
		vmove(y);
		break;
	    case Y4: 
		y = Get4Byte();
		vmove(y);
		break;
	    case Z0: 
		vmove(z);
		break;
	    case Z1: 
		z = GetByte();
		vmove(z);
		break;
	    case Z2: 
		z = Get2Byte();
		vmove(z);
		break;
	    case Z3: 
		z = Get3Byte();
		vmove(z);
		break;
	    case Z4: 
		z = Get4Byte();
		vmove(z);
		break;
	    case FNT1: 
		changefont(GetByte());
		break;
	    case FNT2: 
		changefont(Get2Byte());
		break;
	    case FNT3: 
		changefont(Get3Byte());
		break;
	    case FNT4: 
		changefont(Get4Byte());
		break;
	    case XXX1: 
		special(GetByte());
		break;
	    case XXX2: 
		special(Get2Byte());
		break;
	    case XXX3: 
		special(Get3Byte());
		break;
	    case XXX4: 
		special(Get4Byte());
		break;
	    case FNTDEF1:
		define_font(1,false);
		break;
	    case FNTDEF2:
		define_font(2,false);
		break;
	    case FNTDEF3:
		define_font(3,false);
		break;
	    case FNTDEF4:
		define_font(4,false);
		break;
	    case PRE: 
		message("PRE in middle of page at byte %d", WhereIsRead()-1);
		break;
	    case POST: 
		message("POST in middle of page at byte %d", WhereIsRead()-1);
		break;
	    case POSTPOST: 
		message("POSTPOST in middle of page at byte %d", WhereIsRead()-1);
		break;
	    default:
		message("Unknown opcode %d at byte %d", cmd,WhereIsRead()-1);
		break;
	    };
	} while (cmd != EOP);
    if (obchars>0 || obrules>0) {
	message("Ignored %d characters and %d rules outside page boundaries on page %d",
	    obchars, obrules, curpage);
	};
    return(prevpageptr);
}

vmove(dy)
long dy;
{
    v += dy;
    if (abs(dy)<fontp->vspace) {		/* "small" motion */
	vv += DVItoPXL(dy);
	}
    else {					/* "large" motion */
	vv = DVItoPXL(v);
#ifdef DEBUG
	if (dflg>=EVERYLINE) {
	    dump_line();
	    };
#endif
	};
}

hmove(dx)
long dx;
{
int i;
    h += dx;
    if (abs(dx)<fontp->space) {		/* "small" motion */
	hh += DVItoPXL(dx);
	}
    else {				/* "large" motion */
	hh = DVItoPXL(h);
#ifdef DEBUG
	if (dflg>=EVERYLINE) {
	    append_to_line(' ');
	    for (i=1;i<dx/fontp->size;++i) append_to_line(' ');
	    };
#endif
	};
}

charmove(dh,dhh)
long dh, dhh;
{
    h += dh;
    hh += dhh;
}

setchar(c,moverefpt)
int c;
bool moverefpt;
{
CHAR *cp;
OUTCHAR *ocp;
long xx,yy;
    cp = &(fontp->charinfo[c]);
#ifdef DEBUG
    if (dflg>=EVERYCHAR) {
	fprintf(Vfp,
		"f=%d c=0%o-%c: vh=(%d,%d) vvhh=(%d,%d) wxyz=(%d,%d,%d,%d)\n",
		f,c, 040<=c&&c<=0176 ? (char) c : '?',
		v,h,  vv,hh,  w,x,y,z);
	};
    if (dflg>=EVERYLINE && 041<=c && c<=0176) append_to_line( (char) c);
#endif
    xx = hh+ZERO_X + cp->xcorr-LN_XOFFSET;
    yy = vv+ZERO_Y;
    if (xx>=PAGE_WIDTH || yy>=PAGE_HEIGHT || xx<0 || yy<0) {
	obchars++;
	return;
	};
    ocp = outchar[ocindex++];
    ocp->ch = c;
    ocp->font = f;
    ++(fontp->chars_on_page);
    ocp->yx = Pack(yy,xx);
    if (moverefpt) {
	charmove(cp->dviwidth,cp->pxlwidth);
	};
}

setrule(moverefpt)
bool moverefpt;
{
long height, width;
char buf[100];
int xxul,yyul, xxlr,yylr;
    height = Get4Byte();
    width = Get4Byte();
    xxul = hh+ZERO_X;
    yyul = vv-DVItoRulePXL(height)+ZERO_Y;
    xxlr = xxul + DVItoRulePXL(width);
    yylr = vv+ZERO_Y;
#ifdef DEBUG
    if (dflg>=EVERYCHAR) {
	fprintf(Vfp,
		"Rule: hw=(%d,%d) vh=(%d,%d) vvhh=(%d,%d) wxyz=(%d,%d,%d,%d)\n",
		height,width, v,h, vv,hh, w,x,y,z);
	};
    if (Dflg>=EVERYRULE) 
	fprintf(Vfp,"Rule: yx=(%d,%d) hw=(%d,%d)\n", vv,hh,
			DVItoRulePXL(height),DVItoRulePXL(width) );
#endif
    if (xxlr>=PAGE_WIDTH || yylr>=PAGE_HEIGHT || xxul<0 || yyul<0) {
	obrules++;
	return;
	};
#ifdef DEBUG
    if (dflg>=EVERYPAGE) ++bigcmds;
#endif
    sprintf(buf, LN_RULE, xxul, yyul,
	    yylr-yyul, xxlr-xxul );
    strcat(rulebuffer, buf);
    if (moverefpt) hmove(width);
}

push()
{
STACKITEM * sp;
    if (top>=MAXSTACKDEPTH) Error(2,"Stack overflow at level %d, byte%d",
				top,WhereIsRead()-1);
    sp = &stack[top];
    sp->h = h; sp->v = v;
    sp->w = w; sp->x = x;
    sp->y = y; sp->z = z;
    sp->hh = hh; sp->vv = vv;
    ++top;
}

pop()
{
STACKITEM * sp;
    if (--top<0) Error(2,"Stack underflow at byte %d", WhereIsRead()-1);
    sp = &stack[top];
    h = sp->h;  v = sp->v;
    w = sp->w;  x = sp->x;
    y = sp->y;  z = sp->z;
    hh = sp->hh;  vv = sp->vv;
}

FONT *find_fontp(fontno)
int fontno;
{
int i;
FONT *fontp;
    if (fontno<CACHEFONTS)
	fontp = fcache[fontno];
    else {
	for (i=0;i<fpalen;++i) {
	    if (fontptrarray[i]->number == fontno) {
		fontp = fontptrarray[i];
		break;
		};
	    };
	if (i>=fpalen) {
	    message("Can't find font %d",fontno);
	    };
	};
    return (fontp);
}

changefont(fontno)
int fontno;
{
    f = fontno;
    fontp = find_fontp(fontno);
    fontp->timestamp = time++;
}

define_font(fnlen,really_define)
int fnlen;
bool really_define;
{
FONTDEF fd;
int pxlsize;
char pxlname[MAXNAMESIZE];
char full_pxlname[MAXNAMESIZE];
int pxlindex;
FONT *fp;
char lnname[LNNAME_SIZE];
char full_lnname[MAXNAMESIZE];
int status;
struct stat sbuf;
double pxlmag;
int c;
PXLCHAR *pcp, pxldir[0200];
PXLHEADER pxlhead;
CHAR *cp;
bool using_default;
    get_fontdef(&fd, fnlen);
#ifdef DEBUG
    if (dflg>=EVERYFONTDEF || (inpostamble && dflg>=EVERYAMBLE) ||
		(really_define && Dflg>=EVERYFONTLOAD))
	dump_fontdef(Vfp,&fd);
#endif
    if (!really_define) return;
    				/* select ln file */
    pxlsize = ROUND( (double)preamble.magnification * fd.scalesize/fd.designsize
			* DEVICE_RES/pxlfilePXLperIN );
    ReadFromFile(lncapindex);
    match_lnfile(fd.name,pxlsize, lnname);
    make_pxlname(lnname, pxlname);
    sprintf(full_lnname, "%s/%s", LNPATH, lnname);
    sprintf(full_pxlname, "%s/%s", PXLPATH, pxlname);
    if ( (fp= (FONT *)malloc(sizeof(FONT)))==NULL )
	Error(2,"Cannot allocate memory for %s",pxlname);
    strcpy(fp->truename, lnname);
    fp->missing = false;
    status = stat(full_lnname,&sbuf);
    using_default = false;
    if (status!=0 || (pxlindex=OpenFile(full_pxlname,"r"))<0) {
	using_default = true;
	message("Substituted %s for missing font %s", DEFAULT_FONT, lnname);
	fp->missing = true;
	strcpy(lnname, DEFAULT_FONT);
	make_pxlname(lnname, pxlname);
	sprintf(full_lnname, "%s/%s", LNPATH, lnname);
	sprintf(full_pxlname, "%s/%s", PXLPATH, pxlname);
	status = stat(full_lnname,&sbuf);
	if (status!=0 || (pxlindex=OpenFile(full_pxlname,"r"))<0) {
	    message("Can't open %s",pxlname);
	    finish();
	    };
	};
    ReadFromFile(pxlindex);
    get_pxlheader(&pxlhead);
    if (!using_default &&
      (double) abs(pxlhead.magnification-pxlsize)/pxlsize > SIZE_TOLERANCE) {
	message("Substituted %s for %s.%dpxl -- spacing may be off.",
		pxlname, fd.name, pxlsize);
	fp->missing = true;
	};
				/* read its directory */
    pxlmag = GetRealMag(pxlhead.magnification) * pxlfilePXLperIN / DEVICE_RES;
    GotoByte(pxlhead.directoryptr);
    get_pxldirectory(pxldir);
				/* insert in table */
    if (fd.number<CACHEFONTS)
	fcache[fd.number] = fp;
    else
	fontptrarray[fpalen++] = fp;
				/* fill in font info */
    if (fonts>=MAX_FONTS) {
	message("Too many fonts.");
	finish();
	};
    allfonts[fonts++] = fp;
    fp->number = fd.number;
    strcpy(fp->name,lnname);
    fp->size = fd.scalesize;
    fp->loaded = false;
    fp->timestamp = -fd.number;	/* guess that low number fonts are used first */
    fp->lnno = -1;
    fp->chars_on_page = 0;
    fp->chars_in_doc = 0;
    fp->bytes = 3*(sbuf.st_size)/4;	/* adjust for SIXEL encoding */
    fp->space = fd.scalesize / 6;
    fp->vspace = (5*fd.scalesize) / 6;
				/* fill in character info */
    for (c=0;c<0200;++c) {
	cp = &fp->charinfo[c];  pcp = &pxldir[c];
	cp->xcorr = MIN( -(pcp->xoffset-LN_XOFFSET), 0);
	cp->dviwidth = DUtoDVI(pcp->tfmwidth, fd.scalesize);
	cp->pxlwidth = ROUND( pxlmag *
			FIXtoPXL(DUtoFIX(pcp->tfmwidth, pxlhead.designsize)));
	};
    CloseFile(pxlindex);	/* done with pxl file */
    ReadFromFile(dviindex);	/* return to reading DVI file */
}

special(length)
int length;
{
    Skip(length);
}

preload_fonts()
{
int cmd;
int i,j;
FONT *fp;
    ReadFromFile(dviindex);
    GotoFontdefs();
    do {
	cmd = GetByte();
	switch (cmd) {
	    case FNTDEF1:
		define_font(1,true);
		break;
	    case FNTDEF2:
		define_font(2,true);
		break;
	    case FNTDEF3:
		define_font(3,true);
		break;
	    case FNTDEF4:
		define_font(4,true);
		break;
	    case NOP:
		break;
	    case POSTPOST:
		break;
	    default:
		message("Bad command (0%o) at byte %d in postamble",
			cmd, WhereIsRead()-1);
		break;
	    };
    } while (cmd!=POSTPOST);
    loadedfonts = 0;		/* Mark fonts that are already loaded */
    for (i=0; i<fonts; ++i) {
	fp = allfonts[i];
	for (j=0; j<flsize; ++j) {
	    if (strcmp(fp->name,fontlog[j])==0) {
		loadedfont[loadedfonts++] = fp;
		fp->loaded = true;
		break;
		};
	    };
	};
}

sort_page()
{
OUTCHAR *ocp;
int i,j, t;
long key;
int swaps;
    swaps = 0;
    for (t=ocindex; t>1; ) {			/* Shellsort */
	if (t<5) t = 1;
	  else   t = (5*t-1)/11;
	for (j=t; j<ocindex; ++j) {
	    ocp = outchar[j];
	    key = ocp->yx; 
	    for (i=j-t; i>=0 && outchar[i]->yx>key; i-=t) {
		outchar[i+t] = outchar[i];
		++swaps;
		};
	    outchar[i+t] = ocp;
	    };
	};
#ifdef DEBUG
    if (dflg>=EVERYPAGE)
	fprintf(Vfp, "%d chars, shellsort made %d swaps\n", ocindex, swaps);
#endif
}

print_page()
{
int index, tmp;
OUTCHAR *ocp;
#ifdef DEBUG
    if (dflg>=EVERYPAGE) bigcmds = 0;
#endif
    load_fonts();			/* ensure the fonts are present */
    printf("%s",rulebuffer);
    f = MAXINT;
    xx=yy=MAXINT;
    for (index=0; index<ocindex; ++index) {
	ocp = outchar[index];
	print_char(ocp);
	};
    flush_retries();
    printf(LN_NEWPAGE);  ++bigcmds;
#ifdef DEBUG
    if (debugmode) {
	fprintf(Vfp, "...page %d  (%d big commands)\n", curpage, bigcmds);
	};
#endif
}

load_fonts()
{
int i, missing_chars;
char mcfonts[800];
FONT *fp;
    neededmem = needed_newmem = 0; /* find out how much font memory is needed */
    needed = 0;
    for (i=0;i<fonts;++i) {
	if (allfonts[i]->chars_on_page > 0) {
	    neededmem += allfonts[i]->bytes;
	    if (!allfonts[i]->loaded) {
		needed_newmem += allfonts[i]->bytes;
		};
	    fp = allfonts[needed];		/* move needed fonts to front */
	    allfonts[needed] = allfonts[i];
	    allfonts[i] = fp;
	    ++needed;
	    };
	};
    choose_fonts_to_load();
    download_fonts();
    missing_chars = 0;
    strcpy(mcfonts, "");
    for (i=0; i<needed; ++i) {
	fp = allfonts[i];
	if (fp->missing) {		/* check for missing fonts */
	    missing_chars += fp->chars_on_page;
	    strcat(mcfonts, fp->truename);
	    strcat(mcfonts, " ");
	    };
	fp->chars_in_doc += fp->chars_on_page; /* accumulate reference counts */
	fp->chars_on_page = 0;
	};
    if (missing_chars>0) {
	message("Page %d: substituted for %d characters from fonts %s",
	    curpage, missing_chars, mcfonts);
	};
}

download_fonts()
{
int i;
FONT *fp;
char comment[150];
    if (fonts_to_load==0) return;	/* don't do unnecessary work */
    if (append_new_fonts) {		/* if appending */
	for (i=0;i<loadedfonts;++i) {		/* deassign font IDs */
	    fp = loadedfont[i];
	    fp->lnno = -1;
	    };
	fonts_changed = true;
	}
    else {				/* if reloading */
	for (i=0;i<loadedfonts;++i) {		/* unload current fonts */
	    fp = loadedfont[i];
	    fp->loaded = false;
	    fp->lnno = -1;
	    };
	loadedfonts = 0;
	flsize = 0;				/* also in fontlog */
	fontmem = 0;
	fonts_reloaded = true;
	fonts_changed = true;
	};
    open_font_log();			/* deletes font log, if reloading */
    nrassigned = 0;				/* deassign all font IDs */
#ifdef DEBUG
    if (Dflg>=EVERYFONTLOAD) fprintf(Vfp,"%s %d fonts: ",
		    append_new_fonts? "Appending" : "Loading", fonts_to_load);
#endif
    if (append_new_fonts)			 /* load new ones */
	printf(LN_APPENDFONT);
    else
	printf(LN_LOADFONT);
    for (i=0; i<fonts_to_load; ++i) {		/* for each font to load */
	fp = font_to_load[i];
	loadedfont[loadedfonts++] = fp;		/* remember it's loaded */
	fp->loaded = true;
	strcpy(fontlog[flsize],fp->name);	/* and add to font log */
	fontsize[flsize++] = fp->bytes;
	fontmem += fp->bytes;
#ifdef DEBUG
	if (Dflg>=EVERYFONTLOAD) fprintf(Vfp,"%s ",fp->name);
	if (!debugmode) {	/* don't load if only debugging */
	    send_font_record(fp);
	    };
#else
	send_font_record(fp);			/* ship the font record */
#endif
	};
#ifdef DEBUG
    if (Dflg>=EVERYFONTLOAD) fprintf(Vfp,"\n");
#endif
    sprintf(comment, "TeX fonts for %s at %s", namearg, hostarg);
    printf(LN_ENDLOAD, comment);
    write_font_log();
    set_pagesize(false);
    lnfontp = NULL;		/* LN01 has no current assigned font */
}

/* This procedure selects fonts to be loaded, and decides if they
 * can be appended to the current fonts or if the whole font memory
 * must be reloaded.
 * The procedure makes the following assumptions:
 *	allfonts[..] - contains pointers to all the fonts, with the ones
 *			needed on the current page appearing first.
 *	needed - counts how may fonts are needed on current page.
 *	fontmem - total size in bytes of currently loaded fonts.
 *	neededmem - size of fonts needed on current page.
 *	needed_newmem - size of fonts needed but not currently loaded.
 * It returns its answer as follows:
 *	font_to_load[..] - pointers to fonts that should be loaded
 *	fonts_to_load - how many fonts should be loaded
 *	append_new_fonts - true if fonts can be appended (LN01s only)
 */
choose_fonts_to_load()
{
FONT *fp;
int cutoff, cumul_size, newmem;
int i, j, cmd;
long save_position;
int key;
char *reason;
static char too_many[] = "Too many fonts";
static char too_big[] = "Font memory exceeded";
int nlchars;
char nlfonts[800];
bool newfonts;
#ifdef DEBUG
    if (Dflg>=EVERYFONTLOAD) {
	fprintf(Vfp,"Need %d fonts (%d bytes, %d new).  Available font memory = %d\n",
	    needed, neededmem, needed_newmem, LN_MAXFONTMEM-fontmem);
	};
#endif
    fonts_to_load = 0;
    append_new_fonts = false;
    if (needed_newmem==0) return;	/* no new fonts needed */
#ifdef LN01s
    if (fontmem+needed_newmem <= LN_MAXFONTMEM) { /* if new fonts fit */
	for (i=0;i<needed;++i) {			/* select new ones */
	    if (!allfonts[i]->loaded)
		font_to_load[fonts_to_load++] = allfonts[i];
	    };
	append_new_fonts = true;			/* and append them */
	}
    else if (neededmem<=LN_MAXFONTMEM) {	/* if needed fonts fit */
	for (i=0;i<needed;++i) {			/* select them */
	    font_to_load[fonts_to_load++] = allfonts[i];
	    };
	append_new_fonts = false;			/* and reload them */
	}
    else {		/* needed fonts don't fit, so select most frequent */
	for (i=1; i<needed; ++i) {		/* insertion sort */
	    fp = allfonts[i];
	    key = fp->chars_on_page + LBONUS*(fp->loaded?1:0);
	    for (j=i-1; j>=0; --j) {
		if (allfonts[j]->chars_on_page+LBONUS*(fp->loaded?1:0) > key)
		    allfonts[j+1] = allfonts[j];
		else break;
		};
	    allfonts[j+1] = fp;
	    };
	cumul_size = newmem = 0;
	cutoff = 0;
	for (i=0;i<needed;++i) {		/* select while there's room */
	    fp = allfonts[i];
	    cumul_size += fp->bytes;
	    if (cumul_size<=LN_MAXFONTMEM) {
		font_to_load[fonts_to_load++] = fp;
		if (!fp->loaded) newmem += fp->bytes;
		++cutoff;
		}
	    else break;
	    };
	if (fontmem + newmem <= LN_MAXFONTMEM) {   /* if new fonts will fit */
	    j = fonts_to_load;
	    fonts_to_load = 0;
	    for (i=0;i<j;++i) {				/* select only them */
		fp = font_to_load[i];
		if (!fp->loaded) font_to_load[fonts_to_load++] = fp;
		};
	    append_new_fonts = true;
	    }
	else append_new_fonts = false;			/* otherwise, reload */
	reason = too_big;
	if (cutoff<needed) {	/* Can't load all the fonts needed */
	    nlchars = 0;
	    strcpy(nlfonts, "\0");
	    for (i=cutoff; i<needed; ++i) {
		nlchars += allfonts[i]->chars_on_page;
		strcat(nlfonts, allfonts[i]->truename);
		strcat(nlfonts, " ");
		};
	    message("%s on page %d;  ignored %d characters from fonts %s",
			reason, curpage, nlchars, nlfonts);
	    };
	};
#else
    if (needed<=LN_MAXLOADEDFONTS && neededmem<=LN_MAXFONTMEM) {
	cumul_size = 0;			/* needed fonts fit, so load them */
	for (i=0;i<needed;++i) {
	    fp = allfonts[i];
	    fp->toload = true;
	    cumul_size += fp->bytes;
	    font_to_load[i] = fp;
	    };
	cutoff = needed;
	ReadFromFile(dviindex);		/* now try to load next used fonts too*/
	save_position = WhereIsRead();	/* remember where we are */
	do {				/* look ahead */
	    cmd = GetByte();
	    if (SETCHAR<=cmd && cmd<SET1) {	/* ignore characters */
		continue;
		};
	    if (FNTNUM<=cmd && cmd<FNT1) {	/* wake up for font switches */
		fp = find_fontp(cmd-FNTNUM);
		goto fontswitch;
		};
	    switch (cmd) {		/* wake up for font switches */
		case FNT1:
		    fp = find_fontp(GetByte());
		    goto fontswitch;
		case FNT2:
		    fp = find_fontp(Get2Byte());
		    goto fontswitch;
		case FNT3:
		    fp = find_fontp(Get3Byte());
		    goto fontswitch;
		case FNT4:
		    fp = find_fontp(Get4Byte());
		    goto fontswitch;
		case EOP: 	/* a whole page fits, so update cutoff */
		    fonts_to_load = cutoff;
		    if (fonts_to_load==LN_MAXLOADEDFONTS) cmd = POST; 
				/* stop looking if we've filled all the slots */
		    break;
				/* ignore everything else */
		case BOP:
		    Skip(44); break;
		case NOP: case PRE: case POST: case POSTPOST: 
		case PUSH: case POP: case W0: case X0: case Y0: case Z0: 
		    break;
		case SET1: case PUT1: case RIGHT1: case DOWN1: 
		case W1: case X1: case Y1: case Z1:
		    Skip(1); break;
		case SET2: case PUT2: case RIGHT2: case DOWN2: 
		case W2: case X2: case Y2: case Z2:
		    Skip(2); break;
		case SET3: case PUT3: case RIGHT3: case DOWN3: 
		case W3: case X3: case Y3: case Z3:
		    Skip(3); break;
		case SET4: case PUT4: case RIGHT4: case DOWN4: 
		case W4: case X4: case Y4: case Z4:
		    Skip(4); break;
		case SETRULE: case PUTRULE:
		    Skip(8); break;
		case XXX1: 
		    Skip(GetByte()); break;
		case XXX2: 
		    Skip(Get2Byte()); break;
		case XXX3: 
		    Skip(Get3Byte()); break;
		case XXX4: 
		    Skip(Get4Byte()); break;
		case FNTDEF1:
		    Skip(13);  Skip(GetByte()+GetByte()); break;
		case FNTDEF2:
		    Skip(14);  Skip(GetByte()+GetByte()); break;
		case FNTDEF3:
		    Skip(15);  Skip(GetByte()+GetByte()); break;
		case FNTDEF4:
		    Skip(16);  Skip(GetByte()+GetByte()); break;
		default:
		    Error(2, "Bad command %d near byte %d", cmd, WhereIsRead());
		    break;
		};
	    continue;		/* most commands just keep looping */
fontswitch:			/*  except font switches */
	    if (fp->toload) continue;	/* already seen this font */
	    font_to_load[cutoff++] = fp;	/* append new one */
	    fp->toload = true;
	    cumul_size += fp->bytes;	/* accumulate total font memory */
	    if (cutoff>LN_MAXLOADEDFONTS || cumul_size>LN_MAXFONTMEM) {
		break;		/* stop looking on overflow, and
				    use cutoff from previous page */
		};
	    if (cutoff==fonts) {	/* all the fonts fit! */
		fonts_to_load = cutoff;
		break;
		};
	    } while (cmd!=POST);
	GotoByte(save_position);	/* go back to where we were */
	fonts_to_load = cutoff;
	for (i=0; i<cutoff; ++i) {	/* unmark all fonts */
	    font_to_load[i]->toload = false;
	    };
	}
    else {		/* needed fonts don't fit - load most frequent ones */
	for (i=1; i<needed; ++i) {		/* insertion sort */
	    fp = allfonts[i];
	    key = fp->chars_on_page + LBONUS*(fp->loaded?1:0);
	    for (j=i-1; j>=0; --j) {
		if (allfonts[j]->chars_on_page+LBONUS*(fp->loaded?1:0) > key)
		    allfonts[j+1] = allfonts[j];
		else break;
		};
	    allfonts[j+1] = fp;
	    };
	cutoff = needed;
	cumul_size = 0;				/* add up sizes */
	for (i=0;i<needed;++i) {
	    cumul_size += allfonts[i]->bytes;
	    if (cumul_size>LN_MAXFONTMEM) {
		cutoff = i;
		reason = too_big;
		break;
		};
	    };
	if (cutoff>LN_MAXLOADEDFONTS) {	/* but don't load too many fonts */
	    cutoff = LN_MAXLOADEDFONTS;
	    reason = too_many;
	    };
	newfonts = false;
	for (i=0; i<cutoff; ++i) {		/* mark fonts to load */
	    font_to_load[i] = allfonts[i];
	    if (!font_to_load[i]->loaded) newfonts = true;
	    };
	if (newfonts)	fonts_to_load = cutoff;	/* maybe no new fonts to load */
	else		fonts_to_load = 0;
	if (cutoff<needed) {	/* Can't load all the fonts needed */
	    nlchars = 0;
	    strcpy(nlfonts, "\0");
	    for (i=cutoff; i<needed; ++i) {
		nlchars += allfonts[i]->chars_on_page;
		strcat(nlfonts, allfonts[i]->truename);
		strcat(nlfonts, " ");
		};
	    message("%s on page %d;  ignored %d characters from fonts %s",
			reason, curpage, nlchars, nlfonts);
	    };
	};
#endif
}

send_font_record(fp)
FONT *fp;
{
int count;
FILE *in, *out;
char buf[1024];
    sprintf(buf, "%s/%s", LNPATH, fp->name);
    if ((in = fopen(buf,"r")) == NULL) {
	message("Can't load font %s \n", buf);
	return;
	};
    out = stdout;
    while((count = fread(buf,1,1024,in)) > 0) {
	fwrite(buf,1,count,out);
	};
    fclose(in);
}

print_char(ocp)
OUTCHAR *ocp;
{
int tmp;
bool newline;
    if (ocp->font!=f) changefont(ocp->font);
    if (!fontp->loaded) return; /* ignore chars whose fonts aren't loaded */
    newline = false;
    if (Left(ocp->yx)!=yy) {
	flush_retries();
	newline = true;
	tmp = Left(ocp->yx);
	if (tmp>yy)	printf(LN_YINCR, tmp-yy);
	  else		printf(LN_YABS, tmp);
	yy = tmp;
#ifdef DEBUG
	if (dflg>=EVERYPAGE) ++bigcmds;
#endif
	};
    if (Right(ocp->yx)!=xx) {
	tmp = Right(ocp->yx);
	if (tmp>xx)
	    printf(LN_XINCR, tmp-xx);
	else {
	    if (newline) {
		printf(LN_XABS, tmp);
#ifdef DEBUG
		if (dflg>=EVERYPAGE) ++bigcmds;
#endif
		}
	    else {			/* negative kern */
		retry[retries++] = ocp;
		return;
		};
	    };
	xx = tmp;
	};
    if (ocp->font!=f) changefont(ocp->font); /* retries may have changed font */
    if (lnfontp != fontp) select_lnfont();
    printf("%c",lncode[ocp->ch]);
#ifdef DEBUG
    if (Dflg>=EVERYPOS) fprintf(Vfp,"(%d,%d)", yy,xx);
    if (Dflg>=EVERYOUTFONT) fprintf(Vfp,"[%d]",ocp->font);
    if (Dflg>=EVERYOUTCHAR) fprintf(Vfp,"%c",lncode[ocp->ch]);
#endif
    xx += fontp->charinfo[ocp->ch].pxlwidth;
}

flush_retries()
{
int oldretries, rindex;
int saveDflg;
    if (retries==0) return;
#ifdef DEBUG
    if (Dflg>=EVERYRETRY) {
	fprintf(Vfp,"Retry: {");
	saveDflg = Dflg;
	Dflg = MAX(Dflg,EVERYOUTCHAR);
	};
#endif
    while (retries>0) {
	oldretries = retries;
	retries = 0;
	xx = Right(retry[0]->yx);
	printf(LN_XABS, xx);
#ifdef DEBUG
	if (Dflg>=EVERYRETRY) fprintf(Vfp," [%d,%d] ", yy,xx);
	if (dflg>=EVERYPAGE) ++bigcmds;
#endif
	for (rindex=0; rindex<oldretries; ++rindex) {
	    print_char(retry[rindex]);
	    };
	};
#ifdef DEBUG
    if (Dflg>=EVERYRETRY) {
	fprintf(Vfp,"}\n");
	Dflg = saveDflg;
	};
#endif
}

select_lnfont()
{
int index;
int i;
long lru;
    index = fontp->lnno;
    if (index<0) {		/* if not assigned ... */
	if (nrassigned<LN_ASSIGNEDFONTS) {	/* use a free slot */
	    index = nrassigned++;
	    fontp->lnno = index;
	    }
	else {				/* or replace least recently used */
	    lru = MAXINT;
	    for (i=0;i<LN_ASSIGNEDFONTS;++i) {
		if (fontassignment[i]->timestamp < lru) {
		    index = i;  lru = fontassignment[i]->timestamp;
		    };
		};
	    fontp->lnno = index;
	    fontassignment[index]->lnno = -1;	/* mark unassigned */
	    };
	fontassignment[index] = fontp;
	printf(LN_NAMEFONT, fontp->lnno, fontp->name);
#ifdef DEBUG
	if (Dflg>=EVERYFONTASSIGN)
	    fprintf(Vfp,"Assigned %d to %s\n", fontp->lnno, fontp->truename);
#endif
	};
			/* Assert:  index = fontp->lnno */
    printf(LN_SELECTFONT,index);
    lnfontp = fontp;
}

message(format, a1,a2,a3,a4,a5,a6,a7,a8)
char *format;
{
char str[10*OUTLINELENGTH];
int i;
    sprintf(str, format, a1,a2,a3,a4,a5,a6,a7,a8);
    for (i=0;i<strlen(str);i+=OUTLINELENGTH) {
	strncpy(summary_line[summary_index],&str[i],OUTLINELENGTH);
	summary_line[summary_index++][OUTLINELENGTH] = '\0';
	};
    if (Vflg) fprintf(Vfp,"%s\n", str);
}

#ifdef DEBUG
append_to_line(c)
char c;
{
    line[lineindex++] = c;
    if (lineindex==OUTLINELENGTH) {
	line[lineindex] = '\0';
	fprintf(Vfp,"%s\n",line);
	strcpy(line,"     ... ");
	lineindex = 9;
	};
}

dump_line()
{
    if (lineindex>1) {
	append_to_line(']');
	line[lineindex] = '\0';
	fprintf(Vfp,"%s\n",line);
	line[0]='[';
	lineindex = 1;
	};
}

dump_outchar(fp,ocp)
FILE *fp;
OUTCHAR *ocp;
{
    fprintf(fp,"(0%o,%d,%d,%d)",ocp->ch,ocp->font,Left(ocp->yx),Right(ocp->yx));
}
#endif

finish()
{
    print_summary();
    printf(LN_TOGGLEOFFSET);		/* spooler really should do this */
    fflush(stdout);
    account(namearg, hostarg, acctfile);
    open_font_log();
    write_font_log();
    exit(0);
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'lndvif.h'" '(2982 characters)'
if test -f 'lndvif.h'
then
	echo shar: will not over-write existing file "'lndvif.h'"
else
cat << \SHAR_EOF > 'lndvif.h'
/* lndvif.h	Samuel W. Bent		8/2/84 */
/* Constants for lndvif.c
 */

typedef int bool;
#define true	 1
#define false	 0
#define MAXINT	 2147483647
#define  MIN(A, B)   ((A) < (B) ? (A):(B) )
#define  MAX(A, B)   ((A) > (B) ? (A):(B) )

#define DEFAULT_FONT "amr10.1500ln"

#define MAX_FONTS 64		/* maximum number of fonts in one document */
#define LN_MAXLOADEDFONTS 10	/* number of TeX fonts LN01 can load at once */
#define MAXSTACKDEPTH 51	/* stack size */
#define MAXNAMESIZE 80		/* length of file names */
#define LNNAME_SIZE 21		/* length of LN01 internal font name */
#define MAXSUMMARYLINES 50	/* number of summary lines */
#define OUTLINELENGTH 79	/* length of output lines */
#define CACHEFONTS 64		/* store first few fonts in buckets */
#define TABLEFONTS MAX_FONTS	/* remaining fonts in unordered table */
#define MAXCHARS 15000		/* number of characters per page */
#define MAXRETRIES 100		/* number of negative kerns per line */
#define RULEBUFFERSIZE 5000	/* length of buffer for rule commands */
#define SIZE_TOLERANCE 0.05	/* relative error for mag selection */
#define LBONUS 15		/* a loaded font is worth this many chars */

#define DEVICE_RES 300		/* LN01 prints 300 pixels/inch */
#define ZERO_X  300		/* x coord of (0,0) point (1" from edge) */
#define ZERO_Y  300		/* y coord of (0,0) point (1" from edge) */
#define DEF_PAGE_WIDTH  2550	/* maximum x pixel */
#define DEF_PAGE_HEIGHT  3300	/* maximum y pixel */

typedef struct {long h,v,w,x,y,z,hh,vv} STACKITEM;

typedef struct {	    /* A character in a font */
	long dviwidth;		/* width in DVIs */
	long pxlwidth;		/* width in PXLs */
	int xcorr;		/* PXLs to move left to align ref pt */
	} CHAR;

typedef struct {	    /* A font */
	int number;		/* Number, from DVI file */
	char name[LNNAME_SIZE];	/* Name within LN01 */
	char truename[LNNAME_SIZE]; /* Name user thinks it's called */
	long size;		/* (Scaled) size in DVIs */
	bool loaded;		/* True when downloaded to LN01 */
	bool toload;		/* Tre when selected for next font load */
	int lnno;		/* Assigned number within LN01, or <0 */
	int timestamp;		/* Time when last invoked */
	int chars_on_page;	/* Number of chars on current page */
	int chars_in_doc;	/* Number of chars in document */
	bool missing;		/* True if can't find font or right mag */
	long bytes;		/* Size of font record in bytes */
	long space;		/* Threshold for "large" space, in DVIs */
	long vspace;		/* Same for vertical space */
	CHAR charinfo[0200];	/* The characters themselves */
	} FONT;

typedef struct {	    /* A character ready to be printed */
	long yx;		/* (y,x) position:  y<<16 | x */
	int font;		/* DVI font number */
	short ch;		/* Positon in font */
	} OUTCHAR;

#define EVERYAMBLE 1		/* debugging levels */
#define EVERYPAGE 2
#define EVERYLINE 3
#define EVERYFONTDEF 4
#define EVERYCHAR 5
#define EVERYCMD 6

#define EVERYFONTLOAD 1
#define EVERYFONTASSIGN 2
#define EVERYRETRY 3
#define EVERYOUTCHAR 4
#define EVERYRULE 5
#define EVERYOUTFONT 6
#define EVERYPOS 7
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'lnfile.h'" '(1748 characters)'
if test -f 'lnfile.h'
then
	echo shar: will not over-write existing file "'lnfile.h'"
else
cat << \SHAR_EOF > 'lnfile.h'
/* lnfile.h		Samuel W. Bent		7/17/84 */
/* Declarations common to programs that use LN01 font files */

#include "lncode.h"

/* Constants */

#define LN_HEADERBYTE	0xAA
#define LN_HEADERLENGTH	48
#define LN_TRAILERBYTE	0x55
#define LN_TRAILERLENGTH	8
#define LN_FC		040
#define LN_LC		lncode[0177]
#define LN_SP_ADDR	(LN_HEADERLENGTH+(LN_LC+1)*8)
#define LN_PORTRAIT	0
#define LN_LANDSCAPE	1
#define LN_FIXEDWIDTH	0
#define LN_VARWIDTH	2

/* Types */
typedef short	byte;

typedef struct {	/* info global to an LN01 font file */
    byte    rlev;		/* revision level */
    byte    aspect;		/* portrait/landscape + fixed/variable width */
    short   fsize;		/* length of file-header (bytes) */
    char    name[20];		/* name */
    byte    udist;		/* underline distance */
    byte    uthick;		/* underline thickness */
    byte    sdist;		/* stroke-through distance */
    byte    sthick;		/* stroke-through thickness */
    byte    supdist;		/* superscript distance */
    byte    subdist;		/* subscript distance */
    short   depth;		/* max depth */
    short   height;		/* max height */
    short   baseline;		/* baseline distance */
    byte    firstc;		/* first character code */
    byte    lastc;		/* last character code */
    char    partno[5];		/* part number */
    char    null[3];		/* null */
    } LNHEADER;

typedef struct {		/* LN01 character */
    short   count;		/* number of bytes in bitmap */
    int	    bitp;		/* address of bitmap (bytes) */
    byte    seg;		/* segment (always '377) */
    byte    height;		/* height of bitmap (bytes) */
    byte    offset;		/* y dist from ref pt to LL corner (2 bits) */
    byte    width;		/* char width (pxls) */
    byte    off_adj;		/* 1 if offset is odd, 0 if even */
    } LNCHAR;
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'lnfile.c'" '(1056 characters)'
if test -f 'lnfile.c'
then
	echo shar: will not over-write existing file "'lnfile.c'"
else
cat << \SHAR_EOF > 'lnfile.c'
/* lnfile.c	Samuel W. Bent		7/30/84 */

#include <stdio.h>
#include "lncode.h"
#include "lnfile.h"

/* Printing routines (for debugging) */

dump_lnheader(hp)
LNHEADER *hp;
{
int i;
    fprintf(stderr,"rlev=%d aspect=0%o size=%d name='%.20s'\n",
	    hp->rlev,hp->aspect,hp->fsize,hp->name);
    fprintf(stderr,"  udist=%d uthick=%d sdist=%d sthick=%d supdist=%d subdist=%d\n",
	    hp->udist,hp->uthick,hp->sdist,hp->sthick,hp->supdist,hp->subdist);
    fprintf(stderr,"  depth=%d height=%d bl=%d fc=0%o lc=0%o partno=(",
	    hp->depth,hp->height,hp->baseline,hp->firstc,hp->lastc);
    for (i=0;i<4;++i) fprintf(stderr,"%d,",hp->partno[i]);
    fprintf(stderr,"%d)\n",hp->partno[4]);
}

dump_lnchar(lnchp)
LNCHAR *lnchp;
{
    fprintf(stderr,"count=%d bitp=%d ht=%d off=%d+%d wd=%d\n",
	    lnchp->count,lnchp->bitp,lnchp->height,
	    lnchp->offset,lnchp->off_adj,lnchp->width);
}

dump_lndir(dir)
LNCHAR dir[];
{
int ch;
    for (ch=LN_FC;ch<=LN_LC;++ch) {
	fprintf(stderr,"0%o-%c: ",ch, (040<ch && ch<0177)? ch : '?');
	dump_lnchar(&dir[ch]);
	};
}

SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'makelnentry.c'" '(3852 characters)'
if test -f 'makelnentry.c'
then
	echo shar: will not over-write existing file "'makelnentry.c'"
else
cat << \SHAR_EOF > 'makelnentry.c'
/* makelnentry - create lnfont database entries	Sam Bent  5/25/84 */

/* This program examines each argument (assuming each to be the name of a
 * font raster file in LN01 format), and forms an entry suitable for
 * the lnfont database, 'lncap'.
 * It sends the results to stdout.  The intended use is
 *		makelnentry *.ln > /usr/lib/tex/fonts/lncap
 * 
 * A typical entry in the database, illustrating its format is
 *	amr10|Ten point text roman:\
 *		:1500:1643:1800:
 * meaning a font named 'amr10' (with a comment describing it) exists
 * at magnifications 1, 1.095 and 1.2.
 *
 * Options:
 *	-i	(interactive) Ask user for a comment for each font.
 *	-v	(verbose) Print progress reports on stderr.
 */

/* #define DEBUG */
#include <stdio.h>
#include "../utilities.h"
char PGM_NAME[] = "makelnentry";

#define MAXNAMELENGTH	100	/* length of file names */
#define	MAXENTRIES	10	/* number of database entries per line */
#define	NEWLINE		"\\\n\t:"	/* what to print to start a new line */
#define DEF_COMMENT	"A font"	/* default comment for data base */
\f



/* Data structures */
char	fontname[MAXNAMELENGTH];  /* name of current font */
char	*filename;		/* name of current file */
int	magnification,		/* current font's magnification */
	iflg,			/* interactive? */
	vflg;			/* verbose? */
int 	p;			/* LN file's index */
int	inIndex, outIndex;	/* Indices for stdin and stdout */
\f



/* Main loop.  Open each file, read its directory, and form an entry. */
main (argc, argv)
int argc;
char **argv;
{
char * option;

InitializeFiles(&inIndex,&outIndex);
while (--argc>0) {
    filename = *++argv;
    if (filename[0]=='-') {		/* Really an option! */
	option = filename;
	while (*++option != '\0') {
	    switch (*option) {
	    case 'i':   ++iflg;
			break;
	    case 'v':   ++vflg;
			break;
	    default:    Error(0,"Unknown switch: %s",filename);
			break;
			};
	    };
	continue;			/* so don't open any files */
	};
    if ((p=open_LN_file(filename))<0) continue;
    if (set_fontname_and_mag(filename) != 0) continue;
    print_entry();
    close_LN_file(p);
    };
printf("\n");
}

/* Try to open a LN file.
 * If it looks OK, return its index.
 * If we can't open it, or it looks wrong, return something <0.
 */
open_LN_file(filename)
char *filename;
{
int p;
long dirptr, end;
    if ((p=OpenFile(filename,"r"))<0) {	/* try to open file */
	Error(0,"Can't open %s",filename);
	return(p);
	};
    return(p);
}

/* Close a LN file */
close_LN_file(p)
int p;
{
    CloseFile(p);
}

/* Set fontname and magnification from the name of the font we're looking at */
set_fontname_and_mag(filename)
char *filename;
{
char *s, *t;
    s=filename;  t=fontname;		/* copy filename up to the */
    while (*s!='\0' && *s!='.') {	/* extension `.' into fontname */
	*t++ = *s++;
	};
    *t = '\0';
    if (*s=='.') ++s;
    magnification = atoi(s);		/* copy extension up to 'ln' */
    if (magnification==0) {		/* into magnification */
	Error(0,"%s is missing magnification in extension",filename);
	return(-1);
	};
    if (vflg) fprintf(stderr,"Font %s at magnification %d: ",fontname,magnification);
    return(0);
}

/* Form an entry for the current LN file and print it. */
print_entry()
{
static int entries;
static char oldfontname[MAXNAMELENGTH];
char comment[MAXLINELENGTH];
    if (strcmp(fontname,oldfontname)!=0) {  /* A new font name */
	strcpy(comment,DEF_COMMENT);	/* default comment */
	if (iflg) {			/* get a comment from user */
	    fprintf(stderr,"Comment for font %s: ",fontname);
	    ReadFromFile(inIndex);
	    getline(comment,MAXLINELENGTH);
	    };
	strcpy(oldfontname,fontname);
	printf("\n%s|%s:%s",fontname, comment, NEWLINE); /* start a new line */
	entries = 0;
	};
    if (++entries>MAXENTRIES) {		/* if line is full, start a new one */
	printf("%s",NEWLINE);
	entries=1;
	};
    printf("%d:",magnification); 	 /* print entry */
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'pxltoln01.c'" '(10760 characters)'
if test -f 'pxltoln01.c'
then
	echo shar: will not over-write existing file "'pxltoln01.c'"
else
cat << \SHAR_EOF > 'pxltoln01.c'
/*  pxltoln01		Samuel W. Bent		7/19/84
 *
 * Usage:  pxltoln01 file1 [file2 file3 ... ] 
 *
 * Convert the named PXL files to LN01 format.  The output is a "font record",
 * suitable for downloading to the LN01 after being encoded in SIXBIT form.
 * Typically, you would filter the output through 'conv' to get a file for
 * future loading.  It may be useful (for debugging, say) to save the output
 * before converting to SIXBIT.
 *
 * Conversion proceeds in several phases:
 *	1) Adjust boundaries and offsets
 *	2) Rotate bit maps
 */

/* #define DEBUG	/* also defined in Makefile */
#include <stdio.h>
#include "pxltoln01.h"
#include "lnfile.h"
#include "../dimen.h"
#include "../pxlfile.h"
#include "../utilities.h"
#include "../fontcap.h"
#include "lncode.h"
char PGM_NAME[] = "pxltoln01";
\f



/* Data structures */

PXLHEADER pxlhead;		/* header for current pxl file */
double pxlmag;			/* conversion factor to pixels */
PXLCHAR pxldir[128];		/* directory of current pxl file */
char pxlname[FNAMELEN];		/* name of current pxl file */
char lnname[FNAMELEN];		/* name of LN01 font */
LNHEADER lnhead;		/* header for current LN01 file */
LNCHAR lndir[256];		/* directory of current LN01 file */
int stdinIndex, stdoutIndex;	/* index into file arrays */
#ifdef DEBUG
int dflg;			/* debug flag */
#endif
\f



main(argc,argv)
int argc;
char **argv;
{
int size;
int pxlindex;
InitializeFiles(&stdinIndex,&stdoutIndex);
set_device_resolution(DEVICE_RES);
while (--argc>0) {
    if (**++argv=='-') {
	option(&argc, &argv);
	continue;
	};
    strncpy(pxlname,*argv,FNAMELEN);
    if ((pxlindex=open_pxl_file(pxlname))<0) continue;
    ReadFromFile(pxlindex);
    get_pxlheader(&pxlhead);
    pxlmag = GetRealMag(pxlhead.magnification) * pxlfilePXLperIN / DEVICE_RES;
#ifdef DEBUG
    if (dflg>=EVERYPXLHEADER) dump_pxlheader(&pxlhead); 
#endif
    GotoByte(pxlhead.directoryptr);
    get_pxldirectory(pxldir);
#ifdef DEBUG
    if (dflg>=EVERYPXLDIR) dump_pxldir(pxldir);
#endif
    size = compute_ln_directory(lndir,pxldir,&pxlhead);
#ifdef DEBUG
    if (dflg>=EVERYLNDIR) dump_lndir(lndir);
#endif
    make_lnname(pxlname, lnname);
    compute_ln_header(&lnhead,&pxlhead,size,lnname);
#ifdef DEBUG
    if (dflg>=EVERYLNHEADER) dump_lnheader(&lnhead);
#endif
    write_ln_header_and_directory(&lnhead,lndir);
    rotate_characters(pxldir,lndir);
    write_ln_trailer(3-lnhead.fsize%3);
    }
}

option(argcp, argvp)
int *argcp;
char ***argvp;
{
char *arg;
    arg = **argvp;
    switch (*++arg) {
#ifdef DEBUG
	case 'd':	   
	    if ((*argvp)[0][2]=='\0')
		dflg = EVERYCHAR;
	    else
		sscanf( &((*argvp)[0][2]), "%d", &dflg);
	    ++dflg;
	    break;
#endif
	default:	   
	    Error(1,"Unknown option '%s'",arg); 
	    break;
	};
}

open_pxl_file(name)
char *name;
{
int index;
    if ((index=OpenFile(name,"r"))<0) {
	Error(0,"Can't open %s\n",name);
	};
    return(index);
}

compute_ln_directory(lndir,pxldir,pxlhp)
LNCHAR lndir[];
PXLCHAR pxldir[];
PXLHEADER *pxlhp;
{
int ch, h, w;
long lnpos;
int dsize;
float realmag;
PXLCHAR *pchp;
LNCHAR *lnchp;
int even_offset;
    dsize = pxlhp->designsize;		   /* remember facts relevant to font */
    realmag = GetRealMag(pxlhp->magnification);
    lnpos = LN_SP_ADDR + 2;			 /* start bitmaps after space */
    for (ch=0;ch<128;++ch) {
	pchp = &pxldir[ch];
	lnchp = &lndir[lncode[ch]];
	if (pchp->bitp == 0) {				    /* all-white char */
	    lnchp->count = 2;
	    lnchp->bitp = LN_SP_ADDR;
	    lnchp->seg = 0377;
	    lnchp->height = 2;
	    lnchp->offset = 0;
	    lnchp->off_adj= 0;
	    lnchp->width = ROUND( pxlmag *
			FIXtoPXL(DUtoFIX(pchp->tfmwidth, pxlhp->designsize)));
	    continue;
	    };
	h = pchp->height;		     /* get envelope height and width */
	w = pchp->width;
			   /* adjust y_offset for LL corner, and for evenness */
	lnchp->offset = pchp->yoffset + 1 - h;
	lnchp->off_adj = lnchp->offset%2 == 0 ? 0 : 1;
			       /* adjust width using max_xoffset and x_offset */
	if (LN_XOFFSET>pchp->xoffset)
	    w = w + LN_XOFFSET - pchp->xoffset;
	h = (h+lnchp->off_adj+7) / 8;		   /* adjust height for bytes */
	h = MAX(h,2);				/* minimum height is 2 bytes */
	lnchp->height = h;
					    /* find char width from tfm width */
	lnchp->width = ROUND( pxlmag *
			FIXtoPXL(DUtoFIX(pchp->tfmwidth, pxlhp->designsize)));
	if (lnpos%2!=0) ++lnpos;			/* align to even byte */
	lnchp->count = h*w;
	lnchp->bitp = lnpos;
	lnpos += lnchp->count;
	lnchp->seg = 0377;
	};
    return (lnpos);					/* return file length */
}

compute_ln_header(lnhp,pxlhp,size,name)
LNHEADER *lnhp;
PXLHEADER *pxlhp;
int size;
char *name;
{
double pht;
    lnhp->rlev = 1;
    lnhp->aspect = LN_PORTRAIT + LN_VARWIDTH;
    					    /* adjust for trailer */
    lnhp->fsize = size + LN_TRAILERLENGTH;
    sprintf(lnhp->name,"%-20.20s",name);
    lnhp->firstc = LN_FC;
    lnhp->lastc = LN_LC;
    pht = pxlmag * FIXtoPXL(pxlhp->designsize);
    lnhp->udist = ROUND(pht*SUBPCT);
    lnhp->uthick = 3;
    lnhp->supdist = ROUND(pht*SUPPCT);
    lnhp->subdist = ROUND(pht*SUBPCT);
    lnhp->depth = ROUND(pht*DEPTHPCT);
    lnhp->height = ROUND(pht*HEIGHTPCT);
    lnhp->baseline = lnhp->height+lnhp->depth;
}

rotate_characters(pxldir,lndir)
PXLCHAR pxldir[];
LNCHAR lndir[];
{
PXLCHAR *pchp;
LNCHAR *lnchp;
int lastrow, row, col, ch, start, bits;
int xoffset_adj, width, byte_adj, word_adj, offset_adj;
int i, j, pad;
unsigned raster[ 500*500/32 ];
unsigned A[64];
    for (ch=0;ch<128;++ch) {		/* for each character */
	pchp = &pxldir[ch];
	lnchp = &lndir[lncode[ch]];
	offset_adj = lnchp->off_adj;
	xoffset_adj = lnchp->count/lnchp->height - pchp->width;
	byte_adj = 8*lnchp->height - pchp->height - offset_adj;
	word_adj = 31 - (pchp->height+byte_adj+offset_adj-1)%32;
	width = ((pchp->width+31)/32);
	lastrow = 0;		 /* fill in blank rows for byte alignment */
	for (i=0;i<byte_adj;++i) {
	    for (col=0;col<width;++col)
		raster[lastrow+col] = 0x0;
	    lastrow += width;
	    };
	GotoByte(pchp->bitp);		 /* read in bitmap */
	for (i=0;i<pchp->height;++i) {
	    for (col=0;col<width;++col)
		raster[lastrow+col] = Get4Byte();
	    lastrow += width;
	    };
		       /* fill in blank rows for offset and word alignments */
	for (i=0;i<offset_adj+word_adj;++i) {
	    for (col=0;col<width;++col)
		raster[lastrow+col] = 0x0;
	    lastrow += width;
	    };
	for (row=0;row<lastrow;row+=32*width) { /* for each 32x32 block */
	  for (col=0;col<width;++col) {
	    start = row+col;
	    for (i=0;i<32;++i) {		/* read block into array */
		A[i] = raster[start];
		start += width;
		};
	    rotate_array(A);			/* rotate array */
	    start = row+col;
	    for (i=0;i<32;++i) {		/* replace block */
		raster[start] = A[i];
		start += width;
		};
	    }; /* for col */
	  }; /* for row */
	WriteToFile(stdoutIndex);		/* output result */
	pad = lnchp->bitp - WhereIsWrite();	/* pad to even byte */
	for (i=0;i<pad;++i) PutByte(0);
#ifdef DEBUG
	if (dflg>=EVERYCHAR) {
	    dump_label(ch);
	    dump_pxlchar(pchp);
	    dump_lnchar(lnchp);
	    fprintf(stderr,"%d blank columns\n",xoffset_adj);
	    }
#endif
	for (j=0;j<xoffset_adj;++j) {
	    for (i=0;i<lnchp->height;++i) {
		PutByte(0);
		};
	    };
#ifdef DEBUG
	if (dflg>=EVERYCHAR) {
	    fprintf(stderr,"nr=%d wid=%d\n",lastrow,width);
	    };
#endif
	start = lastrow-32*width + 0;
	for (j=1;j<=pchp->width;++j) {
	    bits = (32-word_adj)/8;
#ifdef DEBUG
	    if (dflg>=EVERYROTATION) {
		fprintf(stderr,"%3d %1d ",j,bits);
		};
#endif
	    for (row=start; row>=0; row-=32*width) {
#ifdef DEBUG
		if (dflg>=EVERYROTATION) {
		    dump_word(raster[row]);
		    };
#endif
		switch (bits) {
		  case 1:    PutByte(raster[row]);  break;
		  case 2:    Put2Byte(raster[row]); break;
		  case 3:    Put3Byte(raster[row]); break;
		  case 4:    Put4Byte(raster[row]); break;
		    };
		bits = 32/8;
		};
	    start += width;
	    if (j%32 == 0) start += 1-32*width;
#ifdef DEBUG
		if (dflg>=EVERYROTATION) {
		    fprintf(stderr,"\n");
		    };
#endif
	    };
	};
}

rotate_array(A)
unsigned A[];
{
static int Mask[]={0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
int i,j, p, m1,m2, dist;
#ifdef DEBUG
    if (dflg>=EVERYBLOCK) dump_array(A);
#endif
    for (i=0,j=31; i<31; ++i,--j) {	/* rotate row i right by 31-i*/
	m1 = ~(0xFFFFFFFE<<i); m2 = ~m1;
	A[i] = ((A[i]>>j) & m1) | ((A[i]<<(i+1)) & m2);
	};
    for (p=0;p<5;++p) {			/* rotate column i up by 31-i */
	m1 = Mask[p];  m2 = ~m1;
	dist = 1<<p;
	for (i=0;i<dist;++i) A[i+32] = A[i];
	for (i=0;i<32;++i) {
	    A[i] = (A[i+dist]&m1) | (A[i]&m2);
	    };
	};
    for (i=1,j=31; i<32; ++i,--j) {	/* rotate row i left by i */
	m1 = ~(0xFFFFFFFF<<i); m2 = ~m1;
	A[i] = ((A[i]>>j) & m1) | ((A[i]<<i) & m2);
	};
#ifdef DEBUG
    if (dflg>=EVERYBLOCK) dump_array(A);
#endif
}

dump_raster(raster,width,frow,lrow)
unsigned raster[];
int width, frow, lrow;
{
int row, i, j, k, c;
    row = frow*width;
    for (i=frow;i<=lrow;++i) {
	fprintf(stderr,"%3d ",i);
	for (j=0;j<width;++j) {
	    dump_word(raster[row+j]);
	    };
	fprintf(stderr,"\n");
	row += width;
	};
}

dump_word(w)
int w;
{
int i;
    for (i=31;i>=0;--i) {
	fprintf(stderr,"%c", (w&(1<<i))==0 ? '.' : 'X');
	};
}

#ifdef DEBUG
dump_array(A)
unsigned A[];
{
int i,j,k;
    for (i=0;i<32;++i) {
	fprintf(stderr,"   %2d ",i);
	dump_word(A[i]);
	fprintf(stderr,"\n");
	};
}

dump_label(ch)
int ch;
{
    fprintf(stderr,"0%o-%c: ", ch, 040<ch && ch<0177 ? ch : '?');
}
#endif

write_ln_header_and_directory(hp,dir)
LNHEADER *hp;
LNCHAR dir[];
{
int i, ch;
LNCHAR *chp;
    WriteToFile(stdoutIndex);
    PutByte(LN_HEADERBYTE); PutByte(LN_HEADERBYTE);
    PutByte(hp->rlev);
    PutByte(hp->aspect);
    PutByte(hp->fsize);    PutByte(hp->fsize >> 8);
    for (i=0;i<20;++i) PutByte(hp->name[i]);
    PutByte(hp->udist);
    PutByte(hp->uthick);
    PutByte(hp->sdist);
    PutByte(hp->sthick);
    PutByte(hp->supdist);
    PutByte(hp->subdist);
    PutByte(hp->depth);    PutByte(hp->depth >> 8);
    PutByte(hp->height);   PutByte(hp->height >> 8);
    PutByte(hp->baseline); PutByte(hp->baseline >> 8);
    PutByte(hp->firstc);
    PutByte(hp->lastc);
    for (i=0;i<5;++i) PutByte(hp->partno[i]);
    for (i=0;i<3;++i) PutByte(0);
				/* now write the directory */
    for (ch=0; ch<hp->firstc; ++ch) {
	Put4Byte(0);  Put4Byte(0);
	};
    for (ch=hp->firstc; ch<=hp->lastc; ++ch) {
	chp = &dir[ch];
	PutByte(chp->count);	PutByte(chp->count >> 8);
	PutByte(chp->bitp);	PutByte(chp->bitp >> 8);
	PutByte(chp->seg);
	PutByte((~chp->height)&077);
	PutByte((chp->offset - chp->off_adj)/2);
	PutByte(chp->width);
	};
		/* finally, write two blank bytes for all-white characters */
    PutByte(0);
    PutByte(0);
}

write_ln_trailer(pad)
int pad;
{
int i;
    for (i=0;i<LN_TRAILERLENGTH;++i) PutByte(LN_TRAILERBYTE);
    for (i=0;i<pad;++i) PutByte(0);
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'pxltoln01.h'" '(702 characters)'
if test -f 'pxltoln01.h'
then
	echo shar: will not over-write existing file "'pxltoln01.h'"
else
cat << \SHAR_EOF > 'pxltoln01.h'
/* pxltoln01.h		Samuel W. Bent		7/17/84 */

/* Constants */

#define DEVICE_RES	300	/* resolution of LN01 */

#define FNAMELEN	50	/* maximum length of file name */
#define SUPPCT		0.5	/* how high to raise superscripts */
#define SUBPCT		0.25	/* how much to lower subscripts */
#define HEIGHTPCT	0.9	/* ratio of design size for height */
#define DEPTHPCT	0.3	/* ratio of design size for depth */
#define BLPCT		1.2	/* ratio of design size for baselines */

#define MAX(X,Y)	( (X)>(Y) ? (X) : (Y) )

/* debug levels */

#define EVERYLNHEADER 1
#define EVERYPXLHEADER 2
#define EVERYCHAR 3
#define EVERYROTATION 4
#define EVERYPREROTATION 5
#define EVERYBLOCK 6
#define EVERYLNDIR 7
#define EVERYPXLDIR 8
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'conv.c'" '(1133 characters)'
if test -f 'conv.c'
then
	echo shar: will not over-write existing file "'conv.c'"
else
cat << \SHAR_EOF > 'conv.c'
/*
 *	conv - convert font file from/to Xerox 2700 format
 *
 *	Fred Wilhelmsen
 *	Dept. of Computer Science
 *	University of Utah
 *
 *	Usage: conv [-] < infile > outfile
 *	- indicates encode mode
 *
 *	Xerox font files must be encoded before downloading.
 */

#include <stdio.h>
static char RCSid[] = "$Header: RCS/conv.c,v 1.1 83/03/14 13:54:21 fmw Exp $";

main(argc,argv)
int argc;
char **argv;
{
	register long accum;
	register char c;
	register int i;

	if( argc == 1 ) {
		for(;;) {
			accum = (long)0;
			for( i = 0; i < 4; i++ ) {
				if( (c = getchar()) == EOF )
					exit(0) ;
				accum = (accum<<6) + (long)((c+1) & 077) ;
			}
			putchar( (char)((accum >> 16) & (long)0377)) ;
			putchar( (char)((accum >> 8) & (long)0377)) ;
			putchar( (char)(accum  & (long)0377)) ;
		}
	}
	if( argc == 2 ) {
		for(;;) {
			accum = (long)0 ;
			for( i = 0; i < 3; i++) {
				if( (c = getchar()) == EOF)
					exit(0) ;
				accum = (accum<<8) + (long)(c & 0377);
			}
			for( i = 3; i >= 0; i-- ) {
				c = (char)(( accum >> ( i*6)) & 077);
				putchar(( c | 0100 ) -1 );
			}
		}
	}
	printf("Usage: conv [-] < infile > outfile\n");
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'ln-fload.c'" '(1944 characters)'
if test -f 'ln-fload.c'
then
	echo shar: will not over-write existing file "'ln-fload.c'"
else
cat << \SHAR_EOF > 'ln-fload.c'
#include <stdio.h>
/*
 * ln-fload
 *
 * load standard fonts (R, I, B & S in 8, 10 & 12 point sizes) onto the ln01.
 *
 * output is sent to stdout.  it can be redirected as required.
 */

#define LOGFILE	"/usr/spool/ln01/currfonts"

FILE *tf, *logf;
int	out;
FILE *con;
char bitdir[] = BITDIR;
char *outf = "/dev/ln0";	/* default output device */
							/* if no arg, output is to stdout */
char buf[1024];

main(argc, argv)
	int argc;
	char *argv[];
{
	umask(000);
	if(argc > 1) {
		outf = argv[1];

		if((tf=fopen(outf, "w")) == NULL) {
			con=fopen("/dev/console", "w");
			fprintf(con, "ln-fload: cannot download to %s\n", outf);
			fclose(con);
			exit(2);
		}
	}
	else tf=stdout;

	if((logf = fopen(LOGFILE, "w")) == NULL) {
		con=fopen("/dev/console", "w");
		fprintf(con, "ln-fload: cannot open font logfile\n");
		fclose(con);
		exit(2);
	}
	out = fileno(tf);
	fprintf(tf, "\33c");		/* init ln01 */
	if (argc>1) fprintf(tf, "\33P1;0y");
		else    fprintf(tf, "\33P1;1y");
	fflush(tf);
	sendfont("R", 8);		/* R font */
	sendfont("R", 12);
	sendfont("R", 10);
	sendfont("I", 8);		/* I font */
	sendfont("I", 12);
	sendfont("I", 10);
	sendfont("B", 12);		/* B font */
	sendfont("B", 10);
	sendfont("B", 8);
	sendfont("S", 8);		/* S font */
	sendfont("S", 10);
	sendfont("S", 12);
	if (argc>1) fprintf(tf, ";Standard fonts loaded\33\134\33c\f\n");
		else    fprintf(tf, ";Standard fonts loaded\33\134\33c");
	fclose(logf);
	/* fclose(tf); */	/* don't close if called by daemon */
}


sendfont(s, size)
	char *s;
	int size;
{
	register in, count, length;

	sprintf(buf, "%s/%s-%d", bitdir, s, size);
	if((in = open(buf, 0)) <0) {
		con = fopen("/dev/console", "w");
		fprintf(con, "ln-fload: Font %s open error\n", buf);
		fclose(con);
		exit(2);
	}

	length=0;
	while((count = read(in, buf, 1024)) > 0) {
		write(out, buf, count);
		length += count;
		};
	length = 3*length/4;

	fprintf(logf, "%s-%d\t%d\n", s, size, length);
	close(in);
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'makefile'" '(1642 characters)'
if test -f 'makefile'
then
	echo shar: will not over-write existing file "'makefile'"
else
cat << \SHAR_EOF > 'makefile'
#
#	ln01 driver routines
#
DEBUGFLAGS = -DDEBUG 
LN01sFLAG = -DLN01s
CFLAGS = -O -c $(DEBUGFLAGS)
PFLAGS = -Pln
LDFLAGS = 

all:	pxltoln01 lndvif makelnentry fonttest

SOURCES = pxltoln01.h pxltoln01.c \
		lndvif.h lndvif.c \
		lncmd.h lncode.h lncode.c lnfile.h lnfile.c \
		makelnentry.c fonttest.c cnvt-plain


PTOLNOBJS = pxltoln01.o lnfile.o lncode.o \
		../utilities.o ../pxlfile.o ../dimen.o ../fontcap.o
PTOLNHEADERS = pxltoln01.h lnfile.h lncode.h \
		../utilities.h ../pxlfile.h ../dimen.h ../fontcap.h

pxltoln01:  $(PTOLNHEADERS) $(PTOLNOBJS)
	    cc -o pxltoln01 $(PTOLNOBJS) $(LDFLAGS)

pxltoln01.o:  $(PTOLNHEADERS) pxltoln01.c 
	    cc $(CFLAGS) pxltoln01.c 


LNDVIFHEADERS = ../paths.h lndvif.h ../utilities.h ../dvifile.h ../pxlfile.h \
		../dimen.h ../fontcap.h lncode.h lncmd.h

LNDVIFOBJS = lndvif.o lncode.o \
		../utilities.o ../dimen.o ../dvifile.o ../pxlfile.o ../fontcap.o

lndvif:	    $(LNDVIFHEADERS) $(LNDVIFOBJS)
	    cc -o lndvif $(LNDVIFOBJS) $(LDFLAGS)

lndvif.o:   $(LNDVIFHEADERS) lndvif.c
	    cc $(CFLAGS) $(LN01sFLAG) lndvif.c


lnfile.o:   lncode.h lnfile.h lnfile.c
	    cc $(CFLAGS) lnfile.c

lncode.o:   lncode.h lncode.c
	    cc $(CFLAGS) lncode.c

MLOBJS = makelnentry.o ../utilities.o 
MLHEADERS = ../utilities.h 

makelnentry.o:	$(MLHEADERS) makelnentry.c
	    cc $(CFLAGS) makelnentry.c

makelnentry: $(MLOBJS)
	    cc $(MLOBJS) -o makelnentry $(LDFLAGS)

fonttest:   ../paths.h fonttest.o lncode.o
	    cc -o fonttest fonttest.o lncode.o $(LDFLAGS)

fonttest.o: lncmd.h lncode.h fonttest.c
	    cc $(CFLAGS) fonttest.c

list:
	    lpr -p $(PFLAGS) $(SOURCES) Makefile

clean:  
	    rm -f *.o
SHAR_EOF
fi # end of overwriting check
echo shar: done with directory "'ln01'"
cd ..
if test ! -d 'doc'
then
	echo shar: creating directory "'doc'"
	mkdir 'doc'
fi
echo shar: entering directory "'doc'"
cd 'doc'
echo shar: extracting "'prtex.l'" '(3524 characters)'
if test -f 'prtex.l'
then
	echo shar: will not over-write existing file "'prtex.l'"
else
cat << \SHAR_EOF > 'prtex.l'
.TH PRTEX LOCAL  12/9/84
.SH NAME
prtex \- cause TeX output to be printed
.SH SYNOPSIS
.B "prtex [-s] [-q] [-m N] [-r] [-c] [-Pdest] [-i] [-I] [-p pages] file1 [ [options] file2 ... ] [lpr options]"
.SH DESCRIPTION
Preprocess the named DVI files and spool the outputs to be printed on
the named printer (default is the LN01).
The extension ``.dvi'' is appended to each filename by default;
an explicit extension overrides this.
A filename of ``-'' denotes the standard input.
.PP
Preprocessing for the varian consists of selecting the right magnification of each font,
converting DVI coordinates to pixel coordinates, and sorting in the 
vertical direction.
The preprocessor,
.I dvi2rmver,
also detects errors due to malformed DVI files, missing fonts, and 
characters or rules off the edge of the page.
.PP
Options allow selecting pages, changing the global magnification, concatenating
files into one DVI file, and rotating the page image.
Options that appear after all file names are passed through to 
.I lpr
(1);
the most useful one is probably -m, to get mail when the file has been printed.
.SH OPTIONS
.TP 1in
-m N
Magnify the output by a factor of N/1000, overriding any magnification
specified in the DVI file.
.TP
-q
Run
.I dvi2rmver,
but do not spool the output for printing.
This is useful to check for errors.
(Implies -s.)
.TP
-s
Save (do not remove) the DVI file after printing.
By default,
.I prtex
removes DVI files.
.TP
-r
Rotate page image (Varian only).
.TP
-Pdest
Select a printer as the destination for the document.
Currently recognized values for dest are "ln" (the LN01 laser printer and
the default), and "va" (the varian).
.TP
-c
Concatenate succeding DVI files into one before printing.
.TP
-p pages
Print only the specified pages of the next DVI file.
A page specifier is a list of "count specifiers", separated by dots (as in
TeX's diagnostic output).
A count specifier can be a single number like 3, a range like 1-10, or
combinations of these separated by commas.
The special character 'x' can be used in ranges to give open ended ranges.
The page specifier selects the set of pages whose \\counts each match at least one
of their corresponding ranges or values.
Several page specifiers can be given for one file, each preceded by -p;
the union of the specified pages will be included in the output.
.TP
-i
Interactively decide whether to include each page of the next file.
.TP
-I
Like -i, but applies to all remaining files.

.SH "EXAMPLES"
.TP 1in
prtex -m1000 foo.dvi
Change the global magnification of foo.dvi to 1000, and print it.
.TP
prtex -s -p 1-4,10 foo.dvi bar.dvi
Print all pages in foo.dvi where \\count0 is between 1 and 4 or equal to 10,
and every page of bar.dvi.
Don't delete the DVI files.
.TP
prtex -p 1-x -p x--1..1 foo.dvi
Print pages where \\count0 is at least 1, or where \\count0 is negative and
\\count2 is 1.
.TP
prtex -p1.1.1 -i foo.dvi -m
Ask whether to include every page; set default to include pages 
where \\counts 0, 1, and 2 all equal 1, and to exclude all others.
Ask lpr to send mail upon completion of printing.

.SH "SEE ALSO"
.I tex
(LOCAL),
.I dviedit
(LOCAL)
.SH AUTHORS
The Varian DVI preprocessor was originally written by Janet Incerpi at Brown,
and later modified by Richard Furuta at Washington.
This version, incorporating a remote database of font magnification information
and interaction with the spooler, is by Samuel Bent at Wisconsin.
The LN01 version, as well as the page selection and concatenation features,
are also by Samuel Bent.

SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'tex.l'" '(7042 characters)'
if test -f 'tex.l'
then
	echo shar: will not over-write existing file "'tex.l'"
else
cat << \SHAR_EOF > 'tex.l'
.TH TEX LOCAL  7/5/84
.SH NAME
tex, initex, virtex  \- text formatting and typesetting
.SH SYNOPSIS
.B tex
[ first line ]
.PP
.B initex
[ first line ]
.PP
.B virtex
[ first line ]

.SH DESCRIPTION
TeX is a document formatting language designed by Donald Knuth at Stanford.
A complete description of the language can be found in official user's guide,
.I The TeXbook,
by Donald E. Knuth.
This book is available from the publisher (Addison-Wesley), from the
TeX User's Group (c/o American Mathematical Society, P.O. Box 6248,
Providence RI  02940, $15 prepaid), or from your local bookstore.
.PP
Arguments given on the command line are passed to the
TeX programs as the first input line.
As described in 
.I The TeXbook,
that line should begin with a file name
or a \\controlsequence.
The normal usage is to say
.RB `` tex
.IR paper ''
to start processing 
.I paper.tex.
The default extension (`.tex') can be overridden by specifying an extension
explicitly.
The name ``paper'' will be the ``jobname'', and is used in forming
output file names.
If TeX doesn't get a file name in the first line, the jobname is ``texput''.
.PP
If there is no paper.tex in the current directory, TeX will look
look through a search path of directories to try to find it.
The standard library on the default search path
has the basic format package, plain.tex, described
in the TeXbook, as well as several others.
It is hardly ever necessary to \\input plain, since the 
.I tex
program has preloaded it.
This means that all of the control sequences discussed in 
.I The TeXbook
are known to 
.I tex.
.PP
A convenient file in the library is null.tex, containing nothing.
When tex can't find a file it thinks you want to input, it keeps
asking you for another file name;  responding `null' gets you out
of the loop if you don't want to input anything.
.PP
TeX
formats the text and commands interspersed in its input,
and outputs a typesetter independent file (called
.I DVI,
for
.IR D e V ice
.IR I ndependent ).
TeX writes the output DVI file on 
.I jobname.dvi,
and a transcript of the session, including error messages, on
.I jobname.log.
To print the output, run
.I prtex
(LOCAL) on the DVI file;  for example,
.RB `` prtex
.IR jobname ''.
.PP
Environment variables can be used to set up directory
paths to search when TeX opens a file for input, or to specify
the editor to use when TeX switches from an error.
For example, the
.I csh
command
.br
.in +2
setenv TEXINPUTS .:/usr/me/mylib:/usr/lib/tex/macros
.in -2
or the
.I sh
command sequence
.br
.in +2
TEXINPUTS=.:/usr/me/mylib:/usr/lib/tex/macros
.br
export TEXINPUTS
.in -2
.br
cause all invocations of tex and its derivatives to look for
\\input files first in the current directory, then in a hypothetical
user's ``mylib'', and finally in the system library.
Normally, the user will place the command sequence which sets up the
TEXINPUTS environment variable in the
.I .cshrc
or
.I .profile
file.
The Environment section below lists the relevant environment variables
and their defaults.
.PP
The
.I e
response to TeX's error prompt causes the
.I vi
editor to start up at the current line of the current file.
The environment variable TEXEDIT can be used to change the
editor used.  It should contain a string with "%s" indicating where the
filename goes and "%d" indicating where the decimal linenumber (if any) goes.
For example, a TEXEDIT string for a local version of
.I vi
can be set by:
.br
.ti +2
setenv TEXEDIT "/usr/local/vi +%d %s"
.br
(replacing the path name for vi as appropriate on your system).
.PP
.PP
Two other TeX programs,
.I initex
and
.IR virtex ,
can be used to create fast-loading customized versions of TeX.
The
.I initex
program is used to create a
.I format (.fmt)
file that permits fast loading of fonts and macro packages.
After processing the fonts and definitions desired, a \\dump command
will create the format file.
The format file is used by
.I virtex.
It needs to be given a format file name as the first thing it reads.
A format file name is preceded by an &, which needs to be escaped with \\
if given on the command line.
So, for instance, one could create a file myfmt.fmt using initex,
and then set up a cshell alias with
.br
.ti +2
alias mytex "virtex \\&myfmt"
.br
to allow the use of ``mytex paper''.
.SH ENVIRONMENT
.PP
.IP TEXINPUTS
Search path for \\input and \\openin files.  It should be colon-separated,
and start with ``.''.  The entire path must be no longer than 700
characters long.
Default: .:/usr/lib/tex
.IP TEXFONTS
Search path for font metric files.  The entire path must be no longer than 100
characters long.  The default doesn't include the current area (".") to
avoid confusing the programs that convert the output for printing on the
various output devices (most of which don't know about the path stuff yet).
Default: /usr/lib/tex/fonts
.IP TEXFORMATS
Search path for format files.  Default: .:/usr/lib/tex/macros
.IP TEXPOOL
Search path for TeX strings.  Default: .:/usr/lib/tex
.IP TEXEDIT
Command template for switching to editor.  Default: "/usr/ucb/vi +%d %s"

.SH "CAVEAT"
There is an older version of TeX, called TeX78, described in the
book
.I TeX and METAFONT,
by Donald E. Knuth (Digital Press, 1979).
The present version (often referred to internally as TeX82)
incorporates literally hundreds of changes from the older version.
There have been incompatible changes in the DVI format
between 
TeX78
and
TeX82,
so programs used to print TeX78 output will not work for TeX82.
.SH FILES

.TP 2.5i
*.tex
Input to TeX
.TP
*.dvi
Device independent output files, to be interpreted by programs that know how
to print on a particular device.
.TP
*.log
Transcripts of TeX sessions, containing error messages and warnings.
.TP
/usr/lib/tex
TeX's library area
.TP
/usr/lib/tex/macros
TeX system macros and .fmt files
.TP
/usr/lib/tex/macros/plain.*
The ``default'' macro package
.TP
/usr/lib/tex/fonts
TeX's font information
.TP
/usr/lib/tex/fonts/*.tfm
Width information used by TeX (TeX Font Metric files)
.TP
spool:/usr/public/pxlfonts/*.*pxl
Bit maps for low resolution devices
.TP
/usr/lib/tex/tex.pool
Encoded text of TeX's messages
.br
.SH "SEE ALSO"
.I prtex
(LOCAL)
.br
Donald E. Knuth,
.I The TeXbook
.br
Leslie Lamport,
.I The LaTeX  Document Preparation System
.br
Michael Spivak,
.I The Joy of TEX
.br
.I TUGBOAT
(the publication of the TeX Users Group)
.br
.I Differences between TeX82 and SAIL TeX
.SH "TRIVIA"
TeX, pronounced properly, rhymes with ``blecchhh.''  The proper
spelling in typewriter-like output is ``TeX'' and not ``TEX'' or ``tex.''
.SH "BUGS"
Maybe there should be character other than & to specify format files,
since if you forget the \\ on the command line, it doesn't do what you want!
Also, there is no way to read a TeX input file with no filename extension.
.SH "AUTHORS"
TeX was designed by Donald E. Knuth, 
who implemented it using his WEB system for Pascal programs.
It was ported to Unix at Stanford by Howard Trickey, and
at Cornell by Pavel Curtis.
This version is a combination of their efforts.
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'dviedit.l'" '(3292 characters)'
if test -f 'dviedit.l'
then
	echo shar: will not over-write existing file "'dviedit.l'"
else
cat << \SHAR_EOF > 'dviedit.l'
.TH DVIEDIT LOCAL  12/7/84
.SH NAME
dviedit \- make simple changes to DVI files
.SH SYNOPSIS
.B "dviedit [-mN] [-ofilename] [-Vfilename] [-pP] [-i] file1   [ [-pP] [-i] file2 ...] "
.SH DESCRIPTION
Selected pages from the named files are concatenated into one DVI file.
The DVI files must be compatible, in the sense that they have the same
numerator and denominator parameters (from the preamble), and that they do
not use the same font number for different fonts.
(DVI files generated by plain TeX with no additonally defined fonts will be
compatible.)
The magnification for the resulting file is taken from the first input file.
.PP
Command line options can be given to select pages from the input files, 
change the overall magnification, and reroute the output to a named file.
.SH OPTIONS
.TP 1in
-m N
Set the overall magnification factor to N/1000, overriding any magnification
specified in the DVI files.
(By default, the magnification from the first input file overrides 
magnifications from the remaining files.)
This magnifies the entire page image, so printing an unmagnified file with
manification 1200 gives an effective \\hsize of 7.8 inches (6.5*1.2),
meaning that lines will fall .8 inches off the right of an 8.5X11 page with
1 inch margins.
.TP
-o filename
Send the output to filename.
(By default, output is sent to stdout.)
.TP
-Vfilename
Verbose.  Print progress reports on filename (or on stderr, if filename is omitted).
.I "No space should appear before the filename."
Progress reports mostly amount to the page number of every page that
is included in the output.
.TP
-i
Interactive.  For every page, you will be asked whether to include it in the
output.  Legal responses are "yes", "no", and "scroll";  other responses will
give a default action (defined by the -p option, if any).
"Scroll" means to take the default action without querying from now on.
(Responses can be abbreviated to one letter.)
.TP
-p <page specifier>
Select pages.
A page specifier is a list of "count specifiers", separated by dots (as in
TeX's diagnostic output).
A count specifier can be a single number like 3, a range like 1-10, or
combinations of these separated by commas.
The special character 'x' can be used in ranges to give open ended ranges.
The page specifier selects the set of pages whose \\counts each match at least one
of their corresponding ranges or values.
A page specifier applies only to the next input file.
Several page specifiers can be given for one file, each preceded by -p;
the union of the specified pages will be included in the output.
.SH "EXAMPLES"
.TP 1in
dviedit -m1000 foo.dvi
Change the global magnification of foo.dvi to 1000, and copy all pages to
stdout.
.TP
dviedit -V -p 1-4,10 foo.dvi bar.dvi
Include all pages in foo.dvi where \\count0 is between 1 and 4 or equal to 10,
and every page of bar.dvi.
Also print progress reports on stderr.
.TP
dviedit -o bar.dvi -p 1-x -p x--1..1 foo.dvi
Include pages where \\count0 is at least 1, or where \\count0 is negative and
\\count2 is 1.
Place output in bar.dvi.
.TP
dviedit -p1.1.1 -i foo.dvi
Ask whether to include every page; set default to include pages 
where \\counts 0, 1, and 2 all equal 1, and to exclude all others.
.SH "SEE ALSO"
.I tex
(LOCAL), and
.I prtex
(LOCAL).
.SH AUTHOR
Samuel Bent.
SHAR_EOF
fi # end of overwriting check
echo shar: done with directory "'doc'"
cd ..
echo shar: extracting "'NOTICE'" '(215 characters)'
if test -f 'NOTICE'
then
	echo shar: will not over-write existing file "'NOTICE'"
else
cat << \SHAR_EOF > 'NOTICE'
The ln01 driver is obsolete and not maintained. Source code
can be found in the ln01.sh file in ../   If you need it
uncompress ln01.sh and run it through sh.  These empty
directories are here for your convenience.
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'README'" '(11951 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
	Instructions on installing LN01 and Varian back ends for TeX
		        and a guide to the files

			    Samuel W. Bent
		    University of Wisconsin--Madison

The files in this directory and its subdirectories implement TeX back ends
(DVI filters) for the DEC LN01, DEC LN01s, and Varian printers.  The filters
work with either the 4.2BSD spooler or Waterloo's modified spooler;  printing
from remote machines is possible.  Some distributions may not have the Varian
files, since other Varian filters are available.


INSTALLATION - GENERAL INSTRUCTIONS

There are 7 steps to installing the filters and related files.

1) Change "paths.h" to relect your system's organization.
2) Install the PXL fonts and database (see below).
3) (LN01 only) Create and install the LN fonts and database (see below).
4) If you choose, redefine DEBUGFLAGS to null in the Makefile of each
     directory.  This speeds up the programs a little at the expense of
     debugging potential.
5) (LN01 only) If you have an LN01, redfine LN01sFLAG to null in the
     Makefile of the /ln01 subdirectory.  If you have an LN01s, redefine
     it to -DLN01s.
6) Compile all the programs by saying 'make all' first in this directory,
     then in all subdirectories.
7) Install the executables and on-line documentation (see below).


PATHS

Before installing the programs, you may want to change some of the
paths embedded in the code.  Here are the paths, their current values
(the ones used at Wisconsin), and what they mean.  They are all defined
in the file paths.h.

    LN01DEVICE	(/dev/lp1): device name for the LN01
    TFMPATH	(/usr/lib/tex/fonts):  where the .tfm files live
    PXLPATH	(/usr/public/pxlfonts):  where the PXL font raster files live
    LNPATH	(/usr/public/pxlfonts):  where the LN01 format rasters live 
    PXLCAP	(/usr/lib/tex/fonts/pxlcap): the database describing PXL files
    LNCAP	(/usr/lib/tex/fonts/lncap):  the database describing LN files
    FONTLOG	(/usr/spool/ln01/currfonts):  says which fonts were last
					    downloaded to the LN01
    DEBUG_FONTLOG (/tmp/currfonts): used instead of FONTLOG when debugging
    TEMPFILE	(/usr/tmp/dvipXXXXXX): temporary file for dviedit

Should you wish to change any of these, you'll have to remake some of the
software.  After making your changes, say
	    make all
first in this directory, then in each subdirectory.

The installation instructions tell you to "put foo somewhere (/usr/local)".
This means to move the file named foo to a reasonable place, usually
somewhere in the execution search path for all users, such as /usr/local
(where we put it at Wisconsin).


HOW TeX AND DITROFF SHARE THE LN01

TeX and ditroff use the FONTLOG file (/usr/spool/ln01/currfonts)
to tell each other which fonts currently reside in the LN01's font
memory.  Both filters should check this file before sending data to
the LN01 to make sure the proper fonts are present, and both should
update the file to reflect any changes they make to the font memory.

The LN01 back end for ditroff uses a set of 12 standard fonts (at least
that's the way it works at Wisconsin).  TeX, on the other hand, uses
whatever fonts are called for in the document.  TeX also reloads in the
middle of a document if it suddenly needs new fonts.  (For the LN01,
there is a limit of 10 fonts per page due to the size of some hardware
tables, but a document can use as many fonts as it likes.  The LN01s is
limited only by the size of its font memory.)

There are two consequences of all this.
1) Be sure the FONTLOG file (/usr/spool/ln01/currfonts) is sufficiently
    unprotected so that the printing daemon can read, write, and create it.
    Ideally, it should be owned by "daemon" with protection -rw-rw-rw-.
2) Be sure your ditroff filter checks the FONTLOG file for the fonts it
    needs, since TeX may unload them if it runs out of room.


BRIEF DESCRIPTION OF ALL FILES

In this directory:

    README	This file.
    HISTORY	Log of changes to the filter
    prtex	Shell script to send DVI files to printer
    paths.h	Definitions of paths
    dvifile.h
    dvifile.c	Utilities for dealing with DVI files
    pxlfile.h
    pxlfile.c	Utilities for dealing with PXL files
    dimen.h
    dimen.c	Dimension conversion routines
    fontcap.h
    fontcap.c	Utilities for reading the font database files
    utilities.h
    utilities.c	Miscellaneous routines, mostly file reading and writing
    makepxlentry.c Create entries for the PXLCAP database
    dviedit.h
    dviedit.c	Utility to concatenate and select pages from DVI files

In ./ln01

    lndvif.h
    lndvif.c	The DVI filter for the LN01
    lncmd.h	Definitions for LN01 commands
    lncode.h
    lncode.c	Conversion from TeX character codes to LN01 codes
    pxltoln01.h
    pxltoln01.c Convert PXL files to raw LN01 format
    conv.c	Convert raw LN01 format to SIXEL or vice-versa
    cnvt-plain	Shell script to convert all plain TeX fonts
    makelnentry.c Create entries for the LNCAP database
    fonttest.c	Send a font to the LN01 (to see if conversion worked right)
    ln-fload.c	Reload ditroff fonts

In ./varian:

    dvi2rmver.h
    dvi2rmver.c First pass of DVI-to-Varian process;  sorts page.
    vardvif.h
    vardvif.c	Second pass;  DVI filter for Varian

In ./=doc:

    tex.l	Man page for tex
    prtex.l	Man page for prtex
    dviedit.l	Man page for dviedit

To be created:

    /usr/lib/tex/fonts/pxlcap	PXLCAP font database
    /usr/lib/tex/fonts/lncap	LNCAP font database
    /usr/spool/ln01/currfonts	FONTLOG


INSTALLING PXL FONTS

1) Make a directory corresponding to PXLPATH, and put all your *.nnnnpxl
    files there.
2) Install makepxlentry somewhere (/usr/local).
3) Connect to the PXLPATH directory and say
	    makepxlentry -i *.*pxl > foo
    The -i is optional;  if you include it you get to invent a short
    comment describing each font.
4) Move foo to the file named by PXLCAP.
5) Should you later add new fonts, do step 3 for the new fonts, then
    merge the results into PXLCAP using an editor.


INSTALLING LN01 FONTS

1) Make a directory corresponding to PXLPATH, and put all your *.nnnnpxl
    file there.
2) Install pxltoln01, conv, and cnvt-plain somewhere (/usr/local).
3) Connect to the PXLPATH directory.  For each font you want available
    for the LN01, say
	    pxltoln01 amr10.1500pxl | conv - > amr10.1500ln
    (Replace "amr10.1500" with the appropriate name for each font.)
    To speed things up, cnvt-plain repeats this command for the 16 fonts
    of plain TeX, at a magnification you supply (default is 1500, namely
    \magstep0 for a 300 pxl/in printer).  For example,
	    cnvt-plain 1500 1643 1800
    does the conversion for all plain TeX fonts at \magstep0, \magstephalf,
    and \magstep1.
    *NOTE* cnvt-plain defines two shell variables, pxlpath and lnpath.
    If necessary, change cnvt-plain so that these agree with the paths
    in paths.h.
4) Move the *ln files to the directory corresponding to LNPATH.
5) Install makelnentry somewhere (/usr/local).
6) Connect to the LNPATH directory and say
	    makelnentry -i *.*ln > foo
    The -i is optional;  if you include it you get to invent a short
    comment describing each font.
7) Move foo to the file name by LNCAP.
8) Should you later add new fonts, do step 6 for the new fonts, then
    merge the results into LNCAP using the editor.


INSTALLING THE LN01 FILTER

1) Put lndvif somewhere (/usr/local).
2) Add a field to the LN01's entry in /etc/printcap that reads
	    df=/usr/local/lndvif
3) If you use the Waterloo spooler, be sure the LN01's entry in
    /etc/printcap has a "d" in its "fx" field.  Wisconsin's entry reads
	    fx=ftpdn
4) Put prtex somewhere (/usr/local) on each remote machine from
    which requests to print DVI files may originate.
5) Put dviedit somewhere (/usr/local) on each remote machine.
6) Put tex.l, prtex.l, and dviedit.l somewhere (/usr/man/manl) on each
    remote machine.
7) Announce to your users that the LN01 is ready for TeX.


INSTALLING THE VARIAN FILTER

1) Put vardvif somewhere (/usr/local).
2) Add a field to the Varian's entry in /etc/printcap that reads
	    df=/usr/local/vardvif
3) If you use the Waterloo spooler, be sure the Varian's entry in
    /etc/printcap has a "d" in its "fx" field.  Wisconsin's entry reads
	    fx=flptdngvc
4) Put prtex somewhere (/usr/local) on each remote machine from which
    requests to print DVI files may originate.
5) Put dviedit somewhere (/usr/local) on each remote machine.
6) Put tex.l, prtex.l, and dviedit.l somewhere (/usr/man/manl) on each
    remote machine.
7) Put dvi2rmver somewhere (/usr/local) on each remote machine.
8) Announce to your users that the Varian is ready for TeX.


SOME COMMENTS

The LN01 assumes that the reference point of each character is at the left
edge of the envelope surrounding the black pixels;  there is no provision
for the envelope to be offset left or right.  Since many TeX characters
have envelopes offset forward from their reference points, the LN01 versions
of TeX fonts need to include several blank columns.  Furthermore, any 
character whose envelope is offset more than LN_XOFFSET pixels backward must
be repositioned before printing.  Making LN_XOFFSET larger reduces the
frequency of repositioning, but increases the number of blank columns for
"forward" characters.  Currently, LN_XOFFSET=4.

The following paragraphs apply only to the LN01 (as opposed to LN01s).

The LN01 stores character raster images in its own memory;  it has about
193K for rasters and about 1740 positions in its character table.
Since TeX fonts use all 128 positions, and since the LN01 doesn't let you
use positions '0-'37 or '200-'237 but charges you for them anyway, there's
only room in the character table for 10 TeX fonts.  Naturally if some of
those fonts need lots of raster storage, you may run out of raster space
before character space.

Font loading works pretty well at magnifications \magstep0 and \magstephalf,
as long as you don't ask for subsubscripts and bold on the same page (or
another combination of sophisticated text and sophisticated math).  At
\magstep1, the size of the amex10.1800ln begins to run you out of
raster space.  

Loading the entire font memory takes two to three minutes.  There is no way
to replace a single font;  whenever you need a new font you have to reload
everything.  The filter uses lookahead to load fonts so as to maximize the
time to the next font load ("Belady optimal lookahead").

Overall, the situation is far from ideal.  When you get frustrated at
the limitations, I suggest kicking the printer.  I'd kick its designer if I
had him around.  

For LN01s owners, here's the good news.

The LN01s has about 400K of font raster memory and no restriction on
the number of fonts per page (other than total font memory).
Furthermore, it can load fonts without erasing its font memory.  Before
printing each page, the filter first tries to load fonts used on the
page that are not already present.  If this fails to load all the fonts
on the page, it will try to erase the font memory and reload, hoping
that removing fonts from previous pages frees up some room.  If this
fails too, it simply loads the most frequent fonts on the page.

The Varian filter is only slightly changed from the version due to Janet
Incerpi and Rick Furuta that I received in April, 1984.  To make it work
with remote spooling, I had to remove the dependence of the first pass
(sorting the page by vertical component) on the PXL files.  This I did by
using a "worst case" vertical offset for each character in the first pass,
then correcting to the real offset in the second pass, which is done on the
machine with the printer and the PXL files.  The worst case offsets are
stored in the PXLCAP file, which needs to live on the remote machines.
I also fixed a few bugs in the Varian filter;  it was printing rules
slightly wrong and doing other minor things I don't remember at the moment.

SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'Makefile'" '(1314 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
#	Routines of general interest
#
DEBUGFLAGS = -DDEBUG
CFLAGS = -O -c $(DEBUGFLAGS)
PFLAGS = -Pln

SOURCES = paths.h \
	    utilities.h utilities.c \
	    dimen.h dimen.c \
	    pxlfile.h pxlfile.c \
	    dvifile.h dvifile.o \
	    fontcap.h fontcap.c \
	    makepxlentry.c \
	    dviedit.h dviedit.c \
	    prtex

support:    utilities.o dimen.o pxlfile.o dvifile.o fontcap.o

all:	    makepxlentry support dviedit


MPOBJS = makepxlentry.o utilities.o pxlfile.o
MPHEADERS = utilities.h pxlfile.h

makepxlentry.o:	$(MPHEADERS) makepxlentry.c
	    cc $(CFLAGS) makepxlentry.c

makepxlentry: $(MPOBJS)
	    cc $(MPOBJS) -o makepxlentry $(LDFLAGS)


utilities.o: utilities.h utilities.c
	    cc $(CFLAGS) utilities.c

dimen.o:    dimen.h dimen.c
	    cc $(CFLAGS) dimen.c

pxlfile.o:  pxlfile.h pxlfile.c dimen.h
	    cc $(CFLAGS) pxlfile.c

dvifile.o:  dvifile.h dvifile.c
	    cc $(CFLAGS) dvifile.c

fontcap.o:  paths.h fontcap.h pxlfile.c utilities.h
	    cc $(CFLAGS) fontcap.c


DVIEDITOBJS = dviedit.o utilities.o dvifile.o dimen.o
DVIEDITHEADERS = paths.h dviedit.h utilities.h dvifile.h dimen.h

divedit.o:  $(DVIEDITHEADERS) dviedit.c
	    cc $(CFLAGS) makepxlentry.c

dviedit:    $(DVIEDITOBJS)
	    cc $(DVIEDITOBJS) -o dviedit $(LDFLAGS)


list:
	lpr -p $(PFLAGS) $(SOURCES) Makefile
clean:
	rm -f *.o
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'dimen.c'" '(2003 characters)'
if test -f 'dimen.c'
then
	echo shar: will not over-write existing file "'dimen.c'"
else
cat << \SHAR_EOF > 'dimen.c'
/* dimen.c	Samuel W. Bent		7/30/84 */
/* utilities for dimensions */

#include <stdio.h>
#include "dimen.h"

int PXLperIN;
double PXLperFIX;
double PXLperDVI;
double PXLperDVIunmag;

static long magnification;
static double realmag;
static long numerator;
static long denominator;

set_device_resolution(p)
int p;
{
    PXLperIN = p;
    PXLperFIX = (double) PXLperIN / FIXperIN;
}

set_DVI_dimens(n,d,m)
long n,d,m;
{
    magnification = m;
    realmag = GetRealMag(magnification);
    numerator = n;  denominator = d;
    PXLperDVIunmag = (double) n/d * INperRSU * PXLperIN;
    PXLperDVI = PXLperDVIunmag * realmag;
}

#include <stdio.h>
long DUtoDVI(du,z)
long du;	/* tfm width in DUs (=2^-20 DSs) */
long z;		/* DVIs per DS */
{
int a,b,c,d,e;
long alpha;
long w;
    a = (du>>24) & 0377;  b = (du>>16) & 0377;
    c = (du>>8)  & 0377;  d = du & 0377;
    alpha = z<<4;  e = 0;
    while (z>=040000000) {
	z >>= 1;  ++e;
	};
    w = ( ( (((d*z)>>8) + c*z) >>8) + b*z) >> (4-e);
    if (a!=0 && a!=0377) Error(0,"Bad tfm width %d",du);
    if (a==0377)  w -= alpha;
    return(w);
}

pxlwidth(du,fix_per_ds,realmag,pxl_per_in)
long du, fix_per_ds;
float realmag;
int pxl_per_in;
{
    return ( FIXtoPXL((int) (DUtoDS(du) * fix_per_ds * realmag) ));
}

/* this routine takes a integer representation of a mag factor (value of the
   magnification times 1000) and returns the float representation (no 1000
   factor).  The routine does a certain amount of faking to make sure that
   the magnification returned is correct. */
double GetRealMag(intmag)
int intmag;
{
double realmag;
    if (intmag == 1095)		realmag = 1.095445;	/* stephalf */
    else if (intmag == 1315)	realmag = 1.314534;	/* stepihalf */
    else if (intmag == 2074)	realmag = 2.0736;	/* stepiv */
    else if (intmag == 2488)	realmag = 2.48832;	/* stepv */
    else if (intmag == 2986)	realmag = 2.985984;	/* stepiv */
    else			realmag = (double) intmag / 1000;
    					/* remaining mags have been ok */
    return (realmag);
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'dimen.h'" '(1148 characters)'
if test -f 'dimen.h'
then
	echo shar: will not over-write existing file "'dimen.h'"
else
cat << \SHAR_EOF > 'dimen.h'
/* dimen.h	Samuel W. Bent		7/30/84  */
/* Common definitions for dimensions in DVI, PXL, and device programs */

/* Interface */

#define ROUND(f)	( (int) (f+0.5) )
#define CEIL(f)		( (int) (f+0.99) )
#define FIXtoPXL(fix)	( ROUND( (double)fix * PXLperFIX ))
#define FIXtoPT(fix)	( (double)fix / FIXperPT )
#define DUtoDS(du)	( (double) du / DUperDS )
#define DVItoPXL(dvi)	( ROUND( (double)dvi * PXLperDVI ))
#define DVItoRulePXL(dvi) ( CEIL( (double)dvi * PXLperDVI ))
#define DVItoPXLunmag(dvi) ( ROUND( (double)dvi * PXLperDVIunmag ))
long DUtoDVI();		/* args=(du,DVIperDS) */
#define DUtoFIX		DUtoDVI
/* long DUtoFIX();		/* args=(du,FIXperDS) */
double GetRealMag();	/* args=(intmag), return intmag/1000 with fudging */

/* Constants */

#define pxlfilePXLperIN	200

#define PTperIN		72.27
#define CMperIN		2.54
#define RSUperCM	100000
#define RSUperIN	(RSUperCM * CMperIN)
#define INperRSU	(1.0/RSUperIN)
#define FIXperPT	1048576
#define FIXperIN	(FIXperPT * PTperIN)
#define DUperDS		1048576
#define SPperPT		65536
#define SPperIN		((double) SPperPT * PTperIN)
extern double PXLperFIX;
extern double PXLperDVI;
extern double PXLperDVIunmag;
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'dvifile.c'" '(4066 characters)'
if test -f 'dvifile.c'
then
	echo shar: will not over-write existing file "'dvifile.c'"
else
cat << \SHAR_EOF > 'dvifile.c'
/* dvifile.c	Samuel W. Bent		8/3/84 */
/* Routines for reading DVI files
 */

#include <stdio.h>
#include "dvifile.h"

get_preamble(pap)
PREAMBLE *pap;
{
int i,k;
char *s;
    pap->version = GetByte();
    pap->numerator = Get4Byte();
    pap->denominator = Get4Byte();
    pap->magnification = Get4Byte();
    k = GetByte();
    s = pap->comment;
    for (i=0;i<k;++i)  *s++ = GetByte();
    *s = '\0';
}

write_preamble(pap)
PREAMBLE *pap;
{
int i,k;
char *s;
    PutByte(PRE);
    PutByte(pap->version);
    Put4Byte(pap->numerator);
    Put4Byte(pap->denominator);
    Put4Byte(pap->magnification);
    k = strlen(pap->comment);
    PutByte(k);
    s = pap->comment;
    for (i=0;i<k;++i) PutByte(*s++);
}

dump_preamble(fp,pap)
FILE *fp;
PREAMBLE *pap;
{
    fprintf(fp,"Preamble: %s\n", pap->comment);
    fprintf(fp,"  ver=%d  num=%d  denom=%d  mag=%d\n",
	pap->version, pap->numerator, pap->denominator, pap->magnification);
}

get_postamble(pap)
POSTAMBLE *pap;
{
    pap->lastpage = Get4Byte();
    pap->numerator = Get4Byte();
    pap->denominator = Get4Byte();
    pap->magnification = Get4Byte();
    pap->maxheight = Get4Byte();
    pap->maxwidth = Get4Byte();
    pap->maxstack = Get2Byte();
    pap->pagecount = Get2Byte();
}

write_postamble(pap)
POSTAMBLE *pap;
{
    PutByte(POST);
    Put4Byte(pap->lastpage);
    Put4Byte(pap->numerator);
    Put4Byte(pap->denominator);
    Put4Byte(pap->magnification);
    Put4Byte(pap->maxheight);
    Put4Byte(pap->maxwidth);
    Put2Byte(pap->maxstack);
    Put2Byte(pap->pagecount);
}

dump_postamble(fp,pap)
FILE *fp;
POSTAMBLE *pap;
{
    fprintf(fp,"Postamble:  pageptr=%d  num=%d  denom=%d  mag=%d\n",
	pap->lastpage, pap->numerator, pap->denominator, pap->magnification);
    fprintf(fp,"  maxht=%d  maxwd=%d  stack=%d  pages=%d\n",
	pap->maxheight, pap->maxwidth, pap->maxstack, pap->pagecount);
}

get_postpostamble(ppp)
POSTPOSTAMBLE *ppp;
{
    ppp->postptr = Get4Byte();
    ppp->version = GetByte();
}

write_postpostamble(ppp)
POSTPOSTAMBLE *ppp;
{
    PutByte(POSTPOST);
    Put4Byte(ppp->postptr);
    PutByte(ppp->version);
}

dump_postpostamble(fp,ppp)
FILE *fp;
POSTPOSTAMBLE *ppp;
{
    fprintf(fp,"Postpostamble:  postptr=%d  version=%d\n",
	ppp->postptr, ppp->version);
}

get_counts(cr)
COUNTREGS cr;
{
int i;
    for (i=0;i<10;++i) {
	cr[i] = Get4Byte();
	};
}

write_counts(cr)
COUNTREGS cr;
{
int i;
    for (i=0;i<10;++i) {
	Put4Byte(cr[i]);
	};
}

get_fontdef(fdp, fnlen)
FONTDEF *fdp;
int fnlen;
{
int i,k;
char *s;
    switch (fnlen) {
	case 1:
	    fdp->number = GetByte();
	    break;
	case 2:
	    fdp->number = Get2Byte();
	    break;
	case 3:
	    fdp->number = Get3Byte();
	    break;
	case 4:
	    fdp->number = Get4Byte();
	    break;
	};
    fdp->checksum = Get4Byte();
    fdp->scalesize = Get4Byte();
    fdp->designsize = Get4Byte();
    fdp->arealen = GetByte();
    fdp->namelen = GetByte();
    k = fdp->arealen + fdp->namelen;
    s = fdp->name;
    for (i=0;i<k;++i) {
	*s++ = GetByte();
	};
    *s = '\0';
}

write_fontdef(fdp)
FONTDEF *fdp;
{
int i,k;
char *s;
    if (fdp->number < 01<<8) {
	PutByte(FNTDEF1);
	PutByte(fdp->number);
	}
    else if (fdp->number < 01<<16) {
	PutByte(FNTDEF2);
	Put2Byte(fdp->number);
	}
    else if (fdp->number < 01<<24) {
	PutByte(FNTDEF3);
	Put3Byte(fdp->number);
	}
    else {
	PutByte(FNTDEF4);
	Put4Byte(fdp->number);
	};
    Put4Byte(fdp->checksum);
    Put4Byte(fdp->scalesize);
    Put4Byte(fdp->designsize);
    PutByte(fdp->arealen);
    PutByte(fdp->namelen);
    k = fdp->arealen + fdp->namelen;
    s = fdp->name;
    for (i=0;i<k;++i) {
	PutByte(*s++);
	};
}

dump_fontdef(fp,fdp)
FILE *fp;
FONTDEF *fdp;
{
    fprintf(fp,"Font %d (%s):  ds=%d  ss=%d  cksum=%d\n",
	fdp->number, fdp->name, fdp->designsize, fdp->scalesize, fdp->checksum);
}

GotoPostamble()
{
    GotoEnd();
    Skip(-4);
    while (GetByte()==DVIPAD) Skip(-2);	/* One step forward, two back */
    Skip(-5);
    GotoByte(Get4Byte());
}

GotoFontdefs()
{
    GotoPostamble();
    Skip(1 + 4 + 4+4+4 + 4+4 + 2+2);	/* Skip postamble proper */
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'dvifile.h'" '(1892 characters)'
if test -f 'dvifile.h'
then
	echo shar: will not over-write existing file "'dvifile.h'"
else
cat << \SHAR_EOF > 'dvifile.h'
/* dvifile.h	Samuel W. Bent		8/2/84 */
/* Common definitions for programs that read and write DVI files
 */

#define VERSION 2		/* works for DVI format version 2 */

typedef struct {
	short version;
	long numerator;
	long denominator;
	long magnification;
	char comment[256];
	} PREAMBLE;

typedef struct {
	long lastpage;
	long numerator;
	long denominator;
	long magnification;
	long maxheight;
	long maxwidth;
	short maxstack;
	short pagecount;
	} POSTAMBLE;

typedef struct {
	long postptr;
	short version;
	} POSTPOSTAMBLE;

typedef int COUNTREGS[10];

typedef struct {
	long number;
	long checksum;
	long scalesize;
	long designsize;
	short arealen;
	short namelen;
	char name[512];
	} FONTDEF;


/* Opcodes */

#define SETCHAR 0 /* set_char commands from 0 .. 127 */
#define SET1 128
#define SET2 129
#define SET3 130
#define SET4 131
#define SETRULE 132
#define PUT1 133
#define PUT2 134
#define PUT3 135
#define PUT4 136
#define PUTRULE 137
#define NOP 138
#define BOP 139
#define EOP 140
#define PUSH 141
#define POP 142
#define RIGHT1 143
#define RIGHT2 144
#define RIGHT3 145
#define RIGHT4 146
#define W0 147
#define W1 148
#define W2 149
#define W3 150
#define W4 151
#define X0 152
#define X1 153
#define X2 154
#define X3 155
#define X4 156
#define DOWN1 157
#define DOWN2 158
#define DOWN3 159
#define DOWN4 160
#define Y0 161
#define Y1 162
#define Y2 163
#define Y3 164
#define Y4 165
#define Z0 166
#define Z1 167
#define Z2 168
#define Z3 169
#define Z4 170
#define FNTNUM 171 /* fnt_num_0 .. fnt_num_63 is 171 to 234 */
#define FNT1 235
#define FNT2 236
#define FNT3 237
#define FNT4 238
#define XXX1 239
#define XXX2 240
#define XXX3 241
#define XXX4 242
#define FNTDEF1 243 
#define FNTDEF2 244
#define FNTDEF3 245
#define FNTDEF4 246
#define PRE 247
#define POST 248
#define POSTPOST 249
#define UNDEF 250  /* 250 .. 255  are undefined opcodes */

#define DVIPAD 223
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'fontcap.c'" '(2813 characters)'
if test -f 'fontcap.c'
then
	echo shar: will not over-write existing file "'fontcap.c'"
else
cat << \SHAR_EOF > 'fontcap.c'
/* fontcap.c	Samuel W. Bent		8/4/84 */
/* Utilities for the font database file, pxlcap and lncap
 */

#include <stdio.h>
#include <strings.h>
#include "paths.h"
#include "fontcap.h"
#include "dimen.h"
#include "utilities.h"

match_pxlfile(name,size, pxlname)
char *name;
int size;
char *pxlname;
{
int len, trymag, bestmatch, bestmag;
char *s;
char line[MAXLINELENGTH+1];
    sprintf(pxlname, "%s.%dpxl", name,size);	/* Set default name */
    len = strlen(name);			/* But try to find the real font */
    GotoByte(0);			/* Should be reading "pxlcap" */
    for (;;) {
	if (getline(line,MAXLINELENGTH)<=0) return;	/* give up if EOF */
	if (strncmp(name,line,len)==0) break;	/* found the right name */
	};
    s = line;				/* now look for mag closest to size */
    bestmatch = MAXINT;
    bestmag = size;
    for (;;) {
	s = index(s,':');
	if (s==NULL || *s++=='\\') {	/* end of the line, get another */
	    if (getline(line,MAXLINELENGTH)<=0) break;
	    s = line;
	    if (*s!='\t' && *s!=' ') break;	/* end of entry for this name */
	    continue;
	    };
	trymag = atoi(s);		/* compare mag with best match */
	if (trymag==0) continue;
	if (abs(size-trymag)<bestmatch) {
	    bestmatch = abs(size-trymag);
	    bestmag = trymag;
	    };
	};
    sprintf(pxlname, "%s.%dpxl", name,bestmag);
}

match_lnfile(name,size, lnname)
char *name;
int size;
char *lnname;
{
int len, trymag, bestmatch, bestmag;
char *s;
char line[MAXLINELENGTH+1];
    sprintf(lnname, "%s.%dln", name,size);	/* Set default name */
    len = strlen(name);			/* But try to find the real font */
    GotoByte(0);			/* Should be reading "lncap" */
    for (;;) {
	if (getline(line,MAXLINELENGTH)<=0) return;	/* give up if EOF */
	if (strncmp(name,line,len)==0) break;	/* found the right name */
	};
    s = line;				/* now look for mag closest to size */
    bestmatch = MAXINT;
    bestmag = size;
    for (;;) {
	s = index(s,':');
	if (s==NULL || *s++=='\\') {	/* end of the line, get another */
	    if (getline(line,MAXLINELENGTH)<=0) break;
	    s = line;
	    if (*s!='\t' && *s!=' ') break;	/* end of entry for this name */
	    continue;
	    };
	trymag = atoi(s);		/* compare mag with best match */
	if (trymag==0) continue;
	if (abs(size-trymag)<bestmatch) {
	    bestmatch = abs(size-trymag);
	    bestmag = trymag;
	    };
	};
    sprintf(lnname, "%s.%dln", name,bestmag);
}

make_lnname(pxlname, lnname)
char *pxlname, *lnname;
{
char *s;
    strcpy(lnname,pxlname);
    s = rindex(lnname,'p');
    if (s!=NULL && strcmp(s,"pxl")==0) {
	lnname[strlen(lnname)-3]='\0';
	};
    strcat(lnname,"ln");
}

make_pxlname(lnname, pxlname)
char *lnname, *pxlname;
{
char *s;
    strcpy(pxlname,lnname);
    s = rindex(pxlname,'l');
    if (s!=NULL && strcmp(s,"ln")==0) {
	pxlname[strlen(pxlname)-2]='\0';
	;}
    strcat(pxlname,"pxl");
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'fontcap.h'" '(144 characters)'
if test -f 'fontcap.h'
then
	echo shar: will not over-write existing file "'fontcap.h'"
else
cat << \SHAR_EOF > 'fontcap.h'
/* fontcap.h	Samuel W. Bent		8/5/84 */
/* Definitions for programs that use the font databases, pxlcap and lncap */

#define MAXINT	 2147483647
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'prtex'" '(1446 characters)'
if test -f 'prtex'
then
	echo shar: will not over-write existing file "'prtex'"
else
cat << \SHAR_EOF > 'prtex'
#! /bin/csh -f
#	print dvi, version 2 files--Richard Furuta, 4/6/83
#	modified to work with spooler -- Samuel Bent 5/11/84
umask 0
set flags=() noglob
set destdir=(/usr/local)
unset q
unset s
unset t
unset v
set hbuf=(-h)		# rotate the output by default
set dest = ln		# send to ln01 by default
top:
	if ($#argv > 0) then
		switch ($argv[1])

		case -m:
			shift argv
			set flags = ($flags -m $argv[1])
			shift argv
			goto top

		case -h:
			set hbuf = (-h)
			shift argv
			goto top

		case -q:
			set q
			set s
			shift argv
			goto top

		case -s:
			set s
			shift argv
			goto top

		case -v:
			set hbuf = ()
			shift argv
			goto top

		case -Pln:
		case -Pln01:
			set dest = ln
			shift argv
			goto top

		case -Pva:
		case -Pvarian:
		case -Pvar:
		case -Pv:
			set dest = va
			shift argv
			goto top

		case -*:
			set flags = ($flags $argv[1])
			shift argv
			goto top

		endsw
	endif
if ($#argv == 0) then
    set argv = ( - )
endif
foreach fname ($argv)
    if ($fname == - ) then
	set jobname = stdin
    else
	set jobname = $fname
	if (-e $fname.dvi) then
	    set fname = $fname.dvi
	endif
    endif
    if ($dest == ln) then
	lpr -d -Pln -J$jobname $fname
    else
	if ($?q) then
	    ${destdir}/dvi2rmver $hbuf $flags < $fname > /dev/null
	else
	    ${destdir}/dvi2rmver $hbuf $flags < $fname | lpr -d -Pva -J$jobname
	endif
    endif
    if ($status == 0 && $?s == 0 && $fname != - ) then
	    rm $fname
    endif
end

SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'makepxlentry.c'" '(5637 characters)'
if test -f 'makepxlentry.c'
then
	echo shar: will not over-write existing file "'makepxlentry.c'"
else
cat << \SHAR_EOF > 'makepxlentry.c'
/* makepxlentry - create pxlfont database entries	Sam Bent  5/25/84 */

/* This program opens each argument (assuming each to be a PXL-format
 * raster file), reads the PXL directory information to find the x- and
 * y-offsets, and forms an entry suitable for the pxlfont database, 'pxlcap'.
 * It sends the results to stdout.  The intended use is
 *		makepxlentry *.pxl > /usr/lib/tex/fonts/pxlcap
 * 
 * A typical entry in the database, illustrating its format is
 *	amr10|Ten point text roman:\
 *		:1000x1y21:1200x3y25:
 * meaning a font named 'amr10' (with a comment describing it) exists
 * at magnification 1 with maximum x-offset 1 and y-offset 21, and at
 * magnification 1.2 with maximum x-offset 3 and y-offset 25.
 *
 * Options:
 *	-i	(interactive) Ask user for a comment for each font.
 *	-v	(verbose) Print progress reports on stderr.
 */

/* #define DEBUG */
#include <stdio.h>
#include "utilities.h"
#include "pxlfile.h"
char PGM_NAME[] = "makepxlentry";

#define MAXNAMELENGTH	100	/* length of file names */
#define	MAXENTRIES	5	/* number of database entries per line */
#define	NEWLINE		"\\\n\t:"	/* what to print to start a new line */
#define DEF_COMMENT	"A font"	/* default comment for data base */
#ifndef MAXLINELENGTH
#define MAXLINELENGTH	100	/* length of input line */
#endif
\f



/* Data structures */
char	fontname[MAXNAMELENGTH];  /* name of current font */
char	*filename;		/* name of current file */
int	max_xoffset,		/* largest x-offset of font (in pixels) */
	max_yoffset,		/* largest y-offset of font (in pixels) */
	magnification,		/* current font's magnification */
	iflg,			/* interactive? */
	vflg;			/* verbose? */
int 	p;			/* PXL file's index */
int	inIndex, outIndex;	/* Indices for stdin and stdout */
\f



/* Main loop.  Open each file, read its directory, and form an entry. */
main (argc, argv)
int argc;
char **argv;
{
char * option;

InitializeFiles(&inIndex,&outIndex);
while (--argc>0) {
    filename = *++argv;
    if (filename[0]=='-') {		/* Really an option! */
	option = filename;
	while (*++option != '\0') {
	    switch (*option) {
	    case 'i':   ++iflg;
			break;
	    case 'v':   ++vflg;
			break;
	    default:    Error(0,"Unknown switch: %s",filename);
			break;
			};
	    };
	continue;			/* so don't open any files */
	};
    if ((p=open_PXL_file(filename))<0) continue;
    if (set_fontname_and_mag(filename) != 0) continue;
    find_max_offsets(p);
    print_entry();
    close_PXL_file(p);
    };
printf("\n");
}

/* Try to open a PXL file.
 * If it looks OK, return its index.
 * If we can't open it, or it looks wrong, return something <0.
 */
open_PXL_file(filename)
char *filename;
{
int p;
long dirptr, end;
    if ((p=OpenFile(filename,"r"))<0) {	/* try to open file */
	Error(0,"Can't open %s",filename);
	return(p);
	};
    ReadFromFile(p);
    GotoByte(0);
    if (Get4Byte()!=PXLMAGIC) {		/* check that 1st word is 1001 */
	Error(0,"%s is not a PXL file",filename);
	return(-1);
	};
    GotoEnd();				/* prepare to read last two words */
    end = WhereIsRead();
    Skip(-8);
    dirptr = Get4Byte()*4;
    if (dirptr!=end-517*4) {		/* directory pointer should point to
	Error(0,"%s has bad directory pointer",filename);  /* end-517 words */
	return(-1);
	};
    if (Get4Byte()!=PXLMAGIC) {		/* check that last word is 1001 */
	Error(0,"%s is not a PXL file",filename);
	return(-1);
	};
    GotoByte(dirptr+4);		/* position at offset field of first entry */
    return(p);			/* return index */
}

/* Close a PXL file */
close_PXL_file(p)
int p;
{
    CloseFile(p);
}

/* Set fontname and magnification from the name of the font we're looking at */
set_fontname_and_mag(filename)
char *filename;
{
char *s, *t;
    s=filename;  t=fontname;		/* copy filename up to the */
    while (*s!='\0' && *s!='.') {	/* extension `.' into fontname */
	*t++ = *s++;
	};
    *t = '\0';
    if (*s=='.') ++s;
    magnification = atoi(s);		/* copy extension up to 'pxl' */
    if (magnification==0) {		/* into magnification */
	Error(0,"%s is missing magnification in extension",filename);
	return(-1);
	};
    if (vflg) fprintf(stderr,"Font %s at magnification %d: ",fontname,magnification);
    return(0);
}

/* Search the directory for the maximum x and y offsets.
 * Assume the file p is positioned at the offset field of the
 * first entry in the directory.
 * Set the global variables max_xoffset and max_yoffset.
 */
find_max_offsets(p)
{
int i, xoffset, yoffset;
    ReadFromFile(p);
    max_xoffset = max_yoffset = 0;
    for (i=0;i<128;++i) {
	xoffset = Get2Byte();		/* compare x-offset */
	max_xoffset = (xoffset>max_xoffset ? xoffset : max_xoffset);
	yoffset = Get2Byte();		/* compare y-offset */
	max_yoffset = (yoffset>max_yoffset ? yoffset : max_yoffset);
	Skip(12);			/* skip to next entry */
	};
    if (vflg) fprintf(stderr,"max_xoffset=%d, max_yoffset=%d\n", max_xoffset, max_yoffset);
}

/* Form an entry for the current PXL file and print it. */
print_entry()
{
static int entries;
static char oldfontname[MAXNAMELENGTH];
char comment[MAXLINELENGTH];
    if (strcmp(fontname,oldfontname)!=0) {  /* A new font name */
	strcpy(comment,DEF_COMMENT);	/* default comment */
	if (iflg) {			/* get a comment from user */
	    fprintf(stderr,"Comment for font %s: ",fontname);
	    ReadFromFile(inIndex);
	    getline(comment,MAXLINELENGTH);
	    };
	strcpy(oldfontname,fontname);
	printf("\n%s|%s:%s",fontname, comment, NEWLINE); /* start a new line */
	entries = 0;
	};
    if (++entries>MAXENTRIES) {		/* if line is full, start a new one */
	printf("%s",NEWLINE);
	entries=1;
	};
    printf("%dx%dy%d:",magnification,max_xoffset,max_yoffset);  /* print entry */
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'pxlfile.h'" '(939 characters)'
if test -f 'pxlfile.h'
then
	echo shar: will not over-write existing file "'pxlfile.h'"
else
cat << \SHAR_EOF > 'pxlfile.h'
/* pxlfile.h		Samuel W. Bent		7/17/84  */
/* Common definitions for programs that use PXL files
 * PXL files store integers in BigEndian order, most significant byte first.
 */

/* Constants */

#define PXLMAGIC	1001

/* Types */

typedef struct {	/* directory entry in pxl file */
    short    height;		/* height of envelope (pixels) */
    short    width;		/* width of envelope (pixels) */
    short    xoffset;		/* x distance from corner to ref point (pxls) */
    short    yoffset;		/* y distance from corner to ref point (pxls) */
    long     bitp;		/* ptr to bitmap (bytes) */
    long     tfmwidth;		/* width (FIXes) */
    } PXLCHAR;

typedef struct {	/* info global to a pxl file */
    long    checksum;		/* checksum (0 means no checksum) */
    long    magnification;	/* magnification factor * 1000 */
    long    designsize;		/* design size (FIXes) */
    long    directoryptr;	/* ptr to directory (bytes) */
    } PXLHEADER;
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'pxlfile.c'" '(1304 characters)'
if test -f 'pxlfile.c'
then
	echo shar: will not over-write existing file "'pxlfile.c'"
else
cat << \SHAR_EOF > 'pxlfile.c'
/* pxlfile.c 	Samuel W. Bent		7/30/84 */

#include <stdio.h>
#include "pxlfile.h"
#include "dimen.h"

get_pxlheader(hp)
PXLHEADER *hp;
{
    GotoEnd();
    Skip(-20);
    hp->checksum = Get4Byte();
    hp->magnification = Get4Byte();
    hp->designsize = Get4Byte();
    hp->directoryptr = Get4Byte()*4;		/* convert words to bytes */
}

get_pxlchar(pchp)
PXLCHAR *pchp;
{
    pchp->width = Get2Byte();
    pchp->height = Get2Byte();
    pchp->xoffset = Get2Byte();
    pchp->yoffset = Get2Byte();
    pchp->bitp = Get4Byte()*4;		/* change words to bytes */
    pchp->tfmwidth = Get4Byte();
}

get_pxldirectory(dir)
PXLCHAR dir[];
{
int ch;
    for (ch=0;ch<0200;++ch) {
	get_pxlchar(&dir[ch]);
	};
}

/* Printing routines (for debugging) */

dump_pxlheader(hp)
PXLHEADER *hp;
{
    fprintf(stderr,"cksum=%d mag=%d dsize=%-4.3f dirp=%u\n",
	    hp->checksum,hp->magnification,
	    FIXtoPT(hp->designsize), hp->directoryptr);
}

dump_pxlchar(pchp)
PXLCHAR *pchp;
{
    fprintf(stderr,"h=%d w=%d xoff=%d yoff=%d addr=%u tfw=%-4.3f\n",
	    pchp->height,pchp->width,pchp->xoffset,pchp->yoffset,
	    pchp->bitp, DUtoDS(pchp->tfmwidth) );
}

dump_pxldir(dir)
PXLCHAR dir[];
{
int ch;
    for (ch=0;ch<128;++ch) {
	fprintf(stderr,"0%o-%c: ",ch, (040<ch && ch<0177)? ch : '?');
	dump_pxlchar(&dir[ch]);
	};
}

SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'utilities.c'" '(5407 characters)'
if test -f 'utilities.c'
then
	echo shar: will not over-write existing file "'utilities.c'"
else
cat << \SHAR_EOF > 'utilities.c'
/* Utilities for DVI and PXL programs */
/* Calling programs must define:
 *	PGM_NAME
 */

#include <stdio.h>
#include "utilities.h"
#define MAXFILES	20	/* hope that's enough */

static FILE * fp[MAXFILES];	/* convert from index to file ptr */
static int nrfiles;		/* how many files in the table */
static char FNAME[MAXFILES][50];/* name of each file */
static FILE * READfp;		/* current file to read */
static int READindex= -1;	/* its index in the table */
static FILE * WRITEfp;		/* current file to write */
static int WRITEindex= -1;	/* its index in the table */
static long bytepos[MAXFILES];	/* byte positions of all files */
static long READpos;		/* byte position of current read file */
static long WRITEpos;		/* byte position of current write file */

/* Initialize the file interface with stdin and stdout */
InitializeFiles(inIndex,outIndex)
int *inIndex, *outIndex;
{
int index;
    index=Insert(stdin);
    bytepos[index]=0;  strcpy(FNAME[index],"stdin");
    *inIndex = index;
    index = Insert(stdout);
    bytepos[index]=0;  strcpy(FNAME[index],"stdout");
    *outIndex = index;
}

/* Open a new file and return its index.
 * Return something <0 if anything goes wrong.
 */
OpenFile(filename,mode)
char * filename;
char * mode;
{
FILE * newfp;
int index;
    if ((newfp=fopen(filename,mode))==NULL) {  /* try to open the file */
	return(-1);
	};
    if ((index=Insert(newfp)) < 0) return (-1);  /* insert it in table */
    bytepos[index] = 0;
    strncpy(FNAME[index],filename,50);
    return(index);
}

/* Close a file */
CloseFile(index)
int index;
{
    fclose(fp[index]);
    Delete(index);
}
    
/* Switch current read file */
ReadFromFile(index)
int index;
{
    if (READindex==index) return;	/* if already reading it, do nothing */
    bytepos[READindex]=READpos;	/* save position of old file */
    READindex = index;
    READfp = fp[READindex];
    READpos = bytepos[READindex];
}

/* Switch current write file */
WriteToFile(index)
int index;
{
    if (WRITEindex==index) return;
    bytepos[WRITEindex]=WRITEpos;
    WRITEindex = index;
    WRITEfp = fp[WRITEindex];
    WRITEpos = bytepos[WRITEindex];
}

/* Return position of read file */
long WhereIsRead()
{
    return(READpos);
}

/* Return position of write file */
long WhereIsWrite()
{
    return(WRITEpos);
}

GetByte()
{
int     i;
    READpos++;
    i = getc (READfp);
    if (i == EOF)
	Error (2,"EOF encountered unexpectedly in %s", FNAME[READindex]);
    return (i);
}

/* Move to given position in read file */
GotoByte (n)
long     n;
{
    fseek (READfp, n, 0);
    READpos = n;
}

/* Skip n bytes in read file */
Skip (n)
int n;
{
	GotoByte(READpos+n);
}

/* Go to the end of the current read file */
GotoEnd()
{
    fseek(READfp,0L,2);		/* read to end of file */
    READpos = ftell(READfp);
}

/* take next two bytes and return as integer */
Get2Byte ()
{
int     n;
    n = 0;
    n |= GetByte ();
    n <<= 8;
    n |= GetByte ();
    n <<= 16;
    n >>= 16;			/* sign extend */
    return (n);
}

/* take next three bytes and return as integer */
Get3Byte ()
{
int     n;
    n = 0;
    n |= GetByte ();
    n <<= 8;
    n |= GetByte ();
    n <<= 8;
    n |= GetByte ();
    n <<= 8;
    n >>= 8;			/* sign extend */
    return (n);
}

/* take next four bytes and return as integer */
Get4Byte ()
{
int     n;
    n = 0;
    n |= GetByte ();
    n <<= 8;
    n |= GetByte ();
    n <<= 8;
    n |= GetByte ();
    n <<= 8;
    n |= GetByte ();
    return (n);
}

PutByte(b)
int b;
{
    putc(b&0377,WRITEfp);
    WRITEpos++;
}

Put2Byte(x)
int x;
{
    PutByte( x>>8 );
    PutByte( x );
}

Put3Byte(x)
int x;
{
    PutByte( x>>16 );
    PutByte( x>>8 );
    PutByte( x );
}

Put4Byte(x)
int x;
{
    PutByte( x>>24 );
    PutByte( x>>16 );
    PutByte( x>>8 );
    PutByte( x );
}

/* Insert a file pointer into table, if not already there */
static Insert(newfp)
FILE * newfp;
{
int i, index;
    index = nrfiles;
    for (i=0;i<nrfiles;++i) {
	if (fp[i]==newfp) {
	    index=i;
	    break;
	    };
	if (fp[i]==NULL) {
	    index = i;
	    };
	};
    if (index==nrfiles) {
	if ((index=nrfiles++)>=MAXFILES) {
	    Error(2,"Too many open files");
	    };
	};
    fp[index] = newfp;
    return(index);
}

/* Remove an entry from file table */
static Delete(index)
int index;
{
    fp[index]=NULL;
}

Left (word)
int     word;
{
int     temp;
    temp = word >> 16;
    if (temp & 0100000)
	temp = temp | ~0177777;	/* sign extend if negative */
    return (temp);
}

Right (word)
int     word;
{
int     temp;
    temp = word & 0177777;
    if (temp & 0100000)
	temp = temp | ~0177777;	/* sign extend if negative */
    return (temp);
}

Pack(l,r)
int l,r;
{
    return( ((l<<16) & ~0177777) | (r & 0177777) );
}

Error (code, format, a1, a2, a3, a4, a5, a6, a7, a8)
int code;
char *format;
/* Print error message. Exit if code<>0. */
{
    fprintf(stderr,"%s: ",PGM_NAME);
    fprintf(stderr,format, a1,a2,a3,a4,a5,a6,a7,a8);
    fprintf(stderr,"\n");
    if (code!=0) exit (code);
}

/* Read a line from current file */
getline(s, lim)
char *s;
int lim;
{
int c;
int len;
    while (--lim>0 && (c=getc(READfp))!=EOF && c!='\n') {
	*s++ = c;
	++len;
	};
    if (lim==0) {
	--s;
	--len;
	};
    *s = '\0';
    if (c==EOF) return(-1); else return(len);
}

putline(format, a1,a2,a3,a4,a5,a6,a7,a8)
char *format;
{
    fprintf(WRITEfp, format, a1,a2,a3,a4,a5,a6,a7,a8);
}

Flush()
{
    fflush(WRITEfp);
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'utilities.h'" '(1993 characters)'
if test -f 'utilities.h'
then
	echo shar: will not over-write existing file "'utilities.h'"
else
cat << \SHAR_EOF > 'utilities.h'
/* utilities.h 		Samuel W. Bent    7/30/84   */
/* Utilities for reading, writing, and manipulating files in the TeX
 * family (DVI, PXL, etc.).  All integers are stored in BigEndian order,
 * that is with the most significant byte first.
 */

extern char PGM_NAME[];

#define MAXLINELENGTH	200	/* length of input lines */

InitializeFiles();	/* args=(&inIndex,&outIndex).  Initialize file system,
				set indices for stdin and stdout */
OpenFile();	/* args=(filename,mode), return index for new file, or <0 if
			error */
CloseFile();	/* args=(index) */
ReadFromFile();	/* args=(index), set current read file */
WriteToFile();	/* args=(index), set current write file */
long WhereIsRead();	/* return byte pos of read file */
long WhereIsWrite();	/* return byte pos of write file */
GetByte();	/* return next byte of read file */
Get2Byte();	/* return integer in next 2 bytes of read file */
Get3Byte();	/* return integer in next 3 bytes of read file */
Get4Byte();	/* return integer in next 4 bytes of read file */
GotoByte();	/* args=(pos).  Set read file to position pos */
GotoEnd();	/* Move to end of read file */
Skip();		/* args=(n), skip n bytes (pos or neg) in read file */
PutByte();	/* args=(b). Append byte b to write file */
Put2Byte();	/* args=(w). Append integer w to write file, using 2 bytes */
Put3Byte();	/* args=(w). Append integer w to write file, using 3 bytes */
Put4Byte();	/* args=(w). Append integer w to write file, using 4 bytes */
Error();	/* args=(code,format,a1,...), print formatted error message
			with components a1,a2,...  Exit with completion code,
			if code is not 0 */
getline();	/* args=(s,lim), read line from stdin into s, but no more than
			lim chars */
Left();		/* args=(w), return signed integer in upper 16 bits of w */
Right();	/* args=(w), return signed integer in lower 16 bits of w */
Pack();		/* args=(l,r), pack signed integers into a word */
#define LEFT(w)	( (w>>16)&0xFFFF )	/* unsigned */
#define RIGHT(w) ( w&0xFFFF )		/* unsigned */
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'paths.h'" '(347 characters)'
if test -f 'paths.h'
then
	echo shar: will not over-write existing file "'paths.h'"
else
cat << \SHAR_EOF > 'paths.h'
#define LN01DEVICE	"/dev/lp1"

#define TFMPATH "/usr/lib/tex"
#define PXLPATH	"/usr/public/pxlfonts"
#define LNPATH	"/usr/public/pxlfonts"
#define PXLCAP	"/usr/lib/tex/fonts/pxlcap"
#define LNCAP	"/usr/lib/tex/fonts/lncap"

#define FONTLOG	"/usr/spool/ln01/currfonts"
#define DEBUG_FONTLOG	"/tmp/currfonts"

#define TEMPFILE "/usr/tmp/dvipXXXXXX"
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'HISTORY'" '(1807 characters)'
if test -f 'HISTORY'
then
	echo shar: will not over-write existing file "'HISTORY'"
else
cat << \SHAR_EOF > 'HISTORY'
August, 1984:  Implemented DVI filter for LN01, revised DVI filter for varian.

10/9/84 Released first version to Furuta.

10/20/84 Reworked font loading code to use lookahead (to find Belady optimal
working set).

11/2/84 Bug: When a font is missing from LNCAP, I was supposed to substitute
a default font.  I wrote make_pxlname(pxlname,lnname) instead of
make_pxlname(lnname,pxlname);  result was error --- "Can't open amr8.1643pxl".
Also changed fontlog code to avoid rewriting the log when debugging.

12/4/84 Changed lndvif to check for preamble before beginning.  Now it will
print a summary page if you spool a non-DVI file, telling you that you blew it.
(Before it just logged an error in the error file.)

1/22/85 Changed the code for loading fonts to completely factor out the
decision of which fonts to load.  Then, added a different algorithm for
selecting fonts that's appropriate for the LN01s.  It uses all the font
memory and loads only the new fonts needed on each page.
Also, changed font loads so they didn't issue a RESET;  this makes the
number in the led display on the LN01s correspond to the page number.

1/23/85 Changed ditroff filter (ln01f and dln01) to check the font log
and load troff fonts if necessary.  Then, removed call to /etc/ln-fload
from lndvif.  The DVI filter no longer reloads ditroff's fonts.

1/29/85 Fixed bug whereby fontlog wasn't getting updated after reloading,
if no appends followed.  This caused subsequent troff jobs to mistakenly
believe their fonts were present, and ended up spitting blank paper all 
over the floor.

1/31/85 Fixed bugs: define_font wasn't closing the PXL file, eventually
leading to too many open files;  open_font_log tried to close fontlog,
even if it wasn't open.  Added information to error messages dealing with
loading fonts.
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'dviedit.c'" '(20791 characters)'
if test -f 'dviedit.c'
then
	echo shar: will not over-write existing file "'dviedit.c'"
else
cat << \SHAR_EOF > 'dviedit.c'
/* dviedit.c		11/24/84		Samuel W. Bent */
/* This program does some simple editing of DVI files.  It is intended to
 * be used as a filter before spooling the DVI file with lpr.
 * Usage is:	dviedit [flags] file1 file2 ...
 *
 * Flags and their meanings:
 *
 *	-p <page specifier>	Extract specified pages.  A <page specifier> is
 *			a sequence of up to 10 <count specifiers> separated
 *			by periods;  it selects pages whose 10 \counts match
 *			the respective specifiers.  A <count specifier> is
 *			either a single number like 4, a range like 1-10,
 *			a sequence of these two types separated by commas,
 *			or empty.  An empty specifier matches any value;
 *			a non-empty one matches a value in any of the given
 *			ranges or equal to any of the given numbers.  The
 *			symbol X (or x) can be used to give "half-ranges",
 *			as in 1-x or x-10.
 *	-m <magnification>	Change the overall magnification of the
 *			DVI file to <magnification>/1000.
 *	-g		Merge Tektronix graphic files given by \special's.
 *	-o <filename>	Send output to named file.
 *	-i		Interactively ask user what to do.
 *
 * The selected pages from all the named files are concatenated into one
 * DVI file.  The output is sent to stdout unless a "-o" argument appears.
 * The input files must all be compatible with the first one, in the sense that
 * their numerator and denominator paramaters (from the preamble) must agree,
 * and they may not use the same font number for different fonts.
 */

/* #define DEBUG 	/* Also defined in Makefile */
#include <stdio.h>
extern char *mktemp();
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <strings.h>
#include "paths.h"
#include "dviedit.h"
#include "utilities.h"
#include "dimen.h"
#include "dvifile.h"
char PGM_NAME[] = "dviedit";
\f



/* Data structures */

int dviindex;		/* index for dvi file */
int pxlcapindex;	/* index for PXL file database */
int curpage;		/* sequence number of current page */
PREAMBLE preamble;	/* preamble of current dvi file */
POSTAMBLE postamble;	/* postamble */
POSTPOSTAMBLE postpostamble; /* postpostamble */
bool inpostamble;	/* true when reading postamble */
long f, h,v, w,x, y,z;	/* DVI registers:  font, position, horiz space amounts,
				vert space amounts */
STACKITEM stack[MAXSTACKDEPTH]; /* stack for registers */
int top=0;		/* index of first free position in stack */
FONT *fontp;		/* pointer to current font structure */
FONT *fcache[CACHEFONTS];	/* buckets for first few fonts */
FONT *fontptrarray[TABLEFONTS];	/* unordered table for remaining fonts */
int fpalen;			/* first free slot in fontptrarray */
FONT *allfonts[MAX_FONTS];	/* list of all fonts */
int fonts;			/* number of fonts */
int Vflg;		/* Print progress reports? */
FILE *Vfp = NULL;	/* where to print progress reports */
char *Vfilename = NULL;	/* where to print progress reports */
#ifdef DEBUG
int dflg;		/* debug level */
#endif

PAGERECORD pagerec[MAXPAGERECS];	/* page specifiers */
int pagerecs=0;		/* number of page specifiers */
int gflg;		/* merge graphics files? */
int iflg;		/* interactive? */
int cflg;		/* concatenate dvi files? */
int magarg;		/* new global magnification */
char *outputarg;	/* file for output */
char *filename;		/* name of currrent input file */
int stdinindex;		/* index of stdin */
int stdoutindex;	/* index of stdout */
int outindex;		/* index of output file */
int postindex;		/* index of postamble file */
char *postfile;		/* name of postamble file */
int nullindex;		/* index of /dev/null */
bool firstfile=true;	/* true while reading the first file to catenate */
PREAMBLE master_pre;	/* preamble for output */
POSTAMBLE master_post;	/* postamble for output */
POSTPOSTAMBLE master_postpost; /* postpostamble for output */
long lastpageptr= -1;	/* address of last page in output file */
char answer[MAXLINELEN]; /* user's answer to interactive question */
\f



main(argc,argv)
int argc;
char **argv;
{
int i;
    InitializeFiles(&stdinindex, &stdoutindex);
    postfile = mktemp(TEMPFILE);
    postindex = OpenFile(postfile,"w");
    if (postindex<0) Error(2,"Can't open temp file %s", postfile);
    nullindex = OpenFile("/dev/null","w");
    if (nullindex<0) Error(2,"Can't open /dev/null");
    Initialize_options();
    while (--argc) {
	if (**++argv == '-')
	    set_option(&argc,&argv);
	else
	    edit_dvifile(*argv);
	};
    cleanup();
    exit(0);
}
\f



Initialize_options()
{
    magarg = 0;
    outputarg = NULL;
    Vfp = stderr;
    Vfilename = NULL;
}

set_option(argcp,argvp)
int *argcp;
char ***argvp;
{
char *pagearg;
int count, sign, value;
PAGERECORD *prp;
char *s;
    switch ((*argvp)[0][1]) {
    case 'V':	/* verbose -- tell file what's happening */
	++Vflg;
	if ((*argvp)[0][2]=='\0') Vfp = stderr;
	else {
	    Vfilename = &((*argvp)[0][2]);
	    Vfp = fopen(Vfilename,"w");
	    if (Vfp==NULL) Error(2,"Can't open %s", Vfilename);
	    };
	break;
#ifdef DEBUG
    case 'd':		/* debug */
	++Vflg;			/* implies V */
	if ((*argvp)[0][2]=='\0')
	    dflg = EVERYAMBLE;
	else
	    sscanf( &((*argvp)[0][2]), "%d", &dflg);
	break;
#endif
    case 'i':		/* interactive */
	++iflg;
	break;
    case 'g':		/* merge graphics files */
	++gflg;
	break;
    case 'c':		/* concatenate files */
	++cflg;
	break;
    case 'm':		/* change global magnification */
	if ((*argvp)[0][2]=='\0') {
	    if (*argcp>1) {
		--*argcp;
		sscanf( *++(*argvp), "%d", &magarg);
		};
	    }
	else {
	    sscanf( &((*argvp)[0][2]), "%d", &magarg);
	    };
	break;
    case 'o': 		/* send output to file */
	if ((*argvp)[0][2]=='\0') {
	    if (*argcp > 1) {
		--*argcp;
		s = *++(*argvp);
		};
	    }
	else {
	    s = &((*argvp)[0][2]);
	    };
	if (firstfile) outputarg = s;
	else fprintf(stderr,"The -o option must precede the file names.\n");
	break;
    case 'p':
	if ((*argvp)[0][2]=='\0') {
	    if (*argcp > 1) {
		--*argcp;
		pagearg = *++(*argvp);
		};
	    }
	else {
	    pagearg = &((*argvp)[0][2]);
	    };
	count = 0;
	prp = &pagerec[pagerecs];
	while (true) {
	    if (*pagearg=='.') {	/* empty count specifier */
		++count;  ++pagearg;
		continue;
		};
	    prp->count = count;	/* non-empty --- fill in count */
	    if (*pagearg=='x' || *pagearg=='X') {	/* minimum low value */
		prp->low = MININT; ++pagearg;
		}
	    else {					/* explicit low value */
		sign = 1;
		if (*pagearg=='-') { sign = -1; ++pagearg; };
		value = 0;
		while (isdigit(*pagearg)) value = 10*value + (*pagearg++)-'0';
		prp->low = sign*value;
		};
	    if (*pagearg!='-') prp->high = prp->low; /* no high value */
	    else if (*++pagearg=='x' || *pagearg=='X') {    /* max high value */
		prp->high = MAXINT; ++pagearg;
		}
	    else {				/* explicit high value */
		sign = 1;
		if (*pagearg=='-') { sign = -1; ++pagearg; };
		value = 0;
		while (isdigit(*pagearg)) value = 10*value + (*pagearg++)-'0';
		prp->high = sign*value;
		};
	    prp = &pagerec[++pagerecs];		/* move to new record */
	    if (*pagearg=='.') ++count;
	    if (*pagearg=='\0') break;
	    if (*pagearg!='.' && *pagearg!=',') 
		Error(2, "Bad page specifier: %s", **argvp);
	    ++pagearg;
	    };
	prp->count = -1;			/* end with dummy record */
	prp->low = prp->high = 0;
	++pagerecs;
	break;
default:
	Error(0, "Unknown option: %s", **argvp);
	break;
    }
}
\f



dump_options()
{
int i;
    fprintf(stderr,"dflg=%d gflg=%d iflg=%d cflg=%d mag=%d output=%s\n",
		dflg, gflg, iflg, cflg, magarg, outputarg);
    if (pagerecs>0) {
	fprintf(stderr,"Pages: %3d %3d %3d\n",
		pagerec[0].count, pagerec[0].low, pagerec[0].high);
	for (i=1;i<pagerecs-1;i++) {
	    fprintf(stderr,"       %3d %3d %3d\n",
		pagerec[i].count, pagerec[i].low, pagerec[i].high);
	    };
	};
}
\f



edit_dvifile(filearg)
char *filearg;
{
int cmd;
long firstpage;
    filename = filearg;
    if (pagerecs>0) --pagerecs;		/* mark end of page specs */
    pagerec[pagerecs].count = -1;
    pagerec[pagerecs++].low = -1;
    dviindex = OpenFile(filename,"r");		/* open file */
    if (dviindex<0) {
	Error(2,"Can't open %s", filename);
	};
    ReadFromFile(dviindex);
    GotoByte(0);				/* read preamble */
    do cmd = GetByte(); while (cmd==NOP);
    if (cmd!=PRE) Error(2,"%s doesn't start with preamble", filename);
    get_preamble(&preamble);
    copy_preamble(&preamble);				/* initialize output */
    firstpage = WhereIsRead();
    preload_fonts();				/* get fonts from postamble */
    GotoByte(firstpage);
    do {				/* then read the rest of the file */
	cmd = GetByte();
#ifdef DEBUG
	if (dflg>=EVERYCMD) fprintf(Vfp,"cmd(%d)=%d ", WhereIsRead()-1,cmd);
#endif
	switch (cmd) {
	    case BOP:
		++curpage;
		read_page();
		break;
	    case NOP:
		break;
	    case FNTDEF1:
		define_font(1,false);
		break;
	    case FNTDEF2:
		define_font(2,false);
		break;
	    case FNTDEF3:
		define_font(3,false);
		break;
	    case FNTDEF4:
		define_font(4,false);
		break;
	    case POST:
		break;
	    default:
		Error(2,"Bad command (%o) at byte %d", cmd, WhereIsRead()-1);
		break;
	    };
	} while (cmd!=POST);
    inpostamble = true;		/* read postamble */
    get_postamble(&postamble);
    copy_postamble(&postamble);
#ifdef DEBUG
    if (dflg>=EVERYAMBLE) dump_postamble(Vfp,&postamble);
#endif
    do {					/* read until postpostamble */
	cmd=GetByte();	
	switch (cmd) {
	    case NOP:
		break;
	    case FNTDEF1:
		define_font(1,false);
		break;
	    case FNTDEF2:
		define_font(2,false);
		break;
	    case FNTDEF3:
		define_font(3,false);
		break;
	    case FNTDEF4:
		define_font(4,false);
		break;
	    case POSTPOST:
		get_postpostamble(&postpostamble);
#ifdef DEBUG
		if (dflg>=EVERYAMBLE) dump_postpostamble(Vfp,&postpostamble);
#endif
		break;
	    default:
		Error(2,"Bad command (%o) at byte %d", cmd, WhereIsRead()-1);
		break;
	    };
	} while (cmd!=POSTPOST);
    pagerecs = 0;				/* reset page specs */
    firstfile = false;				/* finished with first file */
}
\f



read_page()
{
int cmd;
long prevpageptr;
int curcount, curval;
bool allcountsOK, curcountOK;
int i;
PAGERECORD *prp;
long tmp;
COUNTREGS cr;		/* count registers */
#ifdef DEBUG
    if (dflg>=EVERYPAGE) fprintf(Vfp,"Page %d...\n",curpage);
#endif
    get_counts(cr);		/* read count registers */
    prevpageptr = Get4Byte();	/* remember address of previous page */
    allcountsOK = curcountOK = true;	/* see if this page was selected */
    curcount = -2;			/* first count is a new count */
    for (i=0;;++i) {			/* for each page spec ... */
	prp = &pagerec[i];
	if (prp->count != curcount) {	/* if new count, see if last matched */
	    curcount = prp->count;  
	    allcountsOK = allcountsOK && curcountOK;
	    curcountOK = false;
	    };
	if (prp->count != -1) {		/* see if present count matches */
	    curval = cr[curcount];
	    if (prp->low<=curval && curval<=prp->high) {
		curcountOK = true;
		};
	    }
	else {				/* end of clause; see if all match */
	    if (allcountsOK || prp->low==-1) break;
	    allcountsOK = curcountOK = true;	/* prepare for next clause */
	    curcount = -2;
	    };
	};
    if (iflg>0) {			/* ask user whether to copy page */
	ReadFromFile(stdinindex);
	fprintf(stderr,"\nPage ");
	display_counts(cr,stderr);
	fprintf(stderr," (%c) ? ", allcountsOK? 'y' : 'n');
	getline(answer,MAXLINELEN);
	if (*answer=='y' || *answer=='Y') allcountsOK=true;
	if (*answer=='n' || *answer=='N') allcountsOK=false;
	if (*answer=='s' || *answer=='S') iflg=0;
	ReadFromFile(dviindex);
	};
    if (allcountsOK) {			/* prepare to copy page */
	WriteToFile(outindex);
	tmp = lastpageptr;
	lastpageptr = WhereIsWrite();
	PutByte(BOP);			/* write page header */
	write_counts(cr);
	Put4Byte(tmp);
	master_post.pagecount++;	/* increment number of pages */
	if (Vflg) {
	    fprintf(Vfp," [");
	    display_counts(cr,Vfp);
	    };
	}
    else {				/* or copy it to /dev/null */
	WriteToFile(nullindex);
	};
    copy_page();
    if (allcountsOK) {
	if (Vflg) fprintf(Vfp,"]");
	};
    return(prevpageptr);
}

display_counts(cr,fp)
COUNTREGS cr;
FILE *fp;
{
int i,k;
    k=0;
    for (i=0;i<10;++i) {
	if (cr[i]!=0) {
	    for (++k;k<i;++k) fprintf(fp,".");
	    fprintf(fp,"%d",cr[i]);
	    k=i;
	    };
	};
}

copy_page()
{
int cmd;
    do {			/* Command interpreter */
	cmd = GetByte();
#ifdef DEBUG
	if (dflg>=EVERYCMD) fprintf(Vfp, "cmd(%d)=%o ",WhereIsRead()-1,cmd);
#endif
	if (cmd<FNTDEF1 || FNTDEF4<cmd)
	    PutByte(cmd);		/* copy the command */
	if (SETCHAR<=cmd && cmd<SET1) {
	    continue;
	    };
	if (FNTNUM<=cmd && cmd<FNT1) {
	    changefont(cmd-FNTNUM,false);
	    continue;
	    };
	switch (cmd) {
	    case SET1: 
		PutByte(GetByte());
		break;
	    case SET2: 
		Put2Byte(Get2Byte());
		break;
	    case SET3: 
		Put3Byte(Get3Byte());
		break;
	    case SET4: 
		Put4Byte(Get4Byte());
		break;
	    case SETRULE: 
		Put4Byte(Get4Byte());
		Put4Byte(Get4Byte());
		break;
	    case PUT1: 
		PutByte(GetByte());
		break;
	    case PUT2: 
		Put2Byte(Get2Byte());
		break;
	    case PUT3: 
		Put3Byte(Get3Byte());
		break;
	    case PUT4: 
		Put4Byte(Get4Byte());
		break;
	    case PUTRULE: 
		Put4Byte(Get4Byte());
		Put4Byte(Get4Byte());
		break;
	    case NOP: 
		break;
	    case BOP: 
		Error(2,"BOP in middle of page at byte %d", WhereIsRead()-1);
		break;
	    case EOP: 
		break;
	    case PUSH: 
		break;
	    case POP: 
		break;
	    case RIGHT1: 
		PutByte(GetByte());
		break;
	    case RIGHT2: 
		Put2Byte(Get2Byte());
		break;
	    case RIGHT3: 
		Put3Byte(Get3Byte());
		break;
	    case RIGHT4: 
		Put4Byte(Get4Byte());
		break;
	    case W0: 
		break;
	    case W1: 
		PutByte(GetByte());
		break;
	    case W2: 
		Put2Byte(Get2Byte());
		break;
	    case W3: 
		Put3Byte(Get3Byte());
		break;
	    case W4: 
		Put4Byte(Get4Byte());
		break;
	    case X0: 
		break;
	    case X1: 
		PutByte(GetByte());
		break;
	    case X2: 
		Put2Byte(Get2Byte());
		break;
	    case X3: 
		Put3Byte(Get3Byte());
		break;
	    case X4: 
		Put4Byte(Get4Byte());
		break;
	    case DOWN1: 
		PutByte(GetByte());
		break;
	    case DOWN2: 
		Put2Byte(Get2Byte());
		break;
	    case DOWN3: 
		Put3Byte(Get3Byte());
		break;
	    case DOWN4: 
		Put4Byte(Get4Byte());
		break;
	    case Y0: 
		break;
	    case Y1: 
		PutByte(GetByte());
		break;
	    case Y2: 
		Put2Byte(Get2Byte());
		break;
	    case Y3: 
		Put3Byte(Get3Byte());
		break;
	    case Y4: 
		Put4Byte(Get4Byte());
		break;
	    case Z0: 
		break;
	    case Z1: 
		PutByte(GetByte());
		break;
	    case Z2: 
		Put2Byte(Get2Byte());
		break;
	    case Z3: 
		Put3Byte(Get3Byte());
		break;
	    case Z4: 
		Put4Byte(Get4Byte());
		break;
	    case FNT1: 
		changefont(GetByte(),true);
		break;
	    case FNT2: 
		changefont(Get2Byte(),true);
		break;
	    case FNT3: 
		changefont(Get3Byte(),true);
		break;
	    case FNT4: 
		changefont(Get4Byte(),true);
		break;
	    case XXX1: 
		special(GetByte());
		break;
	    case XXX2: 
		special(Get2Byte());
		break;
	    case XXX3: 
		special(Get3Byte());
		break;
	    case XXX4: 
		special(Get4Byte());
		break;
	    case FNTDEF1:
		define_font(1,false);
		break;
	    case FNTDEF2:
		define_font(2,false);
		break;
	    case FNTDEF3:
		define_font(3,false);
		break;
	    case FNTDEF4:
		define_font(4,false);
		break;
	    case PRE: 
		Error(2,"PRE in middle of page at byte %d", WhereIsRead()-1);
		break;
	    case POST: 
		Error(2,"POST in middle of page at byte %d", WhereIsRead()-1);
		break;
	    case POSTPOST: 
		Error(2,"POSTPOST in middle of page at byte %d", WhereIsRead()-1);
		break;
	    default:
		Error(2,"Unknown opcode %o at byte %d", cmd,WhereIsRead()-1);
		break;
	    };
	} while (cmd != EOP);
}
\f



special(length)
int length;
{
int i;
    for (i=0;i<length;++i) {
	PutByte(GetByte());
	};
}
\f



preload_fonts()
{
int cmd;
int i,j;
FONT *fp;
    ReadFromFile(dviindex);
    GotoFontdefs();
    do {
	cmd = GetByte();
	switch (cmd) {
	    case FNTDEF1:
		define_font(1,true);
		break;
	    case FNTDEF2:
		define_font(2,true);
		break;
	    case FNTDEF3:
		define_font(3,true);
		break;
	    case FNTDEF4:
		define_font(4,true);
		break;
	    case NOP:
		break;
	    case POSTPOST:
		break;
	    default:
		Error(2,"Bad command (%o) at byte %d, in postamble",
			cmd, WhereIsRead()-1);
		break;
	    };
    } while (cmd!=POSTPOST);
}

FONT *find_fontp(fontno)
int fontno;
{
int i;
FONT *fontp;
    if (fontno<CACHEFONTS)
	fontp = fcache[fontno];
    else {
	for (i=0;i<fpalen;++i) {
	    if (fontptrarray[i]->number == fontno) {
		fontp = fontptrarray[i];
		break;
		};
	    };
	if (i>=fpalen) {
	    fontp = NULL;
	    };
	};
    return (fontp);
}

define_font(fnlen,really_define)
int fnlen;
bool really_define;
{
FONTDEF fd;
FONT *fp;
    get_fontdef(&fd, fnlen);
#ifdef DEBUG
    if (dflg>=EVERYFONTDEF)
	dump_fontdef(Vfp,&fd);
#endif
    if (!really_define) return;
    if ((fp=find_fontp(fd.number)) != NULL) {	/* if this is an old font */
	if (strcmp(fp->name,fd.name)!=0 || fp->size!=fd.scalesize) { /* check for consistency */
	    Error(2,"Duplicate font number %d -- %s and %s",
		fd.number, fp->name, fd.name);
	    };
	return;
	}
    WriteToFile(postindex);		/* write new fonts to postamble file */
    write_fontdef(&fd);
    WriteToFile(outindex);			/* and to output */
    write_fontdef(&fd);
    if ( (fp= (FONT *)malloc(sizeof(FONT)))==NULL )
	Error(2,"Cannot allocate memory for %s",fd.name);
    if (fd.number<CACHEFONTS)
	fcache[fd.number] = fp;
    else
	fontptrarray[fpalen++] = fp;
				/* fill in font info */
    allfonts[fonts++] = fp;
    fp->number = fd.number;
    strcpy(fp->name, fd.name);
    fp->size = fd.scalesize;
}

changefont(fontno, fntcmd)
int fontno;
bool fntcmd;
{
    f = fontno;
    fontp = find_fontp(fontno);
    if (fntcmd) {
	if (fontno < 1<<8)		PutByte(fontno);
	else if (fontno < 1<<15)	Put2Byte(fontno);
	else if (fontno < 1<<23)	Put3Byte(fontno);
	else				Put4Byte(fontno);
	};
}
\f



copy_preamble(pap)
PREAMBLE *pap;
{
    if (firstfile) {			/* if this is first file in the list */
	master_pre.version = pap->version;		/* save preamble */
	master_pre.numerator = pap->numerator;
	master_pre.denominator = pap->denominator;
	master_pre.magnification = (magarg==0? pap->magnification : magarg);
	sprintf(master_pre.comment, "dviedit:%.247s", pap->comment);
	master_post.pagecount = 0;	/* initialize number of pages */
	if (outputarg==NULL) {		/* open the output file */
	    outindex = stdoutindex;
	    }
	else {
	    outindex = OpenFile(outputarg,"w");
	    if (outindex<0) {
		Error(2,"Can't open %s", outputarg);
		};
	    };
	WriteToFile(outindex);
	write_preamble(&master_pre);		/* write the preamble */
	}
    else {					/* check for consistency */
	if (pap->version!=master_pre.version)
	    Error(2,"Inconsistent preamble version in %s", filename);
	if (pap->numerator!=master_pre.numerator)
	    Error(2,"Inconsistent preamble numerator in %s", filename);
	if (pap->denominator!=master_pre.denominator)
	    Error(2,"Inconsistent preamble denominator in %s", filename);
	};
}

copy_postamble(pap)
POSTAMBLE *pap;
{
    if (firstfile) {			/* copy postamble */
	master_post.lastpage = -1;
	master_post.numerator = pap->numerator;
	master_post.denominator = pap->denominator;
	master_post.magnification = master_pre.magnification;
	master_post.maxheight = pap->maxheight;
	master_post.maxwidth = pap->maxwidth;
	master_post.maxstack = pap->maxstack;
	}
    else {				/* increase maxima */
	if (pap->maxheight>master_post.maxheight)
	    master_post.maxheight = pap->maxheight;
	if (pap->maxwidth>master_post.maxwidth)
	    master_post.maxwidth = pap->maxwidth;
	if (pap->maxstack>master_post.maxstack)
	    master_post.maxstack = pap->maxstack;
	};
}

cleanup()
{
int cmd;
FONTDEF fd;
    WriteToFile(postindex);		/* mark end of postamble file */
    PutByte(POSTPOST);
    CloseFile(postindex);
    WriteToFile(outindex);		/* write postamble in output file */
    master_post.lastpage = lastpageptr;
    master_postpost.postptr = WhereIsWrite();
    master_postpost.version = master_pre.version;
    write_postamble(&master_post);
    postindex = OpenFile(postfile,"r");	/* write font definitions */
    if (postindex<0) Error(2,"Can't reopen temp file %s", postfile);
    ReadFromFile(postindex);
    GotoByte(0);
    do {			
	cmd = GetByte();
	switch(cmd) {
	    case FNTDEF1:
		get_fontdef(&fd,1);
		write_fontdef(&fd);
		break;
	    case FNTDEF2:
		get_fontdef(&fd,2);
		write_fontdef(&fd);
		break;
	    case FNTDEF3:
		get_fontdef(&fd,3);
		write_fontdef(&fd);
		break;
	    case FNTDEF4:
		get_fontdef(&fd,4);
		write_fontdef(&fd);
		break;
	    case POSTPOST:
		break;
	    default:
		Error(2,"Bad command (%0) in postamble file:", cmd);
	    };
	} while (cmd!=POSTPOST);
    write_postpostamble(&master_postpost);	/* write postpostamble */
    PutByte(DVIPAD);				/* write padding */
    PutByte(DVIPAD);
    PutByte(DVIPAD);
    PutByte(DVIPAD);
    CloseFile(postindex);
    unlink(postfile);
    if (Vflg) fprintf(Vfp,"\nDone!\n");
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'dviedit.h'" '(1257 characters)'
if test -f 'dviedit.h'
then
	echo shar: will not over-write existing file "'dviedit.h'"
else
cat << \SHAR_EOF > 'dviedit.h'
typedef int bool;
#define true	 1
#define false	 0
#define MAXINT	 2147483647
#define MININT	 -2147483648
#define  MIN(A, B)   ((A) < (B) ? (A):(B) )
#define  MAX(A, B)   ((A) > (B) ? (A):(B) )

#define MAX_FONTS 64		/* maximum number of fonts in one document */
#define MAXLOADEDFONTS 10	/* number of TeX fonts LN01 can load at once */
#define MAXSTACKDEPTH 51	/* stack size */
#define MAXNAMESIZE 80		/* length of file names */
#define OUTLINELENGTH 79	/* length of output lines */
#define CACHEFONTS 64		/* store first few fonts in buckets */
#define TABLEFONTS MAX_FONTS	/* remaining fonts in unordered table */
#define MAXLINELEN 200		/* length of input lines */

#define MAXPAGERECS 100		/* number of page specifiers allowed */

typedef struct {	    /* A font */
	int number;		/* Number, from DVI file */
	char name[MAXNAMESIZE];	/* Name */
	long size;		/* (Scaled) size in DVIs */
	bool loaded;		/* True when downloaded to LN01 */
	} FONT;

typedef struct {	/* A page specifier record */
	int count;		/* which counter to test */
	int low;		/* low end of range */
	int high;		/* high end of range */
	} PAGERECORD;

typedef struct {long h,v,w,x,y,z,hh,vv} STACKITEM;

#define EVERYPAGE	1
#define EVERYAMBLE	2
#define	EVERYFONTDEF	3
#define EVERYCMD	4
SHAR_EOF
fi # end of overwriting check
echo shar: done with directory "'ln01'"
cd ..
#	End of shell archive
exit 0