/************************************************************************
*																								*
*		print																					*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Module containing the real printer routines.								*
*																								*
************************************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/reqbase.h>
#include <devices/printer.h>
#include <private/help.h>
#include <private/deva.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/reqproto.h>

#include <string.h>

#include	"settings.h"

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

					Definitions

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

#define	SS		( SHORT )Sets[ ActSet ]
#define	ELITE_ON				"\x1b[2w"
#define	ELITE_OFF			"\x1b[1w"
#define	CONDENSED_ON		"\x1b[4w"
#define	CONDENSED_OFF		"\x1b[3w"
#define	LETTERQ_ON			"\x1b[2\"z"
#define	LETTERQ_OFF			"\x1b[1\"z"
#define	PROPORTIONAL_ON	"\x1b[2p"
#define	PROPORTIONAL_OFF	"\x1b[1p"
#define	LINESP6_ON			"\x1b[1z"
#define	LINESP6_OFF			"\x1b[0z"

#define	PINIT					"\x1b[0m\x1b[0w\x1b[1v\x1b[1p\x1b[0q"

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

				External References

***************************************/
/***************************************
					Functions
***************************************/

/***************************************
					Variables
***************************************/

IMPORT	struct IODRPReq			  *GPrtReq;
IMPORT	struct IOStdReq			  *PrtReq;
IMPORT	struct IOPrtCmdReq		  *CmdReq;

IMPORT	struct Window				  *FirstWindow;

IMPORT	UBYTE								LoadString[];
IMPORT	struct FileInfoBlock		  *FIB;
IMPORT	UBYTE								Dir[],
												File[],
												Path[];
IMPORT	struct FileRequester			FReq;

IMPORT	LONG								Memsize;
IMPORT	UBYTE							  *ActFile;

IMPORT	struct Settings				Sets[ 10 ];
IMPORT	SHORT								ActSet;
IMPORT	UBYTE								ScTitle[];
IMPORT	UBYTE								File[];

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

						Globals

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

UBYTE								title[ 1024 ],
									PrtBuf[ 1024 ],
									Req[26]	=	"Print page no.          ?";
struct TRStructure			TR	=
{
	Req,
	NULL,
	NULL,
	"Skip",
	"Yes",
	"Quit",
	"Tell me ...",
	0xffff,
	0,0,0,0,0L,0L
};

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

					Declarations

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

VOID					PreInit( VOID );
VOID					PrintPageWise( VOID );
VOID					PrintAll( VOID );
VOID					Init( struct Settings );
UBYTE				  *PrintLine( UBYTE *, SHORT, SHORT );
UBYTE				  *PrintPage( UBYTE *, SHORT, SHORT, SHORT, SHORT, SHORT );
BOOL					AskStatus( VOID );
UBYTE				  *SkipPage( UBYTE *, SHORT, SHORT, SHORT, SHORT, SHORT );
static UBYTE	  *SkipLine( UBYTE *, SHORT, SHORT );

/************************************************************************
*																								*
*		PreInit																				*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Intailizes the printer to the currently chosen settigs.				*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Parameters		:																	*
*			none																				*
*																								*
*		Returns			:																	*
*			none																				*
*																								*
************************************************************************/

VOID		PreInit( VOID )
{
	if( AskStatus() )
		Init( Sets[ ActSet ] );
}

/************************************************************************
*																								*
*		PrintPageWise																		*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Prints the whole text, asking "Print", "Skip", and "Quit" for		*
*		every page.																			*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Parameters		:																	*
*			none																				*
*																								*
*		Returns			:																	*
*			none																				*
*																								*
************************************************************************/

