/* This is the color TeX previewer DVIVGA */
/* (C)opyright 1994 Wolfgang R. Mueller, Computing Centre,
Heinrich-Heine-University Duesseldorf, Germany,
wolfgang@uni-duesseldorf.de, +49-211-311-3905.
This program may be used without any warranty under
the terms of the GNU general public licence. */
/* translated from the original TurboPascal source
partly with p2c, the Pascal-to-C translator */

#include <stdio.h>
#ifdef __TURBOC__
  #include <mem.h>
  #include <alloc.h>
  #define malloc farmalloc
  #define calloc farcalloc
  #define realloc farrealloc
  #define free farfree
#endif

#define uchar unsigned char
#define ushort unsigned short
#define ulong unsigned long
#define ptr void *

#define maxink     16
#define inkshift    4  /* maxink == 1<<inkshift */
#define smax      100
#define xm 	  319
#define ym        447

#ifdef __MSDOS__
static char tfmprefix[] = "c:\\tex\\fonts\\tfm\\";
static char fontprefix[] = "c:\\tex\\fonts\\canon\\";
#else
static char tfmprefix[] = "/usr/TeX/lib/tex/fonts/";
static char fontprefix[] = "/usr/TeX/lib/tex/fonts/";
#endif

static uchar maskmat[5][4] = {
  {14,4,16,2},{7,9,5,11},{15,1,13,3},{6,12,8,10},{0x88,0x44,0x22,0x11}};
typedef struct greydesc { uchar maskc, maskm, masky; } greydesc;

static uchar stackcy[smax], stackma[smax], stackye[smax], stackbl[smax];
static char STR[99], FOPRE[99], FOMAG[16], FONAM[99], FOLOC[99], FOFUL[99];
static greydesc greymask[8];
static uchar maskb[maxink + 1][4];
static uchar cb[256], *pxlmem[ym+1];

static uchar alles, clearing, fini;
static short colst, xres=300, yres=300, xmax, hoff, voff;
static ushort darkfac;
static short xmb, ymax, hoffa=0, voffa=0;
static ulong zoelli;
static FILE *prot=stderr;

static void finale();
static void Tptr(p) void *p; {  if(p==NULL) {
  fprintf(prot, " - not enough memory :-( ");  finale();
  } /* else fprintf(prot, "(free:%ld)", (long)coreleft());*/
}
static void initpxmem() {  short i;
  for (i = 0; i <= ym; i++)  Tptr(pxlmem[i] = (uchar *)malloc(xm + 1));
}
static void clrpxlmem() {  short i;
  for (i = 0; i <= ym; i++)  memset(pxlmem[i], 0, xm + 1);
}
static void pixet(y, x, b)  ushort y, x;  uchar b;  {
  uchar *wo;  greydesc *WITH1;
  wo = pxlmem[y] + x;  WITH1 = &greymask[y & 7];
  if (clearing) * wo      &= ~b; else * wo      |= (b & WITH1->maskc);
  if (clearing) *(wo +40) &= ~b; else *(wo +40) |= (b & WITH1->maskm);
  if (clearing) *(wo +80) &= ~b; else *(wo +80) |= (b & WITH1->masky);
}
static void paxet(y, x, b)  ushort y, x;  uchar b;  {
  uchar *wo = pxlmem[y] + x;
  if (clearing)  *wo = (*wo * (64 - b)) >> 6;
   else  *wo += ((ushort)b * darkfac) >> inkshift;
}
static ushort vertfac=7;
static void verteil(x, w, y, h, xp, yp, zp)
 ushort x, w, y, h, *xp, *yp, *zp;  {
  ushort xp1, yp1, zp1, xp2, yp2, zp2, wh, tau;  ushort b;
  if (w + h > 2) {
    if (w > h) {  wh = w >> 1;
      verteil(x, wh, y, h, &xp1, &yp1, &zp1);
      verteil(x + wh, w - wh, y, h, &xp2, &yp2, &zp2);
    } else {  wh = h >> 1;
      verteil(x, w, y, wh, &xp1, &yp1, &zp1);
      verteil(x, w, y + wh, h - wh, &xp2, &yp2, &zp2);
    }
    if (zp2 > zp1) {
      tau = xp1;  xp1 = xp2;  xp2 = tau;  tau = yp1;  yp1 = yp2;  yp2 = tau;
    }  *zp = zp1 + zp2;
    if (*zp < 64) {  *xp = xp1;  *yp = yp1;  return;  }
    pxlmem[xp1][yp1] += 1;  *zp -= 64;  *xp = xp2;  *yp = yp2;  return;
  }
  *xp = x;  *yp = y;  b = pxlmem[x][y]; if(b>64) b=64; b*=vertfac;
  pxlmem[x][y] = b >> 6;  *zp = b & 63;
}
#ifdef __TURBOC__
#include <conio.h>
#include <dos.h>
#include <bios.h>
#define BIOI 0x10
static uchar *vgamem=(uchar *)0xa0000000;
static ushort savemode;
static void dispinit()  {  uchar ret, *p;  short i;
  _AX = 0x0f00; geninterrupt(BIOI); ret=_AL; savemode=ret;
  _AX = 0x1a00; geninterrupt(BIOI); ret=_AL;
  if(ret != 0x1a) { fprintf(prot, "Only VGA supported !\n"); exit(1); }
  initpxmem(); vgamem+=80*(480-ym-1);
}
static void dispopen() {  ushort i;  uchar *p;
  /*while(!kbhit()) ;*/
  if (alles) {  xmax = xm * 8 + 7;  ymax = ym * 8 + 7;  }
   else  {  xmb = xm >> 3;  xmax = xm;  ymax = ym;  }
  clrpxlmem();  if (alles < 3) return;
  _AX = 0x12; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0000; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0101; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0202; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0303; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0404; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0505; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0606; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0707; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0708; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x0709; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x070a; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x070b; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x070c; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x070d; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x070e; geninterrupt(BIOI);
  _AX = 0x1000; _BX = 0x070f; geninterrupt(BIOI);
  if (vertfac == 7) {
    _AX = 0x1010; _BX = 0x0000; _CX = 0x3f3f; _DH = 0x3f; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0001; _CX = 0x3636; _DH = 0x36; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0002; _CX = 0x2d2d; _DH = 0x2d; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0003; _CX = 0x2424; _DH = 0x24; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0004; _CX = 0x1b1b; _DH = 0x1b; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0005; _CX = 0x1212; _DH = 0x12; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0006; _CX = 0x0909; _DH = 0x09; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0007; _CX = 0x0000; _DH = 0x00; geninterrupt(BIOI);
  } else {
    _AX = 0x1010; _BX = 0x0000; _CX = 0x3f3f; _DH = 0x3f; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0001; _CX = 0x3f00; _DH = 0x3f; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0002; _CX = 0x3f3f; _DH = 0x00; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0003; _CX = 0x3f00; _DH = 0x00; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0004; _CX = 0x003f; _DH = 0x3f; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0005; _CX = 0x0000; _DH = 0x3f; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0006; _CX = 0x003f; _DH = 0x00; geninterrupt(BIOI);
    _AX = 0x1010; _BX = 0x0007; _CX = 0x0000; _DH = 0x00; geninterrupt(BIOI);
  }  gotoxy(9,1);
  printf("The HHU TeX colour Previewer (V 94.03) distributed by DANTE e.V.");
  gotoxy(25,2);
  printf("supporting \\special{color ...}");
  outportb(0x3c4,2);  outportb(0x3c5,8);
  for (i=0, p=vgamem+39; i<=ym; i++, p+=80)  *p=0x01;
  memset(vgamem-80, 0xff, 80);
  gotoxy(43,4);   printf("p(revious page) or backspace");
  gotoxy(43,5);   printf("n(ext page) or enter or spacebar");
  gotoxy(43,6);   printf("c(olour) g(rey)  q(uit)");
  gotoxy(43,8);   printf("Moving Magnifying Glass");
  gotoxy(43,10);  printf("l(eft) r(ight) u(p) d(own)");
  gotoxy(43,11);  printf(" ALT-ed:    small stepsize");
  gotoxy(43,12);  printf(" unshifted: medium stepsize");
  gotoxy(43,13);  printf(" shifted:   large stepsize");
  gotoxy(43,15);  printf("cursor keys give medium,");
  gotoxy(43,16);  printf("CTRL+left/right arrow large,");
  gotoxy(43,17);  printf("PGUP/PGDOWN large stepsize");
  gotoxy(43,19);  printf("HOME upper left corner");
  gotoxy(43,20);  printf("END lower right corner");
  gotoxy(43,22);  printf("Any of those keys activates");
  gotoxy(43,23);  printf("the magnifying glass here.");
}
static uchar shiftab[4]={1,2,4,4};
static void dispcopy() {  ushort i, j, k;  uchar b, *p, *q, l;
  if (alles)  {
    if (vertfac == 7) {
      alles = 0;
      verteil(0, ym + 1, 0, xm + 1, &i, &j, &k);
      for (l = 0; l < 3; l++) {
	outportb(0x3c4,2); outportb(0x3c5,shiftab[l]);
	for (j = 0; j <= ym; j++)  {  p = vgamem + j * 80;  q = pxlmem[j];
	  for (k = 0; k <= xm; k++) {
	    if ((k & 7) == 0)  b = (*q & 0x01);
	    else  {  b = (b << 1) | (*q & 0x01);
	      if ((k & 7) == 7)  *p++ = b;
	    } *q++ >>=1;
      } } }
    }  else  {  switch (alles)  {
      case 3:  outportb(0x3c4,2);  outportb(0x3c5,2);  break;
      case 2:  outportb(0x3c4,2);  outportb(0x3c5,4);  break;
      case 1:  outportb(0x3c4,2);  outportb(0x3c5,1);  break;
      }  alles--;
      verteil(0, ym + 1, 0, xm + 1, &i, &j, &k);
      for (j = 0; j <= ym; j++)  {  p = vgamem + j * 80;  q = pxlmem[j];
	for (k = 0; k <= xm; k++) {
	  if ((k & 7) == 0)  b = *q++;
	  else  {  b = (b << 1) | *q++;
	    if ((k & 7) == 7)  *p++ = b;
    } } } }
  }  else  {  ushort x1,x2,x,y1,y2,y;
    outportb(0x3ce,4); outportb(0x3cf,3);
    outportb(0x3c4,2); outportb(0x3c5,8);
    x1 = (hoffa + xres) >> 3;  x2 = x1 + (xm >> 3);
    y1 = (voffa + yres) >> 3;  y2 = y1 + (ym >> 3);
    for (x=x1; x<=x2; x++)  for (y=y1; y<=y2; y++)
     if ((x==x1)||(x==x2)||(y==y1)||(y==y2))
      vgamem[y*80+(x>>3)] &= 0xff7f >> (x & 7);
    hoffa = hoff;  voffa = voff;
    x1 = (hoffa + xres) >> 3;  x2 = x1 + (xm >> 3);
    y1 = (voffa + yres) >> 3;  y2 = y1 + (ym >> 3);
    for (x=x1; x<=x2; x++)  for (y=y1; y<=y2; y++)
     if ((x==x1)||(x==x2)||(y==y1)||(y==y2))
      vgamem[y*80+(x>>3)] |= 0x0080 >> (x & 7);
    outportb(0x3c4,2); outportb(0x3c5,2);
    for (j = 0, p = vgamem + 40; j <= ym; j++, p += 80)
     memcpy(p, pxlmem[j]     , 40);
    outportb(0x3c4,2); outportb(0x3c5,4);
    for (j = 0, p = vgamem + 40; j <= ym; j++, p += 80)
     memcpy(p, pxlmem[j] + 40, 40);
    outportb(0x3c4,2); outportb(0x3c5,1);
    for (j = 0, p = vgamem + 40; j <= ym; j++, p += 80)
     memcpy(p, pxlmem[j] + 80, 40);
} }

