/* PRTSPOOL.c - print SPOOLed file program */

/*
**	Date written: 04/23/86
**	Author: Tim Holloway
**		Compuserve: 73026,2026
**		Bix: tholloway
**		Fido node: 112/1 (Casa Mi Amiga).
**
**	Version: 1.1 - a true spooler version
**
**	Copyright (C) 1986, by Tim Holloway.  This program may be
**	freely distributed for non-commercial use only.  Use for commercial
**	purposes without the express permission of the author is a violation
**	of copyright law.
**
**	Description:
**	   This program accepts a printer name (file name) as a parameter.
**	It opens the file and requests the names of files to be printed
**	by sending messages to the SPOOLER program, which fills in a
**	file name and returns the message to PRTSPOOL
**
**	Change History: 
**
**	11/19/86, TFH. added logic to actually drive a printer.
**		removed the tracing code, and changed the error message
**		reporting to use my Gripe procedure so display a requester
**		if the SPOOLED file could not be accessed.
**
**	Usage: See below.
**
**	Special notes: sorry, I mixed AmigaDOS file I/O and Unix-style
**	I/O.  In accordance with my policy of never programming unportable
**	unless neccessary, I had intended to use all Unix-style I/O, but
**	the Lattice version 3.03 and earlier systems buffer files that
**	according to Unix should not be buffered.  I could have used
**	the set-non-buffered function, but two wrongs don't make a right!
*/

/* Basic Amiga system definitions */

#include <exec/types.h>
#include <exec/alerts.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <graphics/gfx.h>
#include <intuition/intuition.h>

struct Library *IntuitionBase, *OpenLibrary();

/* more mundane definitions */

#include "stdio.h"
#include "spool.h"

/* define login and logout stuff in the following #include: */

#include "login.cx"

struct Process *myprocess, *FindTask();
struct FileHandle *outfile, *Open();

BOOL io_error = FALSE,
     aborting = FALSE;

usage()
{
	printf ("PRTSPOOL program v1.1 by Tim Holloway\n");
	printf ("Usage: PRTSPOOL filename\n");
}

SPOOLmsg packet = {{NULL, NULL, 0}, '?', ""};

error (msg)
char *msg;
{
	Gripe ("PRTSPOOL:", msg, "");
}

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

static int linenum = 0;
static char linebuffer[256];
FILE * infile;

#define LINES_PER_PAGE 56

static int hour, minute, year, day, month;

void
getdate()
{
   long dates[3]; int jday;

   (void) DateStamp(dates);
   hour = dates[1] / 60;
   minute = dates[1] % 60;
   year = (dates[0] * 4) / 1461;
   jday = dates[0] - (year*1461)/4;
   year += 1978;
   Julian_to_Gregorian (jday, &year, &month, &day);
}

void xputs(str)
{
	register int i;

	i = strlen(str);
	if (Write (outfile, str, i) != i)
		io_error = TRUE;
}

spool_file(fname)		/* print a file */
char *fname;
{
   register int rc;

   /* Don't use Gripe, here! - it would halt PRTSPOOL until the user */
   /* acknowledged.  Better to waste a page and keep the printer running. */

   if ((infile = fopen (fname, "r")) == 0)
   {
      xputs ("\f\n\n\n");
      xputs ("*******************************************\n");
      xputs ("**** ERROR ********************************\n");
      xputs ("Could not open file to be printed:\n");
      xputs (fname); xputs("\n");
      xputs ("*******************************************\n");
      return;
   }

   getdate();		/* get timestamp */
   getheader();		/* setup page header */
   putheader();

   do
   {
      put_a_line();
   } while (NOT io_error && get_a_line());
   if (io_error)
   {
	io_error = FALSE;
	aborting = TRUE;
	Gripe ("PRTSPOOL Terminating:", "I/O error on printer file.", "");
   }
   xputs ("\n");
   xputs ("EOF\n");
   rc = fclose (infile);

/******** do NOT do the folowing under Lattice C version 3.03 and earlier.
  They didn't realize the the Amiga Close function does not return an
  error code.

   if (rc != 0) Gripe ("PRTSPOOL:", "Error closing file being printed", "");
*********/
}

int
get_a_line()
{
   char *i;

   i = fgets(linebuffer, sizeof(linebuffer), infile);
   return (i != NULL);
}

put_a_line()
{
   if (linenum++ > LINES_PER_PAGE) putheader();

   xputs (linebuffer);
}

#define HBSIZE 32+8+2+6
static char headbuffer[HBSIZE+8];

/*
  two for ff, stretch, 32 for title, 8 for page#, 4 for shrink, 2*NL, NUL
*/

getheader()
{
   int i;

   fgets (linebuffer, 255, infile);
   headbuffer[0] = 0x0c;   /* ff */
   headbuffer[1] = 0x0e;   /* stretch */
   for (i = 0; (i<HBSIZE-14) && (linebuffer[i] >= ' '); i++)
      headbuffer[i+2] = linebuffer[i];
   i+=2;
   headbuffer[i++]= 0x0f;
   headbuffer[i++]= '\n';
   headbuffer[i++]= '\0';
}

putheader()
{
   char outfb[81];

   xputs(headbuffer);
   sprintf (outfb, "As of: %02.2d/%02.2d/%4d, %02d:%02.2d\n\n",
                             month, day, year, hour, minute);
   xputs(outfb);
   linenum = 0;
}

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

main (argc, argv)
int argc;
char *argv[];
{
   PORTPAIR ports;

   if ( (IntuitionBase = OpenLibrary("intuition.library", 0)) == NULL)
   {
	Alert (AT_Recovery + AG_OpenLib + AO_Intuition, NULL);
	exit(20);
   }

   if ((argc < 2) || (argv[1][1] == '?'))
   {
	usage();
	goto abort;
   }

   if ( (outfile= Open(argv[1], MODE_OLDFILE)) == NULL)
   {
	Gripe ("PRTSPOOL:", "Couldn't open printer file:", argv[1]);
	goto abort;
   }

   if (NOT LogInPort (GIMME_A_FILE, &ports, &packet))
   {
	error ("SPOOLER program is inactive");
	goto abort;
   }

/*
printf ("message port for %s is at %lx\n",
 GIMME_A_FILE, ports[OUTPORT]);
*/

    /* raise priority - this program is low-overhead (mostly Waiting)	*/

   myprocess = FindTask(NULL);
   (void) SetTaskPri (myprocess, PRTSPOOL_PRIORITY);

   /* The following loop goes out and solicits for a filename.		*/

   while (NOT aborting)
   {
      packet.filename[0] = NUL;	/* be neat, null out file name */
      packet.minfo.mn_ReplyPort = ports[INPORT];	/* return address */

/* printf ("send/w reply port at %lx\n", packet.minfo.mn_ReplyPort); */

      packet.minfo.mn_Length = sizeof(packet.filename);

/* printf ("===request to spool...\n"); */

      PutMsg (ports[OUTPORT], &packet);
      WaitPort(ports[INPORT]);
      (VOID) GetMsg (ports[INPORT]);
      if (packet.log_status == LOG_OUT) break;
      spool_file(packet.filename);
   }

   Close(outfile);
   LogOutPort (&ports, &packet);

abort:
   CloseLibrary(IntuitionBase);
}
