#include "PostPre.h"
#include "Global.h"

extern	int	page_counter;
extern	BPTR	outfh;

struct	IODRPReq prreq;
struct	PrinterData *prdata;
struct	PrinterExtendedData *prextdata;
struct	Preferences *prprefs;
struct	RastPort prrast;
ULONG		prsig;
UBYTE		prstatus[2];
int		propen=0;

/* Open the printer device and set up the page size */

BOOL setprinter(void)
{
	if (propen == 0)
	{
		if (OpenDevice("printer.device", 0,
			(struct IORequest *) &prreq, 0) != 0)
		{
			okmsg("Can't open printer.device!");
			ioerror = errioerror;
			return(FALSE);
		}
		propen = 1;
	}
	if (prport == NULL)
	{
		prport = CreatePort(NULL, 0);
		if (prport == NULL)
		{
			okmsg("Can't open printer port!");
			CloseDevice((struct IORequest *) &prreq);
			return(FALSE);
		}
		prreq.io_Message.mn_ReplyPort = prport;
		prsig = 1 << prport->mp_SigBit;
		prdata = (struct PrinterData *) prreq.io_Device;
		prextdata = &prdata->pd_SegmentData->ps_PED;
		prprefs = &prdata->pd_Preferences;
	}
	return(TRUE);
}

/* Print the page */

static	int	ybase = 0;
void printpage(struct BitMap *my_print_bm)
{
	ULONG sig;
	UWORD prflags;

/*	char reset_cmd[] = "\0x1b""c";*/

/* Disable break exceptions so we can wait on the signal instead */

	SetExcept(0, SIGBREAKF_CTRL_C);
	breakset = 0;

/* First check the printer is ready */

	if(setprinter() == FALSE) return;
	prreq.io_Command = PRD_QUERY;
	((struct IOStdReq *) &prreq)->io_Data = (APTR) prstatus;
	if (DoIO((struct IORequest *) &prreq))
	{
		ioerror = errioerror;
		return;
	}
	if (((struct IOStdReq *) &prreq)->io_Actual == 1 && prstatus[0] & 3 != 0)
		FPrintf(outfh, "printer not ready (CTRL/C to abort)\n");

/* Now dump the page */

	prrast.BitMap		= my_print_bm;
	prreq.io_Command	= PRD_DUMPRPORT;
	prreq.io_RastPort	= &prrast;
	prreq.io_ColorMap	= (struct ColorMap *) &colormap;
	prreq.io_Modes = 0;
	prreq.io_SrcX = 0;
	prreq.io_SrcY = 0;
	prreq.io_SrcWidth = parm.page.xsize;
	prreq.io_SrcHeight = parm.page.ysize;
	prreq.io_Special = (SPECIAL_DENSITY1 * Options.PostOpts.prden) | SPECIAL_TRUSTME;
	prprefs->PrintDensity = Options.PostOpts.prden;
	if (bandrendering)
	{
		if (ybase + parm.page.ysize >= parm.page.yheight)
		{
			prreq.io_SrcHeight = parm.page.yheight - ybase;
			ybase = -parm.page.ysize;
		}
		else
		{
			prreq.io_Special |= SPECIAL_NOFORMFEED;
		}
		ybase += parm.page.ysize;
	}
	if(Options.PostOpts.formfeed == FALSE) prreq.io_Special |= SPECIAL_NOFORMFEED;
	if(Options.PostOpts.centerpage) prreq.io_Special |= SPECIAL_CENTER;
	if (prextdata->ped_MaxXDots != 0)
	{
		if (prreq.io_SrcWidth > prextdata->ped_MaxXDots)
		{
			prreq.io_SrcWidth = prextdata->ped_MaxXDots;
		}
		if (prextdata->ped_MaxYDots != 0)
		{
			if (prreq.io_SrcHeight > prextdata->ped_MaxYDots)
			{
				prreq.io_SrcHeight = prextdata->ped_MaxYDots;
			}
		}
	}
	prreq.io_DestCols = prreq.io_SrcWidth;
	prreq.io_DestRows = prreq.io_SrcHeight;
	prflags = prprefs->PrintFlags;
	prprefs->PrintFlags = prflags & ~DIMENSIONS_MASK | IGNORE_DIMENSIONS;

/* We use asynchronous IO so we can abort it with a CTRL/C 					*
 * The TaskPri has to be the same as the one of the printer.device task	*
 * Otherwise the ctrl-c Feature does not work									*/

	SendIO((struct IORequest *) &prreq);

	for (;;)
	{
		sig = Wait(prsig | SIGBREAKF_CTRL_C);
		if (sig & SIGBREAKF_CTRL_C)
		{
			AbortIO((struct IORequest *) &prreq);
			WaitIO((struct IORequest *) &prreq);
			ioerror = errioerror;
			break;
		}
		if (GetMsg(prport)) break;
	}
	while(GetMsg(prport));
	if (prreq.io_Error != 0) ioerror = errioerror;

/* Restore break exceptions */

	SetExcept(~0, SIGBREAKF_CTRL_C);
	breakset = 1;

/*	if(ioerror)
	{
		prreq.io_Command = CMD_WRITE;
		((struct IOStdReq *) &prreq)->io_Data = (APTR) reset_cmd;
		((struct IOStdReq *) &prreq)->io_Length = strlen(reset_cmd);
		DoIO((struct IORequest *) &prreq);
	}*/
	prprefs->PrintFlags = prflags;
	if (propen) CloseDevice((struct IORequest *) &prreq);
	if (prport) DeletePort(prport);
	propen = 0;
	prport = 0;

}
