/***********************************************************************
 *      render.c
 *              This module compiles Ok under Aztec C ver 3.4a, note
 *      however that some in-line assembly was required to save reg A6
 *      as the memory allocating routines trash it. (naughty Manx)
 *      Also a modular 6 lookup table is used for speed of graphic dumps.
 *      At the present I use the .0045" grid size on the ln03+ as this
 *      seems to produce the nicest looking grey-scale picture.
 *
 *              written by Bernie Mentink Chistchurch N.Z 1/2/88
 *
 *
 ***********************************************************************/
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include "devices/printer.h"
#include "devices/prtbase.h"
#include <functions.h>
#include "stdio.h"

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

/* for the DEC LN03+ */
long Render(ct,x,y,status)
register ULONG ct;      /* was UBYTE for Lattice compiler */
register ULONG x,y;     /* was UWORD for Lattice compiler */
ULONG status;           /* was UBYTE for Lattice compiler */
{
        static UWORD ROWSIZE;
        static UWORD COLORSIZE;
        static UWORD BUFSIZE, offset,size;
        static BYTE center;
        static UWORD bufptr;       /* pointer to buffer 1 or 2 */
        static UBYTE *lookup;      /* lookup table for sixels (modula-6) */
        register struct PrinterData *pp = PD;
        register UBYTE *ptr;
        register UWORD i,j;
        long err=0;
        FILE *fp;
                              /* patch to save A6 pointer */
        #asm
            move.l a6,-(sp)
        #endasm

        switch(status) {

                case 0: /* alloc memory for printer buffer (uses dbl buf) */
                        ROWSIZE = ((UWORD)x); /* row size for lno3 */
                        BUFSIZE = ROWSIZE+9;  /* buffer size plus offset */
                        lookup = (UBYTE *) AllocMem(y,(long)MEMF_PUBLIC);
                        size = y;             /* save size */
                        for(i=1,j=0;j<y;++j)
                        {
                            if(i==64) i=1;     /* modular 6 */
                            lookup[j] = i;     /* init lookup table */
                            i <<= 1;           /* 1,2,4,8,16,32,1,2 etc  */
                        }
                        pp->pd_PrintBuf = (UBYTE *)
                              AllocMem((long)(BUFSIZE*2),(long)MEMF_PUBLIC);
                        if(err = (pp->pd_PrintBuf==0)) break;
                        if(err = (*(pp->pd_PWrite))("\033c",2L))
                                      break;        /* reset printer */
                        if(err = PWait(1L,0L)) break;
                        bufptr = 0;
                        break;

                case 1: /* put pixel in buffer  */
                        pp->pd_PrintBuf[bufptr+x+7] |=  lookup[y];
                                                   /* set pixel on  */
                        break;

                case 2: /* dump buffer to printer */
                        for(i=bufptr+7;i<bufptr+ROWSIZE+7;++i)
                            pp->pd_PrintBuf[i] += 63;    /* add 077 octal */
                        if(err = (*(pp->pd_PWrite))(&pp->pd_PrintBuf[bufptr],
                             (long)BUFSIZE)) break;      /* send buffer */
                        bufptr = BUFSIZE-bufptr; /* switch to other buffer */
                        break;

                case 3: /* clear  buffer */
                        ptr = &pp->pd_PrintBuf[bufptr];
                        i = BUFSIZE;
                        while(i--) *ptr++ = 0;           /* clear buffer */
                        pp->pd_PrintBuf[bufptr] = 144;    /* start sixel */
                        pp->pd_PrintBuf[bufptr+1] = '9';  /* 1:1 aspect  */
                        pp->pd_PrintBuf[bufptr+2] = ';';
                        pp->pd_PrintBuf[bufptr+3] = '0';
                        pp->pd_PrintBuf[bufptr+4] = ';';
                        pp->pd_PrintBuf[bufptr+5] = '3';  /* .0045" grid */
                        pp->pd_PrintBuf[bufptr+6] = 'q';
                        pp->pd_PrintBuf[bufptr+BUFSIZE-2] = '-'; /* CR LF */
                        pp->pd_PrintBuf[bufptr+BUFSIZE-1] = 156;
                        break;                           /* end of sixel  */

                case 4:  /* free the print buffer memory */
                         /*  eject page, reset printer   */
                        if(err = (*(pp->pd_PWrite))("\014\033c",3L))
                                return(err);      /* eject page,reset */
                        err = (*(pp->pd_PBothReady))();
                        FreeMem(pp->pd_PrintBuf,(long)(BUFSIZE*2));
                        FreeMem(lookup,(long)size);
                        break;

                default:
                        break;
        }
                           /* restore A6 */
        #asm
            move.l (sp)+,a6
        #endasm

        return(err);
}
