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 d

⟦066d2fc4f⟧ TextFile

    Length: 25711 (0x646f)
    Types: TextFile
    Names: »dvisuntool.c-«

Derivation

└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
    └─⟦this⟧ »./DVIware/crt-viewers/dviapollo/dvisuntool.c-« 
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/crt-viewers/dviapollo/dvisuntool.c-« 

TextFile

 /* @(#)dvisuntool.c	1.17 2/19/87 */
#include "header.h"
#include "genwindow.h"
#define NEW(A) ((A *) malloc(sizeof(A)))
/* #define DEBUG   1*/			/* for massive printing of input */
					/* trace information; select by -d */
					/* option before filename. */
#ifdef DEBUG
int Debug = 0;
#endif

#define USEGLOBALMAG 1			/* when defined, the dvi global
   					   magnification is applied */

#define  FIRSTPXLCHAR      0
#define  LASTPXLCHAR     127
#define  NPXLCHARS       128
#define  PXLID          1001
#define  READ              4   /* for access() */
#define  hconvRESOLUTION RESOLUTION /* These numbers are right for my */
#define  vconvRESOLUTION RESOLUTION /* particular sun3 display.  TSF */
#define BORDER_BLACK 3 /* Width of border, in pixels.*/
#define PAGE_HEIGHT 11 /* Height of page, in inches. */
#define PAGE_WIDTH 8.5 /* Width of page, in inches. */
#define  STACKSIZE       100   /* This is bogus.  The DVI file gives */
			       /* us a stacksize, we should use it.*/

#define  MAXOPEN 10     /* _NFILES	 limit on number of open PXL files */

float	ActualFactor();
FILE*	fopen();
void	draw_borders();
void	fatal();
void	FindPostAmblePtr();
void	GetBytes();
void	getfontdef();
void	MoveDown();
void	MoveOver();
void	OpenFontFile();
int	PixRound();
int	ReadFontDef();
int	readpostamble();
void	SetChar();
void	SetFntNum();
void	SetRule();
void	SkipFontDef();
CharImage read_char();
void show_char();
struct char_entry {		/* character entry */
   unsigned short width, height;/* width and height in pixels */
   short xOffset, yOffset;      /* x offset and y offset in pixels */
   struct {
       int isloaded;
       union {
	 int fileOffset;
	 CharImage pixrectptr; /* Not a pixrect if we're
				  using X! */
       } address;
   } where;
   int tfmw;			/* TFM width */
};

struct font_entry {  /* font entry */
   int k, c, s, d, a, l;
   char n[STRSIZE];	/* FNT_DEF command parameters */
   int font_space;	/* computed from FNT_DEF s parameter */
   int font_mag;	/* computed from FNT_DEF s and d parameters */
   char name[STRSIZE];	/* full name of PXL file */
   FILE *font_file_id;  /* file identifier (0 if none) */
   int magnification;	/* magnification read from PXL file */
   int designsize;	/* design size read from PXL file */
   struct char_entry ch[NPXLCHARS];/* character information */
   struct font_entry *next;
};

struct pixel_list
{
    FILE *pixel_file_id;        /* file identifier */
    int use_count;              /* count of "opens" */
    struct font_entry *fptr     /* ptr to its font entry */
};

int hconv; /*  DVI units per pixel */
int vconv;
int den;			/* denominator specified in preamble */
struct font_entry *fontptr;     /* font_entry pointer for current font */
struct font_entry *hfontptr=NULL;/* font_entry pointer for all fonts */
struct font_entry *closedfonts=NULL; /* font_entry pointer for list of */
				     /* closed fonts.  Hfontptr gets */
				     /* put here when a file is */
				     /* closed. */
int h;				/* current horizontal position */
int v;				/* current vertical position */
int mag;			/* magnification specified in preamble */
int nopen = 0;			/* number of open PXL files */
int num;			/* numerator specified in preamble */
struct font_entry *pfontptr = NULL; /* most recent font_entry pointer returned from OpenFontFile. */
struct pixel_list pixel_files[MAXOPEN+1];
                                /* list of open PXL file identifiers */

long postambleptr;		/* Pointer to the postamble */
FILE *pxlfp;			/* PXL file pointer */

/* This is called when a DVI file is closed.  It resets *hfontptr to */
 /* NULL, and sets closedfonts to the old linked list stored in */
 /* closedfonts appended with the value of hfontptr. */
