/* -*-C-*- dvidjp.c */
/*-->dvidjp*/
/**********************************************************************/
/******************************* dvidjp *******************************/
/**********************************************************************/

/* Driver for HP DeskJet Plus printer -- modified from
 * Beebe Laser Jet driver
 * by Paul Kirkaas (kirkaas@cs.ucla.edu) 22 May 1990
 *	patch 1 -- bugs in YOFF & COMPACTION fixed 23 May 1990
 *
 * Employs 3 types of data compaction for greater efficiency --
 * up to 60 - 70% reduction in output file size.  Each compaction 
 * scheme can be switched on or off independently by defining any
 * or all of:
 *
 * XOFF -- X offset -- instead of a string of leading zeros, offset
 * 	by appropriate amount.  Minimal savings when used  with
 *	COMPACTION mode set.
 *
 * YOFF -- Y offset -- compress multiple blank lines into a single
 *	y skip command.
 *
 * COMPACTION -- Uses mode 2 compaction on Desk Jet Plus -- this is
 *	the trickiest but most effective compression modification.
 *	This is the likliest part to have a bug.
 *	Lots of cleaning up can be done here.
 *
 * If you have an old Desk Jet (not a Plus) it may not have
 * all these abilities -- try undfining some of these switches.
 *
 * It should run straight with the Beebe driver set; you might
 * have to make some adjustments.  I have personally only run
 * it on an AT&T System V 3b1.
 *
 * Please let me know if you make any improvements or repairs.
 * Thanks
 *
 * Good Luck.
 */

#include "dvihead.h"

/**********************************************************************/
/************************  Device Definitions  ************************/
/**********************************************************************/

/* All output-device-specific definitions go here.  This section must
be changed when modifying a dvi driver for use on a new device */
#define  MFMODE  "HPDeskJet"
#define  FONTDESTDIR  FONTPATH

#undef HPLASERJET
#define  HPLASERJET       1		/* conditional compilation flag */
#define  HPDESKJET       1		/* conditional compilation flag */
		/* Include the following line for Y offsets*/
#define YOFF	1
		/* Include the following line for using temporary X offsets*/
#define XOFF	1
		/* Include the following line for Mode 2 Compaction */
#define	COMPACTION	1	
/*
#define COMPACTION	0
*/

#define VERSION_NO	"2.10"		/* DVI driver version number */

#define  DEVICE_ID	(comp ? \
		"Hewlett-Packard Desk Jet plus (from LaserJet)\n\
	WITH Data Compaction for faster I/O" : \
		"Hewlett-Packard Desk Jet plus (from LaserJet)\n\
	with-OUT Data Compaction I/O" )
				/* this string is printed at runtime */
#define OUTFILE_EXT	(comp ? "djc" : "dj")
#define COMPRESSED_EXT  "hp.Z"

#define  DEFAULT_RESOLUTION 300		/* default dots/inch on HP Desk Jet */

#define  BYTE_SIZE        8		/* output file byte size */

#undef STDRES
#define STDRES  1			/* 0 for low-resolution devices */

#define  XDPI		300		/* HP Laser Jet horizontal dots/inch */
#define  XPSIZE		8		/* horizontal paper size in inches */

#define  XSIZE		(((XDPI*XPSIZE+2*HOST_WORD_SIZE-1)/\
				(2*HOST_WORD_SIZE))*(2*HOST_WORD_SIZE))
					/* number of horizontal dots; */
					/* MUST BE multiple of */
					/* 2*HOST_WORD_SIZE */
#define  XWORDS		((XSIZE + HOST_WORD_SIZE - 1)/HOST_WORD_SIZE)
					/* number of words in rows  */
					/* of bitmap array */

#define  YDPI		300		/* HP Laser Jet vertical dots/inch */

#define  YPSIZE		11		/* vertical paper size in inches */
#define  YSIZE		(YDPI*YPSIZE)	/* number of vertical dots */