static void dispclos() { _AX = savemode; geninterrupt(BIOI);
}
static char evalkbd() {  char np=0;  while (! kbhit()) ;
  hoff += xres;  voff += yres;
  while (kbhit()) {
    switch (getch()) {
    case 'h': case 'H': hoff=0; voff=0; break;
    case 'u': voff-=64; break;
    case 'U': voff-=256; break;
    case 'd': voff+=64; break;
    case 'D': voff+=256; break;
    case 'l': hoff-=64; break;
    case 'L': hoff-=256; break;
    case 'r': hoff+=64; break;
    case 'R': hoff+=256; break;
    case 'q': case 'Q': fini=1; break;
    case 'n': case 'N': case 13: case ' ': np=1; break;
    case 'p': case 'P': case  8: np=-1; break;
    case 'c': vertfac=1; alles=3; break;
    case 'g': vertfac=7; alles=3; break;
    case 0: switch (getch()) {
      case 19: hoff+=8; break;
      case 22: voff-=8; break;
      case 32: voff+=8; break;
      case 38: hoff-=8; break;
      case 71: hoff=0; voff=0; break;
      case 72: voff-=64; break;
      case 73: voff-=256; break;
      case 75: hoff-=64; break;
      case 77: hoff+=64; break;
      case 79: hoff=xm << 3; voff=ym << 3; break;
      case 80: voff+=64; break;
      case 81: voff+=256; break;
      case 115: hoff-=256; break;
      case 116: hoff+=256; break;
      } break;
    }
  }
  if (hoff<0) hoff=0;  if (hoff>xm*7-1) hoff=xm*7-1;  hoff -= xres;
  if (voff<0) voff=0;  if (voff>ym*7+7) voff=ym*7+7;  voff -= yres;
  return(np);
}
#endif
static void setrect(xl, yl, xh, yh)  ushort xl, yl, xh, yh;  {
  ushort x, y, xll, xrr;  uchar a, b, c;
  xll = xl >> 3;  xrr = xh >> 3;
  a = (0xff >> (xl & 7)) & 255;  c = 0xff << (7 - (xh & 7));
  for (y = yl; y <= yh; y++) {  b = a;
    for (x = xll; x <= xrr; x++) {
      if (x == xrr)  b &= c;
      pixet(y, x, b);  b = 0xff;
} } }
static void setract(xl, yl, xh, yh)  ushort xl, yl, xh, yh;  {
  ushort xlb, xhb, ylb, yhb, x, y;  uchar xf, yf;
  xlb = xl >> 3;  xhb = xh >> 3;  ylb = yl >> 3;  yhb = yh >> 3;
  if (xlb == xhb) {  xf = xh - xl + 1;
    if (ylb == yhb) {  paxet(ylb, xlb, xf * (yh - yl + 1));  }  else  {
      paxet(ylb, xlb, xf * (8 - (yl & 7)));
      paxet(yhb, xlb, xf * ((yh & 7) + 1));
      for (y = ylb + 1; y < yhb; y++)  paxet(y, xlb, xf * 8);
  } }  else  if (ylb == yhb) {  yf = yh - yl + 1;
    paxet(ylb, xlb, yf * (8 - (xl & 7)));
    paxet(ylb, xhb, yf * ((xh & 7) + 1));
    for (x = xlb + 1; x < xhb; x++)  paxet(ylb, x, yf * 8);
  }  else  {  xf = 8 - (xl & 7);
    for (x = xlb; x <= xhb; x++) {
      yf = 8 - (yl & 7);  if (x == xhb)  xf = (xh & 7) + 1;
      for (y = ylb; y <= yhb; y++) {
        if (y == yhb)  yf = (yh & 7) + 1;  paxet(y, x, xf * yf);  yf = 8;
      } xf = 8;
} } }

static char dviname[73];
static FILE *dvifile;
static long dvimag;
static uchar dvibuf[2048];
static ushort dvibufp, dvibufe;