void close_fonts ()
{
  if (closedfonts == NULL) {
    closedfonts = hfontptr;
  } else {
    struct font_entry *scanner;
    for (scanner = closedfonts; scanner -> next != NULL; scanner =
	 scanner -> next);
    scanner -> next = hfontptr;
  };
  hfontptr = NULL;
}

int Nosignextend(fp, n)	/* return n byte quantity from file fp */
     register FILE *fp;	/* file pointer    */
     register int n;		/* number of bytes */
{
  register int x;		/* number being constructed */

  x = 0;
  while (n--)  {
    x <<= 8;
    x |= getc(fp);
  }
  return(x);
}

int signextend(fp, n)   /* return n byte quantity from file fp */
     register FILE *fp;  /* file pointer    */
     register int n;     /* number of bytes */
{
  int n1;			/* number of bytes	    */
  register int x;		/* number being constructed */

  x = getc(fp);			/* get first (high-order) byte */
  n1 = n--;
  while (n--)  {
    x <<= 8;
    x |= getc(fp);
  }
  /* NOTE: This code assumes that the right-shift is an arithmetic, rather
     than logical, shift which will propagate the sign bit right.   According
     to Kernighan and Ritchie, this is compiler dependent! */
  /* Also, assuming sizeof(int) == 4 is machine dependent (32-bit ints) */
  x<<=32-8*n1;
  x>>=32-8*n1;			/* sign extend */
#ifdef DEBUG
  if (Debug)
    {
      fprintf(stderr,"\tsignextend(fp,%d)=%X\n",n1,x);
    }
#endif
  return(x);
}

/* This reads the stuff between the front of the dvi file and the */
 /* start of the first page.  It returns the number of pages in the */
 /* document. */
int start_reading_dvi_file(dvifp)
     FILE *dvifp;
{
  int pages;
  fseek (dvifp, (long) 0, 0);
  if ((Nosignextend(dvifp, 1)) != PRE)  {
    fatal("PRE doesn't occur first. Are you sure this is a DVI file?");
  }
  {
    int i;
    i = signextend(dvifp, 1);
    if (i != DVIFORMAT)  {
      fatal ("DVI format = %d, can only process DVI format %d files\n\n",
	     i, DVIFORMAT);
    }
  }
  pages = readpostamble (dvifp);
  if (preload) getfontdef (dvifp);
  fseek(dvifp, (long) 14, 0);
  {
    char n[STRSIZE];
    GetBytes(dvifp, n, Nosignextend(dvifp, 1));
  };
  return (pages);
}

/* Draw borders around the page.  Knuth says that the (0,0) point in */
 /* DVI units should be one inch from the top and from the left edges */
 /* of the page.  The page is 8.5 by 11 inches, of course. The borders */
 /* are BORDER_BLACK pixels wide, and it lies just barely outside of the page.*/
void draw_borders(xscreen, yscreen)
     int xscreen, yscreen;
{
  int height = PAGE_HEIGHT * RESOLUTION; /* These are in pixels. */
  int width = PAGE_WIDTH * RESOLUTION;
  int x = - RESOLUTION - xscreen;
  int  y = - RESOLUTION - yscreen;

  /* top horizontal */
  black_box (x - BORDER_BLACK, y - BORDER_BLACK, 
	     width + 2 * BORDER_BLACK, BORDER_BLACK);
  /* bottom horizontal */
  black_box (x - BORDER_BLACK, y + height,
	     width + 2 * BORDER_BLACK, BORDER_BLACK);
  /* left vertical */
  black_box (x - BORDER_BLACK, y - BORDER_BLACK,
	     BORDER_BLACK, height + 2 * BORDER_BLACK);
  /* right vertical */
  black_box (x + width, y - BORDER_BLACK, 
	     BORDER_BLACK,  height + 2 * BORDER_BLACK);
}