/* The printer bit map (must have an even number of columns). */

#define XBIT ((1+2*XWORDS)/2)
#define YBIT YSIZE
#if    (IBM_PC_LATTICE | IBM_PC_MICROSOFT | IBM_PC_WIZARD)
#undef SEGMEM
#define SEGMEM 1 /* ( ((long)XBIT * (long)YBIT) > 65536L ) */
#endif
int comp = COMPACTION;		/* compaction flag -- reset in option.h */

#include "bitmap.h"

#include "main.h"
#undef STDMAG
#undef RESOLUTION
#define STDMAG 1500
#define	RESOLUTION	(((float)STDMAG)/5.0)	/* dots per inch */
#include "abortrun.h"
#include "actfact.h"
#include "alldone.h"
#include "chargf.h"
#include "charpk.h"
#include "charpxl.h"
#include "clrbmap.h"
#include "clrrow.h"
#include "dbgopen.h"

/*-->devinit*/
/**********************************************************************/
/****************************** devinit *******************************/
/**********************************************************************/

void
devinit(argc,argv)		/* initialize device */
int argc;
char *argv[];
{
    (void)getbmap();
    OUTS("\033E");	/* printer reset */
    OUTS("\033&l0L");	/* Disable perforation skip */
/* OUTS("\033*rB");	/* End graphics */
    OUTS("\033*t300R");	/* printer resolution */
if (comp)
    OUTS("\033*b2M");	/* Select Compacted Graphics Mode Two */
else
    OUTS("\033*b0M");	/* Select Full Graphics Mode */

    OUTS("\033*r0A");	/* Start graphics, at leftmost position */
}

/*-->devterm*/
/**********************************************************************/
/****************************** devterm *******************************/
/**********************************************************************/

void
devterm()			/* terminate device */
{
    OUTS("\033E");	/* printer reset*/
}

#include "dvifile.h"
#include "dviinit.h"
#include "dviterm.h"
#include "dispchar.h"
#if 0
#include "f20open.h"
#endif
#include "fatal.h"
#include "fillrect.h"
#include "findpost.h"
#include "fixpos.h"
#include "fontfile.h"
#include "fontsub.h"
#include "getbmap.h"
#include "getbytes.h"
#include "getfntdf.h"
#include "getpgtab.h"
#include "initglob.h"
#include "inch.h"
#include "loadchar.h"
#include "movedown.h"
#include "moveover.h"
#include "moveto.h"
#include "nosignex.h"
#include "openfont.h"
#include "option.h"

/*-->outline*/
/**********************************************************************/
/****************************** outline *******************************/
/**********************************************************************/

void
outline(pbit)
UNSIGN32 *pbit;				/* pointer to raster line */

/*************************************************************************
Use machine-specific coding here for efficiency.  For TOPS-20, we encode
9 bytes from every pair  of 36-bit words.

For each raster line on the paper, the Laser Jet expects a binary  8-bit
byte stream of the form

    <ESC>*bnnnWxxxxxxx ... xxxxxxx
               <--- nnn bytes --->

where each byte contains, in order from high to low bit, a left-to-right
bit pattern.  No  end-of-line marker  is required;  the escape  sequence
automatically causes a new raster line to be started.
*************************************************************************/