static void baddvi(s)  char *s;  {
  fprintf(prot, "bad dvi: %s\n", s);  dispclos();  exit(1);
}
static void dvibytes(s, l)   char *s;  uchar l;  {  ushort ll;
  s[l] = '\0';  ll = dvibufe - dvibufp;
  if (ll >= l) {
    memmove((ptr)s, (ptr)(&dvibuf[dvibufp]), (long)l);
    dvibufp += l;  return;
  }
  if (ll > 0)  memmove((ptr)s, (ptr)(&dvibuf[dvibufp]), (long)ll);
  dvibufe = fread(dvibuf, 1, 2048, dvifile);
  if (dvibufe + ll < l)  baddvi("ends prematurely !");
  memmove((ptr)(&s[ll]), (ptr)dvibuf, (long)(l - ll));
  dvibufp = l - ll;
}
static uchar dvibyte() { uchar b;
  if (dvibufp >= dvibufe) {  dvibufp = 0;
    dvibufe = fread(dvibuf, 1, 2048, dvifile);
  }
  if (dvibufp >= dvibufe)  baddvi("ends prematurely !");
  b = dvibuf[dvibufp];  dvibufp++;  return b;
}
static void dviskip(l)  long l;  {  uchar b;
  while (l > 0) {
    l += (long)dvibufp - (long)dvibufe;
    if (l <= 0)  dvibufp = dvibufe + l;
    else {  dvibufp = dvibufe;  l--;  dvibyte();  }
} }
static long dvinum(b)  uchar b;  {  uchar i;  long n;
  n = 0;
  if (dvibufp + b > dvibufe) {
    for (i = 1; i <= b; i++)  n = (n << 8) | dvibyte();  return n;
  }
  for (i = 0; i < b; i++)  n = (n << 8) | dvibuf[dvibufp + i];
  dvibufp += b;  return n;
}
static long dviint(b)  uchar b;  {  uchar i;  long n;
  if (dvibufp + b <= dvibufe) {
    n = dvibuf[dvibufp];
    if (n > 127)  n -= 256;
    for (i = 1; i < b; i++)  n = (n << 8) | dvibuf[dvibufp + i];
    dvibufp += b;  return n;
  }
  n = dvibyte();
  if (n > 127)  n -= 256;
  for (i = 2; i <= b; i++)  n = (n << 8) | dvibyte();  return n;
}
static void dviposit(l)  long l;  {  fseek(dvifile, l, 0);
  dvibufe = fread(dvibuf, 1, 2048, dvifile);  dvibufp = 0;
}
static void dviopen() {  long l;  uchar j, em;  ushort k;
  sprintf(STR, "%s.dvi", dviname);
  if ((dvifile = fopen(STR, "rb"))==0) {  strcpy(STR, dviname);
    if ((dvifile = fopen(STR, "rb"))==0)  baddvi("not existing !");
  }
  dvibufe = fread(dvibuf, 1, 2, dvifile);
  if (dvibufe < 2) baddvi("empty !");
  em = dvibuf[1];
  if (dvibuf[0] != 247) baddvi("no valid preamble");
  /* now position to postamble */
  fseek(dvifile, 0L, 2);  l=ftell(dvifile);  if(l>2048) l=2048;
  fseek(dvifile, -l, 2);  k = fread(dvibuf, 1, 2048, dvifile);
  do {  k--;  } while (k >= 4 && dvibuf[k] != em);
  if (k < 4)  baddvi("no postamble in last 2048 bytes !");
  dvibufe = k + 1;  dvibufp = k - 4;  l = dvinum(4);
  fseek(dvifile, l, 0);  dvibufe = fread(dvibuf, 1, 2048, dvifile);
  dvibufp = 0;  dvibyte();
}

typedef union chdesc { uchar b8[16];
  struct { short wid, hei, hof, vof; long bmp, tfw; } U1;
  struct { long tfh, tfd, dum1, dum2; } U2;
} chdesc;
typedef struct fontdesc {
  long dfn;  char *fonam;  chdesc *chv;
  long danf;  uchar *chm;  short mch, fty;
} fontdesc;
static fontdesc **fontvect;
static uchar fontint;
static FILE *fofil;
static uchar *achm, *pkbuf;
static uchar fofbyte() {  uchar b;
  if (fread(&b, 1, 1, fofil) <= 0) b = 0;  return b;
}
static long fofint(b)  uchar b;  {  uchar i;  long n;
  n = fofbyte();  if (n > 127)  n -= 256;
  for (i = 2; i <= b; i++)  n = (n << 8) | fofbyte();
  return n;
}

static long hs[smax], vs[smax], ws[smax], xs[smax], ys[smax], zs[smax];
static long cnt[10];
static uchar bitrev[256];
static char comment[256];
static double conv, vconv;
static long l, landx, landy, newmag;
static long a, b, c, f, q, h, v, w, x, y, z;
static long chk, scf, dsz, fofchk, num, den, mag, spl, lpp, mxh, mxv;
static int pagnum, pag1, paganz, i, k;
static ushort s, mst, mpn;
static char dviori;
static uchar o, j, post, started, below;

static void initbitrev() {  uchar b, i, j, k, m, n;
  for (i = 0; i <= maxink; i++) {
    for (j = 0; j <= 3; j++) {  b = 0;
      for (k = 0; k <= 3; k++) {
	if (maskmat[j][k] <= i)  b |= maskmat[4][k];
  }  maskb[i][j] = b;  } }
  cb[0] = 0;  bitrev[0] = 0;  m = 0x80;  n = 1;
  while (m) {  /* count bits / put bits into reverse order within a byte */
    for (j = 0; j < n; j++)  {  cb[j + n] = cb[j] + 1;
      bitrev[j + n] = bitrev[j] | m;
    }  n += n;  m >>= 1;
} }
/*static long prodovz(a, b)  ushort a, b;  {  return ((long)a * (long)b);  }
static long scaled(w)  long w;  {  long s;
  union {  long l;  struct {  ushort n, h;  } U1;  } a, b;
  a.l = w;  b.l = scf;
  s = (((((ulong)prodovz(a.U1.n, b.U1.n)) >> 16) + prodovz(a.U1.n,
	  b.U1.h) + prodovz(a.U1.h, b.U1.n)) >> 4) +
      (prodovz(a.U1.h, b.U1.h) << 12);
  if (w < 0)  s -= scf << 12;  return s;
}*/
static long scaled(w)  long w;  {  long s; ulong t=w, u=scf;
  /* should return  w * scf / 2**20  */
  s = ( ( (((t & 65535L) * (u & 65535L)) >> 16)
	+   (t & 65535L) * (u >>    16)
	+   (t >>    16) * (u & 65535L)         ) >> 4)
    + ( (   (t >>    16) * (u >>    16)         ) << 12);
  if (w < 0)  s -= scf << 12;  return s;
}