VOID		PrintPageWise( VOID )
{
	UBYTE	  *p,
			  *pn;
	SHORT		i,
				j,
				pcnt,
				res;
	BOOL		go;

	/***/

	if( AskStatus() )
		Init( Sets[ ActSet ] );
	else
		return;

	p	=	ActFile;
	i	=	1;
	pcnt	=	0;
	go	=	TRUE;
	while(( p != NULL )&&( p < ActFile + Memsize )&&( go == TRUE ))
	{
		pn	=	itoa( i );
		while( strlen( pn ) < 5 )
			pn--;

		for( j = 0; j < 5; j++ )
			Req[ j + 17 ]	=	pn[j];

		res	=	TextRequest( &TR );
		switch( res )
		{
			case	0	:	go	=	FALSE;
							break;
			case	1	:	p	=	PrintPage( p, SS.PageLen, SS.Numb, i, SS.Tabsize, SS.PageWidth );
							pcnt++;
							break;
			case	2	:	p	=	SkipPage( p, SS.PageLen, SS.Numb, i, SS.Tabsize, SS.PageWidth );
							break;
		}
		i++;
	}
	SimpleRequest(	"Sent %s pages", itoa( pcnt ));
}

/************************************************************************
*																								*
*		PrintAll																				*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Prints the whole text without asking.										*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Parameters		:																	*
*			none																				*
*																								*
*		Returns			:																	*
*			none																				*
*																								*
************************************************************************/

VOID		PrintAll( VOID )
{
	UBYTE	  *p;
	SHORT		i;

	/***/

	if( AskStatus() )
		Init( Sets[ ActSet ] );
	else
		return;

	p	=	ActFile;
	i	=	1;
	while(( p != NULL )&&( p < ActFile + Memsize ))
	{
		p	=	PrintPage( p, SS.PageLen, SS.Numb, i, SS.Tabsize, SS.PageWidth );
		i++;
	}
	SimpleRequest(	"Sent %s pages", itoa( --i ));
}

/************************************************************************
*																								*
*		Init																					*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Initializes the printer															*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Parameters		:																	*
*			set			:	Settings to init											*
*																								*
*		Returns			:																	*
*			none																				*
*																								*
************************************************************************/

VOID		Init( struct Settings set )
{
	static struct Settings	Store;
	SHORT							i;
	UBYTE						  *p,
								  *q;
	BOOL							ne	=	FALSE;

	/***/

	/*	Compare set and Store, to determine if the set is already set, and to
		give the use the opportunity, to change settings on his printer.
		*/

	p	=	( UBYTE * )&Store;
	q	=	( UBYTE * )&set;

	for( i = 0; i < sizeof( struct Settings ); i++ )
	{
		if( p[i]	!= q[i] )
		{
			ne	=	TRUE;
			break;
		}
	}
	if( ne == FALSE )
		return;

	Printer_WRITE( PrtReq, PINIT, strlen( PINIT ));

	Printer_PRTCOMMAND( CmdReq, aSLRM, ( UBYTE )set.LMarg, ( UBYTE )set.RMarg, 0, 0 );

	if( set.Cond )
		Printer_WRITE( PrtReq, CONDENSED_ON, 4L );
	else
		Printer_WRITE( PrtReq, CONDENSED_OFF, 4L );

	if( set.LetterQ )
		Printer_WRITE( PrtReq, LETTERQ_ON, 5L );
	else
		Printer_WRITE( PrtReq, LETTERQ_OFF, 5L );

	if( set.LSpace6 )
		Printer_WRITE( PrtReq, LINESP6_ON, 4L );
	else
		Printer_WRITE( PrtReq, LINESP6_OFF, 4L );

	switch( set.Style )
	{
		case	STYLE_ELITE	:	Printer_WRITE( PrtReq, ELITE_ON, 4L );
									break;
		case	STYLE_PICA	:	Printer_WRITE( PrtReq, ELITE_OFF, 4L );
									break;
		case	STYLE_PROP	:	Printer_WRITE( PrtReq, PROPORTIONAL_ON, 4L );
									break;
		default				:	break;
	}
	Store	=	set;
}

/************************************************************************
*																								*
*		PrintLine																			*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Print one line.																	*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Parameters		:																	*
*			p				:	Pointer to the beginning of the line				*
*			TS				:	Tab - size for this line.								*
*			ll				:	Line length													*
*																								*
*		Returns			:																	*
*			Pointer to the beginnig of the next line, or NULL if the end	*
*			of the text was encountered.												*
*																								*
************************************************************************/

