#include <intuition/intuition.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <stdio.h>
#include "instant.h"
#define BPTR long

#define SECSPERDAY (60*60*24)
#define SECSPERMIN 60
#define TICKSPERSEC TICKS_PER_SECOND
FILE *stdprt;
FILE *stdlog;

int select1(), ready();

struct FuncTable ft[] = {
	"Select File", select1,
	"Print Files", ready,
	0, 0
};

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

main(ac, av)
int ac;
char **av;
{
	if(ac == 0) {
		IntuitionBase = (struct IntuitionBase *)
			OpenLibrary("intuition.library", 0);
		GfxBase = (struct GfxBase *)
			OpenLibrary("graphics.library", 0);
		noneselected();
		if(instant("Print Files", 0, 0, ft)) {
			if(stdprt=fopen("PRT:", "w")) {
				stdlog=fopen("CON:0/0/400/50/Printer log", "w");
				printselected();
				if(stdlog) fclose(stdlog);
				fclose(stdprt);
			}
		} else
			freeselected();
		CloseLibrary(IntuitionBase);
		CloseLibrary(GfxBase);
		exit(0);
	}
	if(strcmp(av[1], "debug") == 0 ||
	   strcmp(av[1], "DEBUG") == 0) {
		stdprt = stdout;
		av++;
	} else if(!(stdprt=fopen("PRT:", "w"))) {
		perror("PRT:");
		return -1;
	}
	stdlog = stderr;
	while(*++av) {
		prfiles(*av);
	}
	if(stdprt != stdout)
		fclose(stdprt);
}

prfiles(f)
char *f;
{
	struct FileInfoBlock *FIB;
	char path[MAXFILENAME], name[MAXNAME];
	static WORD PatCode[128];
	char *p;
	BPTR dirlock;

	if((FIB = AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC)) == 0)
		return 0;

	if((p=strrchr(f, '/'))==0) {
		if((p=strrchr(f, ':'))==0) {
			strcpy(name, f);
			path[0] = 0;
		} else {
			char c;

			c = *p;
			*p = 0;
			strcpy(path, f);
			*p = c;
			strcpy(name, p);
		}
	} else {
		*p++ = 0;
		strcpy(path, f);
		strcpy(name, p);
	}

	CmplPat(name, PatCode);

	dirlock = Lock(path, ACCESS_READ);

	p = &path[strlen(path)];
	if(p > path && p[-1]!=':')
		*p++ = '/';
	*p = 0;

	if(!dirlock) {
		FreeMem(FIB, sizeof(struct FileInfoBlock));
		return 0;
	}

	if(!Examine(dirlock, FIB)) {
		UnLock(dirlock);
		FreeMem(FIB, sizeof(struct FileInfoBlock));
		return 0;
	}
	if(FIB->fib_DirEntryType < 0) {
		UnLock(dirlock);
		FreeMem(FIB, sizeof(struct FileInfoBlock));
	}
	while(ExNext(dirlock, FIB)) {
		if(Match(name, PatCode, FIB->fib_FileName)) {
			strcpy(p, FIB->fib_FileName);
			pr(path);
		}
	}
	FreeMem(FIB, sizeof(struct FileInfoBlock));
	UnLock(dirlock);
	return 1;
}