void showpage (cpagep, ppagep, SkipMode, PagesLeft, borders, dvifp, xscreen, yscreen)
     long *cpagep, *ppagep;
     int SkipMode, PagesLeft;
     BOOLEAN borders; /* Whether to draw borders.*/
     FILE *dvifp;
     int xscreen, yscreen;
{
  int w;			/* current horizontal spacing */
  int x;			/* current horizontal spacing */
  int y;			/* current vertical spacing */
  int z;			/* current vertical spacing */
  int sp;			/* stack pointer */
  struct stack_entry {		/* stack entry */
    int h, v, w, x, y, z;	/* what's on stack */
  };
  struct stack_entry stack[STACKSIZE]; /* stack */
  int SkipEOP = FALSE;		/* input is waiting from the terminal, skip to EOP */
  int command; /* current command */

  w = x = y = z = 0; /*Let's hope that each page specifies values for */
		     /*w,x,y,and z before it uses them.  Sincx Knuth */
		     /*says that DVI format should be readable from */
		     /*back to front, this seems reasonable.*/
  do {
    command = Nosignextend(dvifp, 1);
    switch (command)  {
    case SET1:case SET2:case SET3:case SET4:
      {int val;
       val = Nosignextend(dvifp, command-SET1+1);
       if (!SkipMode) SetChar(val, command, xscreen, yscreen);}
      break;
    case SET_RULE:
      {int val, val2;
       val = Nosignextend(dvifp, 4);
       val2 = Nosignextend(dvifp, 4);
       if (!SkipMode) SetRule(val, val2, 1, xscreen, yscreen);}
      break;
    case PUT1:case PUT2:case PUT3:case PUT4:
      {int val;
       val = Nosignextend(dvifp,command-PUT1+1);
       if (!SkipMode) SetChar(val, command, xscreen, yscreen);}
      break;
    case PUT_RULE:
      {int val, val2;
       val = Nosignextend(dvifp, 4);
       val2 = Nosignextend(dvifp, 4);
       if (!SkipMode) SetRule(val, val2, 0, xscreen, yscreen);}
      break;
    case NOP:
      break;
    case BOP:
      (*cpagep) = ftell(dvifp) - 1;
      {int i;
       for (i=0; i<=9; i++)
	 Nosignextend(dvifp, 4);}
      (*ppagep) = Nosignextend(dvifp, 4);
      h = v = w = x = y = z = 0;
      sp = 0;
      fontptr = NULL;
      if (PagesLeft) {
	PagesLeft--;
	if (PagesLeft <= 0) SkipMode = FALSE;
      };
      break;
    case EOP:
      if (borders && !SkipMode && !SkipEOP)
	draw_borders(xscreen, yscreen);
      if (SkipEOP) { SkipMode = FALSE; SkipEOP = FALSE; }
      break;
    case PUSH:
      if (sp >= STACKSIZE)
	fatal("stack overflow");
      stack[sp].h = h;
      stack[sp].v = v;
      stack[sp].w = w;
      stack[sp].x = x;
      stack[sp].y = y;
      stack[sp].z = z;
      sp++;
      break;
    case POP:
      --sp;
      if (sp < 0)
	fatal("stack underflow");
      h = stack[sp].h;
      v = stack[sp].v;
      w = stack[sp].w;
      x = stack[sp].x;
      y = stack[sp].y;
      z = stack[sp].z;
      break;
    case RIGHT1:case RIGHT2:case RIGHT3:case RIGHT4:
      {int val;
       val = signextend(dvifp,command-RIGHT1+1);
       if (!SkipMode) MoveOver(val);}
      break;
    case W0:
      if (!SkipMode) MoveOver(w);
      break;
    case W1:case W2:case W3:case W4:
      w = signextend(dvifp,command-W1+1);
      if (!SkipMode) MoveOver(w);
      break;
    case X0:
      if (!SkipMode) MoveOver(x);
      break;
    case X1:case X2:case X3:case X4:
      x = signextend(dvifp,command-X1+1);
      if (!SkipMode) MoveOver(x);
      break;
    case DOWN1:case DOWN2:case DOWN3:case DOWN4:
      {int val;
       val = signextend(dvifp,command-DOWN1+1);
       if (!SkipMode) MoveDown(val);}
      break;
    case Y0:
      if (!SkipMode) MoveDown(y);
      break;
    case Y1:case Y2:case Y3:case Y4:
      y = signextend(dvifp,command-Y1+1);
      if (!SkipMode) MoveDown(y);
      break;
    case Z0:
      if (!SkipMode) MoveDown(z);
      break;
    case Z1:case Z2:case Z3:case Z4:
      z = signextend(dvifp,command-Z1+1);
      if (!SkipMode) MoveDown(z);
      break;
    case FNT1:case FNT2:case FNT3:case FNT4:
      if (!SkipMode) SetFntNum(Nosignextend(dvifp,command-FNT1+1));
      break;
    case XXX1:case XXX2:case XXX3:case XXX4:
      {int k;
       k = Nosignextend(dvifp,command-XXX1+1);
       while (k--)
	 Nosignextend(dvifp, 1);}
      break;
    case FNT_DEF1:case FNT_DEF2:case FNT_DEF3:case FNT_DEF4:
      if (preload) {
	SkipFontDef (Nosignextend(dvifp, command-FNT_DEF1+1), dvifp);
      } else {
	ReadFontDef (Nosignextend(dvifp, command-FNT_DEF1+1), dvifp);
      }
      break;
    case PRE:
      fatal("PRE occurs within file");
      break;
    case POST:
      fseek(dvifp, (*cpagep), 0);
      SkipMode = FALSE;
      PagesLeft = 0;
      break;
    case POST_POST:
      fatal("POST_POST with no preceding POST");
      break;
    default:
      if (command >= FONT_00 && command <= FONT_63)
	 {if (!SkipMode) SetFntNum(command - FONT_00);}
      else if (command >= SETC_000 && command <= SETC_127)
	{if (!SkipMode) SetChar(command - SETC_000, command, xscreen, yscreen);}
      else
	fatal("%d is an undefined command", command);
      break;
    }				/* case */
  } while (command != EOP || SkipMode);
}