static void tfmdef() {  short ll, lh, bc, ec, nw, nh, nd, i;
  uchar b1, b2, b3;  short FORLIM;
  fontdesc *WITH = fontvect[fontint];
  sprintf(STR, "%s%s.tfm", tfmprefix, FONAM);
  fprintf(prot, "trying  %s  instead", STR);
  fofil = fopen(STR, "rb");
  if (fofil==0) {  fprintf(prot, " - absent as well :-(\n");  return;  }
  ll = fofint(2);  lh = fofint(2);  bc = fofint(2);  ec = fofint(2);
  nw = fofint(2);  nh = fofint(2);  nd = fofint(2);  fseek(fofil, 0L, 2);
  if (ll * 4 > ftell(fofil) || ll < lh + ec - bc + nw + nh + nd + 7) {
    fprintf(prot, " - not a TFMfile !\n");  fclose(fofil);  return;
  }
  WITH->mch = ec;
  Tptr( WITH->chv = (chdesc *)calloc(WITH->mch + 1, sizeof(chdesc)) );
  fseek(fofil, 24L, 0);  fofchk = fofint(4);
  if (chk != 0) if (fofchk != 0) if (chk != fofchk)
    fprintf(prot, " *+* wrong checksum *+* ");
  fseek(fofil, (lh + ec - bc + 7L) * 4, 0);
  FORLIM = nw + nh + nd;
  for (i = 0; i < FORLIM; i++)
    WITH->chv[i].U2.dum1 = scaled(fofint(4));
  fseek(fofil, lh * 4L + 24, 0);
  for (i = bc; i <= ec; i++) {
    b1 = fofbyte();  b2 = fofbyte();  fofbyte();  fofbyte();
    WITH->chv[i].U1.tfw = WITH->chv[b1].U2.dum1;
    WITH->chv[i].U2.tfh = WITH->chv[nw + (b2 >> 4)].U2.dum1;
    WITH->chv[i].U2.tfd = WITH->chv[nw + nh + (b2 & 15)].U2.dum1;
  }
  fclose(fofil);  WITH->fty = 1;  fprintf(prot, " - TFMfile OK\n");
}
static void tfmchar() {  short hr, vr, br, ar;  uchar li, re, ob, un;
  chdesc *WITH = &fontvect[fontint]->chv[c];
  switch (dviori) {
  case 0:
    hr = (short)(conv * h + 0.5)-hoff;
    vr = (short)(vconv * (v - WITH->U2.tfh) + 0.5)-voff;
    br = (short)(conv * (h + WITH->U1.tfw) + 0.5)-hoff;
    ar = (short)(vconv * (v + WITH->U2.tfd) + 0.5)-voff;
    break;
  case 1:
    hr = (short)(conv * (landx + v - WITH->U2.tfh) + 0.5)-hoff;
    vr = (short)(vconv * (landy - h - WITH->U1.tfw) + 0.5)-voff;
    br = (short)(conv * (landx + v + WITH->U2.tfd) + 0.5)-hoff;
    ar = (short)(vconv * (landy - h) + 0.5)-voff;
    break;
  case 3:
    hr = (short)(conv * (landx - v - WITH->U2.tfd) + 0.5)-hoff;
    vr = (short)(vconv * (landy + h) + 0.5)-voff;
    br = (short)(conv * (landx - v + WITH->U2.tfh) + 0.5)-hoff;
    ar = (short)(vconv * (landy + h + WITH->U1.tfw) + 0.5)-voff;
    break;
  case 2:
    hr = (short)(conv * (landx - h - WITH->U1.tfw) + 0.5)-hoff;
    vr = (short)(vconv * (landy - v - WITH->U2.tfd) + 0.5)-voff;
    br = (short)(conv * (landx - h) + 0.5)-hoff;
    ar = (short)(vconv * (landy - v + WITH->U2.tfh) + 0.5)-voff;
    break;
  }
  li = 1;  re = 1;  ob = 1;  un = 1;
  if (hr < 0) {  hr = 0;  li = 0;  }
  if (br > xmax) {  br = xmax;  re = 0;  }
  if (vr < 0) {  vr = 0;  ob = 0;  }
  if (ar > ymax) {  ar = ymax;  un = 0;  below = 1;  }
  if (hr > br)  return;
  if (vr > ar)  return;
  if (ob)  setrect(hr, vr, br, vr);
  if (li)  setrect(hr, vr, hr, ar);
  if (un)  setrect(hr, ar, br, ar);
  if (re)  setrect(br, vr, br, ar);
}
static void drawract(xl, yl, xh, yh)  ushort xl, yl, xh, yh;  {
  ushort xlb, xhb, ylb, yhb, x, y;  uchar xf, yf;
  xlb = xl >> 3;  xhb = xh >> 3;  ylb = yl >> 3;  yhb = yh >> 3;
  if (xlb == xhb) {  xf = xh - xl;
    if (ylb == yhb) {  paxet(ylb, xlb, (xf + yh - yl) << 1);  }  else  {
      paxet(ylb, xlb, xf - ((yl & 7) << 1) + 15);
      paxet(yhb, xlb, xf + ((yh & 7) << 1) + 1);
      for (y = ylb + 1; y < yhb; y++)  paxet(y, xlb, maxink);  return;
  } }  else  if (ylb == yhb) {  yf = yh - yl;
    paxet(ylb, xlb, yf - ((xl & 7) << 1) + 15);
    paxet(ylb, xhb, yf + ((xh & 7) << 1) + 1);
    for (x = xlb + 1; x < xhb; x++)  paxet(ylb, x, maxink);  return;
  }  else  {
    for (x = xlb + 1; x < xhb; x++) {  paxet(ylb, x, 8);  paxet(yhb, x, 8);  }
    for (y = ylb + 1; y < yhb; y++) {  paxet(y, xlb, 8);  paxet(y, xhb, 8);  }
    paxet(ylb, xlb, 15 - (yl & 7) - (xl & 7));
    paxet(ylb, xhb, (xh & 7) - (yl & 7) + 8);
    paxet(yhb, xlb, (yh & 7) - (xl & 7) + 8);
    paxet(yhb, xhb, (xh & 7) + (yh & 7) + 1);
} }
static void tfmcher() {  short hr, vr, br, ar;
  chdesc *WITH = &fontvect[fontint]->chv[c];
  switch (dviori) {
  case 0:
    hr = (short)(conv * h + 0.5);
    vr = (short)(vconv * (v - WITH->U2.tfh) + 0.5);
    br = (short)(conv * (h + WITH->U1.tfw) + 0.5);
    ar = (short)(vconv * (v + WITH->U2.tfd) + 0.5);
    break;
  case 1:
    hr = (short)(conv * (landx + v - WITH->U2.tfh) + 0.5);
    vr = (short)(vconv * (landy - h - WITH->U1.tfw) + 0.5);
    br = (short)(conv * (landx + v + WITH->U2.tfd) + 0.5);
    ar = (short)(vconv * (landy - h) + 0.5);
    break;
  case 3:
    hr = (short)(conv * (landx - v - WITH->U2.tfd) + 0.5);
    vr = (short)(vconv * (landy + h) + 0.5);
    br = (short)(conv * (landx - v + WITH->U2.tfh) + 0.5);
    ar = (short)(vconv * (landy + h + WITH->U1.tfw) + 0.5);
    break;
  case 2:
    hr = (short)(conv * (landx - h - WITH->U1.tfw) + 0.5);
    vr = (short)(vconv * (landy - v - WITH->U2.tfd) + 0.5);
    br = (short)(conv * (landx - h) + 0.5);
    ar = (short)(vconv * (landy - v + WITH->U2.tfh) + 0.5);
    break;
  }
  if (hr < 0)  hr = 0;  if (br > xmax)  br = xmax;
  if (vr < 0)  vr = 0;  if (ar > ymax)  ar = ymax;
  if (hr <= br)  if (vr <= ar)  drawract(hr, vr, br, ar);
}

