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

⟦274a91aa0⟧ TextFile

    Length: 101382 (0x18c06)
    Types: TextFile
    Notes: Uncompressed file

Derivation

└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
    └─⟦17e2956c5⟧ »./DVIware/obsolete/imagen.sh.Z« 
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦17e2956c5⟧ »DVIware/obsolete/imagen.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:
#	./imagen
# This archive created: Fri Mar 11 16:12:04 1988
export PATH; PATH=/bin:$PATH
if test ! -d './imagen'
then
	mkdir './imagen'
fi
cd './imagen'
if test -f 'NOTICE'
then
	echo shar: will not over-write existing file "'NOTICE'"
else
cat << \SHAR_EOF > 'NOTICE'
The imagen driver is obsolete and not maintained. Source code
can be found in the imagen.sh file in ../   If you need it
uncompress imagen.sh and run it through sh.  These empty
directories are here for your convenience.
SHAR_EOF
fi # end of overwriting check
if test -f 'NewImagenNote'
then
	echo shar: will not over-write existing file "'NewImagenNote'"
else
cat << \SHAR_EOF > 'NewImagenNote'
From morgan.uci@Rand-Relay  Fri Mar 11 02:50:29 1983
Return-Path: <Morgan.UCI.UCI@Rand-Relay>
Date: 10 Mar 83 22:50:46 PST (Thu)
From: Tim Morgan <morgan.uci@Rand-Relay>
Subject: dvi-imagen program
To: pavel@Cornell
Via:  UCI; 10 Mar 83 23:19-PDT
Status: R

I'm one of the two people here who made slight changes in dvi-imagen.c
to make it run with the version of the software in the Imagen we
have here.  The major problem was that the line

	@document(language imPress, jobheader on)

must appear in the impress file.  Fortunately, whenever Imagen changed
their software, they provided a switch on ipr to add that information
to the imp file when spooled.  Actually, there are two switches,

	-LimPress
and
	-Djobheader on

(language imPress and docdoheader "jobheader on").  I'm not sure the
-D switch is needed, but without the language spec, the software in the
Imagen just prints a fatal error message and stops with only a banner page.

The other problem was the information that TeX puts in the DVI file
at the beginning, the date and so forth.  That apparently was being
copied into the impress file, which then was shipped verbatim to the
Imagen, resulting in undefined glyph errors.  We simply put an
#ifndef UciHacks ... #endif around the 2 or so lines of code that put
the info into the impress file, and that seemed to fix the problem.

I've been using the program in that state for about a day and a half,
and things which got to the Imagen all seemed ok.  Note that the error
routines were not loaded in.  Of course, it bombed when a the specified
file didn't exist, and I've been able to create some .dvi files which
also caused it to bomb.  The error routines are being added now, and if
that provides some information as to what's going on, I'll let you know.
Alternately, I can mail you the .tex file which lead to the error (it's
short).

		Tim Morgan
		morgan.uci@rand-relay


SHAR_EOF
fi # end of overwriting check
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
The device driver for the Imagen was originally written by Pavel Curtis of
Cornell University.  Subsequently, Mike Urban at TRW revised the driver.
Ralph Campbell of Berkeley made modifications to bring things over to 4.2
bsd.

This software is not supported by the Imagen Corporation.  Problems should
be reported to the Unix TeX Site Coordinator.

The version in this directory is for 4.1bsd.  See ./4.2note for information
on modifications to get to 4.2bsd.

Below are excerpts from messages from Mike Urban describing what is
different between this version and the previous one.

 1-Nov-83 01:12:19-PST,1733;000000000011
Return-Path: <trw-unix!trwspp!urban@Berkeley>
Received: from ucbvax.ARPA (UCB-VAX.ARPA) by WASHINGTON.ARPA with TCP; Tue 1 Nov 83 01:12:15-PST
Received: by ucbvax.ARPA (4.16/4.13)
	id AA27692; Tue, 1 Nov 83 01:12:40 pst
From: trw-unix!trwspp!urban@Berkeley (Mike Urban)
Date: Friday, 28 Oct 1983 13:59-PDT
Subject: dvi-imagen
Message-Id: <8310282059.AA17910@trwspp.UUCP>
To: Richard Furuta <furuta@WASHINGTON.ARPA>
Reply-To: Mike Urban <urban@rand-unix.ARPA>

   By the way, I've done some heavy mucking with dvi-imagen
around here.  The major changes are:

	-s produces its output on standard output instead
	   of making you hunt the output down in /tmp as it
	   previously did.
	-cN produces N copies.
	-L produces the output in Landscape mode (this is
	   done rather badly as I stupidly rotate EVERY
	   glyph, but it does work, if slowly); this item
	   is required for the Reference-card thingy.
	-U disables the usual centering on the page, moving
	   things to the upper-left corner of the page.

        \special{xxx} now works where xxx is one of
		insert(filename)
		overlay(filename)
	filename is taken to refer to an IMPRESS file which
	is either inserted with the current point as the
	origin, or overlaid on the page.  This code was
	adapted from Imagen's dvi-2 driver.

   As noted, some of the code is somewhat kludgy, but it
works well enough for us to get graphics output from the
USG "stat" tools onto pretty viewgraphs in landscape mode,
which is the sort of thing that management types think is
the ultimate purpose of computer science.
   D'you want me to send you this stuff, should I sit on it
until it looks cleaner, or should I send it to someone else?

	Mike
=============================================================
 8-Nov-83 03:15:01-PST,94926;000000000001
Return-Path: <trw-unix!trwspp!urban@Berkeley>
Received: from ucbvax.ARPA (UCB-VAX.ARPA) by WASHINGTON.ARPA with TCP; Tue 8 Nov 83 03:13:47-PST
Received: by ucbvax.ARPA (4.16/4.13)
	id AA18261; Tue, 8 Nov 83 03:12:36 pst
From: trw-unix!trwspp!urban@Berkeley (Mike Urban)
Date: Monday,  7 Nov 1983 11:40-PST
Subject: dvi-imagen sources
Message-Id: <8311071941.AA00471@trwspp.UUCP>
To: furuta@washington.ARPA (Richard Furuta)

Following is a uuencoded version of a tar file of my
current copy of the dvi-imagen sources.  Let me know if you
get this message, and were able to extract everything
correctly.

When I installed the magstep fixes, I noticed that the
magnification from the DVI preamble wasn't getting
multiplied in.  Sure enough, when I ran a document with
\magnification=\magstep 2 at the beginning, all the spacing
was enlarged, but the glyphs were still unmagnified.  I
considered that this was a bug, not a feature, and fixed
it.

As I said before, the rotation stuff is done inefficiently,
but it does seem to work.  I should also note that
attempting to print a document with a width wider than the
physical paper width (e.g. forgetting to print a
landscape-mode thingy with the -L landscape option) usually
causes the Imagen to abort the job with no output and a
mysterious error message.  At least, OUR machine behaves
that way.

Finally, I include a copy of the manual page.  We name the
binary for dvi-imagen "iptex" to make it resemble the other
Imagen spooling commands (iprint, ipr, ipq).  Many of our
users are easily confused by names like "dvi-imagen".

   Cheers,

	Mike
================================================================
SHAR_EOF
fi # end of overwriting check
if test -f '4.2dvif.sh'
then
	echo shar: will not over-write existing file "'4.2dvif.sh'"
else
cat << \SHAR_EOF > '4.2dvif.sh'
#! /bin/csh -f
#
# DVI 2 filter for the imagen
#

