/***********************************************************************

   RENDER.C for an Amiga printer driver for the Hewlett Packard DeskJet

                    Copywrite © 1989 Creative Focus

   This software is freely redistributable, as long as all code,
   comments, and documentation are included unaltered, and no other
   conditions are imposed on its redistribution.

   THIS SOFTWARE IS PROVIDED "AS IS," AND NO GUARANTEE IS MADE OF ITS
   FITNESS FOR ANY PURPOSE.  CREATIVE FOCUS MAY NOT BE HELD ACCOUNTABLE
   FOR ANY DAMAGE, REAL OR IMAGINED, RESULTING FROM ITS USE OR MISUSE.

                           Creative Focus
                           Dr. Gerald Hull
                           12 White Street
                           Binghamton, New York  13901

                           (607) 648-4082
                           BIX:  ghull
                           PLINK:  DRJERRY

***********************************************************************/

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <devices/prtbase.h>
#include <devices/printer.h>

#define CMDLENGTH   19
#define FMTLENGTH    7
#define FRMLENGTH   11
#define DENSITY     11
#define LM           6
#define RM          10
#define LEN          6

extern char initform[FRMLENGTH];

extern void Transfer();
extern void anitoa();
extern UBYTE *AllocMem();
extern void FreeMem();

extern struct PrinterData *PD;
extern struct PrinterExtendedData *PED;

/*
   00-04   \033&l0L     perf skip mode off
   05-11   \033*t300R   set raster graphics resolution (dpi)
   12-16   \033*r0A     start raster graphics
   17-18   \0339        clear margins to default (0 & 79)
*/

char startgfx[CMDLENGTH] = "\033&l0L\033*t300R\033*r0A\0339";

char format[FMTLENGTH] = "\033*b000W";

/* SPECIAL_DENSITY    0   1   2    3    4    5    6    7 */
int xdots[8] =      {75, 75, 100, 150, 300, 300, 300, 300};

Render(ct, x, y, status)
   long ct, x, y, status;
   {

   static UWORD rowsize, bufsize;
   static UBYTE *prtstart;
   static int lmarg, rmarg;
   UBYTE *ptr;
   int i, err;
   ULONG code;

   err = PDERR_NOERR;   /* default to error-free processing */
   switch(status)
      {
      case 0:  /* Master Initialization */
         /*
            ct  - pointer to IODRPReq structure.
            x   - width of printed picture in pixels.
            y   - height of printed picture in pixels.
         */

         rowsize = (x + 7) / 8;
         bufsize = rowsize + FMTLENGTH;
         PD->pd_PrintBuf = AllocMem(bufsize*2, MEMF_PUBLIC);
         if (PD->pd_PrintBuf == NULL)
            err = PDERR_BUFFERMEMORY;
         else     /* prep output buffer */
            {
            prtstart = PD->pd_PrintBuf;
            ptr = prtstart;
            x = 0;
            while (x < FMTLENGTH)
               *ptr++ = format[x++];
            ptr = prtstart + bufsize;
            x = 0;
            while (x < FMTLENGTH)
               *ptr++ = format[x++];
            /* save current margins to restore after graphic */
            lmarg = PD->pd_Preferences.PrintLeftMargin;
            rmarg = PD->pd_Preferences.PrintRightMargin;
            /* perf skip off, set dpi, start graphics, clear margins */
            err = (*(PD->pd_PWrite))(startgfx, CMDLENGTH);
            }
         break;

      case 1:  /* Scale, Dither and Render */
         /*
            ct  - pointer to PrtInfo structure.
            x   - 0.
            y   - row # (0 to Height - 1).
         */

         Transfer(ct, y, prtstart+FMTLENGTH);
         break;

      case 2:  /* Dump Buffer to Printer */
         /*
            ct  - 0.
            x   - 0.
            y   - # of rows sent (1 to NumRows).
         */

         /* don't bother to send trailing whitespace */
         i = bufsize;
         ptr = prtstart + i - 1;
         while (*ptr == 0)
            {
            i--;
            ptr--;
            }
         anitoa(i-FMTLENGTH, prtstart+LEN);
         /* send data for row */
         err = (*(PD->pd_PWrite))(prtstart, i);
         /* double buffer output for speed */
         if (err == PDERR_NOERR)
            if (prtstart == PD->pd_PrintBuf)
               prtstart += bufsize;
            else prtstart = PD->pd_PrintBuf;
         break;

      case 3:  /* Clear and Init Buffer */
         /*
            ct  - 0.
            x   - 0.
            y   - 0.
         */

         ptr = prtstart + FMTLENGTH;
         i = rowsize;
         do
            {
            *ptr++ = 0;
            }
         while (--i);
         break;

      case 4:  /* Close Down */
         /*
            ct  - error code.
            x   - io_Special flag from IODRPReq struct.
            y   - 0.
         */

         /* don't try to send if cancelled by user! */
         if (ct != PDERR_CANCEL)
            {
            /* end graphics, perf skip back on */
            err = (*(PD->pd_PWrite))("\033*rB\033&l1L", 9);
            if (err == PDERR_NOERR && !(x & SPECIAL_NOFORMFEED))
                  /* send formfeed to eject page */
                  err = (*(PD->pd_PWrite))("\014", 1);
            if (err == PDERR_NOERR)
               {
               anitoa(lmarg, initform+LM);
               anitoa(rmarg, initform+RM);
               /* restore margins */
               err = (*(PD->pd_PWrite))(initform, FRMLENGTH);
               }
            }
         /* flag Close that another page eject not needed */
         PED->ped_PrintMode = 0;
         /* make sure both buffers empty */
         (*(PD->pd_PBothReady))();
         if (PD->pd_PrintBuf != NULL)
            FreeMem(PD->pd_PrintBuf, bufsize*2);
         break;

      case 5:  /* Pre-Master Initialization */
         /*
            ct  - 0 or pointer to IODRPReq structure.
            x   - io_Special flag from IODRPReq struct.
            y   - 0.
         */

         code = (x & SPECIAL_DENSITYMASK) / SPECIAL_DENSITY1;
         code = xdots[code];
         PED->ped_MaxXDots = code * 8;    /* for 8 inch width */
         PED->ped_MaxYDots = code * 10;   /* for 10 inch length */
         PED->ped_XDotsInch = PED->ped_YDotsInch = code;
         anitoa(code, startgfx+DENSITY);
         break;
      }

   return(err);
   }
