/****************************************************************************
 *
 *        Screen_Printer driver.
 */

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

#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>

extern struct Library *AbsExecBase;
extern struct Library *IntuitionBase;

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

extern void SetDensity(ULONG);
extern void Transfer(struct PrtInfo *PInfo, UWORD y, BYTE *ptr, UWORD colors[]);

#define MAXCOLORBUFS 3

int OpenMyScrn(ULONG w, ULONG h);
void Eject(void);

        UWORD BufSize, ColorSize;
	long linesleft;
        UBYTE *ptr, *planeptr[MAXCOLORBUFS];
	UWORD colors[MAXCOLORBUFS];
	BOOL color_on;
int Render(long ct, long x, long y, long status)
{
        int i, err, total;

        err=PDERR_NOERR;
        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.
                        */
                        BufSize = ((PED->ped_MaxXDots + 15) / 16) * 2;
			ColorSize = BufSize;
			if (PD->pd_Preferences.PrintShade == SHADE_COLOR)
				BufSize *= 3;
			colors[0] = ColorSize * 0; /* Black or yellow */
			colors[1] = ColorSize * 1; /* Magenta */
			colors[2] = ColorSize * 2; /* Cyan */
                        PD->pd_PrintBuf = AllocMem(BufSize, MEMF_ANY);
                        if (PD->pd_PrintBuf == NULL) {
                                err = PDERR_BUFFERMEMORY; /* no mem */
                        }
                        else if (OpenMyScrn(PED->ped_MaxXDots,
				PED->ped_MaxYDots) == NULL) {
					err = PDERR_BUFFERMEMORY;
				}
                        break;

                case 1 : /* Scale, Dither and Render */
                        /*
                                ct      - pointer to PrtInfo structure.
                                x       - 0.
                                y       - row # (0 to Height - 1).
                        */
                        Transfer((struct PrtInfo *)ct, y, PD->pd_PrintBuf,
				colors);
                        err = PDERR_NOERR; /* all ok */
                        break;

                case 2 : /* Dump Buffer to Printer */
                        /*
                                ct      - 0.
                                x       - 0.
                                y       - # of rows sent (1 to NumRows).
                        */
			ptr=PD->pd_PrintBuf;
			total=PD->pd_Preferences.PrintShade ==
				SHADE_COLOR ? 3 : 1;
			for (i=0; i<total; i++) {
				CopyMem(ptr,planeptr[i],ColorSize);
				planeptr[i] +=
					myScrnHandle->BitMap.BytesPerRow;
				ptr += ColorSize;
			};
			linesleft--;
                        break;

                case 3 : /* Clear and Init Buffer */
                        /*
                                ct      - 0.
                                x       - 0.
                                y       - 0.
                        */
                        ptr = PD->pd_PrintBuf;
                        i = BufSize;
                        do {
                                *ptr++ = 0;
                        } while (--i);
                        break;

                case 4 : /* Close Down */
                        /*
                                ct      - error code.
                                x       - io_Special flag from IODRPReq struct
                                y       - 0.
                        */
                        err = PDERR_NOERR; /* assume all ok */
                        /* if user did not cancel the print */
                        if (ct != PDERR_CANCEL) {
                        	/* if want to unload paper */
                        	if (!(x & SPECIAL_NOFORMFEED)) {
                        		/* eject paper */
					Eject();
                                }
                        }
                        if (PD->pd_PrintBuf != NULL) {
                                FreeMem(PD->pd_PrintBuf, BufSize);
                        }
                        break;

                case 5 : /* Pre-Master Initialization */
                        /*
                                ct      - 0 or pointer to IODRPReq structure.
                                x       - io_Special flag from IODRPReq struct
                                y       - 0.
                        */
                        /* select density */
                        SetDensity(x & SPECIAL_DENSITYMASK);
                        break;
        }
        return(err);
}

/* Open Screen File */
int OpenMyScrn(ULONG w, ULONG h)
{
	static WORD scrnpal[9][4] = {
		{0,-1,-1,-1},{1,-1,-1, 0},
		{2,-1, 0,-1},{3,-1, 0, 0},
		{4, 0,-1,-1},{5, 0,-1, 0},
		{6, 0, 0,-1},{7, 0, 0, 0},
		{-1,0,0,0}
	};

	int i;
	
	if (myScrnHandle) {
		if ((color_on) == (PD->pd_Preferences.PrintShade ==
			SHADE_COLOR)) return TRUE;
		else return FALSE;
	}
	if (color_on = (PD->pd_Preferences.PrintShade == SHADE_COLOR))
		myScrnHandle=OpenScreenTags(NULL,
			SA_Width,	w,
			SA_Height,	h,
			SA_Depth,	(ULONG)3,
			SA_DisplayID,	(ULONG)0x8004,
			SA_Colors,	scrnpal,
			SA_AutoScroll,	(ULONG)TRUE,
			SA_Quiet,	(ULONG)TRUE,
			SA_Overscan,	(ULONG)OSCAN_STANDARD,
			TAG_END);
	else myScrnHandle=OpenScreenTags(NULL,
		SA_Width,	w,
		SA_Height,	h,
		SA_Depth,	(ULONG)1,
		SA_DisplayID,	(ULONG)0x8004,
		SA_AutoScroll,	(ULONG)TRUE,
		SA_Quiet,	(ULONG)TRUE,
		SA_Overscan,	(ULONG)OSCAN_STANDARD,
		TAG_END);
	if(myScrnHandle==NULL) return FALSE;
	linesleft = h;
	for (i=0; i<3; i++) {
		planeptr[i]=myScrnHandle->BitMap.Planes[i];
	};
	return TRUE;
}
	
void Eject(void) {
	if (myScrnHandle == NULL) return;

	CloseScreen(myScrnHandle);
	myScrnHandle=NULL;
}
