#include <signal.h>
#include <atarierr.h>

#ifdef __GNUC__

#include <fcntl.h>
#include <ioctl.h>
#include <osbind.h>
#include <mintbind.h>

#else
#ifdef __TURBOC__

#include <tos.h>
#include "mintbind.h"

#else

#include <osbind.h>
#include "mintbind.h"

#endif
#endif


#include <stdlib.h>
#include <string.h>

#include "treiber.h"

#define FALSE 0
#define TRUE 1

/********************************************************************/
/* Externe routinen in Assembler (FAST_DVI.S) */

#ifdef FAST_PRN
extern long	prn_byte( char *ptr, long byte );
extern void	exstall( void );
#endif

extern volatile long	old_vec;
/* 22.1.93 */

/********************************************************************/

/* Pufferspeicher */
static char	*puffer, *druck_puffer;
extern long	max_puffer_laenge;	/* Kann vom Programm modifiziert werden */
static long	puffer_laenge = 0L;
static char signal_installed=FALSE;

/* Shared Memory */
char				shm_name[128];
static int	shm;
static char	*memory;

/* Name des tempor„ren Files */
char 				tmp_file[256];
long				MiNT;

#ifdef SHOW_PRT
char	*disp_status="\033Hp";
char	*char_status="/-\\|"; /* Kann man auch durch vier eigene Symbole ersetzen */
char	rot_status;
#endif

/********************************************************************/
/* Einige Routinen zum Druck */

void	disp_prn( void *ptr, long len )
{
	if(  !signal_installed  )
	{
		signal_installed = TRUE;
		Psignal( SIGINT, (long)exstall );
		Psignal( SIGTERM, (long)exstall );
	}
	while(  prn_byte( ptr, len  )  )
	{
		(void)Fselect( 500, 0L, 0L, 0L );
#ifdef SHOW_PRT
		disp_status[2] = char_status[rot_status++];
		rot_status &= 3;
		Cconws( disp_status );
#endif
	}
}
/* 10.9.94 */


void	disp_wait( void )
{
	while(  old_vec!=0L  )
	{
		(void)Fselect( 500, 0L, 0L, 0L );
#ifdef SHOW_PRT
		disp_status[2] = char_status[rot_status++];
		rot_status &= 3;
		Cconws( disp_status );
#endif
	}
}


	/* Gibt Puffer aus (SCHNELL!!) */
void	flush_block( int fh )
{
	if(  fh>0  )
	{
		Fclose( fh );
		return;
	}
	if(  puffer_laenge>0  )
	{
		disp_wait();
		memcpy( druck_puffer, puffer, puffer_laenge );
		disp_prn( druck_puffer, puffer_laenge );
	}
	puffer_laenge = 0;
}
/* 23.1.93 */



	/* Gibt an aus (SCHNELL! ber Spooler) */
long	print_block( long laenge, char *blk, int fh )
{
	if(  fh>0  )
	{
#ifdef SHOW_PRT
		disp_status[2] = char_status[rot_status++];
		rot_status &= 3;
		Cconws( disp_status );
#endif
		return Fwrite( fh, laenge, blk );
	}
	if(  laenge+puffer_laenge>=max_puffer_laenge  )
	{
		disp_wait();
		if(  puffer_laenge>0  )
		{
			memcpy( druck_puffer, puffer, puffer_laenge );
			disp_prn( druck_puffer, puffer_laenge );
		}
		puffer_laenge = 0L;
	}

		/* Zu lang... */
	if(  laenge>=max_puffer_laenge  )
	{
		disp_prn( blk, laenge );
		disp_wait();
	}
	else
	{
		memcpy( puffer+puffer_laenge, blk, laenge );
		puffer_laenge += laenge;
	}
	return laenge;
}
/* 22.1.93 */


long	print_str( char *str, int fh )
{
	return print_block( strlen(str), str, fh );
}
/* 3.9.94 */



/* Versucht Drucker zu ™ffnen und zu Verriegeln! */ 
int	open_printer( int devh )
{
	puffer = druck_puffer = 0L;
	if(  devh<0  &&  max_puffer_laenge>128  )
	{
		puffer = Malloc( max_puffer_laenge );	/* Speicher holen */
		if(  puffer<=0L  )
			return 0;	/* Out of Memory */
		druck_puffer = Malloc( max_puffer_laenge );
		if(  druck_puffer<=0L  )
		{
			Mfree( puffer );
			return 0;	/* Out of Memory */
		}
	}

	/* Druckersemaphore bekommen! (Wird bei Beendigung automatisch frei) */
	devh = (int)Psemaphore( 0, 0x50524E3AL /*PRN:*/, -1 /*Kein Timeout*/ );
	if(  devh!=0  )
		Psemaphore( 2, 0x50524E3AL /*PRN:*/, -1 /*Kein Timeout*/ );

#ifdef SHOW_PRT
	disp_status[2] = '|';
	Cconws( disp_status );
#endif

	return 1;	/* Erfolg */
}
/* 6.2.93 */