#define PKN1 *achm++
static short pki1()  {  short b;
  b = PKN1;  if (b > 127)  b -= 256;  return b;
}
static short pkn2()  {  short b;
  b = PKN1;  return (b * 256 + PKN1);
}
static short pki2()  {  short b;
  b = PKN1;  if (b > 127)  b -= 256;
  return (b * 256 + PKN1);
}
static long pkn3()  {  long b;  short c;
  b = PKN1;  c = PKN1;
  return ((b * 256 + c) * 256 + PKN1);
}
static long pki3()  {  long b;
  b = pki1();  return (b * 65536L + pkn2());
}
static long pki4()  {  long b;
  b = pki2();  return (b * 65536L + pkn2());
}
static void pkdef()  {  long a, l;  ushort d;  uchar b, bb;
  uchar terminate;  short i, j, c;  fontdesc *WITH;  chdesc *WITH1;
  WITH = fontvect[fontint];  sprintf(STR, "%spk", FOFUL);
  fprintf(prot,"preparing font %ld: %s", f, STR);
  if( (fofil = fopen(STR, "rb"))==0) {
    fprintf(prot," not found :-(\n");
    sprintf(STR, "%spk", FOLOC);
    fprintf(prot,"preparing font %ld: %s", f, STR);
    fofil = fopen(STR, "rb");
  }
  if (fofil==0) {  WITH->mch = -1;
    fprintf(prot, " - file not found !\n");  return;
  }
  if ((fgetc(fofil)!=0xf7)||(fgetc(fofil)!=0x59)){  WITH->mch = -1;
    fprintf(prot, " - not a PKfile !\n");  fclose(fofil);  return;
  } else {
    fseek(fofil, 0L, 2);  WITH->danf = ftell(fofil);
    if (WITH->danf > 65520L) {  WITH->mch = -1;  fclose(fofil);
      fprintf(prot, " - too big for this driver\n");  return;
    } else {
      Tptr( WITH->chv = (chdesc *)calloc(256, sizeof(chdesc)) );
      Tptr( pkbuf = (uchar *)malloc(WITH->danf) );
      fseek(fofil, 0L, 0);  fread(pkbuf, WITH->danf, 1, fofil);
      fclose(fofil);  WITH->mch = -1;  achm=pkbuf;  terminate = 0;
      do {  b = PKN1;
	if (b >= 240) {
	  switch (b) {
	  case 240:  case 241:  case 242:  case 243: l = 0;
	    for (i = 240; i <= b; i++)  l = (l << 8) + PKN1;
	    achm += l;  break;
	  case 244:  achm += 4;  break;
	  case 245:  terminate = 1;  break;
	  case 246:  break;
	  case 247:  b = PKN1;  i = PKN1;
	    achm += i + 4;  fofchk = pki4();
	    if (chk != 0) if (fofchk != 0) if (chk != fofchk)
             fprintf(prot, " *+* wrong checksum *+* ");
	    achm += 8;  break;
	  case 248:  case 249:  case 250:  case 251:
	  case 252:  case 253:  case 254:  case 255:  break;
	  }
	} else {  d = (achm - pkbuf) - 1;  bb = b & 7;
	  switch (bb) {
	  case 0:  case 1:  case 2:  case 3:
	    l = bb * 256 + PKN1 - 8;  c = PKN1;  break;
	  case 4:  case 5:  case 6:  l = bb - 4;
	    l = (l << 16) + pkn2() - 13;  c = PKN1;  break;
	  case 7:  l = pki4() - 28;  c = pki4();  break;
	  }
	  WITH1 = &WITH->chv[c];
	  switch (bb) {
	  case 0:  case 1:  case 2:  case 3:
	    WITH1->U1.tfw = scaled(pkn3());  PKN1;
	    WITH1->U1.wid = PKN1;  WITH1->U1.hei = PKN1;
            WITH1->U1.hof = pki1();  WITH1->U1.vof = pki1();  break;
	  case 4:  case 5:  case 6:
	    WITH1->U1.tfw = scaled(pkn3());  pkn2();
	    WITH1->U1.wid = pkn2();  WITH1->U1.hei = pkn2();
            WITH1->U1.hof = pki2();  WITH1->U1.vof = pki2();  break;
	  case 7:
	    WITH1->U1.tfw = scaled(pki4());  pki4();  pki4();
	    WITH1->U1.wid = pki4();   WITH1->U1.hei = pki4();
            WITH1->U1.hof = pki4();   WITH1->U1.vof = pki4();  break;
	  }
	  achm += l;
	  if ((unsigned)c <= 255) {
	    if (WITH->mch < c)  WITH->mch = c;
	    WITH->chv[c].U1.bmp = d;
      }	} } while (!terminate); free(pkbuf);
      if (WITH->mch < 0)  fprintf(prot, " - PKfile in error !\n");
       else  fprintf(prot, " - available\n");
      WITH->chv = (chdesc *) realloc(WITH->chv, 16*(WITH->mch + 1));
      Tptr( WITH->fonam = (char *) malloc(strlen(STR)+1) );
      strcpy(WITH->fonam, STR);
} } }
static struct  {  long repc, count;  short xs, wid1, dynf, dyng, dynh;
  ushort d;  uchar db, white, bmerk, buf[ym + 1];
}  Lpkc;
static uchar pknib()  {  uchar Result;
  if (Lpkc.bmerk != 0) {
    Result = Lpkc.bmerk & 0xf;  Lpkc.bmerk = 0;  return Result;
  }
  Lpkc.bmerk = PKN1;  Result = Lpkc.bmerk >> 4;
  Lpkc.bmerk |= 0xf0;  return Result;
}
static long pknum()  {  uchar i, j, k;  long n;
  k = 1;
  do {  i = pknib();  k++;
    if (i == 0) {
      do {  j = pknib();  i++;  } while (j == 0);
      n = j;
      while (i > 0) {  i--;  n = (n << 4) + pknib();  }
      n += Lpkc.dyng;
    } else if (i <= Lpkc.dynf)  n = i;
    else if (i < 14)  n = (i << 4) + pknib() + Lpkc.dynh;
    else if (i == 14)  k = 0;
    else {  k = 1;  n = 1;  }
    if (k == 1)  Lpkc.repc = n;
  } while (k != 2);  return n;
}
static void pkline()  { short j, x=0; uchar dd;
  if (Lpkc.dynf == 14) {
    j = Lpkc.wid1 + Lpkc.xs;
    Lpkc.db += Lpkc.xs;
    do {
      if (Lpkc.db < 8)	Lpkc.d = (Lpkc.d << 8) | PKN1;
      else  Lpkc.db -= 8;
      dd = (Lpkc.d >> Lpkc.db) & 255;
      if (j >= 8) {  j -= 8;	Lpkc.buf[x] = dd;
      } else {	Lpkc.db += 8 - j;
	Lpkc.buf[x] = dd & (0xff00L >> j) & 255;
	j = 0;
      }  x++;
    } while (j != 0);
    Lpkc.d &= 0xffffL >> (16 - Lpkc.db);  return;
  }
  j = Lpkc.wid1;  Lpkc.db = 8 - Lpkc.xs;  Lpkc.d = 0;
  if (Lpkc.repc > 0) {  Lpkc.repc--;  return;  }
  while (j > 0) {
    if (Lpkc.count == 0) { Lpkc.count = pknum();  Lpkc.white = !Lpkc.white; }
    dd = Lpkc.db;
    if (dd > j)  dd = j;
    if (dd > Lpkc.count)  dd = Lpkc.count;
    if (Lpkc.white)  Lpkc.db -= dd;
    else {  Lpkc.d += 1 << Lpkc.db;
      Lpkc.db -= dd;  Lpkc.d -= 1 << Lpkc.db;
    }
    Lpkc.count -= dd;  j -= dd;
    if (Lpkc.db == 0 || j == 0) {
      Lpkc.buf[x] = Lpkc.d & 255;
      x++;  Lpkc.d = 0;  Lpkc.db = 8;
} } }
static void pkchar()  {  short hr, vr;  long bma, bmx;
  short x, x1, x2, x3, y1, y2, y;  uchar b, bb, mach, mac, mpm, bach;
  fontdesc *WITH;  chdesc *WITH1;
  WITH = fontvect[fontint];  WITH1 = &WITH->chv[c];
  achm += WITH1->U1.bmp;  b = PKN1;
  Lpkc.white = ((b & 8) == 0);  Lpkc.wid1 = WITH1->U1.wid;
  Lpkc.dynf = b >> 4;
  Lpkc.dyng = (13 - Lpkc.dynf) * 16 + Lpkc.dynf - 15;
  Lpkc.dynh = -(Lpkc.dynf + 1) * 15;  bb = b & 7;
  switch (bb) {
  case 0:  case 1:  case 2:  case 3:  achm += 10;  break;
  case 4:  case 5:  case 6:  achm += 16;  break;
  case 7:  achm += 36;  break;
  }
  Lpkc.bmerk = 0;  Lpkc.d = 0;  Lpkc.db = 0;  Lpkc.repc = 0;
  Lpkc.count = 0;  Lpkc.white = !Lpkc.white;
  switch (dviori) {
  case 0:
    hr = (short)(conv * h + 0.5) - WITH1->U1.hof-hoff;
    vr = (short)(vconv * v + 0.5) - WITH1->U1.vof-voff;
    if (vr > ymax)  below = 1;  else {
      if (vr + WITH1->U1.hei >= 1) {
	x1 = (hr & -8L) / 8;  x2 = ((hr + WITH1->U1.wid - 1) & -8L) / 8;
	Lpkc.xs = hr & 7;	y2 = vr + WITH1->U1.hei - 1;
	if (y2 > ymax) {  y2 = ymax;  below = 1;  }
	x3 = x1;  if (x3 < 0) x3 = 0;  if (x2 > xmb) x2 = xmb;
	if (x3 <= x2) {
	  for (y = vr; y <= y2; y++) {  pkline();
	    if (y >= 0) {
	      for (x = x3; x <= x2; x++)
		pixet(y, x, Lpkc.buf[x-x1]);
    } } } } }  break;
  case 1:
    hr = (short)(conv * (landx + v) + 0.5) - WITH1->U1.vof-hoff;
    vr = (short)(vconv * (landy - h) + 0.5) + WITH1->U1.hof-voff;
    if (vr - WITH1->U1.wid + 1 > ymax)  below = 1;  else {
      if (vr >= 0) {  Lpkc.xs = 0;  mac = 0x80;  bma = 0;	y1 = vr;
	if (y1 > ymax) {  below = 1;  bma += ((ulong)(y1 - ymax)) >> 3;
	  mac = 0x80 >> ((y1 - ymax) & 7);  y1 = ymax;
	}
	y2 = vr - WITH1->U1.wid + 1;  if (y2 < 0)  y2 = 0;
	x2 = hr + WITH1->U1.hei - 1;  if (x2 > xmax)  x2 = xmax;
	for (x3 = hr; x3 <= x2; x3++) {  pkline();
	  if (x3 >= 0) {
	    mach = mac;  x = ((unsigned)x3) >> 3;
	    mpm = 0x80 >> (x3 & 7);  bmx = bma;  bach = Lpkc.buf[bmx];
	    for (y = y1; y >= y2; y--) {
	      if ((bach & mach) != 0)  pixet(y, x, mpm);
	      mach >>= 1;
	      if (mach == 0) {
		mach = 0x80;  bmx++;  bach = Lpkc.buf[bmx];
    } } } } } }  break;
  case 3:
    hr = (short)(conv * (landx - v) + 0.5) + WITH1->U1.vof-hoff;
    vr = (short)(vconv * (landy + h) + 0.5) - WITH1->U1.hof-voff;
    if (vr > ymax)  below = 1;  else {
      if (vr + WITH1->U1.wid >= 1) {
	Lpkc.xs = 0;  mac = 0x80;  bma = 0;  y1 = vr;
	if (y1 < 0) {  bma += ((unsigned)(-y1)) >> 3;
	  mac = 0x80 >> ((-y1) & 7);  y1 = 0;
	}
	y2 = vr + WITH1->U1.wid - 1;
	if (y2 > ymax) {  y2 = ymax;  below = 1;  }
	x2 = hr - WITH1->U1.hei + 1;  if (x2 < 0)  x2 = 0;
	for (x3 = hr; x3 >= x2; x3--) {  pkline();
	  if (x3 <= xmax) {
	    mach = mac;  x = ((unsigned)x3) >> 3;
	    mpm = 0x80 >> (x3 & 7);  bmx = bma;  bach = Lpkc.buf[bmx];
	    for (y = y1; y <= y2; y++) {
	      if ((bach & mach) != 0)  pixet(y, x, mpm);
	      mach >>= 1;
	      if (mach == 0) {
		mach = 0x80;  bmx++;  bach = Lpkc.buf[bmx];
    } } } } } }  break;
  case 2:
    hr = (short)(conv * (landx - h) + 0.5) + WITH1->U1.hof-hoff;
    vr = (short)(vconv * (landy - v) + 0.5) + WITH1->U1.vof-hoff;
    if (vr - WITH1->U1.hei + 1 > ymax)  below = 1;  else {
      if (vr >= 0) {
	x1 = (hr & -8L) / 8;  x2 = ((hr - WITH1->U1.wid + 1) & -8L) / 8;
	Lpkc.xs = (7 - hr) & 7;  y2 = vr - WITH1->U1.hei + 1;
	if (y2 < 0)  y2 = 0;
	if (vr > ymax)  below = 1;
	if (x2 < 0) x2 = 0;  x3 = x1;  if (x3 > xmb) x3 = xmb;
	if (x2 <= x3) {
	  for (y = vr; y >= y2; y--) {  pkline();
	    if (y <= ymax) {
	      for (x = x3; x >= x2; x--)
		pixet(y, x, bitrev[Lpkc.buf[x1 - x]]);
    } } } } }  break;
} }
static void pklene() {  short j;  uchar dd;  short s = 0;
  if (Lpkc.dynf == 14) {  j = Lpkc.wid1 + Lpkc.xs;  Lpkc.db += Lpkc.xs;
    do {
      if (Lpkc.db < 8)	Lpkc.d = (Lpkc.d << 8) | PKN1;
      else  Lpkc.db -= 8;
      dd = (Lpkc.d >> Lpkc.db) & 255;
      if (j >= 8) {  j -= 8;  Lpkc.buf[s] = cb[dd];
      } else {	Lpkc.db += 8 - j;
        Lpkc.buf[s] = cb[dd & (0xff00L >> j) & 255];  j = 0;
      }  s++;
    } while (j != 0);
    Lpkc.d &= 0xffffL >> (16 - Lpkc.db);  return;
  }
  j = Lpkc.wid1;  Lpkc.db = 8 - Lpkc.xs;  Lpkc.d = 0;
  if (Lpkc.repc > 0) {  Lpkc.repc--;  return;  }
  while (j > 0) {
    if (Lpkc.count == 0) {  Lpkc.count = pknum();  Lpkc.white = !Lpkc.white;  }
    dd = Lpkc.db;  if (dd > j)  dd = j;
    if (dd > Lpkc.count)  dd = Lpkc.count;
    if (!Lpkc.white)  Lpkc.d += dd;
    Lpkc.db -= dd;  Lpkc.count -= dd;  j -= dd;
    if (Lpkc.db == 0 || j == 0) {
      Lpkc.buf[s] = Lpkc.d;  s++;  Lpkc.d = 0;  Lpkc.db = 8;
} } }
static void pkcher() {  short hr, vr, br, ar;
  ushort s, s1, s2, t, t1, t2;
  uchar ts, te, tr, tt, b, bb;  uchar sum[ym + 1];
  fontdesc *WITH;  chdesc *WITH1;
  WITH = fontvect[fontint];  WITH1 = &WITH->chv[c];
  achm += WITH1->U1.bmp;  b = PKN1;
  Lpkc.white = ((b & 8) == 0);  Lpkc.wid1 = WITH1->U1.wid;
  Lpkc.dynf = b >> 4;
  Lpkc.dyng = (13 - Lpkc.dynf) * 16 + Lpkc.dynf - 15;
  Lpkc.dynh = -(Lpkc.dynf + 1) * 15;  bb = b & 7;
  switch (bb) {
  case 0:  case 1:  case 2:  case 3:  achm += 10;  break;
  case 4:  case 5:  case 6:  achm += 16;  break;
  case 7:  achm += 36;  break;
  }
  Lpkc.bmerk = 0;  Lpkc.d = 0;  Lpkc.db = 0;  Lpkc.repc = 0;
  Lpkc.count = 0;  Lpkc.white = !Lpkc.white;
  switch (dviori) {
  case 0:
    hr = (short)(conv * h + 0.5) - WITH1->U1.hof;
    br = hr + WITH1->U1.wid - 1;
    vr = (short)(vconv * v + 0.5) - WITH1->U1.vof;
    ar = vr + WITH1->U1.hei - 1;
    if (vr >= 0) if (ar <= ymax) if (hr >= 0) if (br <= xmax) {
      s1 = hr >> 3;  s2 = br >> 3;  Lpkc.xs = hr & 7;
      t1 = vr >> 3;  t2 = ar >> 3;  ts = vr & 7;
      te = 7;  tr = ar & 7;
      for (t = t1; t <= t2; t++) {  if (t == t2)  te = tr;
        for (s = s1; s <= s2; s++)  sum[s] = 0;
        for (tt = ts; tt <= te; tt++) {  pklene();
          for (s = s1; s <= s2; s++)  sum[s] += Lpkc.buf[s - s1];
        }  ts = 0;  for (s = s1; s <= s2; s++)  paxet(t, s, sum[s]);
    } }  break;
  case 1:
    hr = (short)(conv * (landx + v) + 0.5) - WITH1->U1.vof;
    br = hr + WITH1->U1.hei - 1;
    vr = (short)(vconv * (landy - h) + 0.5) + WITH1->U1.hof;
    ar = vr - WITH1->U1.wid + 1;
    if (ar >= 0) if (vr <= ymax) if (hr >= 0) if (br <= xmax) {
      s1 = vr >> 3;  s2 = ar >> 3;  Lpkc.xs = 7 - (vr & 7);
      t1 = hr >> 3;  t2 = br >> 3;  ts = hr & 7;
      te = 7;  tr = br & 7;
      for (t = t1; t <= t2; t++) {  if (t == t2)  te = tr;
        for (s = s1; s >= s2; s--)  sum[s] = 0;
        for (tt = ts; tt <= te; tt++) {  pklene();
          for (s = s1; s >= s2; s--)  sum[s] += Lpkc.buf[s1 - s];
        }  ts = 0;  for (s = s1; s >= s2; s--)  paxet(s, t, sum[s]);
    } }  break;
  case 3:
    hr = (short)(conv * (landx - v) + 0.5) + WITH1->U1.vof;
    br = hr - WITH1->U1.hei + 1;
    vr = (short)(vconv * (landy + h) + 0.5) - WITH1->U1.hof;
    ar = vr + WITH1->U1.wid - 1;
    if (vr >= 0) if (ar <= ymax) if (br >= 0) if (hr <= xmax) {
      s1 = vr >> 3;  s2 = ar >> 3;  Lpkc.xs = vr & 7;
      t1 = hr >> 3;  t2 = br >> 3;  ts = 7 - (hr & 7);
      te = 7;   tr = 7 - (br & 7);
      for (t = t1; t >= t2; t--) {  if (t == t2)  te = tr;
        for (s = s1; s <= s2; s++)  sum[s] = 0;
        for (tt = ts; tt <= te; tt++) {  pklene();
          for (s = s1; s <= s2; s++)  sum[s] += Lpkc.buf[s - s1];
        }  ts = 0;  for (s = s1; s <= s2; s++)  paxet(s, t, sum[s]);
    } }  break;
  case 2:
    hr = (short)(conv * (landx - h) + 0.5) + WITH1->U1.hof;
    br = hr - WITH1->U1.wid + 1;
    vr = (short)(vconv * (landy - v) + 0.5) + WITH1->U1.vof;
    ar = vr - WITH1->U1.hei + 1;
    if (ar >= 0) if (vr <= ymax) if (br >= 0) if (hr <= xmax) {
      s1 = hr >> 3;  s2 = br >> 3;  Lpkc.xs = 7 - (hr & 7);
      t1 = vr >> 3;  t2 = ar >> 3;  ts = 7 - (vr & 7);
      te = 7;  tr = 7 - (ar & 7);
      for (t = t1; t >= t2; t--) {  if (t == t2)  te = tr;
        for (s = s1; s >= s2; s--)  sum[s] = 0;
	for (tt = ts; tt <= te; tt++) {  pklene();
          for (s = s1; s >= s2; s--)  sum[s] += Lpkc.buf[s1 - s];
        }  ts = 0;  for (s = s1; s >= s2; s--)  paxet(t, s, sum[s]);
    } }  break;
} }