/* compute the actual size factor given the approximation */
float ActualFactor(unmodsize)
int unmodsize;  /* actually factor * 1000 */
{
  float realsize;		/* the actual magnification factor */

  realsize = (float)unmodsize / 1000.0;
  /* 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 */
  return(realsize);
}

int DoConv(num, den, convResolution)
{
    register float conv;
    conv = ((float)num/(float)den) * 
#ifdef USEGLOBALMAG
  	ActualFactor(mag) *	      /* put back in by clp, 8/22/84 */
/*	((float) mag/1000.0) *           and this taken out...	     */
#endif
	((float)convResolution/254000.0);
    return((int) (1.0 / conv + 0.5));
}

void fatal(fmt, args)/* issue a fatal error message */
     char *fmt;	/* format */
     char *args; /* arguments */
{
    fprintf(stderr, "Fatal error.  ");
    _doprnt(fmt, &args, stderr);
    fprintf(stderr, "\n");
    exit(1);
}

void FindPostAmblePtr(postambleptr, dvifp)
     long *postambleptr;
     FILE *dvifp;
/* this routine will move to the end of the file and find the start
    of the postamble */
{
    int     i;

    fseek (dvifp, (long) 0, 2);   /* goto end of file */
    *postambleptr = ftell (dvifp) - 4;
    fseek (dvifp, *postambleptr, 0);

    while (TRUE) {
	fseek (dvifp, --(*postambleptr), 0);
	if (((i = Nosignextend(dvifp, 1)) != 223) &&
	    (i != DVIFORMAT))
	    fatal ("Bad end of DVI file");
	if (i == DVIFORMAT)
	    break;
    }
    fseek (dvifp, (*postambleptr) - 4, 0);
    *postambleptr = Nosignextend(dvifp, 4);
    fseek (dvifp, *postambleptr, 0);
}

void GetBytes(fp, cp, n)	/* get n bytes from file fp */
     register FILE *fp;	/* file pointer	 */
     register char *cp;	/* character pointer */
     register int n; /* number of bytes  */
{
    while (n--)
	*cp++ = getc(fp);
}

void getfontdef(dvifp)
     FILE *dvifp;
/* Read the font  definitions as they  are in the  postamble of the  DVI
   file.  Note that the font directory  is not yet loaded.  In order  to
   adapt ourselves to the existing "verser" the following font paramters
   are  copied	 onto  output	fontno  (4   bytes),  chksum,	fontmag,
   fontnamelength (1 byte), fontname.  At the end, a -1 is put onto  the
   file.*/
{
    char    str[50], *calloc ();
    unsigned char   byte;
    int     i, fnamelen;

    while (((byte = Nosignextend(dvifp, 1)) >= FNT_DEF1) &&
	(byte <= FNT_DEF4)) {
	switch (byte) {
	case FNT_DEF1:
	    ReadFontDef (Nosignextend(dvifp, 1), dvifp);
	    break;
	case FNT_DEF2:
	    ReadFontDef (Nosignextend(dvifp, 2), dvifp);
	    break;
	case FNT_DEF3:
	    ReadFontDef (Nosignextend(dvifp, 3), dvifp);
	    break;
	case FNT_DEF4:
	    ReadFontDef (Nosignextend(dvifp, 4), dvifp);
	    break;
	default:
	    fatal ("Bad byte value in font defs");
	    break;
	}
    }
    if (byte != POST_POST)
	fatal ("POST_POST missing after fontdefs");
}