pr(file)
char *file;
{
	FILE *fp;
	int line, page;
	char linebuf[81];
	BPTR lock;
	struct FileInfoBlock *fib;
	unsigned long datestamp;
	char *timestr;

	if(!(lock = Lock(file, ACCESS_READ))) {
		if(stdlog)
			fprintf(stdlog, "Can't obtain lock for %s\n", file);
		return;
	}
	if(!(fib = AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC))) {
		UnLock(lock);
		if(stdlog)
			fprintf(stdlog, "Out of memory.\n");
		fclose(stdprt);
		exit(20);
	}
	if(!(Examine(lock, fib))) {
		if(stdlog)
			fprintf(stdlog, "Can't examine %s\n", file);
		UnLock(lock);
		FreeMem(fib, sizeof(struct FileInfoBlock));
		return;
	}
	UnLock(lock);

	if(fib->fib_DirEntryType >= 0) {
		if(stdlog)
			fprintf(stdlog, "%s is a directory.\n", file);
		FreeMem(fib, sizeof(struct FileInfoBlock));
		return;
	}

	if(!(fp = fopen(file, "r"))) {
		perror(file);
		FreeMem(fib, sizeof(struct FileInfoBlock));
		return;
	}

	line = 61;
	page = 0;
	datestamp =
		(unsigned long)fib->fib_Date.ds_Days*SECSPERDAY +
		(unsigned long)fib->fib_Date.ds_Minute*SECSPERMIN +
		(unsigned long)fib->fib_Date.ds_Tick/TICKSPERSEC;
	timestr = ctime(&datestamp);
	timestr[strlen(timestr)-1] = 0;

	if(stdlog)
		fprintf(stdlog, "Printing %s.\n", file);
	while(getline(linebuf, 80, fp)) {
		linebuf[80] = 0;
		if(line++ > 55) {
			page++;
			fprintf(stdprt, "\f\r%-30s       %5d       %30s\n\n",
				fib->fib_FileName, page, timestr);
			if(stdlog)
				fprintf(stdlog, " Page %d\r", page);
			line = 0;
		}
		fputs(linebuf, stdprt);
	}
	
	fclose(fp);
	FreeMem(fib, sizeof(struct FileInfoBlock));
}

getline(buffer, max, fp)
FILE *fp;
char *buffer;
int max;
{
	int c;
	int len;

	len = 0;
	while((c = getc(fp)) != '\n' && c != EOF && len<max) {
		c = c & 0x7F;
		buffer[len] = c;
		if(c<' ') {
			switch(c) {
				case '\t':
					do {
						buffer[len] = ' ';
						len++;
					} while((len&0x7) && len<max);
					break;
				case '\b':
					if(len>0) len--;
					break;
				case '\r':
					len = 0;
					break;
			}
		} else
			len++;
	}
	if(c=='\n' && len<max)
		buffer[len++] = c;
	else if(!feof(fp))
		ungetc(c, fp);
	buffer[len] = 0;
}

struct SelectedFile {
	struct SelectedFile *sf_next;
	char *sf_name;
} *filelist;

noneselected()
{
	filelist = 0;
}

printselected()
{
	struct SelectedFile *next;

	while(filelist) {
		next = filelist->sf_next;
		pr(filelist->sf_name);
		free(filelist->sf_name);
		free(filelist);
		filelist = next;
	}
}

freeselected()
{
	struct SelectedFile *next;


	while(filelist) {
		next = filelist->sf_next;
		free(filelist->sf_name);
		free(filelist);
		filelist = next;
	}
}

select1(lock, name, id)
BPTR lock;
char *name;
int id;
{
	struct SelectedFile *next, *ptr;

	if(!name)
		return 0;

	ptr = malloc(sizeof(struct SelectedFile));
	if(!ptr)
		return -1;
	ptr->sf_next = 0;
	ptr->sf_name = malloc(strlen(name)+1);
	if(!ptr->sf_name) {
		free(ptr);
		return -1;
	}
	strcpy(ptr->sf_name, name);
	if(!filelist)
		filelist = ptr;
	else {
		for(next = filelist; next->sf_next; next = next->sf_next)
			if(strcmp(name, next->sf_name) == 0) { /* already selected */
				free(ptr->sf_name);
				free(ptr);
				return 0;
			}
		next->sf_next = ptr;
	}
	return 0;
}

ready(lock, name, id)
BPTR lock;
char *name;
int id;
{
	if(name)
		select1(lock, name, id);
	return 1;
}

perror(s)
char *s;
{
	extern int errno;
	extern char *sys_errlist[];

	if(stdlog)
		fprintf(stdlog, "%s: %s\n", s, sys_errlist[errno]);
	else
		DisplayBeep();
}