static void fontdef() {  uchar a, b, p, q;  fontdesc *WITH;
  if (f < 0)  baddvi("negative fontnumber");
  b = f & 0xff;  a = 0;
  if ((f > 255) || (fontvect[b] != NULL)) do {
    if (fontvect[a] == NULL)  b = a;
    else if (fontvect[a]->dfn == f)  baddvi("double fontnumber");
    a++;
  } while (a);
  if (fontvect[b] != NULL)  baddvi("too many fonts");
  fontint = b;
  Tptr( fontvect[b] = (fontdesc *)malloc(sizeof(fontdesc)) );
  WITH = fontvect[fontint];  WITH->dfn = f;
  chk = dvinum(4);  scf = dvinum(4);  dsz = dvinum(4);
  WITH->chm = NULL;  WITH->fty = -1;
  p = dvibyte();  q = dvibyte();  dvibytes(FONAM, q);
  if (p == 0)  strcpy(FOPRE, fontprefix);  else dvibytes(FOPRE, p);
  sprintf(FOMAG, "%ld",
	  (long)(xres * dvimag / 1000.0 * ((double)scf / dsz) + 0.5));
#ifdef __MSDOS__
  sprintf(FOFUL, "%s%s\\%s.", FOPRE, FOMAG, FONAM);
  sprintf(FOLOC, "%s.", FONAM);
#else
  sprintf(FOFUL, "%s%s.%s", FOPRE, FONAM, FOMAG);
  sprintf(FOLOC, "%s.%s", FONAM, FOMAG);
#endif
  pkdef();  if (WITH->mch < 0)  tfmdef();
}