void MoveDown(a)
int a;
{
  v += a;
}

void MoveOver(b)
int b;
{
    h += b;
}

void OpenFontFile()
/* The original version of this dvi driver reopened the font file  each
   time the font changed, resulting in an enormous number of relatively
   expensive file  openings.   This version  keeps  a cache  of  up  to
   MAXOPEN open files,  so that when  a font change  is made, the  file
   pointer, pxlfp, can  usually be  updated from the  cache.  When  the
   file is not found in  the cache, it must  be opened.  In this  case,
   the next empty slot  in the cache  is assigned, or  if the cache  is
   full, the least used font file is closed and its slot reassigned for
   the new file.  Identification of the least used file is based on the
   counts of the number  of times each file  has been "opened" by  this
   routine.  On return, the file pointer is always repositioned to  the
   beginning of the file.*/
{
    register int i,least_used,current;

#ifdef DEBUG
    if (Debug) printf("Open Font file\n");
#endif
    if (pfontptr == fontptr)
        return;                 /* we need not have been called */

    for (current = 1;
	(current <= nopen) &&
	    (pixel_files[current].pixel_file_id != fontptr->font_file_id);
	++current); /* try to find file in open list */
    if (current <= nopen) {      /* file already open */
	pxlfp = pixel_files[current].pixel_file_id;
	fseek(pxlfp,0,0);	/* reposition to start of file */
    } else {                        /* file not in open list */
        if (nopen < MAXOPEN)    /* just add it to list */
            current = ++nopen;
	else {/* list full -- find least used file, close it, and */
	      /* reuse slot for new file */ 
	    least_used = 1;
            for (i = 2; i <= MAXOPEN; ++i)
	        if (pixel_files[least_used].use_count >
                    pixel_files[i].use_count)
		    least_used = i;
	    fclose(pixel_files[least_used].pixel_file_id);
	    pixel_files[least_used].fptr -> font_file_id = 0;
	    current = least_used;
        }
        if ((pxlfp=fopen(fontptr->name,"r")) == NULL) {
	  perror ("");
	  fatal("PXL file \"%s\" could not be opened; %d PXL files are open",
		fontptr->name,nopen);
	};
	pixel_files[current].pixel_file_id = pxlfp;
	pixel_files[current].fptr = fontptr;
	pixel_files[current].use_count = 0;
    }
    pfontptr = fontptr;			/* make previous = current font */
    fontptr->font_file_id = pxlfp;	/* set file identifier */
    pixel_files[current].use_count++;	/* update reference count */
}

int PixRound(x, conv)	/* return rounded number of pixels */
     register int x;		/* in DVI units     */
     int conv;		/* conversion factor */
{
  return((int)((x + (conv >> 1)) / conv));
}

/* Put the given font pointer on the global list of font pointers and */
 /* make it the current font. */
void installfontptr (tfontptr)
     struct font_entry *tfontptr;
{
  tfontptr->next = hfontptr;
  fontptr = hfontptr = tfontptr;
}