{
    register UNSIGN32 w_even,w_odd;
    register UNSIGN32 *p;
    register BYTE *pbuf;
    BYTE buf[1+(XSIZE+7)/8];		/* space for EOS + n 8-bit bytes */
    register INT16 i,last_word;
    int ic,jc;			/* just counters */
    unsigned char * endb;	/* pointer to end of buf */
    unsigned char greystr[129]; /* Max length of 127 in compacted mode 2 */
    unsigned char * greyp;	/* Pointer to greystr[]  */
    unsigned char outstr[999];	/* Compacted mode 2 output string */
    unsigned char * outp;	/* Pointer to outstr[]  */
    unsigned char * endob;	/* pointer to end of outstr */
    unsigned char cmp;		/* Comparison variable */
    int outsz;			/* Size of outstr -- since includes NULLs */
    int count;
    int gcnt;	/* Length of grey runs */


#if    IBM_PC_MICROSOFT
    for (last_word = XBIT - 1;
	(last_word >= 1) && (*(UNSIGN32*)normaddr(pbit,last_word) == 0);
	--last_word)
        ;				/* trim white space a word at a time */
#else
    p = pbit + XBIT - 1;		/* point to last word on line */
    for (last_word = XBIT - 1; (last_word >= 1) && (*p == 0); --last_word)
        --p;				/* trim white space a word at a time */
#endif

    p = pbit;
    pbuf = &buf[0];
    for (i = 0; i <= last_word; i += 2)	/* loop over trimmed raster */
    {
        w_even = (*p++);
        w_odd = (*p++);

#if    (HOST_WORD_SIZE == 36)
	*pbuf++ = (BYTE)( (w_even >> 28) & 0xff);
	*pbuf++ = (BYTE)( (w_even >> 20) & 0xff);
	*pbuf++ = (BYTE)( (w_even >> 12) & 0xff);
	*pbuf++ = (BYTE)( (w_even >>  4) & 0xff);
	*pbuf++ = (BYTE)( ((w_even <<  4) | (w_odd >> 32)) & 0xff);
	*pbuf++ = (BYTE)( (w_odd  >> 24) & 0xff);
	*pbuf++ = (BYTE)( (w_odd  >> 16) & 0xff);
	*pbuf++ = (BYTE)( (w_odd  >>  8) & 0xff);
	*pbuf++ = (BYTE)( (w_odd       ) & 0xff);
#else /* HOST_WORD_SIZE == 32 */
	/* encode 8 bytes at a time on 32-bit machines */
	*pbuf++ = (BYTE)( (w_even >> 24) & 0xff);
	*pbuf++ = (BYTE)( (w_even >> 16) & 0xff);
	*pbuf++ = (BYTE)( (w_even >>  8) & 0xff);
	*pbuf++ = (BYTE)( (w_even      ) & 0xff);
	*pbuf++ = (BYTE)( (w_odd  >> 24) & 0xff);
	*pbuf++ = (BYTE)( (w_odd  >> 16) & 0xff);
	*pbuf++ = (BYTE)( (w_odd  >>  8) & 0xff);
	*pbuf++ = (BYTE)( (w_odd       ) & 0xff);
#endif

    }

    *pbuf = '\0';			/* trailing EOS marker */

    last_word |= 1;			/* make last_word ODD */
    for (i = ((last_word+1)*HOST_WORD_SIZE)/8;
        (*(--pbuf) == '\0') && (i > 1); --i)
	;	/* trim trailing zero bytes, leaving at least one */
    last_word = i;
#ifdef XOFF
	/* Trim leading zero bytes & do appropriate Temporary X offset */
    OUTS("\033*b"); /* Set up for raster transfer */
    pbuf=buf;
    for (ic=0; !buf[ic] && ic<last_word ; ic++, pbuf++)
	;
    if (ic>10) /* Do an X-shift */
	{
	    OUTF("%dx",8*ic); /* Shift by 8*ic # of blank pixels */
	}
    else	/* don't bother */
	{ pbuf = buf; ic = 0; }

    endb = &buf[last_word];

if (comp)
  {
    greyp = greystr;
    outp = outstr;
    outsz = gcnt = 0;
    endb = &buf[last_word];
    while (pbuf <= endb)
    {
      cmp = *pbuf;
      for (count = 0; count<127 && pbuf<=endb && cmp==*pbuf; count ++, pbuf++)
	;
      if (count==0){printf("DANGER DANGER ***COUNT IS ZERO***!!!\n");exit(0);}
      if (count <= 3) /* No run yet -- just put them in greystr */
	{
	  gcnt += count;
	  for (jc = 0; jc < count ; jc ++)
	    {
		*greyp = cmp;
		greyp++;
	    }
	  if (gcnt >= 124)  /* Can't have more than 127, so ... */
	    {
		outstr[outsz] = gcnt-1;
		outsz++;
		for (jc = 0; jc < gcnt; jc ++)
		  {
		    outstr[outsz + jc] = greystr[jc];
		  }
		outsz += gcnt;
		gcnt = 0;
		greyp = greystr;
		continue;
	    }
	}
      else /* We have a run of 4 or more */
	{
	    if (gcnt) /* Flush our accumilated grey */
	    {
		outstr[outsz] = gcnt-1;
		outsz++;
		for (jc = 0; jc < gcnt; jc ++)
		  {
		    outstr[outsz + jc] = greystr[jc];
		  }
		outsz += gcnt;
		gcnt = 0;
		greyp = greystr;
	    }
	    outstr[outsz] = (unsigned char) (1-count); /* Is this cast right? */
	    outsz ++;
	    outstr[outsz] = cmp;
	    outsz++;
	}
    }
    if (gcnt) /* Flush our accumilated grey */
      {
	outstr[outsz] = gcnt-1;
	outsz++;
	for (jc = 0; jc < gcnt; jc ++)
	  {
	    outstr[outsz + jc] = greystr[jc];
	  }
	outsz += gcnt;
	gcnt = 0;
	greyp = greystr;
      }
    OUTF("%dW",outsz); /* How much is coming ... */
    endob = outstr + outsz -1; /* End of the outstr */ 
    for (outp = outstr; outp <= endob; outp++ )
        OUTC(*outp);

  }
 else 
  {
    OUTF("%dW",(int)last_word-ic); /* How much is coming ... */
    /* cannot use fprintf with %s format because of
    			   NUL's in string, and it is slow anyway */
    for (i = ic; i < last_word; ++pbuf,++i)
        OUTC(*pbuf);
  }
#else
    OUTF("\033*b%dW",(int)last_word);
    pbuf = &buf[0];	/* cannot use fprintf with %s format because of
    			   NUL's in string, and it is slow anyway */
    for (i = 0; i < last_word; ++pbuf,++i)
        OUTC(*pbuf);
#endif XOFF
}