static void fontlod() { uchar b = 0;
  fontdesc *WITH = fontvect[fontint];
  WITH->chm = (uchar *)malloc(WITH->danf);
  if (WITH->chm == NULL) { do {
      if (fontvect[b] != NULL) {
	if (fontvect[b]->chm) free(fontvect[b]->chm);
	fontvect[b]->chm = NULL;
      }  b++;
    } while (b);
    Tptr( WITH->chm = (uchar *)malloc(WITH->danf) );
  }
  fofil = fopen(WITH->fonam, "rb");
  fread(WITH->chm, WITH->danf, 1, fofil);  fclose(fofil);
}

static void fontset() {  uchar a, b, x;
  b = f & 0xff;  x = 0;
  if (fontvect[b] != NULL)  if (fontvect[b]->dfn == f)  x = 1;
  if (x == 0) {  a = 0;
    do {
      if (fontvect[a] == NULL)	a++;
      else if (fontvect[a]->dfn != f)  a++;
      else {  x = 1;  b = a;  a = 0;  }
    } while (a != 0);
  }
  if (x == 0)  baddvi("undefined fontnumber");
  fontint = b;
}
static void putrale() {  short hr, vr, br, ar;
  if (b <= 0)  return;
  switch (dviori) {
  case 0:
    hr = (short)(conv * h + 0.5);
    vr = (short)(vconv * (v - a) + 0.5);
    br = (short)(conv * b + 0.5);  if (br > 0)  br--;
    ar = (short)(vconv * a + 0.5);
    break;
  case 1:
    hr = (short)(conv * (landx + v - a) + 0.5);
    vr = (short)(vconv * (landy - h - b) + 0.5);
    br = (short)(conv * a + 0.5);
    ar = (short)(vconv * b + 0.5);  if (ar > 0)  ar--;
    break;
  case 3:
    hr = (short)(conv * (landx - v) + 0.5);
    vr = (short)(vconv * (landy + h) + 0.5);
    br = (short)(conv * a + 0.5);
    ar = (short)(vconv * b + 0.5);  if (ar > 0)  ar--;
    break;
  case 2:
    hr = (short)(conv * (landx - h - b) + 0.5);
    vr = (short)(vconv * (landy - v) + 0.5);
    br = (short)(conv * b + 0.5);  if (br > 0)  br--;
    ar = (short)(vconv * a + 0.5);
    break;
  }
  ar += vr;  br += hr;
  if (hr < 0)  hr = 0;
  if (br > xmax)  br = xmax;
  if (vr < 0)  vr = 0;
  if (ar > ymax) {  ar = ymax;  below = 1;  }
  if (hr <= br)  if (vr <= ar) {
    setract(hr, vr, br, ar);
} }
static void putrule() {  short hr, vr, br, ar;
  if (b <= 0)  return;
  if (alles)  {  putrale();  return;  }
  switch (dviori) {
  case 0:
    hr = (short)(conv * h + 0.5)-hoff;
    vr = (short)(vconv * (v - a) + 0.5)-voff;
    br = (short)(conv * b + 0.5);  if (br > 0)  br--;
    ar = (short)(vconv * a + 0.5);
    break;
  case 1:
    hr = (short)(conv * (landx + v - a) + 0.5)-hoff;
    vr = (short)(vconv * (landy - h - b) + 0.5)-voff;
    br = (short)(conv * a + 0.5);
    ar = (short)(vconv * b + 0.5);  if (ar > 0)  ar--;
    break;
  case 3:
    hr = (short)(conv * (landx - v) + 0.5)-hoff;
    vr = (short)(vconv * (landy + h) + 0.5)-voff;
    br = (short)(conv * a + 0.5);
    ar = (short)(vconv * b + 0.5);  if (ar > 0)  ar--;
    break;
  case 2:
    hr = (short)(conv * (landx - h - b) + 0.5)-hoff;
    vr = (short)(vconv * (landy - v) + 0.5)-voff;
    br = (short)(conv * b + 0.5);  if (br > 0)  br--;
    ar = (short)(vconv * a + 0.5);
    break;
  }
  ar += vr;  br += hr;
  if (hr < 0)  hr = 0;
  if (br > xmax)  br = xmax;
  if (vr < 0)  vr = 0;
  if (ar > ymax) {  ar = ymax;  below = 1;  }
  if (hr <= br)  if (vr <= ar) {
    setrect(hr, vr, br, ar);
} }
static void putchar_() {  fontdesc *WITH;  chdesc *WITH1;
  WITH = fontvect[fontint];
  if (c > WITH->mch) {  q = 0;  return;  }
  WITH1 = &WITH->chv[c];  q = WITH1->U1.tfw;
  if (WITH->fty == 1) {  if (alles) tfmcher(); else tfmchar();  return;  }
  if (WITH1->U1.bmp == 0)  return;
  if (WITH->chm == NULL)  fontlod();
  achm = WITH->chm;  if(alles) pkcher(); else pkchar();
}
static void pageinit() {  greydesc *WITH;
  s = 0;  w = 0;  x = 0;  y = 0;  z = 0;
  if (alles) {
    h = (long)(xres / conv + 0.5);
    v = (long)(yres / vconv + 0.5);
  }  else  {  h = 0;  v = 0;  }
  for (j = 0; j <= 7; j++) {  WITH = &greymask[j];
    WITH->maskc = 0xff;  WITH->maskm = 0xff;  WITH->masky = 0xff;
  }  darkfac = maxink;
}
static void pagebeg() {  uchar j;
  for (j = 0; j <= 9; j++)  cnt[j] = dvinum(4);
  lpp = dvinum(4);  pagnum++;  alles = 3;
  if (pagnum >= pag1) {  started = 1;  }
  zoelli = ftell(dvifile);  zoelli += (long)dvibufp - (long)dvibufe;
  dispopen(); pageinit();
}
static void pageend() { char np;
  if (s != 0)  fprintf(prot, "Stack not empty at EOP\n");
  if (!started)  return;  dispcopy();
  if (alles)  np = 0;  else  np = evalkbd();
  if (np == 0) {  dviposit(zoelli);  pageinit();
    dispopen();
  }
  if (np < 0) if (lpp) dviposit(lpp);
}
static void deffont() {  ushort l, m;
  if (!post) {  fontdef();  return;  }
  dviskip(12L);  l = dvibyte();  m = dvibyte();  dviskip((long)(l + m));
}
static void special() {  long i, j, k;  char *parm;
  double x, y, cy, ma, ye, bl;  short cle, m, n, b;
  if (spl > 255) {  fprintf(prot, "special >>");
    for (i = spl; i > 0; i--)  fputc(dvibyte(), prot);
    fprintf(prot, "<< ignored\n");  return;
  }
  dvibytes(comment, (int)spl);
  if (!memcmp(comment, "landend", 7)) {  dviori = 0;  return;  }
  if (!memcmp(comment, "landstart", 9)) {
    if (comment[10] == '1')  dviori = 1;
    else if (comment[10] == '0')  dviori = 3;
    else dviori = 2;
    sscanf(comment+12, "%lg%lg", &x,&y);
    j = (long)(x * 65535L + 0.5);
    k = (long)(y * 65535L + 0.5);
    switch (dviori) {
    case 1:  landx = h - v;  landy = v + j + h;  break;
    case 3:  landx = h + k + v;  landy = v - h;  break;
    case 2:  landx = h + h + k;  landy = v + j + v;  break;
  } return; }
  if (memcmp(comment, "color", 5)) {
    fprintf(prot, "special >>%s<< ignored", comment);  return;
  }
  parm = comment+6;
  if (!memcmp(parm, "pop", 3)) {  parm +=4;  colst--;
    if (colst < 0) {  colst = 0;  fprintf(prot, " color stack underflow"); }
  } else {
    if (!memcmp(parm, "push cmyk", 9)) {  parm +=10;  colst++;
      if (colst > smax-1) { colst = smax-1;
        fprintf(prot, " color stack overflow");
    } }
    if (sscanf(parm,"%lg%lg%lg%lg",&cy,&ma,&ye,&bl)<4) {
      fprintf(prot," color: cmyk values <%s> incomplete ",comment); return;
    }
    cy+=bl; ma+=bl; ye+=bl; bl=cy*0.3+ma*0.59+ye*0.11;
    n = (short)(cy * maxink);  if (n < 0) n = 0;
    if (n > maxink) n = maxink;  stackcy[colst] = n;
    n = (short)(ma * maxink);  if (n < 0) n = 0;
    if (n > maxink) n = maxink;  stackma[colst] = n;
    n = (short)(ye * maxink);  if (n < 0) n = 0;
    if (n > maxink) n = maxink;  stackye[colst] = n;
    n = (short)(bl * maxink);  if (n < 0) n = 0;
    if (n > maxink) n = maxink;  stackbl[colst] = n;
  }
  b = stackbl[colst];  cle = b;
  n = stackcy[colst];  cle += n;  if (alles == 3) darkfac = n;
  for (m = 0; m <= 7; m++)
   greymask[m].maskc = maskb[n][m & 3];
  n = stackma[colst];  cle += n;  if (alles == 2) darkfac = n;
  for (m = 0; m <= 7; m++)
   greymask[m].maskm = maskb[n][m & 3];
  n = stackye[colst];  cle += n;  if (alles == 1) darkfac = n;
  for (m = 0; m <= 7; m++)
   greymask[m].masky = maskb[n][m & 3];
  clearing = (cle == 0);  if (vertfac == 7)  darkfac = b;
}
static void preambl() {  uchar l;
  l = dvibyte();  num = dvinum(4);  den = dvinum(4);
  dvimag = dvinum(4);  if (newmag != 0) dvimag = newmag;
  conv = num / 254000.0 * ((double)xres / den) * (dvimag / 1000.0);
  vconv = num / 254000.0 * ((double)yres / den) * (dvimag / 1000.0);
  l = dvibyte();  dvibytes(comment, l);  fprintf(prot, "%s\n", comment);
}
static void postamb() {
  lpp = dvinum(4);  num = dvinum(4);  den = dvinum(4);
  dvimag = dvinum(4);  if (newmag != 0) dvimag = newmag;
  conv = num / 254000.0 * ((double)xres / den) * (dvimag / 1000.0);
  vconv = num / 254000.0 * ((double)yres / den) * (dvimag / 1000.0);
  mxv = dvinum(4);  mxh = dvinum(4);  mst = dvinum(2);  mpn = dvinum(2);

}