int ReadFontDef(k, dvifp)
     int k;
     FILE *dvifp;
{
  int t, i;
  register struct font_entry *tfontptr;	/* temporary font_entry pointer   */
  register struct char_entry *tcharptr;	/* temporary char_entry pointer  */
  char *direct, *tcp, *tcp1;
  int found;
  char curarea[STRSIZE];

  if ((tfontptr = NEW(struct font_entry)) == NULL)
    fatal("can't malloc space for font_entry");

  tfontptr->k = k;
  tfontptr->c = Nosignextend(dvifp, 4);	/* checksum */
  tfontptr->s = Nosignextend(dvifp, 4);	/* space size */
  tfontptr->d = Nosignextend(dvifp, 4);	/* design size */
  tfontptr->a = Nosignextend(dvifp, 1);	/* area length for font name */
  tfontptr->l = Nosignextend(dvifp, 1);	/* device length */
  GetBytes(dvifp, tfontptr->n, tfontptr->a+tfontptr->l);
  tfontptr->n[tfontptr->a+tfontptr->l] = '\0';
  tfontptr->font_space = tfontptr->s/6;	/* never used */
  tfontptr->font_mag = (int)((ActualFactor((int)(((float)tfontptr->s/
						  (float)tfontptr->d)*1000.0 + 0.5)) * 
#ifdef USEGLOBALMAG
			      ActualFactor(mag) *
#endif
			      (float)RESOLUTION * 5.0) + 0.5);

#ifdef DEBUG
  printf ("Trying to open font %s, mag %d.\n", tfontptr -> n, 
	  tfontptr -> font_mag);
#endif
  /* Look for a font with the same file name as tfontptr in */
  /* closedfonts. */
  {
    struct font_entry *prevptr=NULL; /* Follows curptr in the closed */
    /* fonts list. */
    struct font_entry *curptr;
    for (curptr = closedfonts;
	 (curptr != NULL) &&
	 !((curptr->font_mag == tfontptr -> font_mag) &&
	   (strcmp (curptr -> n, tfontptr -> n) == 0));
	 prevptr = curptr,curptr = curptr -> next);
    if (curptr != NULL) {
#ifdef DEBUG
      printf ("Re-opening closed font %s, mag %d, filename is %s.\n",
	      tfontptr -> n, tfontptr -> font_mag, curptr -> name);
#endif
      /* We found a font with the same name in the list of closed */
      /* fonts.  Now delete it from the list of closed fonts. */
      if (prevptr == NULL) {
	/* curptr was the first font on the list of closed fonts. */
	closedfonts = closedfonts -> next;
      } else {
	/* curptr wasn't first. */
	prevptr -> next = curptr -> next;
      };
      /* Verify that all of the relevant font parameters are the */
      /* same. */
      if ((tfontptr -> c != curptr -> c) ||
	  (tfontptr -> s != curptr -> s) ||
	  (tfontptr -> d != curptr -> d)) {
	  fatal ("Font %s at magnification %d reencountered with different parameters.",
		 tfontptr -> n, tfontptr -> font_mag);
	};
      curptr -> k = tfontptr -> k;
      /* The following is somewhat bogus.  I should fix the above */
      /* code so that no mallocs happen if the font is in the closed */
      /* list.  Oh well, spaghetti code begats spaghetti code. */
      free (tfontptr);
      installfontptr (curptr);
    } else {
      /* Opening a new font. */
      if (tfontptr->a != 0) {
	sprintf(tfontptr->name, "%s.%dpxl", tfontptr->n, tfontptr->font_mag);
      } else {
	direct = PXLpath;
	found = FALSE;
	do { 
	  tcp = index(direct, ':');
	  if (tcp == NULL) tcp = strlen(direct) + direct;
	  strncpy(curarea, direct, tcp-direct);
	  tcp1 = curarea + (tcp - direct);
	  *tcp1++ = '/';
	  *tcp1++ = '\0';

	  sprintf(tfontptr->name, "%s%s.%dpxl", curarea, tfontptr->n, tfontptr->font_mag);
	  found = (access(tfontptr->name, READ) == 0);
	  if (*tcp) direct = tcp + 1; else direct = tcp;
	} while ( !found && *direct != '\0');
      };
#ifdef DEBUG
      printf ("Filename is %s.\n", tfontptr -> name);
#endif
      installfontptr (tfontptr);
      OpenFontFile();
      if ((t = Nosignextend(pxlfp, 4)) != PXLID)
	fatal("PXL ID = %d, can only process PXL ID = %d files",
	      t, PXLID);
      fseek(pxlfp, -20, 2);
      t = Nosignextend(pxlfp, 4);
      if ((tfontptr->c != 0) && (t != 0) && (tfontptr->c != t))
	fatal("font = \"%s\",\n-->font checksum = %d,\n-->dvi checksum = %d",
	      tfontptr->name, tfontptr->c, t);
      tfontptr->magnification = Nosignextend(pxlfp, 4);
      tfontptr->designsize = Nosignextend(pxlfp, 4);

      fseek(pxlfp, Nosignextend(pxlfp, 4) * 4, 0);

      for (i = FIRSTPXLCHAR; i <= LASTPXLCHAR; i++) {
	tcharptr = &(tfontptr->ch[i]);
	tcharptr->width = Nosignextend(pxlfp, 2);
	tcharptr->height = Nosignextend(pxlfp, 2);
	tcharptr->xOffset= signextend(pxlfp, 2);
	tcharptr->yOffset = signextend(pxlfp, 2);
	tcharptr->where.isloaded = FALSE;
	tcharptr->where.address.fileOffset = Nosignextend(pxlfp, 4) * 4;
	tcharptr->tfmw = ((float)Nosignextend(pxlfp, 4)*(float)tfontptr->s) /
	  (float)(1<<20);
      }
    }
  }
}