/********************************************************************/
/* Routinen fr Optimierung */


/* Ist diese Zeile Leerzeile? */
int	ist_leerzeile( char *ptr, long offset )
{
	long	i;
	for(  i=0;  i<offset;  i++  )
		if(  *ptr++!=0  )
			return FALSE;
	return TRUE;
}
/* 16.1.93 */



/* Sind in den n„chsten #next Zeilen Zeichen? */
int	ist_next_leer( char *ptr, long offset, long next )
{
	while(  next-->0  )
	{
		if(  *ptr!=0  )
			return FALSE;
		ptr += offset;
	}
	return TRUE;
}
/* 16.1.93 */



/********************************************************************/
/* Hauptprogramm */


int	main( int argc, const char *argv[] )
{
	long	x;
	int		ret, th, flag, quer=0;
	char	optionen[16];

	if(  argc<6  )
	{
		Cconws( "Zuwenig Argumente!\xD\xA" );
		Cconws( "Richtig: shared_mem_file -Offset -l(=landscape, sonst -0) weite hoehe hdpi vdpi (file) (-\"Optionen) \xD\xA" );
		return -1;
	}

	th = -3;	/* Nix ge”ffnet! */
	old_vec = 0L;	/* Keine Routine installiert */

		/* Diese Routine mit Parameter versehen! */
		/* Es wird mit Shared Memory gearbeitet */
		/* Wenn der erste Buchstabe eine Zahl ist, */
		/* dann wird diese als Adresse angenommen */
	strcpy( shm_name, (char *)argv[1] );
	if(  shm_name[0]>='0'  &&  shm_name[0]<='9'  )
	{
		memory = (char *)atol( shm_name );
		shm_name[0] = 0;
	}
	else
	{
		(long)memory = Fopen( shm_name, O_RDONLY );
		if(  memory<0L  )
			return (int)memory; /* Access denied */
		shm = (int)memory;
		memory = (char *)Fcntl( shm, 0L, SHMGETBLK );
	}
	if(  memory<=0  )
		return -33;

	tmp_file[0] = 0;
	quer = 0;
	flag = 7;
	/* Mehrere Teile */
	x = -atol(argv[2]);
	/* Mehrere Teile */
	if(  argv[3][1]!='1'  )
		flag = 2;
	if(  x==0  )
		flag |= 1;
	if(  argv[3][2]=='l'  )
		quer = 1;

	/* Evt. Zieldatei ”ffnen */
	if(  argc>8  )
	{
		if(  argv[8][0]=='-'  )
			strcpy( optionen, argv[9]+2 );
		else
		{
			strcpy( tmp_file, argv[8] );
			th = (int)Fopen( tmp_file, O_RDWR );
			if(  th<0  )
				th = (int)Fcreate( tmp_file, 0 );
			Fseek( 0, th, 2 );
			if(  argc>9  )
				strcpy( optionen, argv[10]+2 );
		}
	}
#ifndef FAST_PRN
	else
		th = (short)Fopen( "PRN:", O_RDONLY );
#endif


	/* Druckerinitialisierung */
	while(  max_puffer_laenge>0  &&  !open_printer(th)  )
	{
		max_puffer_laenge >>= 1;
		if(  max_puffer_laenge<=128L  )
			return -39;	/* Zu wenig Speicher */
	}


		/* Und endlich drucken */
	if(  (long)memory==1L  )
		ret = drucke( 0L, 0, 0, 0, 0, 0, th, 4, quer, optionen );
	else
		ret = drucke( memory, x, atol(argv[4]), atol(argv[5]), atol(argv[6]), atol(argv[7]), th, flag, quer, optionen );

	if(  shm>0  )
	{
		Fclose( shm );
		Mfree( memory );	/* so kann der Speicher wieder freigegeben werden */
		Fdelete( shm_name );
		shm = 0;
	}

	if(  ret>=0  )	/* Erfolgreich? */
	{
		disp_wait();
		/* Nur Datei erzeugen? */
		if(  th>0  )
			Fclose( th );
		Cconws( "\033H " );
		return 0;
	}

	return ret;
}
/* 17.1.93 */