/*-->prtbmap*/
/**********************************************************************/
/****************************** prtbmap *******************************/
/**********************************************************************/

void
prtbmap()

{
    register UNSIGN32 *p;
    register INT16 j,k,ybottom,ytop;
#ifdef YOFF
    int ycnt = 0;
#endif YOFF
/*   OUTS("\033E");	/* printer reset */
/*    OUTS("\033&l0L");	/* Disable perforation skip */
/*    OUTS("\033*rB");	/* End graphics */
/*    OUTS("\033*t300R");	/* printer resolution */
if (comp)
    OUTS("\033*b2M");	/* Select Compacted Graphics Mode Two */
else
    OUTS("\033*b0M");	/* Select Full Graphics Mode */

    OUTS("\033*r0A");	/* Start graphics, at leftmost position */

    if (DBGOPT(DBG_PAGE_DUMP))
    {
	INT16 k1,k2,k3;

	for (k3 = 0; k3 < XBIT; (k3 += 7, ++p))
	{	/*  print bitmap 7 words at a pass */
	    k1 = k3;
	    k2 = MIN(XBIT,k1+7);
	    (void)printf("prtbmap()...bitmap words %d..%d",k1,k2-1);
	    NEWLINE(stdout);
	    (void)printf("     ");
	    for (k = k1; k < k2; ++k)
	        (void)printf("%10d",k*HOST_WORD_SIZE);
	    NEWLINE(stdout);
	    for (j = YBIT-1; j >= 0; --j)
	    {
	        p = BITMAP(j,0);
		for (k = 0; k < XBIT; (++k,++p))
		{
	            if (*p)	/* print non-blank raster line */
		    {
		        p = BITMAP(j,k1);
			(void)printf("%5d:",j);
			for (k = k1; k < k2; (++k,++p))
			    (void)printf(" %09lx",*p);
			NEWLINE(stdout);
			break;	/* exit loop over k */
		    }
		}
	    }
	}
    }

    (void)clearerr(plotfp);

#if    ZAPTHISOUT
    k = -1;	    /* find top non-zero raster */
    for (j = YBIT-1; (j > 0) && (k < 0); --j)  /* loop over raster lines */
    {
	p = BITMAP(j,XBIT-1);
	for (k = XBIT - 1; ((k >= 0) && (*p == 0)); --k)
	    --p;		/* trim white space */
    }
    ytop = j;
#else
    ytop = YBIT-1;
#endif

    k = -1;	    /* find bottom non-zero raster */
    for (j = 0; (j < ytop) && (k < 0); ++j) /* loop over raster lines */
    {

#if    IBM_PC_MICROSOFT
	for (k = XBIT - 1;((k >= 0) && (*BITMAP(j,k) == 0));--k)
	    ;		/* trim white space */
#else
	p = BITMAP(j,XBIT-1);
	for (k = XBIT - 1; ((k >= 0) && (*p == 0)); --k)
	    --p;		/* trim white space */
#endif

    }
    ybottom = MAX(0,j-1);

#if    ZAPTHISOUT
    for (j = ytop; (j >= ybottom); --j)
        {
	OUTF("%5d:",(int)j);
        for (k = 0; k < XBIT; ++k)
            OUTF(" %9x",*BITMAP(j,k));
	NEWLINE(plotfp);
        }
#endif


#ifdef YOFF
    ycnt = 0;
    for (j = ytop; (j >= ybottom) ; --j)	/* loop over raster lines */
      {
	if (isNul (BITMAP(j,0)))
	  ycnt ++;
	else
	{
	    if (ycnt) OUTF("\033*p+%dY",ycnt);
	    outline(BITMAP(j,0));
	    ycnt = 0;
	}
      }
#else
    for (j = ytop; (j >= ybottom) ; --j)	/* loop over raster lines */
	outline(BITMAP(j,0));
#endif YOFF

    OUTS("\033*rB\f");			/* end raster graphics, eject page */

    (void)fflush(plotfp);
    if (DISKFULL(plotfp))
	(void)fatal("Output error -- disk storage probably full");
}
#ifdef YOFF
isNul (pbit) UNSIGN32 *pbit;	
{
  UNSIGN32 * p;
#if    IBM_PC_MICROSOFT
  int last_word;
  for (last_word = XBIT - 1;
	(last_word >= 1) && (*(UNSIGN32*)normaddr(pbit,last_word) == 0);
	--last_word)
        ;				/* trim white space a word at a time */
   if (last_word <=1) return 1;
   return 0;
#else
  p = pbit + XBIT - 1;		/* point to last word on line */
  while ( !*p && p>pbit ) p--;
  if (p==pbit && !*p) return 1;
  return 0;
#endif IBM_PC_MICROSOFT
}
#endif YOFF

#include "outrow.h"
#include "prtpage.h"
#include "readfont.h"
#include "readgf.h"
#include "readpk.h"
#include "readpost.h"
#include "readpxl.h"
#include "reldfont.h"
#include "rulepxl.h"
#include "setchar.h"
#include "setfntnm.h"
#include "setrule.h"
#include "signex.h"
#include "skgfspec.h"
#include "skipfont.h"
#include "skpkspec.h"
#include "special.h"
#include "strchr.h"
#include "strcm2.h"
#include "strid2.h"
#include "strrchr.h"
#include "tctos.h"
#include "usage.h"
#include "warning.h"