int readpostamble (dvifp)
     FILE *dvifp;
/* This  routine  is  used  to  read  in  the  postamble  values.    It
   initializes the magnification and checks  the stack height prior  to
   starting printing the document.  It returns the number of pages in the document. */
{
    FindPostAmblePtr (&postambleptr, dvifp);
    if (Nosignextend(dvifp, 1) != POST)
	fatal ("POST missing at head of postamble");
#ifdef DEBUG
    if (Debug) fprintf (stderr, "got POST command\n");
#endif
    /*	  lastpageptr = */ Nosignextend(dvifp, 4);
    num = Nosignextend(dvifp, 4);
    den = Nosignextend(dvifp, 4);
    mag = Nosignextend(dvifp, 4);
    hconv = DoConv(num, den, hconvRESOLUTION);
    vconv = DoConv(num, den, vconvRESOLUTION);

    Nosignextend(dvifp, 4);	/* height-plus-depth of tallest page */
    Nosignextend(dvifp, 4);	/* width of widest page */
    if (Nosignextend(dvifp, 2) >= STACKSIZE)
	fatal ("Stack size is too small");
    return (Nosignextend(dvifp, 2));	/* this reads the number of pages in */
    /* the DVI file */
}

void LoadAChar(ptr)
     register struct char_entry *ptr;
{
  if (ptr->where.address.fileOffset == 0) {
    ptr->where.address.pixrectptr = NULL;
    return;
  }
  OpenFontFile();
  fseek(pxlfp, ptr->where.address.fileOffset, 0);
  ptr->where.address.pixrectptr =
    read_char (pxlfp, ptr -> width, ptr -> height);
  ptr->where.isloaded = TRUE;
}

/* Display a character.*/
void SetChar(c, command, xscreen, yscreen)
     int c; /* Character to display */
     int command; /* Command we are doing */
     int xscreen, yscreen;
{
  register struct char_entry *ptr; /* temporary char_entry pointer */
  int k;
  int hh; /* current horizontal position in pixels */
  int vv; /* current vertical position in pixels */

  ptr = &(fontptr->ch[c]);
  hh = PixRound(h, hconv);
  vv = PixRound(v, vconv);
  if (!ptr->where.isloaded) LoadAChar(ptr);
  show_char (hh-ptr->xOffset-xscreen, vv-ptr->yOffset-yscreen,
	     ptr->width, ptr->height,
	     ptr->where.address.pixrectptr);
  if (command <= SET4) h += ptr->tfmw;
}

void SetFntNum(k)
     int k;
/*  this routine is used to specify the font to be used in printing future
    characters */
{
    fontptr = hfontptr;
    while ((fontptr!=NULL) && (fontptr->k!=k))
	fontptr = fontptr->next;
    if (fontptr == NULL)
	fatal("font %d undefined", k);
}

void SetRule(a, b, Set, xscreen, yscreen)
     int a, b;
     BOOLEAN Set;
     int xscreen, yscreen;
{	    /*	 this routine will draw a rule on the screen */
    int ehh, evv;
    int hh; /* current horizontal position in pixels */
  int vv; /* current vertical position in pixels */

    hh = PixRound(h, hconv);
    vv = PixRound(v-a, vconv);
    ehh = PixRound(h + b, hconv);
    evv = PixRound(v, vconv);
    if (hh == ehh) ehh++;
    if (vv == evv) vv--;
    if ((a > 0) && (b > 0))
      black_box (hh-xscreen, vv-yscreen, ehh-hh, evv-vv);
    if (Set) {
	h += b;
/*        v += a; */
    }
}

void SkipFontDef(k, dvifp)
     int k;
     FILE *dvifp;
{
  int a, l;
  char n[STRSIZE];

  Nosignextend(dvifp, 4);
  Nosignextend(dvifp, 4);
  Nosignextend(dvifp, 4);
  a = Nosignextend(dvifp, 1);
  l = Nosignextend(dvifp, 1);
  GetBytes(dvifp, n, a+l);
}