/* Render() for DotsPerfect-MX80

NB:   Render() has been recast as LONG (it was an error
      to be an int). ("prtbase.i" has to be modified as well) */

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

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

LONG Render(ct,x,y,status)
UBYTE ct;     /* null for B/W printers */
UWORD x,y;    /* the x & y coordinates */
UBYTE status; /* print status: 0=init, 1=enter pixel, 2=dump,
                              3=init buffer, 4=deallocate buffer, 5=Pre-init */
 
{
	static UWORD ROWSIZE;
	static UWORD BUFSIZE;
	static UWORD bufptr, offset;
	static BYTE  center;
	static UBYTE *ptr, bit_table[] = {128,64,32,16,8,4,2,1};
	UWORD  i;
	LONG    err;   /* error */

	switch(status)
	{
	case 0:
		/* Allocate memory for printer buffer */
		i = (center) ? ((PED->ped_MaxXDots - x)/2) : 0;
		offset = i+4;
		ROWSIZE = x+i; /* Row size required */
		BUFSIZE = (6 + ROWSIZE); /*Buffer size required */
		PD->pd_PrintBuf = (UBYTE *)
			AllocMem(BUFSIZE*2,MEMF_PUBLIC); /* Alloc. public mem */
		if(err=(PD->pd_PrintBuf == 0)) return(err);
		/* Reset printer to power-up state */
		if(err=(*(PD->pd_PWrite))("\033@",2)) return(err);
		if(err=PWait(1,0)) return(err);
		/* Select 24/216 (8/72) inch spacing */
		if(err=(*(PD->pd_PWrite))("\0333\030",3)) return(err);
		/* Set unidirectional print mode */
		if(err=(*(PD->pd_PWrite))("\033U1",3)) return(err);
		bufptr = 0;
		return(0); /* Flag as all okay */
		break;
	
	case 1:
		/* Put pixel in buffer */
		i = bufptr+x+4; /* Calculate which byte to use */
		/* Fill print buffer*/
		PD->pd_PrintBuf[i] = PD->pd_PrintBuf[i] | (1 << (7-(y&7)));
		PD->pd_PrintBuf[bufptr+x+offset] |= bit_table[y&7];
		return(0); /* Flag as all okay */
		break;
		
	case 2:
		/* Dump buffer to printer */
		if(err=(*(PD->pd_PWrite))(&(PD->pd_PrintBuf[bufptr]),
				BUFSIZE)) return(0);
		bufptr = BUFSIZE - bufptr;
		return(0); /* Flag as all okay */
		break;
	
	case 3:
		/* Clear and initialize buffer */
		for(i=bufptr; i<bufptr+BUFSIZE; i++)
			PD->pd_PrintBuf[i] = 0; /* Clear buffer */
		ptr = &PD->pd_PrintBuf[bufptr];
		i = BUFSIZE;
		while(i--) *ptr++ = 0;
		PD->pd_PrintBuf[bufptr] = 27;
		PD->pd_PrintBuf[bufptr+1] = 'L';
		PD->pd_PrintBuf[bufptr+2] = ROWSIZE & 0xff;
		PD->pd_PrintBuf[bufptr+3] = ROWSIZE >> 8;
		PD->pd_PrintBuf[bufptr+BUFSIZE-2] = 10;
		PD->pd_PrintBuf[bufptr+BUFSIZE-1] = 13;
		return(0); /* Flag as all okay */
		break;
	
	case 4:
		/*Free the print buffer memory */
		err=(*(PD->pd_PWrite))("\033@",2); /* Reset to power-up state */
		if(!err) err=(*(PD->pd_PBothReady))(); /* Wait for buffers
								to empty */
		FreeMem(PD->pd_PrintBuf,BUFSIZE*2); /* Free buffer memory */
		return(err); /* Return Status */
		break;
		
	case 5:
		/* io_special flag call */
		center = x & SPECIAL_CENTER; /* Set center flag */
		return(0); /* Flag as all okay */
		break;
	
	default:
		return(0);

	}
}