UBYTE	  *PrintLine( UBYTE *p, SHORT TS, SHORT ll )
{
	SHORT			i,
					j,
					len,
					nt;
	UBYTE		  *q,
				  *re;

	/***/

	if( TS == 0 )			/* Don't wanna run into a division by zero */
		TS	=	1;

	/*	First, we find our return value.
		*/

	for( q = p;( *q != '\n' )&&( q < ( ActFile + Memsize )); q++ )
		;
	if( q < ( ActFile + Memsize ))
	{
		q++;
		re	=	q;
	}
	else
		re	=	NULL;

	/*	Now, we process the line, using the tab replacing algorithm, we
		developed for "PS". We stop, when we have written the line length.
		*/

	i		=	0;
	len	=	0;
	while(( p != q )&&( len < ll ))
	{
		if( *p == '\t' )
		{
			nt	=	TS - ( len % TS );
			for( j = 0; j < nt; j++ )
			{
				PrtBuf[i++]	=	' ';
				len++;
			}
			p++;
			continue;
		}
		if( *p == '\x1b' )
		{
			while( !isalpha( *p ))
				PrtBuf[i++]	=	*p++;

			PrtBuf[i++]	=	*p++;
			continue;
		}
		PrtBuf[i++]	=	*p++;
		len++;
		continue;
	}
	PrtBuf[ i - 1 ]	=	'\n';
	Printer_WRITE( PrtReq, PrtBuf, ( LONG )i );
	if( p < q )
		re	=	p;

	return	re;
}

/************************************************************************
*																								*
*		PrintPage																			*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Print one page of text, including the concluding form feed.			*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Parameters		:																	*
*			p				:	Pointer to the beginning of the page				*
*			pl				:	Page length	( in lines )								*
*			numb			:	Page numbering flag ( 0 = No, 1 = Top, 2 = Bot,	*
*								3 = Line )													*
*			nr				:	Page number													*
*			TS				:	Tab size														*
*			ll				:	Line length													*
*																								*
*		Returns			:																	*
*			Pointer to the beginning of the next page, of NULL, if we		*
*			reached the end of the text.												*
*																								*
************************************************************************/

UBYTE	  *PrintPage( UBYTE *p, SHORT pl, SHORT numb, SHORT nr, SHORT TS, SHORT ll )
{
	UBYTE		  *q,
				  *ns,
					lf[]	=	"\n",
					ff[]	=	"\xc";
	SHORT			i,
					j;

	/***/

	pl--;

	if( numb != 0 )
	{
		for( i = 0; i < ll; i++ )
			title[i]	=	' ';
		pl	-=	2;
	}
	if( numb == 3 )
	{
		q	=	stpcpy( title, File );
		*q	=	' ';
	}
	if( numb != 0 )
	{
		q	=	stpcpy( &title[ ll - 12 ], "Page:" );
		*q++	=	' ';
		ns	=	itoa( nr );
		while( strlen( ns ) < 5 )
			ns--;

		q	=	stpcpy( q, ns );
		*q	=	'\n';
	}

	if(( numb == 1 )||( numb == 3 ))
	{
		Printer_WRITE( PrtReq, title, ( LONG )ll );
		Printer_WRITE( PrtReq, lf, 1L );
	}

	for( i = 0; i < pl; i++ )
	{
		p	=	PrintLine( p, TS, ll );
		if( p == NULL )
		{
			for( j = i; j < pl; j++ )
				Printer_WRITE( PrtReq, lf, 1L );

			break;
		}
	}

	if( numb	==	2 )
	{
		Printer_WRITE( PrtReq, lf, 1L );
		Printer_WRITE( PrtReq, title, ( LONG )ll );
	}
	Printer_WRITE( PrtReq, ff, 1L );

	return	p;
}