umask 0
set name=() host=()
top:
	if ($#argv > 0) then
		switch ($argv[1])
		case -n:
			shift argv
			if ($#argv > 0) then
				set name = $argv[1]
				shift argv
			endif
			goto top
		case -h:
			shift argv
			if ($#argv > 0) then
				set host = $argv[1]
				shift argv
			endif
			goto top
		default:
			shift argv
			goto top
		endsw
	endif
onintr cleanup
echo Converting DVI output > /usr/spool/ipd/status
/usr/local/lib/dvi-imagen -s > /tmp/imp$$
(echo -n \@document\(owner \"$name\", site \"$host\", spooldate \"`date`\", \
    language \"imPress\", jobheader on, jamresistance on\) ; \
    cat /tmp/imp$$ ) | /usr/local/lib/ips -s
/bin/rm -f /tmp/imp$$
exit(0)

cleanup:
/bin/rm -f /tmp/imp$$
exit(1)
SHAR_EOF
fi # end of overwriting check
if test -f '4.2Note'
then
	echo shar: will not over-write existing file "'4.2Note'"
else
cat << \SHAR_EOF > '4.2Note'
Berkeley has moved some include files around in 4.2bsd.  If you are running
an imagen and 4.2bsd, this will be of interest to you (thanks to Brown
University for tracking it down):

	From jsb Mon Nov 21 23:59:00 1983
	Date:     21 Nov 83 (Monday) 23:58 EST
	From:     John Bazik <jsb>
	To:       jsv
	Subject:  changes to =devices/imagen for 4.2
	
	There are two changes that have to be made.
	
	In dvi-imagen.c change #include <unctrl.h> to #include <curses.h>
	
	In ipr.h change #include <dir.h> to #include <sys/dir.h>

=================

It is also possible to integrate this stuff into the Berkeley line printer
software as described in the following note and subsequent diff listing.
Here's the note:
=================
From ralph%ucbarpa@Berkeley Thu Dec  1 11:18:39 1983
Return-Path: <ralph%ucbarpa@Berkeley>
Received: from UCB-VAX.ARPA by WASHINGTON.ARPA with TCP; Wed 30 Nov 83 18:31:09-PST
Received: from ucbarpa.ARPA by UCB-VAX.ARPA (4.22/4.16)
	id AA04286; Wed, 30 Nov 83 17:04:09 pst
Received: by ucbarpa.ARPA (4.22/4.16)
	id AA10306; Wed, 30 Nov 83 16:43:07 pst
From: ralph%ucbarpa@Berkeley (Ralph Campbell)
Message-Id: <8312010043.AA10306@ucbarpa.ARPA>
Date: 30 Nov 1983 1643-PST (Wednesday)
To: Richard Furuta <Furuta@WASHINGTON.ARPA>
Subject: Re: Interested in testing out some Imagen software?
Cc: harrison%ucbarpa@Berkeley
In-Reply-To: Your message of Thu 17 Nov 83 18:54:43-PST.
             <8311180254.AA02253@ucbarpa.ARPA>
ReSent-date: Thu 1 Dec 83 03:50:05-PST
ReSent-from: Richard Furuta <Furuta@WASHINGTON.ARPA>
ReSent-to: furuta@UW-JUNE.ARPA

I have installed the imagen software you sent as our standard dvi-imagen
program and it seems to work. I haven't tried to use the landscape
option yet. I did need to make a few changes for 4.2 and the line printer
software here (We don't use most of what imagen sends, (ipr, ipq, iprm, etc.).
The changes are:
	dvi-imagen.c: uncntrl.h is in curses.h.
	dvi-imagen.c: if no file specified, uses stdin.
	ipr.h: include stat.h & dir.h -> sys/stat.h, sys/dir.h
	output.c: printf changed to remark so output is valid.
==========================
and here's a diff of the changes:
==========================
diff -c -r -b tex82work/newimagen/dvi-imagen.c 4.2stuff/imagen/dvi-imagen.c
*** tex82work/newimagen/dvi-imagen.c	Mon Nov  7 09:45:49 1983
--- 4.2stuff/imagen/dvi-imagen.c	Mon Nov 28 11:06:28 1983
***************
*** 22,28
  */
  
  #include <stdio.h>
! #include <unctrl.h>
  #include <pwd.h>
  #include "dvi.h"
  #include "font.h"

--- 22,28 -----
  */
  
  #include <stdio.h>
! #include <curses.h>
  #include <pwd.h>
  #include "dvi.h"
  #include "font.h"
***************
*** 36,42
                                       /* 8 inches of printing area */
  #define PIXELS_PER_PAGE      (11 * 240)
                                       /* 11 inches of printing area */
! #define FONT_DIRECTORY       "/usr/lib/tex/fonts"
  
  #define pixel_round(x)      ((long) (conv * (double) (x) + 0.5))
  #define dvi_round(x)        ((long) ((double) (x) / conv + 0.5))

--- 36,42 -----
                                       /* 8 inches of printing area */
  #define PIXELS_PER_PAGE      (11 * 240)
                                       /* 11 inches of printing area */
! #define FONT_DIRECTORY       "/usr/local/fonts/pixel"
  
  #define pixel_round(x)      ((long) (conv * (double) (x) + 0.5))
  #define dvi_round(x)        ((long) ((double) (x) / conv + 0.5))
***************
*** 73,79
  double      conv;
  long        numerator, denominator, magnification;
  char        *output_file_name;
! char        *Usage_str = "Usage: iptex [-U] [-L] [-v] [-s] [-d] <dvi-file>";
  
  long            read_postamble();
  unsigned long   num();

--- 73,79 -----
  double      conv;
  long        numerator, denominator, magnification;
  char        *output_file_name;
! char        *Usage_str = "Usage: dvi-imagen [-U] [-L] [-v] [-s] [-d] [dvi-file]";
  
  long            read_postamble();
  unsigned long   num();
***************
*** 89,95
  	long    last_page;     /* file offset of last page of output */
  	int	nc;
  
!         while (argv[1][0] == '-')
  	{
  	    switch (argv[1][1])
  	    {

--- 89,95 -----
  	long    last_page;     /* file offset of last page of output */
  	int	nc;
  
!         while (argc > 1 && argv[1][0] == '-')
  	{
  	    switch (argv[1][1])
  	    {
***************
*** 130,136
              argc--;
  	}
          
!         if (argc != 2)
              error(Usage_str);
  
  	if ((fp = fopen(argv[1], "r")) == NULL) {

--- 130,136 -----
              argc--;
  	}
  
!         if (argc > 2)
              error(Usage_str);
  
  	if (argc == 2) {
***************
*** 133,139
          if (argc != 2)
              error(Usage_str);
  
! 	if ((fp = fopen(argv[1], "r")) == NULL) {
  	    char longername[256];
  	    strcpy (longername, argv[1]);
  	    strcat (longername, ".dvi");

--- 133,139 -----
          if (argc > 2)
              error(Usage_str);
  
! 	if (argc == 2) {
  	    char longername[256];
  
  	    if ((fp = freopen(argv[1], "r", stdin)) == NULL) {
***************
*** 135,140
  
  	if ((fp = fopen(argv[1], "r")) == NULL) {
  	    char longername[256];
  	    strcpy (longername, argv[1]);
  	    strcat (longername, ".dvi");
  	    if ((fp = fopen (longername, "r")) == NULL)

--- 135,142 -----
  
  	if (argc == 2) {
  	    char longername[256];
+ 
+ 	    if ((fp = freopen(argv[1], "r", stdin)) == NULL) {
  		strcpy (longername, argv[1]);
  		strcat (longername, ".dvi");
  		if ((fp = freopen(longername, "r", stdin)) == NULL)
***************
*** 137,143
  	    char longername[256];
  	    strcpy (longername, argv[1]);
  	    strcat (longername, ".dvi");
! 	    if ((fp = fopen (longername, "r")) == NULL)
  		error("dvi-imagen: Can't open %s", argv[1]);
  	}
  	strcpy (InputName, argv[1]);

--- 139,145 -----
  	    if ((fp = freopen(argv[1], "r", stdin)) == NULL) {
  		strcpy (longername, argv[1]);
  		strcat (longername, ".dvi");
! 		if ((fp = freopen(longername, "r", stdin)) == NULL)
  		    error("dvi-imagen: Can't open %s", argv[1]);
  	    }
  	    strcpy (InputName, argv[1]);
***************
*** 141,146
  		error("dvi-imagen: Can't open %s", argv[1]);
  	}
  	strcpy (InputName, argv[1]);
  	    
  	process_preamble(fp);
  	

--- 143,152 -----
  		    error("dvi-imagen: Can't open %s", argv[1]);
  	    }
  	    strcpy (InputName, argv[1]);
+ 	} else {
+ 	    fp = stdin;
+ 	    strcpy (InputName, "stdin");
+ 	}
  
  	process_preamble(fp);
  
***************
*** 388,393
          long    glyph_ptr[128];     /* Seek locations of each glyph */
          int     i, j, k;
  	
  	realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
  	unmodsize = (realsize * 1000) + 0.5;
  	/* a real hack to correct for rounding in some cases -- rkf */

--- 394,404 -----
          long    glyph_ptr[128];     /* Seek locations of each glyph */
          int     i, j, k;
  
+ 	if (debug)
+ 		remark("scale = %d, design = %d", fontp->scale, fontp->design);
+ #ifdef OLD
+  	realsize = ((float) fontp->scale / fontp->design);
+ #else
  	realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
  #endif
  	unmodsize = (realsize * 1000) + 0.5;
***************
*** 389,394
          int     i, j, k;
  	
  	realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
  	unmodsize = (realsize * 1000) + 0.5;
  	/* a real hack to correct for rounding in some cases -- rkf */
  	if(unmodsize==1095) realsize = 1.095445;	/* stephalf */

--- 400,406 -----
   	realsize = ((float) fontp->scale / fontp->design);
  #else
  	realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
+ #endif
  	unmodsize = (realsize * 1000) + 0.5;
  	if (debug)
  		remark("real = %g, unmod = %d", realsize, unmodsize);
***************
*** 390,395
  	
  	realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
  	unmodsize = (realsize * 1000) + 0.5;
  	/* a real hack to correct for rounding in some cases -- rkf */
  	if(unmodsize==1095) realsize = 1.095445;	/* stephalf */
  	else if(unmodsize==1315) realsize=1.314534;	/* stepihalf */

--- 402,409 -----
  	realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
  #endif
  	unmodsize = (realsize * 1000) + 0.5;
+ 	if (debug)
+ 		remark("real = %g, unmod = %d", realsize, unmodsize);
  	/* a real hack to correct for rounding in some cases -- rkf */
  	if(unmodsize==1095) realsize = 1.095445;	/* stephalf */
  	else if(unmodsize==1315) realsize=1.314534;	/* stepihalf */
***************
*** 413,418
              }
  	}
  
  	fseek(pxlfp, - (5 * 4L), 2);        /* Seek to trailer info   */
          checksum      = four(pxlfp);
          magnify = four(pxlfp);

--- 427,435 -----
              }
  	}
  
+ 	if (debug)
+ 		remark("read font %s", filename);
+ 
  	fseek(pxlfp, - (5 * 4L), 2);        /* Seek to trailer info   */
          checksum      = four(pxlfp);
          magnify = four(pxlfp);
***************
*** 532,538
  	}
  	else
          	ImPressStart((char *)0, job_id, verbose);
- 	
  }
  
  \f



--- 549,554 -----
  	}
  	else
          	ImPressStart((char *)0, job_id, verbose);
  }
  
  \f


diff -c -r -b tex82work/newimagen/ipr.h 4.2stuff/imagen/ipr.h
*** tex82work/newimagen/ipr.h	Fri May 20 11:39:14 1983
--- 4.2stuff/imagen/ipr.h	Fri Nov 18 11:38:57 1983
***************
*** 20,27
  # define LineSize 128			/* size of a data line */
  
  # include <sys/types.h>
! # include <dir.h>
! # include <stat.h>
  # include <signal.h>
  # include <stdio.h>
  # include "c.h"

--- 20,27 -----
  # define LineSize 128			/* size of a data line */
  
  # include <sys/types.h>
! # include <sys/dir.h>
! # include <sys/stat.h>
  # include <signal.h>
  # include <stdio.h>
  # include "c.h"
diff -c -r -b tex82work/newimagen/output.c 4.2stuff/imagen/output.c
*** tex82work/newimagen/output.c	Tue Oct 25 14:50:38 1983
--- 4.2stuff/imagen/output.c	Wed Nov 23 11:10:09 1983
***************
*** 422,428
       register struct font **fp;
       
       if (debug) 
!         printf( "Begin page, Needed = %d, available = %d\n",
  		 MemoryNeeded, MemoryAvailable );
       if (MemoryNeeded >= MemoryAvailable) ImPressDeleteGlyphs();
  

--- 422,428 -----
       register struct font **fp;
       
       if (debug) 
!         remark( "Begin page, Needed = %d, available = %d\n",
  		 MemoryNeeded, MemoryAvailable );
       if (MemoryNeeded >= MemoryAvailable) ImPressDeleteGlyphs();
 
SHAR_EOF
fi # end of overwriting check
if test -f 'special.c'
then
	echo shar: will not over-write existing file "'special.c'"
else
cat << \SHAR_EOF > 'special.c'
#include <stdio.h>
#include "resfonts.h"
#include "imPcodes.h"

#define white(x) (x==' ' || x=='\t')
char *index(),*rindex();

extern int landscape;

typedef char bool;
#define TRUE 1
#define FALSE 0
DoSpecial(bytes,fp) long bytes; FILE *fp;
{
	static bool initfonts=FALSE;
	bool first;
	unsigned long size, tempsize;
	FILE *tempin;
	char *ai,*bi,*ci,*di,*ei,*fi;
	char inchar;	
	int  tempi;
	int  i;
	enum spectype {INSERT, OVERLAY};
	enum spectype optype;

	ai = bi = (char *) malloc((tempsize = bytes)+1);
	while (tempsize--) *bi++=(char) fgetc(fp);
	*bi='\0'; /* null out string */
	bi = ai;
	if (size > 132){
		fprintf(stderr, "special command > 132 characters\n");
		free(ai);
		return;
	}

	while(white(*bi)) bi++;		/* skip leading white space */
	ei = ci = bi;

	if (!index(ei,'(') || !rindex(ei,')')){ 	/* check for leading and trailing *\
			  fprintf(stderr, "incorrect special format\n"); /* prens */
		free(ai);
		return;
	}

	while (!white(*ci) && *ci != '(' ) ci++;  /* skip non white till ( or white */
	*ci='\0';				/* make a string of it */
	while (*ei){				/* and lowercase it all */
		if (*ei >= 'A' && *ei <= 'Z') *ei = *ei + 'a' - 'A';
		ei++;
	}
	if (!strcmp("insert",bi)) 		/* find include, overlay, or */
		optype = INSERT;
	else if (!strcmp("overlay",bi)) 	/* else it is an error */
		optype = OVERLAY;
	else {
		fprintf(stderr,
		"special command operation must be 'insert' or 'overlay'\n");
		free(ai);
		return;
	}

	bi = ++ci;
	while(white(*bi) || *bi == '(' ) bi++;	/* find the file name */
	while(white(*bi)) bi++;
	ci = bi;
	while(!white(*ci) && *ci != ')') ci++;	/* delimited by a ) */
	*ci = '\0';				/* make a string of it */

	if ((tempin = fopen(bi ,"r")) == NULL){	/* open the file */
		fprintf(stderr, " can't open %s \n",bi);
		free(ai);
		return;
	}
	free(ai);				/* no longer need this */

/*	UpdPos(); */
	ImPressPutc(APUSH);
	switch (optype){
/* At the moment, only overlay(file) and insert(file) are
 * recognized.  We use a slightly modified 'impen' (from Stanford
 * via Imagen to produce this stuff, which makes plots come out
 * in landscape mode.  Hence the rotation and stuff.  Other
 * Impress-production software may, of course, behave differently...
 */
	case OVERLAY:				
		ImPressPutc(APAGE);
		if (landscape) {
			ImPressPutc(AMS);
			ImPressPutc(0104);
		}
		else {
			ImPressPutc(ASABSV);
			ImPressBufWord(2040);	/* 8.5 in down */
			ImPressPutc(AMS);
			ImPressPutc(0147);
			ImPressPutc(APAGE);
		}
		break;

	case INSERT:
		ImPressPutc(AMS);
		if (landscape)
			ImPressPutc(0144);
		else
			ImPressPutc(0147);
		break;
	}
	if (!initfonts) {		/* Haven't initialized res fonts */
		for (i=0;i<N_RES_FONTS; i++) {
			ImPressPutc(ACREFAM);
			ImPressPutc(fontTable[i].family);
			ImPressPutc(1);
			ImPressPutc(0);
			ImPressPrintf("%s",fontTable[i].name);
			ImPressPutc(0);
		}
		initfonts=TRUE;
	}
	first = TRUE;
	while ((tempi = getc(tempin)) != EOF) { 	
		inchar = (char) tempi;
		if (inchar ==  '@' && first) {			/* remove document control */
			while (((inchar = getc(tempin)) != EOF)
			          && (inchar != ')' ));
			tempi = getc(tempin);
		}
		first = FALSE;

		ImPressPutc(tempi);
	}
	ImPressPutc(APAGE);
	ImPressPutc(APOP);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'rotate.c'
then
	echo shar: will not over-write existing file "'rotate.c'"
else
cat << \SHAR_EOF > 'rotate.c'
char *malloc();

char *rotate (glyph, ht, wd) char *glyph; int ht, wd;
{
    int		byteswide;
    int		oldwidth;
    int		byteoff, bitmask, outbitoff, outbit, posn, i;
    char	*opt, *outptr;
    
    if (ht == 0 || wd == 0) return (glyph);
    byteswide = (ht+7)/8;
    oldwidth = (wd+7)/8;

    opt = malloc (1 + byteswide*wd);
    outptr = opt; *outptr = '\0';
    
    for (posn = 0; posn < wd; posn++)	/* Pick the nth bit off each row */
    {
	bitmask = 1 << (7 - (posn%8) );
	byteoff = posn/8;
	outbitoff = 7;
	for (i = 0; i < ht ; i++)	/* Get from each row... */
	{
	    if (outbitoff < 0) {
		outbitoff = 7;
		outptr++; *outptr = '\0';
	    }
	    outbit =(*(glyph + ((ht-i)-1)*oldwidth + byteoff) & bitmask) != 0;
	    *outptr |= outbit << outbitoff;
	    outbitoff--;
    	}
	outptr++; *outptr = '\0';
    }
    return (opt);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'resfonts.h'
then
	echo shar: will not over-write existing file "'resfonts.h'"
else
cat << \SHAR_EOF > 'resfonts.h'
#define TEXTURE_FAMILY 110
#define N_RES_FONTS  8

typedef struct {
	short family;
	char *name;
	}  resfont;


resfont fontTable[]= {
	{	TEXTURE_FAMILY+0,	"textures"},
	{	TEXTURE_FAMILY+1,	"cmasc8"},
	{	TEXTURE_FAMILY+2,	"cmasc10"},
	{	TEXTURE_FAMILY+3,	"cmasc12"},
	{	TEXTURE_FAMILY+4,	"cmasc14"},
	{	TEXTURE_FAMILY+5,	"cmasc7"},
	{	TEXTURE_FAMILY+6,	"cmb18"},
	{	TEXTURE_FAMILY+7,	"IMAGEN80"}
};
SHAR_EOF
fi # end of overwriting check
if test -f 'output.c'
then
	echo shar: will not over-write existing file "'output.c'"
else
cat << \SHAR_EOF > 'output.c'
/*
 * output.c - implements the ImPress output primitives
 *	This is the verbose (decoded) version,
 *	along with the encoded version, default unless
 *	
 *
 * written by Bill Nowicki, September 1981
 * Stanford University
 *
 * January 1982		Bill Nowicki
 *	- Added page buffering
 *	- Added glyph deletion
 */
 
# include <stdio.h>
# include "font.h"
# include "imPcodes.h"
# include "ipr.h"
# include "impress.h"

static struct font *CurrentFont = NULL;
static FILE        *imPressFile = NULL;
static int         Verbose = 0;
static int         MemoryAvailable = GlyphSize;
static int         MemoryNeeded = 0;

extern int	landscape;

  /*
   * The page buffer.  A list of Glyphs, i.e. (font,char) pairs
   * that are needed on this page, and a list of the actual typesetting
   * commands.
   */
static struct font *GlyphTable[GlyphsPerPage];
static char GlyphChars[GlyphsPerPage];
static char PageBuffer[InputSize];
static int GlyphPointer = 0, PagePointer = 0;

ImPressPutc( c )
  {
  	/*
	 * Put the indicated character into the page buffer
	 */
    if (PagePointer>=InputSize) fprintf( stderr, "Input Area overflow\n");
    PageBuffer[PagePointer++] = c;
  }


ImPressBufWord( w )
 {
 	/*
	 * output a (big-endian) word to the ImPress page buffer
	 */
   ImPressPutc( (w>>8)&0377 );
   ImPressPutc( (w)&0377 );
 }


ImPressPrintf( s, arg1, arg2, arg3, arg4, arg5 )
  {
    /*
     * printf the string with arguments into the page buffer
     */
    char buf[512];
    int len;
    sprintf( buf, s, arg1, arg2, arg3, arg4, arg5 );
    len = strlen(buf);
    if (PagePointer+len>=InputSize) fprintf( stderr, "Input Area overflow\n");
    strncpy( PageBuffer+PagePointer, buf, len);
    PagePointer += len;
  }


ImPressFont( f )
 struct font *f;
  {
     /*
      * switch to font f
      */
    if (CurrentFont == f) return;
    if (Verbose)  ImPressPrintf(  "@F %d@", f->Inumber );
        else {
	       ImPressPutc( AF );
	       ImPressPutc( f->Inumber );
	     }
     CurrentFont = f;
  }


ImPressMplus()
{
    if (Verbose)
        ImPressPrintf("@MPLUS@");
    else
        ImPressPutc( AMP );
}


ImPressMminus()
{
    if (Verbose)
        ImPressPrintf("@MMINUS@");
    else
        ImPressPutc( AMM );
}

ImPressMove( deltaX )
  {
    /*
     * Move the X (major axis) coordinate 
     */
   
   if (-128 <= deltaX  &&  deltaX <= 127)
   {
     if (Verbose) ImPressPrintf(  "@M %d@\n", deltaX);
      else {
	     ImPressPutc( AM );
	     ImPressPutc( deltaX );
	     ImPressPutc( AM );
	   }
   } 
   else
   {
     if (Verbose) ImPressPrintf(  "@H %d 1@\n", deltaX);
      else {
	     ImPressPutc( AH );
	     ImPressPutc( (deltaX >> 7) & 0377 );
	     ImPressPutc( (deltaX << 1) & 0376 | 01 );
	   }
   }
  }


ImPressSetX( x )
  {
    /*
     * set the X (major axis) coordinate 
     */
     
     if (Verbose) ImPressPrintf(  "@H %d 0@\n", x);
      else {
	     ImPressPutc( AH );
	     ImPressPutc( (x>>7)&0377 );
	     ImPressPutc( (x<<1)&0376 );
	   }
  }


ImPressSetSpace( s )
  {
    /*
     * set the "word space" value
     */
     
     if (Verbose) ImPressPrintf(  "@SETSP %d@\n", s);
      else {
	     ImPressPutc( ASETSP );
	     ImPressBufWord( s );
	   }
     
  }


ImPressSpace()
  {
     /*
      * do a default word space
      */
    
     if (Verbose) ImPressPrintf(  "@SP0@\n" );
      else ImPressPutc( ASP0 );
  }


ImPressSetY(y)
  {
    /*
     * set the Y (minor axis) coordinate 
     */
     
     
     if (Verbose) ImPressPrintf(  "@V %d 0@\n", y);
      else {
	     ImPressPutc( AV );
	     ImPressPutc( (y>>7)&0377 );
	     ImPressPutc( (y<<1)&0376 );
	   }
  }


ImPressCharacter( c )
 char c;
  {
    /*
     * Output the character c in the current font at the current
     * position.  First we check its state (loaded, wanted, etc.)
     */

   switch (CurrentFont->state[c])
       {
        case Ready:
         	CurrentFont->state[c]=Wanted;
		GlyphChars[GlyphPointer  ]=c;
		GlyphTable[GlyphPointer++]=CurrentFont;
		MemoryNeeded += ImPressSize( CurrentFont, c );
		break;


        case Loaded:
         	CurrentFont->state[c]=Kept;
		GlyphChars[GlyphPointer  ]=c;
		GlyphTable[GlyphPointer++]=CurrentFont;
		break;

        case Wanted:
        case Kept:
        case InProm:
		break;
		
	default:
		remark("Weird state for character %d in font %s\n",
		                                   c, CurrentFont->fontname );
                abort(); 
       }
       
        if (Verbose && c=='@')
            ImPressPrintf( "@AT@" );
	else
            ImPressPutc( c );
   }
  


ImPressGlyph( f, c )
 struct font *f;
 unsigned char c;
  {
    register char *glyph = f->Glyph[c];
    int bytes = (f->W[c]+7) / 8;
    int row, col;

    /*
     * send the indicated glyph in the font f to the Imprint file.
     * "Small" glyphs have all dimensions less than eight bits.
     */
   if (f->W[c] == 0  ||  f->H[c] == 0)
	return;

   if (Verbose)  
   {
    if  ( abs(f->W[c]) < 128 && abs(f->H[c]) < 128 && 
	  abs(f->X[c]) < 128 && abs(f->Y[c]) < 128 )
	 fprintf( imPressFile,  "@SGLY" );
    else fprintf( imPressFile,  "@BGLY" );
    fprintf( imPressFile,  " 0 %d %d %d %d %d %d %d\n", f->Inumber, c, 
        f->pxl_adv[c], f->W[c], f->X[c], 
    	f->H[c], f->Y[c]);
    fprintf( imPressFile,  "f = %o, f->TeXnumber = %d\n", f, f->TeXnumber);

    for (row=0; row < f->H[c]; row++)
      {
        for (col=0; col<bytes; col++)
	  {
	    static char map[] = { '.', 'O' };

	    putc( map[ (*glyph >> 7) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 6) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 5) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 4) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 3) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 2) & 1 ], imPressFile );
	    putc( map[ (*glyph >> 1) & 1 ], imPressFile );
	    putc( map[ (*glyph     ) & 1 ], imPressFile );
	    if (col&1) putc( ' ', imPressFile );
	    glyph++;
	  }
	if (bytes&1) fprintf( imPressFile,  "........" );
	putc( '\n', imPressFile );
      }
    	
     fprintf( imPressFile, "@\n" );
    }
    else
     {
        /*
	 * the encoded form of glyph loading
	 */
      int rotation;
      if (landscape) rotation = 0100; else rotation = 0;
      if  ( abs(f->W[c]) < 128 && abs(f->H[c]) < 128 && 
	   abs(f->X[c]) < 128 && abs(f->Y[c]) < 128 )
	  {
	    int temp;
	    putc( ASGLY, imPressFile );
	    putc(rotation | (f->Inumber>>1), imPressFile );
	    putc( ( (f->Inumber&1)<<7)|c, imPressFile );
	    putc( f->pxl_adv[c], imPressFile );
	    putc( f->W[c], imPressFile );
	    putc( f->X[c], imPressFile );
	    putc( f->H[c], imPressFile );
	    putc( f->Y[c], imPressFile );
	  }
       else
          {

	putc( ABGLY, imPressFile );
	putc(rotation | (f->Inumber>>1), imPressFile );
	putc( ((f->Inumber&1)<<7)|c, imPressFile );
	ImPressPutWord( f->pxl_adv[c] );
	ImPressPutWord( f->W[c] );
	ImPressPutWord( f->X[c] );
	ImPressPutWord( f->H[c] );
	ImPressPutWord( f->Y[c] );
       }
       fwrite( glyph, 1, f->H[c]*bytes, imPressFile );
     }
    f->state[c] = Loaded;
  }


ImPressRule( w, h )
  {
  	/*
	 * draw a rule (rectangle) at current point with given dimensions
	 */
    if (Verbose)
      {
        if ( abs(w) < 127 && abs(h) < 127 )
	      ImPressPrintf( "@SRULE" );
         else ImPressPrintf( "@BRULE" );
        ImPressPrintf(  " %d %d %d@\n", w, h, -h);
        return;
      }
      if ( abs(w) < 127 && abs(h) < 127 )
        {
	     ImPressPutc( ASRULE );
	     ImPressPutc( w );
	     ImPressPutc( h );
	     ImPressPutc(-h );
	     return;
	}
         ImPressPutc( ABRULE );
         ImPressBufWord( w );
	 ImPressBufWord( h );
	 ImPressBufWord(-h );
  }


ImPressPutWord( w )
 {
 	/*
	 * output a (big-endian) word to the ImPress file
	 */
   putc( (w>>8)&0377, imPressFile );
   putc( (w)&0377, imPressFile );
 }


ImPressStart( fileName, jobID, verbosity )
 char *fileName;
 char *jobID;
 int verbosity;	
  {
    /*
     * open the indicated file name for imPress output
     * Verbosity is true to use the Verbose (decoded) mode.
     * Here we write a dummy job name and ImPress version.
     * Returns nonzero if it cannot open the file.
     */
    if (fileName == (char *)0) 
	imPressFile = stdout;
    else
    	imPressFile = fopen( fileName, "w" );
    if (imPressFile==NULL)
      {
        if (debug) printf( "Unable to open %s\n", fileName );
	return(TRUE);
      }
    Verbose = verbosity;
#ifdef OLDIMAGEN
    fprintf( imPressFile, "2 %s", jobID );
    putc( 0, imPressFile );
    fprintf( imPressFile, "12345678");
#endif
    if (landscape)
    {
	if(Verbose)
	{
	    fprintf(imPressFile,"@SET-HV-SYSTEM");
	    fprintf(imPressFile,"  %o\n",0101);
	}
	else
	{
	    fprintf(imPressFile,"%c%c",AMS,0101);
	}
    }
    MemoryNeeded = 0;
    MemoryAvailable = GlyphSize;
    return(FALSE);
  }


ImPressBeginPage()
 {
   /*
    * begin a page of an imPress file
    */
    PagePointer = 0;
    GlyphPointer = 0;
 }


ImPressEndPage()
 {
   /*
    * end a page of an impress file.
    *
    * First we delete glyphs we do not use on this page if necessary,
    * then output all the glyphs we need, then finally dump the Page buffer.
    */
     register char *glyphc;
     register struct font **fp;
     
     if (debug) 
        printf( "Begin page, Needed = %d, available = %d\n",
		 MemoryNeeded, MemoryAvailable );
     if (MemoryNeeded >= MemoryAvailable) ImPressDeleteGlyphs();

     for (glyphc=GlyphChars, fp=GlyphTable; glyphc < GlyphChars+GlyphPointer;
     		glyphc++, fp++)
	  switch ( (*fp)->state[ *glyphc] )
	    {
	      case Wanted:  ImPressGlyph( *fp, *glyphc );
	      default:	    (*fp)->state[ *glyphc ] = Loaded;
	    }
     MemoryAvailable -= MemoryNeeded;
    
     if (Verbose) fprintf( imPressFile, "@PAGE@\n" );
      else putc( APAGE, imPressFile );
     fwrite( PageBuffer, 1, PagePointer, imPressFile );
     if (Verbose) fprintf( imPressFile, "@END@\n" );
      else  putc( AEND, imPressFile );
     MemoryNeeded = 0;
 }


ImPressFinish()
 {
    /*
     * End and close out the imPress file
     */
    
     if (Verbose) fprintf( imPressFile, "@EOF@" );
      else putc( AEOF, imPressFile );
    fclose( imPressFile );
 }


ImPressSize( f, c )
 register struct font *f;
 register char c;
  {
  	/*
	 * Returns the size of a glyph in the ImPrint's memory.
	 * VERY dependent on the controller code.
	 */
    register int size;
    int bytes = (f->W[c]+7)/8;

    if ( ( f->pxl_adv[c] | f->W[c] | f->H[c] | abs(2*f->X[c]) | abs(2*f->Y[c]) ) < 256 ) 
          size = 12;
     else size = 16;
    size += bytes*f->H[c];
    if (bytes&1) size += f->H[c];
    if (bytes<=2 && f->H[c]&1) size += bytes;
    return(size);
  }
  

ImPressDeleteGlyphs()
  {
  	/*
	 * Make a pass through all the fonts we have loaded, 
	 * deleting those glyphs that are loaded but not needed onthis page.
	 */
    register struct font *f;
    register char c;
    
    for (f=fontListHead; f; f=f->next)
      for (c=f->bc;c<=f->ec;c++)
       if (f->state[c]==Loaded)
        {
	  if (Verbose) 
	      fprintf( imPressFile, "@DELG 0 %d %d @\n" , f->Inumber, c );
	   else
	     {
	       putc( ADELG, imPressFile );
	       putc( f->Inumber>>1, imPressFile );
	       putc( (f->Inumber&1)<<7|c, imPressFile );
	     }
	   MemoryAvailable += ImPressSize( f, c );
	   f->state[c] = Ready;
	}
    if (debug) 
      printf( "After Deleting glyphs, Memory Needed = %d bytes, Available = %d\n",
      MemoryNeeded, MemoryAvailable );
  }


ImPressSendIt( fileName, banner, inputName, numberPages, 
     numberCopies, writeFlag, mailFlag)
  char *fileName;		/* name of temporary file */
  char *banner;			/* banner */
  char *inputName;		/* name of input file */
  int   numberPages;		/* hint of length */
  int   numberCopies;		/* number of copies wanted */
  int   writeFlag;		/* write when done */
  int   mailFlag;		/* mail when done */
   {
	/*
	 * Use the ipr spooler to send fileName to an ImPress printer.
	 *  Use banner as the tag for the spooler, or inputName if banner is null.
	 * Note that this routine execs, so it should normally never return.
	 */
    char *tag;
    char  pages[20], copies[20];
    char *args[20];
    int   count = 0;

    if (banner) tag = banner;
    else if (inputName) tag = inputName;
    else tag = "stdin";

    args[count++] = "ipr";
    if (debug)     args[count++] = "-d";
    args[count++] = "-Limpress";
    args[count++] = "-Djobheader on";
    args[count++] = "-r";
    args[count++] = "-t"; 
    args[count++] = tag; 
    if (numberPages>0)
      {
        sprintf( pages, "-p%d", numberPages );
        args[count++] =  pages;
      }	
    if (numberCopies>0)
      {
        sprintf( copies, "-c%d", numberCopies );
        args[count++] =  copies;
      }	
    if (mailFlag)  args[count++] = "-m";
    if (writeFlag) args[count++] = "-n";
    args[count++] =  fileName;
    args[count++] =  NULL;
    if (debug)
      {
        int i;
        printf( "Command line: " );
	for (i=0; i<count; i++) printf( " %s", args[i] );
	putchar( '\n' );
	fflush(stdout);
      }
    execv( COMMAND, args );
    fperror("Couldn't execute ipr.  ImPress file in %s",fileName);
  }

SHAR_EOF
fi # end of overwriting check
if test -f 'iptex.1'
then
	echo shar: will not over-write existing file "'iptex.1'"
else
cat << \SHAR_EOF > 'iptex.1'
.ds TX T\h'-.1667m'\v'.22m'E\h'-.125m'\v'-.22m'X
.TH IPTEX 1 TRW(9/7/84)
.SH NAME
iptex \- spool TeX output for Imagen printing
.SH SYNOPSIS
.B iptex
[ flags ] dvi-file
.SH DESCRIPTION
.I iptex
is used to convert \*(TX device-independent (DVI) output
files into the appropriate format for the Imagen ImPrint-10
Laser Printer.
Only one file can be processed at a time.
If the named file cannot be found, then
.IB filename .dvi
is tried.
The output is placed in a file in /tmp which
is then spooled by the
.IR ipr (1)
program.
.SS Options
.TP
\-L
Print in landscape mode.  Since this involves rotating the bitmaps
for each different character and font in the input, this can
be quite time-consuming.
.TP
\-U
Uncentered output.  Normally,
.I iptex
will add enough margin to center the page image in the middle of
the physical page.  This option causes the page image to be flush with
the upper left corner of the page.
.TP
\-I
One inch margins.  Starts the output one inch from the top and left
edges of the physical page.  This is a \*(TX standard positioning.  Note that
you should specify at most one of the \-U and \-I options and that
when neither is specified, the output is centered.  If both \-U and \-I are
specified, the \-I option will take precedence.
.TP
\-v
Verbose output; the Imprint-10 output is listed on standard output
in symbolic form, but nothing is queued.
.TP
\-s
.I ipr
is not called, and the Impress output is written to standard output.
.TP
\-c\fIn\fR
Requests than
.I n
copies be produced.  Default is one copy.
.TP
\-d
Causes debugging information to be produced.
.TP
\-D
Causes even more debugging information, including dumping the
glyphs in each font in a readable format.
.SH DIAGNOSTICS
.B "scale=\fIn\fB design=\fIm\fR"
.br
.B "Can't find font:\fI font\fR"
.br
 ...occurs when the bitmap for a font with a particular magnification isn't
there.
.sp
Most (self explanatory) diagnostics start with "dvi-imagen:"
for historical reasons, and usually refer to a particularly
incomprehensible dvi file.
.SH FILES
The bitmap for font amr10, scaled at 1:1 (\*(TX's
.BR "\escaled 1000" )
will be found in the file /usr/lib/tex/fonts/amr10.1200pxl.  1200
is the basic raster size for the (240 dot/inch) Imagen.  If
.B "amr10 scaled 1200"
is used to create 12-point Roman, the font will be
amr10.1440pxl, and so on.
.sp
/tmp/dviXXXXX\ \ Temporary (output) file.
.SH SEE ALSO
tex82(1),ipr(1)
.br
\*(TXware documentation for formats of DVI and TFM files.
.SH BUGS
The \*(TX fonts and the fonts distributed by Imagen aren't the
same.  This is a minor annoyance that takes up a lot of disk
space unnecessarily.
SHAR_EOF
fi # end of overwriting check
if test -f 'ipr.h'
then
	echo shar: will not over-write existing file "'ipr.h'"
else
cat << \SHAR_EOF > 'ipr.h'
/*
 * ipr.h -- ImPress printer spooler definitions
 *
 * by Bill Nowicki September 29, 1981
 * at Stanford University for Imagen Corporation
 */

# define SPOOLDIR "/usr/spool/ipd"		/* the spooling directory */
# define LOCK     "/usr/spool/ipd/lock"		/* the lock file  */
# define LOG      "/tmp/implog"		/* the error log file  */
# define DAEMON   "/usr/local/lib/imagen/ipd"		/* the unqueuing daemon */
# define PRINTING "/usr/local/lib/imagen/ips"		/* the printing program */
# define COMMAND  "/usr/local/bin/ipr"		/* the command for enqueing */
# define WRITE    "/usr/local/lib/imagen/dwrite"		/* write to a user */
# define HUMAN    "ImPress printer Daemon"	/* Human understandable name */
# define KIND	  "ImPrint"			/* kind of printer we use */

# define LOCKTIMEOUT	5*60		/* seconds for the lock timeout */

# define LineSize 128			/* size of a data line */

# include <sys/types.h>
# include <dir.h>
# include <stat.h>
# include <signal.h>
# include <stdio.h>
# include "c.h"
# define bool int

/*
 * I am not sure if the following is documented anywhere, so
 * I thought I would include it here so nonone else has to go through
 * what I did to discover how the standard spooling stuff works.
 * I also added a few of my own codes, which should not conflict
 * with anything.
 *
 * Basically there are files in the spool directory of the form:
 * dfXXXXXa (where XXXXX is the pid), that have lines with a one
 * character code followed by informational lines:
 *	B	treated like F in ipq.c
 *	C	number of copies to print
 *	F	File name to print
 *	L	User's name responsible for printing
 *	M	Mail address to inform when printing is complete
 *	N	User to notify when printing is complete
 *	P	Pages in body (total)
 *	R	"Real" user name for cover sheet
 *	T	"Tag" to identify this job, usually the file name
 *	U	File to unlink after finishing
 */

extern int debug;	/* for extra debugging messages */

int Copies;		/* number of copies to print */
int Pages;		/* number of pages (approx) */
SHAR_EOF
fi # end of overwriting check
if test -f 'impress.h'
then
	echo shar: will not over-write existing file "'impress.h'"
else
cat << \SHAR_EOF > 'impress.h'
/*
 * impress.h
 *
 * header file for finding data bases having to do with the imprint printer
 * by Bill Nowicki, Stanford University, September 1981
 */

# define PixelsPerInch 240		/* Resolution of the printer being used */

  /*
   * size of printable area, 8x10.5 inches
   */
# define PixelsPageHeight ( (int)( PixelsPerInch*10.5 )	)
# define PixelsPageWidth ( PixelsPerInch*8 )

  /*
   * memory parameters
   */
# define K 1024
# define GlyphSize (164*K)	/* size of printer's Glyph buffer */
# define InputSize (24*K)	/* size of printer's input buffer */
# define GlyphsPerPage (10*K)	/* number of distinct glyphs per page */

SHAR_EOF
fi # end of overwriting check
if test -f 'imPcodes.h'
then
	echo shar: will not over-write existing file "'imPcodes.h'"
else
cat << \SHAR_EOF > 'imPcodes.h'
/* command codes */

#define	ASP0	128
#define	ASP1	129
#define	AM	130
#define AMP	131
#define	AMM	132

#define ASABSH	135	/* Absolute horizontal */
#define ASABSV	137	/* Absolute vertical   */

#define	ASRULE	192
#define	ABRULE	193

#define	AS	194	/* not implemented yet */
#define	AH	195
#define	AV	196
#define	AN	197

#define	ASGLY	198
#define	ABGLY	199
#define	ADELG	200
#define	ADELC	201
#define	ADELF	202
#define	AFONT	203

#define	APAGOR	204
#define	AMS	205
#define	AROTMS	206

#define	AF	207
#define	ABSKIP	208
#define	AMARGIN	209
#define	ASETSP	210

#define	APUSH	211
#define	APOP	212

#define	APAGE	213
#define	AEND	219

#define ACREFAM	221
#define	ANOP	254
#define	AEOF	255
SHAR_EOF
fi # end of overwriting check
if test -f 'font.h'
then
	echo shar: will not over-write existing file "'font.h'"
else
cat << \SHAR_EOF > 'font.h'
/*
 * font.h - some definitions for the font manipulation routines
 *           **CHANGED at Cornell for the dvi-imagen program **
 *
 * Note that our terminology is slightly different from that of Knuth
 * and Parc. Since TROFF assumes that fonts are scalable, we must
 * use a single Knuth font (which we call a family, similar to a Parc face),
 * at different magnifications (which is what we call a "font").
 */


/*
 * the layout of a font information block
 * There is one of these for every loaded "font", or
 * magnification thereof in Knuthian terms.
 *
 * Also note the strange units.  The design size is in 1/2^20 point
 * units (also called micro-points), and the individual character widths
 * are in the TFM file in 1/2^20 ems units, i.e. relative to the design size.
 */

# define TwoToTheTwenty (1024*1024)
# define MAXCHARS 256		/* make 128 for 7 bit characters */

enum CharStatus {NotThere, Ready, Loaded, Wanted, Kept, InProm};

struct font
 {
    struct font * next;   	/* link to next font info block            */
    int Inumber;   		/* font number (on Imagen)                 */
    int TeXnumber;              /* font number (in DVI file)               */
    int scale;             	/* scaled size in DVI units                */
    int design;               	/* design size in DVI units                */

    unsigned char bc;       	/* beginning char defined                  */
    unsigned char ec;       	/* ending char defined                     */

    enum CharStatus state[ MAXCHARS ];
    	    			/* loaded, existant, or in Prom??          */

				/* following are in pixels                 */
    short H[ MAXCHARS ];    	/* height for each glyph raster            */
    short W[ MAXCHARS ];    	/* width for each glyph raster             */
    short Y[ MAXCHARS ];    	/* Y-offset for each glyph raster          */
    short X[ MAXCHARS ];    	/* X-offset for each glyph raster          */
    short pxl_adv[ MAXCHARS ];	/* pixels to move reference point          */
    long  dvi_adv[ MAXCHARS ];	/* DVI units to move reference point       */

    char  *Glyph[ MAXCHARS ];	/* pointers to actual glyph bitmaps        */
    char  fontname[100];
 };

extern struct font *fontListHead; /* head of linked list of font structures */
int debug;			        /* true for debugging information */
SHAR_EOF
fi # end of overwriting check
if test -f 'error.c'
then
	echo shar: will not over-write existing file "'error.c'"
else
cat << \SHAR_EOF > 'error.c'
/*********************************************************************
function:	error
description:	Error message routines
programmer:	Alan S. Watt

history:
	11/04/81	original version
	07/17/82	fixes for lint
	08/10/82	modest cleanup before posting.
*********************************************************************/

#ifndef lint
 static char Sccsid[] = "@(#)error.c	1.1";
#endif !lint

#include <stdio.h>
#define NOTOK	(-1)

/* VARARGS1 */
error (mesg, args)
char *mesg;
{
	_doprnt (mesg, &args, stderr);
	putc ('\n', stderr);
	exit (NOTOK);
}

extern	errno;
extern	sys_nerr;
extern	char *sys_errlist[];
#ifdef lint
 int	errno;
 int	sys_nerr;
 char *sys_errlist[1];
#endif lint
static	char ehuh[]	= "Unknown System Error";

/* VARARGS1 */
fperror (mesg, args)
char *mesg;
{
	char *err = ((unsigned)errno >= sys_nerr ? ehuh : sys_errlist[errno]);

	_doprnt (mesg, &args, stderr);
	fprintf (stderr, ": %s\n", err);
	exit (NOTOK);
}

/*VARARGS1*/
remark (mesg, args)
char *mesg;
{
	_doprnt (mesg, &args, stderr);
	putc ('\n',stderr);
}

/*VARARGS1*/
fpremark (mesg, args)
char *mesg;
{
	char *err = ((unsigned)errno >= sys_nerr ? ehuh : sys_errlist[errno]);

	_doprnt (mesg, &args, stderr);
	fprintf (stderr, ":%s\n", err);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'dvi.h'
then
	echo shar: will not over-write existing file "'dvi.h'"
else
cat << \SHAR_EOF > 'dvi.h'
#define SETCHAR0    0
#define SET1        128
#define SETRULE     132
#define PUT1        133
#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 FNTNUM0     171
#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 TRAILER     223     /* Trailing bytes at end of file */
SHAR_EOF
fi # end of overwriting check
if test -f 'c.h'
then
	echo shar: will not over-write existing file "'c.h'"
else
cat << \SHAR_EOF > 'c.h'
/*
 * Standard C macros
 *
 **********************************************************************
 * HISTORY
 * 23-Apr-81  Mike Accetta (mja) at Carnegie-Mellon University
 *	Added "sizeofS" and "sizeofA" macros which expand to the size
 *	of a string constant and array respectively.
 *
 **********************************************************************
 */

#define ABS(x)		((x) >= 0 ? (x):-(x))
#define MAX(a,b)	((a) > (b) ? (a):(b))
#define MIN(a,b)	((a) < (b) ? (a):(b))

#define FALSE		0
#define TRUE		1
#define	CERROR		(-1)

#define	sizeofS(string)	(sizeof(string) - 1)
#define sizeofA(array)	(sizeof(array)/sizeof(array[0]))
SHAR_EOF
fi # end of overwriting check
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
CFLAGS= -O
dvi-imagen: dvi-imagen.o output.o error.o rotate.o special.o 
	cc -o dvi-imagen dvi-imagen.o output.o error.o rotate.o special.o -lcurses

clean:
	rm -f *.o
SHAR_EOF
fi # end of overwriting check
if test -f 'dvi-imagen.c'
then
	echo shar: will not over-write existing file "'dvi-imagen.c'"
else
cat << \SHAR_EOF > 'dvi-imagen.c'
/*
**      dvi-imagen.c    Imagen driver for DVI format 2
**
**  Syntax:
**      dvi-imagen [options] <dvi-file>
**
**  Description:
**      Translates the DVI commands in the <dvi-file> into commands
**      for the Imagen ImPrint-10 Laser Printer.  These are placed
**      into a /tmp file which is then handed to the ipr(1) program.
**
**	The -L option takes a shot at Landscape mode.
**	The -U option disables centering
**	The -I option provides one-inch margins
**      The -v option makes the output be in decoded (verbose) form
**              -v implies -s
**      The -s option makes dvi-imagen refrain from calling ipr(1),
**		with Impress output on stdout.
**	The -cX option requests X copies (default 1)
**      The -d option makes dvi-imagen produce debugging information.
**      The -D option gets everything -d does and more, including
**          dumping out the glyphs in each font in a readable format.
*/

#include <stdio.h>
#include <unctrl.h>
#include <pwd.h>
#include "dvi.h"
#include "font.h"

#define MAXFONTS    64      /* Due to 6-bit field in Imagen codes */
                            /* I may fix this in the next version */
			    
#define PIXELS_PER_INCH      240
#define HARD_XPAGE_OFFSET    160     /* Damn it */
#define PIXELS_PER_LINE      (8 * PIXELS_PER_INCH - HARD_XPAGE_OFFSET)
                                     /* 8 inches of printing area */
#define PIXELS_PER_PAGE      (11 * PIXELS_PER_INCH)
                                     /* 11 inches of printing area */
#define FONT_DIRECTORY       "/usr/lib/tex/fonts"

#define pixel_round(x)      ((long) (conv * (double) (x) + 0.5))
#define dvi_round(x)        ((long) ((double) (x) / conv + 0.5))

#define one(fp)     num (fp, 1)
#define sone(fp)    snum(fp, 1)
#define two(fp)     num (fp, 2)
#define four(fp)    num (fp, 4)
#define sfour(fp)   snum(fp, 4)

typedef unsigned char   ubyte;

struct frame
{
        long    pxl_h, dvi_h, pxl_v, dvi_v, w, x, y, z;
};

struct frame    *stack;
int             stackp;

extern int	landscape;

int         debug = 0;
int         verbose = 0;
int         spoolit = 1;
int	    landscape = 0;
int	    center = 1;
int         inchmargin = 0;
int	    numcopies = 1;
struct font *fontListHead = NULL;
char        job_id[300];
char	    InputName[300];
int         total_pages, maxstack, Xpage_offset, Ypage_offset;
int         fontnum = 0;
double      conv;
long        numerator, denominator, magnification;
char        *output_file_name;
char        *Usage_str = "Usage: iptex [-U] [-I] [-L] [-v] [-s] [-d] <dvi-file>";

long            read_postamble();
unsigned long   num();
long            snum();
char            *malloc();
char            *mktemp();

main(argc, argv)
int     argc;
char    *argv[];
{
        FILE    *fp;
	long    last_page;     /* file offset of last page of output */
	int	nc;

        while (argv[1][0] == '-')
	{
	    switch (argv[1][1])
	    {
		case 'c':
		    if ((nc=atoi(&argv[1][2])) > 0) numcopies=nc;
		    break;
		    
		case 's':
                    spoolit = 0;
                    break;
                    
	        case 'd':
                    debug = 1;
                    break;
                
                case 'D':
                    debug = 2;
                    break;
                
                case 'v':
                    verbose = 1;
                    spoolit = 0;
                    break;

		case 'L':
		    landscape = 1;
		    break;

		case 'U':
		    center = 0;
		    break;

		case 'I':
		    inchmargin = 1;
		    break;
                
                default:
                    error(Usage_str);
	    }
            
            argv++;
            argc--;
	}
        
        if (argc != 2)
            error(Usage_str);

	if ((fp = fopen(argv[1], "r")) == NULL) {
	    char longername[256];
	    strcpy (longername, argv[1]);
	    strcat (longername, ".dvi");
	    if ((fp = fopen (longername, "r")) == NULL)
		error("dvi-imagen: Can't open %s", argv[1]);
	}
	strcpy (InputName, argv[1]);
	    
	process_preamble(fp);
	
	find_postamble(fp);
	
	last_page = read_postamble(fp);
	
	start_output();
	
	do_pages(fp, last_page);
	
	finish_output();
}

\f


/*
**      process_preamble(fp)
**
**      fp is a FILE pointer for a DVI file which is positioned at the
**      beginning.
**
**      process_preamble reads the information in the preamble and stores
**      it into global variables for later use.
*/

process_preamble(fp)
FILE    *fp;
{
        ubyte   k;
	double  fraction;

        if (one(fp) != PRE)
	    error("dvi-imagen: DVI file doesn't start with preamble");
	    
	if (one(fp) != 2)
	    error("dvi-imagen: Wrong version of DVI output for this program");
	
	numerator     = four(fp);
	denominator   = four(fp);
	magnification = four(fp);
	
	fraction = (((double) numerator * magnification)
	                                 / ((double) denominator * 1000.));
	
	conv = ((fraction / 100000) / 2.54) * PIXELS_PER_INCH;
	
	k = one(fp);
	fread(job_id, sizeof(char), k, fp);
	job_id[k] = '\0';
}

\f


/*
**      find_postamble(fp)
**
**      fp is a FILE pointer for a DVI-format file.  find_postamble locates
**      the beginning of the postamble and leaves the file ready to start
**      reading at that location.
*/

find_postamble(fp)
FILE    *fp;
{
        ubyte   byte;
	long    offset = -4;        /* At least 4 TRAILERS */
	
	do
	{
	    offset--;
	    fseek(fp, offset, 2);
	    byte = one(fp);
	} while(byte == TRAILER);
	
	if (byte != 2)
	    error("dvi-imagen: Wrong version of DVI output for this program");
	
	offset -= 4;
	fseek(fp, offset, 2);

	fseek(fp, four(fp), 0);
}

\f


/*
**      long
**      read_postamble(fp)
**
**      fp is a FILE pointer for a DVI-format file.  read_postamble reads the
**      information in the postamble, storing it into global variables.
**      It also takes care of reading in all of the PXL files for the fonts
**      used in the job.
**
**      read_postamble returns the file offset of the beginning of the last
**      page of DVI output.
*/

long
read_postamble(fp)
FILE    *fp;
{
        long    last_page;
        long    tallest, widest;
        ubyte   cmnd;

        if (one(fp) != POST)
	    error("dvi-imagen: Postamble doesn't begin with POST");
	
	last_page = four(fp);
	
	if (numerator != four(fp)
	          ||  denominator != four(fp)
		  ||  magnification != four(fp))
	    error("dvi-imagen: Postamble doesn't match preamble");
	      
	tallest      = four(fp);
	if (!landscape) {
	    Ypage_offset = (PIXELS_PER_PAGE - pixel_round(tallest)) / 2;
	    widest       = four(fp);
	    Xpage_offset = (PIXELS_PER_LINE - pixel_round(widest)) / 2
                                                        + HARD_XPAGE_OFFSET;
	} else {
	    Ypage_offset = (PIXELS_PER_LINE - pixel_round(tallest))/2
					+ HARD_XPAGE_OFFSET;
	    widest       = four(fp);
	    Xpage_offset = (PIXELS_PER_PAGE - pixel_round(widest))/2;
	}

	if (!center) Ypage_offset = Xpage_offset = 0;

	if (inchmargin) Ypage_offset = Xpage_offset = PIXELS_PER_INCH;
	    
	maxstack     = two(fp);
	total_pages  = two(fp);
        
        if (debug)
            remark("tall, wide, po, stk, pages = %d, %d, %d, %d, %d",
                    tallest, widest, Xpage_offset, maxstack, total_pages);
	
	do
	{
	    switch(cmnd = one(fp))
	    {
	        case FNTDEF1:
	        case FNTDEF2:
	        case FNTDEF3:
	        case FNTDEF4:
		    define_font(fp, cmnd);
		    break;
		    
		case POSTPOST:
		    break;
		
		default:
		    error("dvi-imagen: Non-fntdef cmnd found in postamble");
	    }
	} while (cmnd != POSTPOST);
	
	return (last_page);
}

\f


/*
**      define_font(fp, cmnd)
**
**      fp is a FILE pointer for a DVI file which is positioned right after
**      a fntdef command.  The opcode for the command is in cmnd.
**
**      define_font reads the rest of the fntdef command and then reads in
**      the specified PXL file, adding it to the global linked-list holding
**      all of the fonts used in the job.
*/

define_font(fp, cmnd)
FILE    *fp;
ubyte   cmnd;
{
        struct font *fontp;
	long        checksum;
	int         len;
	char        fontname[513];
	
	if (fontnum >= MAXFONTS)
	    error("dvi-imagen: Too many fonts.  Maximum is %d", MAXFONTS);
	
	fontp = (struct font *) malloc( sizeof(struct font) );
	
	if (fontp == NULL)
	    error("dvi-imagen: Out of memory while reading font %d", fontnum);

	fontp->next      = fontListHead;
	fontListHead     = fontp;
	
        fontp->TeXnumber = num(fp, cmnd - FNTDEF1 + 1);
	fontp->Inumber   = fontnum++;
	
	checksum = four(fp);
	
	fontp->scale     = four(fp);
	fontp->design    = four(fp);
	
	len = one(fp) + one(fp);
	fread(fontname, sizeof(char), len, fp);
	fontname[len] = '\0';
        strcpy(fontp->fontname, fontname);
        
	read_pxl_file(fontp, fontname);
        
        if (debug > 1)
            dump_font(fontp, fontname);
}

\f


/*
**      read_pxl_file(fontp, fontname)
**
**      fontp points to a (struct font) which has been partially initialised
**      with the information in the DVI-file FNTDEF command.  fontname is the
**      name of a font.
**
**      read_pxl_file constructs the expected name of the font's PXL file
**      from the info in *fontp and fontname.  It then reads the glyph
**      bitmaps into memory.
**
**      Note: the 'size' of a font (i.e. the 1200 in 'cmr10.1200pxl') is
**      given by the following formula (rounded):
**
**              scaled-size   PIXELS_PER_INCH
**              ----------- * --------------- * 1000
**              design-size         200
**
**	In the actual implementation, scaled-size/design-size hasn't been
**	stored with sufficient precision, hence the messing around to find
**	its actual value.
*/
char *rotate();

read_pxl_file(fontp, fontname)
struct font     *fontp;
char            *fontname;
{
        char    filename[1025];
	FILE    *pxlfp;
	int	unmodsize;
	float	realsize;
	int     size;
        long    checksum, magnify,
                design_size, font_dir_ptr, pxl_id_word;
        long    glyph_ptr[128];     /* Seek locations of each glyph */
        int     i, j, k;
	
	realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
	unmodsize = (realsize * 1000) + 0.5;
	/* a real hack to correct for rounding in some cases -- rkf */
	if(unmodsize==1095) realsize = 1.095445;	/* stephalf */
	else if(unmodsize==1315) realsize=1.314534;	/* stepihalf */
	else if(unmodsize==2074) realsize=2.0736;	/* stepiv */
	else if(unmodsize==2488) realsize=2.48832;	/* stepv */
	else if(unmodsize==2986) realsize=2.985984;	/* stepiv */
	/* the remaining magnification steps are represented with sufficient
		accuracy already */
	size = (realsize * PIXELS_PER_INCH * 5) + 0.5;
	
	sprintf(filename, "%s.%dpxl", fontname, size);
	
	if ((pxlfp = fopen(filename, "r")) == NULL)
	{
	    sprintf(filename, "%s/%s.%dpxl", FONT_DIRECTORY, fontname, size);
	    
	    if ((pxlfp = fopen(filename, "r")) == NULL)
            {
	        remark("scale = %d, design = %d",fontp->scale, fontp->design);
	        fperror("Can't find font: \"%s\"", filename);
            }
	}

	fseek(pxlfp, - (5 * 4L), 2);        /* Seek to trailer info   */
        checksum      = four(pxlfp);
        magnify = four(pxlfp);
        design_size   = four(pxlfp);
        font_dir_ptr  = four(pxlfp) * 4;
        pxl_id_word   = four(pxlfp);

	fseek(pxlfp, font_dir_ptr, 0);      /* Seek to font directory */
        
        fontp->bc = 0;
        fontp->ec = 127;
	for (i=0; i < 128; i++)
	{
            fontp->state[i] = Ready;
	    fontp->W[i]     = two(pxlfp);
	    fontp->H[i]     = two(pxlfp);
	    fontp->X[i]     = two(pxlfp);
	    fontp->Y[i]     = two(pxlfp);
            glyph_ptr[i]    = four(pxlfp) * 4;
                    /*
                    **  The TFM-width word is kind of funny in the units
                    **  it is expressed in.  It works this way:
                    **
                    **  If a glyph has width 'w' in a font with design-size
                    **  'd' (both in same units), the TFM-width word is
                    **
                    **                    (w/d) * 2^20
                    **
                    **  Therefore, in order to find the glyph width in
                    **  DVI units (1 / 2^16 points), we take the design-size
                    **  'd' (in DVI's), the magnification 'm' of the PXL file
                    **  and the TFM-width word 't' to the width (in DVI's)
                    **  as follows:
                    **
                    **                     dmt
                    **                w = -----
                    **                    2^20
                    **
                    **  But the magnification of the PXL file is just the
                    **  scaled size 's' over the design size, so the final
                    **  expression for the width is
                    **
                    **                     st
                    **                w = ----
                    **                    2^20
                    **
                    */      
#ifndef UNDEFINED
            fontp->dvi_adv[i] =
                    ((double) fontp->scale * four(pxlfp)) / (1 << 20);
#else
            fontp->dvi_adv[i] =
                    ((double) fontp->design * four(pxlfp)) / (1 << 20);
#endif
            fontp->pxl_adv[i] = pixel_round(fontp->dvi_adv[i]);
	}
        
        for (i=0; i < 128; i++)
	{
            int     real_bytes_wide = (fontp->W[i] + 7) / 8;
            int     file_bytes_wide = ((fontp->W[i] + 31) / 32) * 4;
            char    *ptr;
            char    junk;
            
            ptr = fontp->Glyph[i] = malloc(fontp->H[i] * real_bytes_wide);
            if (ptr == NULL)
                error("Out of memory while reading character %d of font %s\n",
                                                                 i, fontname);
	    fseek(pxlfp, glyph_ptr[i], 0);
            for (j=0; j < fontp->H[i]; j++)
	    {
	        for (k=0; k < file_bytes_wide; k++)
		{
		    if (k < real_bytes_wide)
                        *(ptr++) = one(pxlfp);
                    else
                        junk = one(pxlfp);
		}
	    }
	    if (landscape) {
		char	*holdglyph;
		int	width,height,x,y;

		holdglyph = fontp->Glyph[i];
		fontp->Glyph[i] = rotate(holdglyph, fontp->H[i], fontp->W[i]);
	/*	free(holdglyph); */
		width = fontp->W[i]; height=fontp->H[i];
		x = fontp->X[i]; y=fontp->Y[i];
		fontp->W[i] = height; fontp->H[i] = width;
		fontp->X[i] = height-y; fontp->Y[i] = x;
	    }
		
	}
        fclose(pxlfp);
}

\f


/*
**              start_output()
**
**      Arrange for the stuff at the beginning of the output to the Imagen
**      to be sent out, including the jobid, etc.
**
*/

start_output()
{
        char            *buffer[50];
        struct passwd   *pwbuf, *getpwuid();
        
        pwbuf = getpwuid(getuid());
        sprintf(buffer, " (%s [%d pages])", pwbuf->pw_name, total_pages);
        strcat(job_id, buffer);
	if (spoolit) {
        	output_file_name = mktemp("/tmp/dviXXXXXX");
        	ImPressStart(output_file_name, job_id, verbose);
	}
	else
        	ImPressStart((char *)0, job_id, verbose);
	
}

\f


/*
**              do_pages(fp, last_page)
**
**      Process the pages in the FILE fp.  last_pages is the offset of the
**      last page.  (We do the pages in reverse order, of course.)
**
*/

#define PXL_H   stack[stackp].pxl_h
#define PXL_V   stack[stackp].pxl_v
#define DVI_H   stack[stackp].dvi_h
#define DVI_V   stack[stackp].dvi_v
#define WW      stack[stackp].w
#define XX      stack[stackp].x
#define YY      stack[stackp].y
#define ZZ      stack[stackp].z

#define nope(str)       error("Can't hack %s", str)

#define correct()       diff = PXL_H - pixel_round(DVI_H);  \
                        if (diff < 0)                       \
		        {                                   \
		            while (diff++)                  \
                                ImPressMplus();             \
		        }                                   \
                        else if (diff > 0)                  \
		        {                                   \
		            while (diff--)                  \
                                ImPressMminus();            \
		        }                                   \
                        PXL_H = pixel_round(DVI_H);

do_pages(fp, last_page)
FILE    *fp;
long    last_page;
{
        char        input_left = 1;
        long        next_page;
        struct font *curr_font;
        int         diff;
        struct font *ptr;
        ubyte       ch;
                
        stack = (struct frame *) malloc( sizeof(struct frame) * (maxstack+1));
        
        if (stack == NULL)
            error("Can't allocate stack space.");
            
        fseek(fp, last_page, 0);
        
        while (input_left)
	{
            ch = one(fp);
            
 	    if (ch <= SETCHAR0 + 127)
	    {
                ImPressCharacter(ch);
                DVI_H += curr_font->dvi_adv[ch];
                PXL_H += curr_font->pxl_adv[ch];
                correct();
	    }
	    else if (FNTNUM0 <= ch  &&  ch <= FNTNUM0 + 63)
	    {
                for (ptr = fontListHead; ptr != NULL; ptr = ptr->next)
                    if (ptr->TeXnumber == ch - FNTNUM0)
                        break;
                
                if (ptr == NULL)
                    error("FNTNUM to non-existant font #%d", ch - FNTNUM0);
                
                curr_font = ptr;
                ImPressFont(ptr);
            }
	    else
	    {
                long    a, b;
                
		switch (ch)
		{
		    case SET1:
                        nope("SET1");
			break;

		    case SETRULE:
			a = sfour(fp); b = sfour(fp);
                        if (a > 0  &&  b > 0)
			{
			    correct();
                            ImPressRule(pixel_round(b), pixel_round(a));
			}
			DVI_H += b;
                        diff = pixel_round(DVI_H);
                        ImPressMove(diff - PXL_H);
                        PXL_H = diff;
			break;

		    case PUT1:
			nope("PUT1");
			break;

		    case PUTRULE:
			a = sfour(fp); b = sfour(fp);
                        if (a > 0  &&  b > 0)
			{
			    correct();
                            ImPressRule(pixel_round(b), pixel_round(a));
			}
			break;

		    case NOP:
			break;

		    case BOP:
                        a = four(fp);
			if (debug)
                            remark("Beginning page %d", a);
			for (a=0; a < 9; a++)
			    four(fp);
                        next_page = sfour(fp);
                        stackp = 0;
                        DVI_H = dvi_round(Xpage_offset);
                        PXL_H = Xpage_offset;
                        DVI_V = dvi_round(Ypage_offset);
                        PXL_V = Ypage_offset;
                        WW = XX = YY = ZZ = 0;
                        curr_font = NULL;
                        ImPressBeginPage();
                        ImPressSetX(PXL_H);
			break;

		    case EOP:
                        ImPressEndPage();
                        if (stackp > 0)
                            remark("Stack not empty at EOP; stackp = %d",
                                                                      stackp);
                        if (next_page < 0)
                            input_left = 0;
                        else
                            fseek(fp, next_page, 0);
			break;

		    case PUSH:
                        stackp++;
                        if (stackp > maxstack)
                            error("More PUSHes than were promised");
                        stack[stackp] = stack[stackp - 1];
			break;

		    case POP:
                        stackp--;
                        if (stackp < 0)
                            error("More POPs than PUSHes");
                        ImPressSetX(PXL_H);
                        ImPressSetY(PXL_V);
			break;

		    case RIGHT1:
		    case RIGHT2:
		    case RIGHT3:
		    case RIGHT4:
			DVI_H += snum(fp, ch - RIGHT1 + 1);
                        diff = pixel_round(DVI_H);
                        ImPressMove(diff - PXL_H);
                        PXL_H = diff;
			break;

		    case X0:
		    case X1:
		    case X2:
		    case X3:
		    case X4:
			if (ch != X0)
                        {
			    XX = snum(fp, ch - X0);
                            ImPressSetSpace(pixel_round(XX));
                        }
                        ImPressSpace();
                        DVI_H += XX;
                        PXL_H += pixel_round(XX);
                        correct();
			break;

		    case W0:
		    case W1:
		    case W2:
		    case W3:
		    case W4:
			if (ch != W0)
			    WW = snum(fp, ch - W0);
			DVI_H += WW;
                        diff = pixel_round(DVI_H);
                        ImPressMove(diff - PXL_H);
                        PXL_H = diff;
			break;

		    case Y0:
		    case Y1:
		    case Y2:
		    case Y3:
		    case Y4:
			if (ch != Y0)
			    YY = snum(fp, ch - Y0);
			DVI_V += YY;
                        PXL_V = pixel_round(DVI_V);
                        ImPressSetY(PXL_V);
			break;

		    case Z0:
		    case Z1:
		    case Z2:
		    case Z3:
		    case Z4:
			if (ch != Z0)
			    ZZ = snum(fp, ch - Z0);
			DVI_V += ZZ;
                        PXL_V = pixel_round(DVI_V);
                        ImPressSetY(PXL_V);
			break;

		    case DOWN1:
		    case DOWN2:
		    case DOWN3:
		    case DOWN4:
			DVI_V += snum(fp, ch - DOWN1 + 1);
                        PXL_V = pixel_round(DVI_V);
                        ImPressSetY(PXL_V);
			break;

		    case FNT1:
		    case FNT2:
		    case FNT3:
		    case FNT4:
			a = num(fp, ch - FNT1 + 1);
                        for (ptr = fontListHead; ptr != NULL; ptr = ptr->next)
                            if (ptr->TeXnumber == a)
                                break;
                
                        if (ptr == NULL)
                            error("FNT to non-existant font #%d", a);
                
                        curr_font = ptr;
                        ImPressFont(ptr);
			break;

		    case XXX1:
		    case XXX2:
		    case XXX3:
		    case XXX4:
                        /*nope("XXXX");*/
			a = num(fp, ch-XXX1+1);
			if(a > 0)
			    DoSpecial (a, fp);
			break;

		    case FNTDEF1:
		    case FNTDEF2:
		    case FNTDEF3:
		    case FNTDEF4:
                        fseek(fp, 12 + ch - FNTDEF1 + 1, 1);
                        a = one(fp) + one(fp);
                        fseek(fp, a, 1);
			break;

		    case PRE:
                        error("Can't Happen:  PRE encountered.");
			break;

		    case POST:
                        error("Can't Happen:  POST encountered.");
			break;

		    case POSTPOST:
                        error("Can't Happen:  POSTPOST encountered.");
			break;
		    
		    default:
			error("Unknown Op-code: %d; Offset: %d",
                                                               ch, ftell(fp));
		} /* end switch*/
	    } /* end else (ch not a SETCHAR or FNTNUM) */
	} /* end while */
}

\f


/*
**              finish_output()
**
**      Wrap it up.  This routine does not return, since ImPressSendIt()
**      doesn't.
**
*/

finish_output()
{
        ImPressFinish();
        if (! spoolit)
            exit(0);
        ImPressSendIt(output_file_name, NULL, InputName,
			total_pages, numcopies, 0, 0);
}

\f


/*
**              num(fp, size)       snum(fp, size)
**
**      Read size bytes from the FILE fp, constructing them into a
**      signed/unsigned integer.
**
*/

unsigned long
num(fp, size)
FILE    *fp;
int     size;
{
        int     i;
	long    x;
	
	x = 0;
	for (i=0; i < size; i++)
	{
	    x = x * 256 + (unsigned) fgetc(fp);
	}
	
	return(x);
}

long
snum(fp, size)
FILE    *fp;
int     size;
{
        int     i;
	long    x;
	
	x = fgetc(fp) & 0377;
        if (x & 0200)
            x -= 256;
            
	for (i=1; i < size; i++)
	{
	    x = x * 256 + (unsigned) fgetc(fp);
	}
	
	return(x);
}

\f


/*
**              dump_font(fontp, fontname)
**
**      Debugging routine which prints a representation of the information
**      read from a PXL file into a 'struct font'.
**
*/

dump_font(fontp, fontname)
struct  font    *fontp;
char            *fontname;
{
	int     i, j, k, l;
        
        printf("\n+++++DUMP OF FONT \"%s\":  ", fontname);
        printf("TeXnumber, Inumber, scale, design = %d, %d, %d, %d\n",
                        fontp->TeXnumber,
                        fontp->Inumber,
                        fontp->scale,
                        fontp->design);
        printf("\tfontp = %o\n", fontp);
        
        for (i=0; i < 128; i++)
	{
	    char    *ptr;
            
	    printf("\nCharacter %d (%s):  ", i, unctrl(i));
            printf("H, W, X, Y = %d, %d, %d, %d\n",
                        fontp->H[i],
                        fontp->W[i],
                        fontp->X[i],
                        fontp->Y[i]);
            printf("\t\tdvi_adv, pxl_adv = %d, %d\n\n",
                        fontp->dvi_adv[i],
                        fontp->pxl_adv[i]);
            
	    ptr = fontp->Glyph[i];
            for (j=0; j < fontp->H[i]; j++)
	    {
	        for (k=0; k < (fontp->W[i] + 7) / 8; k++)
		{
		    for (l=7; l >= 0; l--)
		    {
		        if (*ptr & (1 << l))
                            putchar('@');
                        else
                            putchar(' ');
		    }
                    
                    ptr++;
		}
                
                putchar('\n');
	    }
	}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'CROSS-REFERENCES'
then
	echo shar: will not over-write existing file "'CROSS-REFERENCES'"
else
cat << \SHAR_EOF > 'CROSS-REFERENCES'
Imagen owners may also be interested in the programs found in
./tex82/=utils/salkind.

8/300 owners may prefer to look at the files in ../imagen300
SHAR_EOF
fi # end of overwriting check
if test -f 'dvi-imagen.c_o'
then
	echo shar: will not over-write existing file "'dvi-imagen.c_o'"
else
cat << \SHAR_EOF > 'dvi-imagen.c_o'
/*
**      dvi-imagen.c    Imagen driver for DVI format 2
**
**  Syntax:
**      dvi-imagen [options] <dvi-file>
**
**  Description:
**      Translates the DVI commands in the <dvi-file> into commands
**      for the Imagen ImPrint-10 Laser Printer.  These are placed
**      into a /tmp file which is then handed to the ipr(1) program.
**
**	The -L option takes a shot at Landscape mode.
**	The -U option disables centering
**      The -v option makes the output be in decoded (verbose) form
**              -v implies -s
**      The -s option makes dvi-imagen refrain from calling ipr(1),
**		with Impress output on stdout.
**	The -cX option requests X copies (default 1)
**      The -d option makes dvi-imagen produce debugging information.
**      The -D option gets everything -d does and more, including
**          dumping out the glyphs in each font in a readable format.
*/

#include <stdio.h>
#include <unctrl.h>
#include <pwd.h>
#include "dvi.h"
#include "font.h"

#define MAXFONTS    64      /* Due to 6-bit field in Imagen codes */
                            /* I may fix this in the next version */
			    
#define PIXELS_PER_INCH      240
#define HARD_XPAGE_OFFSET    160     /* Damn it */
#define PIXELS_PER_LINE      (8 * 240 - HARD_XPAGE_OFFSET)
                                     /* 8 inches of printing area */
#define PIXELS_PER_PAGE      (11 * 240)
                                     /* 11 inches of printing area */
#define FONT_DIRECTORY       "/usr/lib/tex/fonts"

#define pixel_round(x)      ((long) (conv * (double) (x) + 0.5))
#define dvi_round(x)        ((long) ((double) (x) / conv + 0.5))

#define one(fp)     num (fp, 1)
#define sone(fp)    snum(fp, 1)
#define two(fp)     num (fp, 2)
#define four(fp)    num (fp, 4)
#define sfour(fp)   snum(fp, 4)

typedef unsigned char   ubyte;

struct frame
{
        long    pxl_h, dvi_h, pxl_v, dvi_v, w, x, y, z;
};

struct frame    *stack;
int             stackp;

extern int	landscape;

int         debug = 0;
int         verbose = 0;
int         spoolit = 1;
int	    landscape = 0;
int	    center = 1;
int	    numcopies = 1;
struct font *fontListHead = NULL;
char        job_id[300];
char	    InputName[300];
int         total_pages, maxstack, Xpage_offset, Ypage_offset;
int         fontnum = 0;
double      conv;
long        numerator, denominator, magnification;
char        *output_file_name;
char        *Usage_str = "Usage: iptex [-U] [-L] [-v] [-s] [-d] <dvi-file>";

long            read_postamble();
unsigned long   num();
long            snum();
char            *malloc();
char            *mktemp();

main(argc, argv)
int     argc;
char    *argv[];
{
        FILE    *fp;
	long    last_page;     /* file offset of last page of output */
	int	nc;

        while (argv[1][0] == '-')
	{
	    switch (argv[1][1])
	    {
		case 'c':
		    if ((nc=atoi(&argv[1][2])) > 0) numcopies=nc;
		    break;
		    
		case 's':
                    spoolit = 0;
                    break;
                    
	        case 'd':
                    debug = 1;
                    break;
                
                case 'D':
                    debug = 2;
                    break;
                
                case 'v':
                    verbose = 1;
                    spoolit = 0;
                    break;

		case 'L':
		    landscape = 1;
		    break;

		case 'U':
		    center = 0;
		    break;
                
                default:
                    error(Usage_str);
	    }
            
            argv++;
            argc--;
	}
        
        if (argc != 2)
            error(Usage_str);

	if ((fp = fopen(argv[1], "r")) == NULL) {
	    char longername[256];
	    strcpy (longername, argv[1]);
	    strcat (longername, ".dvi");
	    if ((fp = fopen (longername, "r")) == NULL)
		error("dvi-imagen: Can't open %s", argv[1]);
	}
	strcpy (InputName, argv[1]);
	    
	process_preamble(fp);
	
	find_postamble(fp);
	
	last_page = read_postamble(fp);
	
	start_output();
	
	do_pages(fp, last_page);
	
	finish_output();
}

\f


/*
**      process_preamble(fp)
**
**      fp is a FILE pointer for a DVI file which is positioned at the
**      beginning.
**
**      process_preamble reads the information in the preamble and stores
**      it into global variables for later use.
*/

process_preamble(fp)
FILE    *fp;
{
        ubyte   k;
	double  fraction;

        if (one(fp) != PRE)
	    error("dvi-imagen: DVI file doesn't start with preamble");
	    
	if (one(fp) != 2)
	    error("dvi-imagen: Wrong version of DVI output for this program");
	
	numerator     = four(fp);
	denominator   = four(fp);
	magnification = four(fp);
	
	fraction = (((double) numerator * magnification)
	                                 / ((double) denominator * 1000.));
	
	conv = ((fraction / 100000) / 2.54) * PIXELS_PER_INCH;
	
	k = one(fp);
	fread(job_id, sizeof(char), k, fp);
	job_id[k] = '\0';
}

\f


/*
**      find_postamble(fp)
**
**      fp is a FILE pointer for a DVI-format file.  find_postamble locates
**      the beginning of the postamble and leaves the file ready to start
**      reading at that location.
*/

find_postamble(fp)
FILE    *fp;
{
        ubyte   byte;
	long    offset = -4;        /* At least 4 TRAILERS */
	
	do
	{
	    offset--;
	    fseek(fp, offset, 2);
	    byte = one(fp);
	} while(byte == TRAILER);
	
	if (byte != 2)
	    error("dvi-imagen: Wrong version of DVI output for this program");
	
	offset -= 4;
	fseek(fp, offset, 2);

	fseek(fp, four(fp), 0);
}

\f


/*
**      long
**      read_postamble(fp)
**
**      fp is a FILE pointer for a DVI-format file.  read_postamble reads the
**      information in the postamble, storing it into global variables.
**      It also takes care of reading in all of the PXL files for the fonts
**      used in the job.
**
**      read_postamble returns the file offset of the beginning of the last
**      page of DVI output.
*/

long
read_postamble(fp)
FILE    *fp;
{
        long    last_page;
        long    tallest, widest;
        ubyte   cmnd;

        if (one(fp) != POST)
	    error("dvi-imagen: Postamble doesn't begin with POST");
	
	last_page = four(fp);
	
	if (numerator != four(fp)
	          ||  denominator != four(fp)
		  ||  magnification != four(fp))
	    error("dvi-imagen: Postamble doesn't match preamble");
	      
	tallest      = four(fp);
	if (!landscape) {
	    Ypage_offset = (PIXELS_PER_PAGE - pixel_round(tallest)) / 2;
	    widest       = four(fp);
	    Xpage_offset = (PIXELS_PER_LINE - pixel_round(widest)) / 2
                                                        + HARD_XPAGE_OFFSET;
	} else {
	    Ypage_offset = (PIXELS_PER_LINE - pixel_round(tallest))/2
					+ HARD_XPAGE_OFFSET;
	    widest       = four(fp);
	    Xpage_offset = (PIXELS_PER_PAGE - pixel_round(widest))/2;
	}
	    
	if (!center) Ypage_offset = Xpage_offset = 0;
	maxstack     = two(fp);
	total_pages  = two(fp);
        
        if (debug)
            remark("tall, wide, po, stk, pages = %d, %d, %d, %d, %d",
                    tallest, widest, Xpage_offset, maxstack, total_pages);
	
	do
	{
	    switch(cmnd = one(fp))
	    {
	        case FNTDEF1:
	        case FNTDEF2:
	        case FNTDEF3:
	        case FNTDEF4:
		    define_font(fp, cmnd);
		    break;
		    
		case POSTPOST:
		    break;
		
		default:
		    error("dvi-imagen: Non-fntdef cmnd found in postamble");
	    }
	} while (cmnd != POSTPOST);
	
	return (last_page);
}

\f


/*
**      define_font(fp, cmnd)
**
**      fp is a FILE pointer for a DVI file which is positioned right after
**      a fntdef command.  The opcode for the command is in cmnd.
**
**      define_font reads the rest of the fntdef command and then reads in
**      the specified PXL file, adding it to the global linked-list holding
**      all of the fonts used in the job.
*/

define_font(fp, cmnd)
FILE    *fp;
ubyte   cmnd;
{
        struct font *fontp;
	long        checksum;
	int         len;
	char        fontname[513];
	
	if (fontnum >= MAXFONTS)
	    error("dvi-imagen: Too many fonts.  Maximum is %d", MAXFONTS);
	
	fontp = (struct font *) malloc( sizeof(struct font) );
	
	if (fontp == NULL)
	    error("dvi-imagen: Out of memory while reading font %d", fontnum);

	fontp->next      = fontListHead;
	fontListHead     = fontp;
	
        fontp->TeXnumber = num(fp, cmnd - FNTDEF1 + 1);
	fontp->Inumber   = fontnum++;
	
	checksum = four(fp);
	
	fontp->scale     = four(fp);
	fontp->design    = four(fp);
	
	len = one(fp) + one(fp);
	fread(fontname, sizeof(char), len, fp);
	fontname[len] = '\0';
        strcpy(fontp->fontname, fontname);
        
	read_pxl_file(fontp, fontname);
        
        if (debug > 1)
            dump_font(fontp, fontname);
}

\f


/*
**      read_pxl_file(fontp, fontname)
**
**      fontp points to a (struct font) which has been partially initialised
**      with the information in the DVI-file FNTDEF command.  fontname is the
**      name of a font.
**
**      read_pxl_file constructs the expected name of the font's PXL file
**      from the info in *fontp and fontname.  It then reads the glyph
**      bitmaps into memory.
**
**      Note: the 'size' of a font (i.e. the 1200 in 'cmr10.1200pxl') is
**      given by the following formula (rounded):
**
**              scaled-size   PIXELS_PER_INCH
**              ----------- * --------------- * 1000
**              design-size         200
**
**	In the actual implementation, scaled-size/design-size hasn't been
**	stored with sufficient precision, hence the messing around to find
**	its actual value.
*/
char *rotate();

read_pxl_file(fontp, fontname)
struct font     *fontp;
char            *fontname;
{
        char    filename[1025];
	FILE    *pxlfp;
	int	unmodsize;
	float	realsize;
	int     size;
        long    checksum, magnify,
                design_size, font_dir_ptr, pxl_id_word;
        long    glyph_ptr[128];     /* Seek locations of each glyph */
        int     i, j, k;
	
	realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
	unmodsize = (realsize * 1000) + 0.5;
	/* a real hack to correct for rounding in some cases -- rkf */
	if(unmodsize==1095) realsize = 1.095445;	/* stephalf */
	else if(unmodsize==1315) realsize=1.314534;	/* stepihalf */
	else if(unmodsize==2074) realsize=2.0736;	/* stepiv */
	else if(unmodsize==2488) realsize=2.48832;	/* stepv */
	else if(unmodsize==2986) realsize=2.985984;	/* stepiv */
	/* the remaining magnification steps are represented with sufficient
		accuracy already */
	size = (realsize * PIXELS_PER_INCH * 5) + 0.5;
	
	sprintf(filename, "%s.%dpxl", fontname, size);
	
	if ((pxlfp = fopen(filename, "r")) == NULL)
	{
	    sprintf(filename, "%s/%s.%dpxl", FONT_DIRECTORY, fontname, size);
	    
	    if ((pxlfp = fopen(filename, "r")) == NULL)
            {
	        remark("scale = %d, design = %d",fontp->scale, fontp->design);
	        fperror("Can't find font: \"%s\"", filename);
            }
	}

	fseek(pxlfp, - (5 * 4L), 2);        /* Seek to trailer info   */
        checksum      = four(pxlfp);
        magnify = four(pxlfp);
        design_size   = four(pxlfp);
        font_dir_ptr  = four(pxlfp) * 4;
        pxl_id_word   = four(pxlfp);

	fseek(pxlfp, font_dir_ptr, 0);      /* Seek to font directory */
        
        fontp->bc = 0;
        fontp->ec = 127;
	for (i=0; i < 128; i++)
	{
            fontp->state[i] = Ready;
	    fontp->W[i]     = two(pxlfp);
	    fontp->H[i]     = two(pxlfp);
	    fontp->X[i]     = two(pxlfp);
	    fontp->Y[i]     = two(pxlfp);
            glyph_ptr[i]    = four(pxlfp) * 4;
                    /*
                    **  The TFM-width word is kind of funny in the units
                    **  it is expressed in.  It works this way:
                    **
                    **  If a glyph has width 'w' in a font with design-size
                    **  'd' (both in same units), the TFM-width word is
                    **
                    **                    (w/d) * 2^20
                    **
                    **  Therefore, in order to find the glyph width in
                    **  DVI units (1 / 2^16 points), we take the design-size
                    **  'd' (in DVI's), the magnification 'm' of the PXL file
                    **  and the TFM-width word 't' to the width (in DVI's)
                    **  as follows:
                    **
                    **                     dmt
                    **                w = -----
                    **                    2^20
                    **
                    **  But the magnification of the PXL file is just the
                    **  scaled size 's' over the design size, so the final
                    **  expression for the width is
                    **
                    **                     st
                    **                w = ----
                    **                    2^20
                    **
                    */      
#ifndef UNDEFINED
            fontp->dvi_adv[i] =
                    ((double) fontp->scale * four(pxlfp)) / (1 << 20);
#else
            fontp->dvi_adv[i] =
                    ((double) fontp->design * four(pxlfp)) / (1 << 20);
#endif
            fontp->pxl_adv[i] = pixel_round(fontp->dvi_adv[i]);
	}
        
        for (i=0; i < 128; i++)
	{
            int     real_bytes_wide = (fontp->W[i] + 7) / 8;
            int     file_bytes_wide = ((fontp->W[i] + 31) / 32) * 4;
            char    *ptr;
            char    junk;
            
            ptr = fontp->Glyph[i] = malloc(fontp->H[i] * real_bytes_wide);
            if (ptr == NULL)
                error("Out of memory while reading character %d of font %s\n",
                                                                 i, fontname);
	    fseek(pxlfp, glyph_ptr[i], 0);
            for (j=0; j < fontp->H[i]; j++)
	    {
	        for (k=0; k < file_bytes_wide; k++)
		{
		    if (k < real_bytes_wide)
                        *(ptr++) = one(pxlfp);
                    else
                        junk = one(pxlfp);
		}
	    }
	    if (landscape) {
		char	*holdglyph;
		int	width,height,x,y;

		holdglyph = fontp->Glyph[i];
		fontp->Glyph[i] = rotate(holdglyph, fontp->H[i], fontp->W[i]);
	/*	free(holdglyph); */
		width = fontp->W[i]; height=fontp->H[i];
		x = fontp->X[i]; y=fontp->Y[i];
		fontp->W[i] = height; fontp->H[i] = width;
		fontp->X[i] = height-y; fontp->Y[i] = x;
	    }
		
	}
        fclose(pxlfp);
}

\f


/*
**              start_output()
**
**      Arrange for the stuff at the beginning of the output to the Imagen
**      to be sent out, including the jobid, etc.
**
*/

start_output()
{
        char            *buffer[50];
        struct passwd   *pwbuf, *getpwuid();
        
        pwbuf = getpwuid(getuid());
        sprintf(buffer, " (%s [%d pages])", pwbuf->pw_name, total_pages);
        strcat(job_id, buffer);
	if (spoolit) {
        	output_file_name = mktemp("/tmp/dviXXXXXX");
        	ImPressStart(output_file_name, job_id, verbose);
	}
	else
        	ImPressStart((char *)0, job_id, verbose);
	
}

\f


/*
**              do_pages(fp, last_page)
**
**      Process the pages in the FILE fp.  last_pages is the offset of the
**      last page.  (We do the pages in reverse order, of course.)
**
*/

#define PXL_H   stack[stackp].pxl_h
#define PXL_V   stack[stackp].pxl_v
#define DVI_H   stack[stackp].dvi_h
#define DVI_V   stack[stackp].dvi_v
#define WW      stack[stackp].w
#define XX      stack[stackp].x
#define YY      stack[stackp].y
#define ZZ      stack[stackp].z

#define nope(str)       error("Can't hack %s", str)

#define correct()       diff = PXL_H - pixel_round(DVI_H);  \
                        if (diff < 0)                       \
		        {                                   \
		            while (diff++)                  \
                                ImPressMplus();             \
		        }                                   \
                        else if (diff > 0)                  \
		        {                                   \
		            while (diff--)                  \
                                ImPressMminus();            \
		        }                                   \
                        PXL_H = pixel_round(DVI_H);

do_pages(fp, last_page)
FILE    *fp;
long    last_page;
{
        char        input_left = 1;
        long        next_page;
        struct font *curr_font;
        int         diff;
        struct font *ptr;
        ubyte       ch;
                
        stack = (struct frame *) malloc( sizeof(struct frame) * (maxstack+1));
        
        if (stack == NULL)
            error("Can't allocate stack space.");
            
        fseek(fp, last_page, 0);
        
        while (input_left)
	{
            ch = one(fp);
            
 	    if (ch <= SETCHAR0 + 127)
	    {
                ImPressCharacter(ch);
                DVI_H += curr_font->dvi_adv[ch];
                PXL_H += curr_font->pxl_adv[ch];
                correct();
	    }
	    else if (FNTNUM0 <= ch  &&  ch <= FNTNUM0 + 63)
	    {
                for (ptr = fontListHead; ptr != NULL; ptr = ptr->next)
                    if (ptr->TeXnumber == ch - FNTNUM0)
                        break;
                
                if (ptr == NULL)
                    error("FNTNUM to non-existant font #%d", ch - FNTNUM0);
                
                curr_font = ptr;
                ImPressFont(ptr);
            }
	    else
	    {
                long    a, b;
                
		switch (ch)
		{
		    case SET1:
                        nope("SET1");
			break;

		    case SETRULE:
			a = sfour(fp); b = sfour(fp);
                        if (a > 0  &&  b > 0)
			{
			    correct();
                            ImPressRule(pixel_round(b), pixel_round(a));
			}
			DVI_H += b;
                        diff = pixel_round(DVI_H);
                        ImPressMove(diff - PXL_H);
                        PXL_H = diff;
			break;

		    case PUT1:
			nope("PUT1");
			break;

		    case PUTRULE:
			a = sfour(fp); b = sfour(fp);
                        if (a > 0  &&  b > 0)
			{
			    correct();
                            ImPressRule(pixel_round(b), pixel_round(a));
			}
			break;

		    case NOP:
			break;

		    case BOP:
                        a = four(fp);
			if (debug)
                            remark("Beginning page %d", a);
			for (a=0; a < 9; a++)
			    four(fp);
                        next_page = sfour(fp);
                        stackp = 0;
                        DVI_H = dvi_round(Xpage_offset);
                        PXL_H = Xpage_offset;
                        DVI_V = dvi_round(Ypage_offset);
                        PXL_V = Ypage_offset;
                        WW = XX = YY = ZZ = 0;
                        curr_font = NULL;
                        ImPressBeginPage();
                        ImPressSetX(PXL_H);
			break;

		    case EOP:
                        ImPressEndPage();
                        if (stackp > 0)
                            remark("Stack not empty at EOP; stackp = %d",
                                                                      stackp);
                        if (next_page < 0)
                            input_left = 0;
                        else
                            fseek(fp, next_page, 0);
			break;

		    case PUSH:
                        stackp++;
                        if (stackp > maxstack)
                            error("More PUSHes than were promised");
                        stack[stackp] = stack[stackp - 1];
			break;

		    case POP:
                        stackp--;
                        if (stackp < 0)
                            error("More POPs than PUSHes");
                        ImPressSetX(PXL_H);
                        ImPressSetY(PXL_V);
			break;

		    case RIGHT1:
		    case RIGHT2:
		    case RIGHT3:
		    case RIGHT4:
			DVI_H += snum(fp, ch - RIGHT1 + 1);
                        diff = pixel_round(DVI_H);
                        ImPressMove(diff - PXL_H);
                        PXL_H = diff;
			break;

		    case X0:
		    case X1:
		    case X2:
		    case X3:
		    case X4:
			if (ch != X0)
                        {
			    XX = snum(fp, ch - X0);
                            ImPressSetSpace(pixel_round(XX));
                        }
                        ImPressSpace();
                        DVI_H += XX;
                        PXL_H += pixel_round(XX);
                        correct();
			break;

		    case W0:
		    case W1:
		    case W2:
		    case W3:
		    case W4:
			if (ch != W0)
			    WW = snum(fp, ch - W0);
			DVI_H += WW;
                        diff = pixel_round(DVI_H);
                        ImPressMove(diff - PXL_H);
                        PXL_H = diff;
			break;

		    case Y0:
		    case Y1:
		    case Y2:
		    case Y3:
		    case Y4:
			if (ch != Y0)
			    YY = snum(fp, ch - Y0);
			DVI_V += YY;
                        PXL_V = pixel_round(DVI_V);
                        ImPressSetY(PXL_V);
			break;

		    case Z0:
		    case Z1:
		    case Z2:
		    case Z3:
		    case Z4:
			if (ch != Z0)
			    ZZ = snum(fp, ch - Z0);
			DVI_V += ZZ;
                        PXL_V = pixel_round(DVI_V);
                        ImPressSetY(PXL_V);
			break;

		    case DOWN1:
		    case DOWN2:
		    case DOWN3:
		    case DOWN4:
			DVI_V += snum(fp, ch - DOWN1 + 1);
                        PXL_V = pixel_round(DVI_V);
                        ImPressSetY(PXL_V);
			break;

		    case FNT1:
		    case FNT2:
		    case FNT3:
		    case FNT4:
			a = num(fp, ch - FNT1 + 1);
                        for (ptr = fontListHead; ptr != NULL; ptr = ptr->next)
                            if (ptr->TeXnumber == a)
                                break;
                
                        if (ptr == NULL)
                            error("FNT to non-existant font #%d", a);
                
                        curr_font = ptr;
                        ImPressFont(ptr);
			break;

		    case XXX1:
		    case XXX2:
		    case XXX3:
		    case XXX4:
                        /*nope("XXXX");*/
			a = num(fp, ch-XXX1+1);
			if(a > 0)
			    DoSpecial (a, fp);
			break;

		    case FNTDEF1:
		    case FNTDEF2:
		    case FNTDEF3:
		    case FNTDEF4:
                        fseek(fp, 12 + ch - FNTDEF1 + 1, 1);
                        a = one(fp) + one(fp);
                        fseek(fp, a, 1);
			break;

		    case PRE:
                        error("Can't Happen:  PRE encountered.");
			break;

		    case POST:
                        error("Can't Happen:  POST encountered.");
			break;

		    case POSTPOST:
                        error("Can't Happen:  POSTPOST encountered.");
			break;
		    
		    default:
			error("Unknown Op-code: %d; Offset: %d",
                                                               ch, ftell(fp));
		} /* end switch*/
	    } /* end else (ch not a SETCHAR or FNTNUM) */
	} /* end while */
}

\f


/*
**              finish_output()
**
**      Wrap it up.  This routine does not return, since ImPressSendIt()
**      doesn't.
**
*/

finish_output()
{
        ImPressFinish();
        if (! spoolit)
            exit(0);
        ImPressSendIt(output_file_name, NULL, InputName,
			total_pages, numcopies, 0, 0);
}

\f


/*
**              num(fp, size)       snum(fp, size)
**
**      Read size bytes from the FILE fp, constructing them into a
**      signed/unsigned integer.
**
*/

unsigned long
num(fp, size)
FILE    *fp;
int     size;
{
        int     i;
	long    x;
	
	x = 0;
	for (i=0; i < size; i++)
	{
	    x = x * 256 + (unsigned) fgetc(fp);
	}
	
	return(x);
}

long
snum(fp, size)
FILE    *fp;
int     size;
{
        int     i;
	long    x;
	
	x = fgetc(fp) & 0377;
        if (x & 0200)
            x -= 256;
            
	for (i=1; i < size; i++)
	{
	    x = x * 256 + (unsigned) fgetc(fp);
	}
	
	return(x);
}

\f


/*
**              dump_font(fontp, fontname)
**
**      Debugging routine which prints a representation of the information
**      read from a PXL file into a 'struct font'.
**
*/

dump_font(fontp, fontname)
struct  font    *fontp;
char            *fontname;
{
	int     i, j, k, l;
        
        printf("\n+++++DUMP OF FONT \"%s\":  ", fontname);
        printf("TeXnumber, Inumber, scale, design = %d, %d, %d, %d\n",
                        fontp->TeXnumber,
                        fontp->Inumber,
                        fontp->scale,
                        fontp->design);
        printf("\tfontp = %o\n", fontp);
        
        for (i=0; i < 128; i++)
	{
	    char    *ptr;
            
	    printf("\nCharacter %d (%s):  ", i, unctrl(i));
            printf("H, W, X, Y = %d, %d, %d, %d\n",
                        fontp->H[i],
                        fontp->W[i],
                        fontp->X[i],
                        fontp->Y[i]);
            printf("\t\tdvi_adv, pxl_adv = %d, %d\n\n",
                        fontp->dvi_adv[i],
                        fontp->pxl_adv[i]);
            
	    ptr = fontp->Glyph[i];
            for (j=0; j < fontp->H[i]; j++)
	    {
	        for (k=0; k < (fontp->W[i] + 7) / 8; k++)
		{
		    for (l=7; l >= 0; l--)
		    {
		        if (*ptr & (1 << l))
                            putchar('@');
                        else
                            putchar(' ');
		    }
                    
                    ptr++;
		}
                
                putchar('\n');
	    }
	}
}
SHAR_EOF
fi # end of overwriting check
cd ..
#	End of shell archive
exit 0