main(int argc, char **argv) { char *parm;
  post = 0;  fini = 0;  started = 0;  dviori = 0;  pagnum = 0;
  pag1 = 1;  paganz = 9999;  newmag = 0;  q = 0;  hoff = -xres;  voff = -yres;
  Tptr( fontvect = (fontdesc **) calloc(256, 4) );
  initbitrev();  colst = 0;  dispinit();
  stackcy[colst] = maxink;  stackma[colst] = maxink;
  stackye[colst] = maxink;  stackbl[colst] = maxink;

  fprintf(prot, "This is the VGA Color TeX driver, V 94.02 .\n");
  fprintf(prot, "(C)opyright 1994 Wolfgang R. Mueller, Computing Centre,\n");
  fprintf(prot, "Heinrich-Heine-University Duesseldorf, Germany\n");
  if (argc == 1) {
    fprintf(prot, "Please use with dvifilename and optional parameters\n");
    fprintf(prot, " -s<starting page>     (default: 1  i.e. first in file)\n");
    fprintf(prot, " -m<new magnification> (default: from DVIfile)\n");
    fprintf(prot, " -f<font directory>    (default: %s)\n", fontprefix);
    fprintf(prot, " -t<TFMfile directory> (default: %s)\n", tfmprefix);
    exit(0);
  }
  strcpy(dviname, "texput");
  for (j = 1; j < argc; j++) {  parm = argv[j];
    if (parm[0] != '-') {  strcpy(dviname, parm);
    } else {  switch (parm[1]) {
      case 's':  case 'S':  sscanf(parm+2, "%d", &pag1);  break;
      case 'f':  case 'F':  strcpy(fontprefix, parm+2);  break;
      case 't':  case 'T':  strcpy(tfmprefix, parm+2);  break;
      case 'm':  case 'M':  sscanf(parm+2, "%ld", &newmag);  break;
  } } }
  dviopen();  postamb();
  do {  o = dvibyte();  /* fprintf(prot, "(%u)", (ushort)o); */
    if (o <= 127) {
      c = o;  if (started) putchar_();  h += q;
    } else if (o >= 171 && o <= 234) {
      f = o - 171;  if (started)  fontset();
    } else  switch (o) {
    case 128:  case 129:  case 130:  case 131:
      c = dvinum(o - 127);  if (started) putchar_();  h += q;  break;
    case 132:  a = dviint(4);  b = dviint(4);
      if (started) putrule();  h += b;  break;
    case 133:  case 134:  case 135:  case 136:
      c = dvinum(o - 132);  if (started) putchar_();  break;
    case 137:  a = dviint(4);  b = dviint(4);
      if (started) putrule();  break;
    case 138:  break;
    case 139:  pagebeg();  break;
    case 140:  pageend();  break;
    case 141:  if (s < smax) {	s++;  hs[s - 1] = h;  vs[s - 1] = v;
	ws[s - 1] = w;	xs[s - 1] = x;	ys[s - 1] = y; zs[s - 1] = z;
      } else  baddvi("stack overflow");  break;
    case 142:  if (s > 0) {  h = hs[s - 1];  v = vs[s - 1];
	w = ws[s - 1];	x = xs[s - 1];	y = ys[s - 1];	z = zs[s - 1];	s--;
      } else  baddvi("stack underflow");  break;
    case 143:  case 144:  case 145:  case 146:
      h += dviint(o - 142);  break;
    case 147:  h += w;  break;
    case 148:  case 149:  case 150:  case 151:
      w = dviint(o - 147);  h += w;  break;
    case 152:  h += x;  break;
    case 153:  case 154:  case 155:  case 156:
      x = dviint(o - 152);  h += x;  break;
    case 157:  case 158:  case 159:  case 160:
      v += dviint(o - 156);  break;    case 161:  v += y;  break;
    case 162:  case 163:  case 164:  case 165:
      y = dviint(o - 161);  v += y;  break;
    case 166:  v += z;  break;
    case 167:  case 168:  case 169:  case 170:
      z = dviint(o - 166);  v += z;  break;
    case 235:  case 236:  case 237:  case 238:
      f = dvinum(o - 234);  if (started) fontset();  break;
    case 239:  case 240:  case 241:  case 242:
      spl = dvinum(o - 238);  special();  break;
    case 243:  case 244:  case 245:  case 246:
      f = dvinum(o - 242);  deffont();  break;
    case 247:  preambl();  break;
    case 248:  fini = 1;  break;
    case 249:  dviposit(0L);  post = 1;  break;
    case 250:  case 251:  case 252:
    case 253:  case 254:  case 255:  break;
  } } while (!fini);
  dispclos(); fclose(dvifile); exit(0);
}
static void finale()  {  dispclos();  exit(1);  }