/************************************************************************
*																								*
*		AskStatus																			*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Asks the printer status.														*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Parameters		:																	*
*			none																				*
*																								*
*		Returns			:																	*
*			TRUE if the printer is ready to print, FALSE if the printer		*
*			is not ready.																	*
*																								*
************************************************************************/

BOOL		AskStatus( VOID )
{
	UWORD		status;

	/***/

	Printer_QUERY( PrtReq, &status );
	/*	SimpleRequest( "status is %s", itoa( status )); */
	switch( status & 0x0700 )
	{
		case	0x0400	:	return	TRUE;
								break;
		case	0x0500	:	SimpleRequest( "Please turn your printer online !" );
								return	FALSE;
								break;
		case	0x0700	:	SimpleRequest( "Please insert paper and\nturn your printer online !" );
								return	FALSE;
								break;
		default			:	SimpleRequest( "Something is wrong with your printer !" );
								return	FALSE;
								break;
	}
}

/************************************************************************
*																								*
*		SkipPage																				*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Skip one page of text.															*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Parameters		:																	*
*			p				:	Pointer to the beginning of the page				*
*			pl				:	Page length	( in lines )								*
*			numb			:	Page numbering flag ( 0 = No, 1 = Top, 2 = Bot,	*
*								3 = Line )													*
*			nr				:	Page number													*
*			TS				:	Tab size														*
*			ll				:	Line length													*
*																								*
*		Returns			:																	*
*			Pointer to the beginning of the next page, of NULL, if we		*
*			reached the end of the text.												*
*																								*
************************************************************************/

UBYTE	  *SkipPage( UBYTE *p, SHORT pl, SHORT numb, SHORT nr, SHORT TS, SHORT ll )
{
	SHORT			i,
					j;

	/***/

	pl--;

	if( numb != 0 )
	{
		pl	-=	2;
	}

	for( i = 0; i < pl; i++ )
	{
		p	=	SkipLine( p, TS, ll );
		if( p == NULL )
		{
			for( j = i; j < pl; j++ )
				;
			break;
		}
	}
	return	p;
}
/************************************************************************
*																								*
*		SkipLine																				*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Skip one line.																		*
*																								*
*-----------------------------------------------------------------------*
*																								*
*		Parameters		:																	*
*			p				:	Pointer to the beginning of the line				*
*			TS				:	Tab - size for this line.								*
*			ll				:	Line length													*
*																								*
*		Returns			:																	*
*			Pointer to the beginnig of the next line, or NULL if the end	*
*			of the text was encountered.												*
*																								*
************************************************************************/

static UBYTE	  *SkipLine( UBYTE *p, SHORT TS, SHORT ll )
{
	SHORT			i,
					j,
					len,
					nt;
	UBYTE		  *q,
				  *re;

	/***/

	if( TS == 0 )			/* Don't wanna run into a division by zero */
		TS	=	1;

	/*	First, we find our return value.
		*/

	for( q = p;( *q != '\n' )&&( q < ( ActFile + Memsize )); q++ )
		;
	if( q < ( ActFile + Memsize ))
	{
		q++;
		re	=	q;
	}
	else
		re	=	NULL;

	/*	Now, we process the line, using the tab replacing algorithm, we
		developed for "PS". We stop, when we have written the line length.
		*/

	i		=	0;
	len	=	0;
	while(( p != q )&&( len < ll ))
	{
		if( *p == '\t' )
		{
			nt	=	TS - ( len % TS );
			for( j = 0; j < nt; j++ )
			{
				PrtBuf[i++]	=	' ';
				len++;
			}
			p++;
			continue;
		}
		if( *p == '\x1b' )
		{
			while( !isalpha( *p ))
				PrtBuf[i++]	=	*p++;

			PrtBuf[i++]	=	*p++;
			continue;
		}
		PrtBuf[i++]	=	*p++;
		len++;
		continue;
	}
	PrtBuf[ i - 1 ]	=	'\n';
	if( p < q )
		re	=	p;

	return	re;
}
