/* pt.C		Generalized random-file printer ********************************

	(C) 1982,1983 Perfect Software, Inc.

This program prints an ASCII file using the definitions in PF.DAT. 
*****************************************************************************/

#include "pp.h"

#define MAXTABS	32		/* max # of tabs */
struct {
	MICA tabcolumns[MAXTABS];/* where tabs are */
	MICA headerspace;		/* vertical space to leave after header */
	MICA footerspace;		/* and before footer */
	char prefjust;			/* preferred justification style
							'b' both  or  'l' left */
	char footstyle;		/* where footnotes go:  'i' inline,
							'b' bottom, 'e' end */
	MICA indent;			/* amount to indent paragraphs */
	MICA spread;			/* number of lines between paragraphs */
	MICA linespacing;
	FLAG footpush;			/* footnote references */
	FLAG scriptpush;		/* do supper/sub scripts get more space */
	FLAG ischapter;		/* does @chapter command exist */
	MICA stop;			/* margins */
	MICA sleft;
	MICA sright;
	MICA sbottom;
	MICA above;			/* space to leave before an environment */
	MICA below;			/* space to leave after an environment */
	FLAG levindent;		/* do nested Level environments indent? */
	FLAG levhang;			/* are Level paragraphs outdented? */
	int endsize;			/* space to reserve for enddata */
	} scribrec;


char *devname;				/* device to print on */
int headingp;				/* print heading on each page? */
int leftmar, rightmar;		/* text margins */
int cleftmar, crightmar;		/* margins as entered from command line */
int perfskip;				/* amount to skip around page perfs */



main (argc, argv)
	int argc;
	char **argv;
{
	int ntimes, itab, iarg, tabwidth;
	char *optname;
	struct {
		char *fname;
		int fntimes;
		} files[20];
	int nfiles;
	
	dskreset();
	printf("Perfect Typer Version %s\n", VERSION);
	printf("(C) 1982 Perfect Software, Inc.\n");
	ntimes = 1;
	nfiles = 0;
	pausep = FALSE;
	title = "";
	portname = DEFAULT;
	devname = DEFAULT;
	quietp = TRUE;
	startpage = 1;
	headingp = FALSE;
	leftmar = 8;							/* XXX */
	rightmar = 0;							/* XXX */
	cleftmar = crightmar = -1;
	perfskip = 3;
	tabwidth = DEFAULT;
	for (iarg = 1; iarg < argc; ++iarg) {
		if (*argv[iarg] == '-') {
			optname = argv[iarg] + 1;
			if(isdigit(*optname))
				stcd_i(optname, &ntimes);
			else if(match (optname, "Dev")){
				devname = argv[++iarg];
				if (!quietp)
					printf ("Using the '%s' device.\n", devname);
			}
			else if(match(optname,"Version")){
				printf("Version %s as of %s\n", VERSION, DATE);
			}
			else if(match (optname, "L") ||  match(optname, "Left")){
				stcd_i(argv[++iarg], &cleftmar);
				if(*argv[iarg] == '+' || *argv[iarg] == '-'){
					cleftmar += leftmar;
					cleftmar = (cleftmar < 0 ? 0 : cleftmar);
				}
				if (!quietp)
					printf("Left margin set to %d characters.\n",
						cleftmar);
			}
			else if(match(optname, "H") || match(optname, "Heading")){
				if(!quietp)
					puts("Printing page headings.\n");
				headingp = TRUE;
			}
			else if(match(optname, "NS") || match(optname, "NoSkip")){
				if (!quietp)
					puts("Not skipping page perforations.\n");
				perfskip = 0;
			}
			else if(match (optname, "Page")){
				stcd_i(argv[++iarg], &startpage);
				if (!quietp)
					printf("Starting at page %d.\n", startpage);
			}
			else if(match (optname, "Pause")){
				pausep = TRUE;
				puts("Pausing for manual insertion of each page.\n");
			}
			else if(match (optname, "Port")){
				portname = argv[++iarg];
				if (!quietp) 
					printf ("Using the '%s' port(s).\n", portname);
			}
			else if(match(optname, "V") || match(optname, "Verbose"))
				quietp = FALSE;
			else if(match(optname, "R") || match(optname, "Right")){
				stcd_i(argv[++iarg], &crightmar);
				if(*argv[iarg] == '+' || *argv[iarg] == '-'){
					crightmar += rightmar;
					crightmar = (crightmar < 0 ? 0 : crightmar);
				}
				if (!quietp)
					printf("Right margin set to %d characters.\n",
						crightmar);
			}
			else if(match(optname, "Tab") || match(optname, "Tabs")){
				stcd_i(argv[++iarg], &tabwidth);
				if(!quietp)
					printf("Tab stops set every %d characters.\n",
						tabwidth);
			}
			else if(match(optname, "T") || match(optname, "Title")){
				title = argv[++iarg];
				if(!quietp)
					printf("Title string is '%s'.\n", title);
			}
			else printf("Unknown command line option: '%s'\n",
					   argv[iarg]);
		}
		else {
			files[nfiles].fname = argv[iarg];
			files[nfiles].fntimes = ntimes;
			++nfiles;
		}
	}
	if (((datfd = open ("pf.dat", INPUT | 0x8000)) < 0	/* XXX */
	    && (datfd = open ("a:pf.dat", INPUT|0x8000)) < 0))	/* XXX */
		Fatal ("Can't open the system database file (PF.DAT)\n");
	lseek (datfd, 2 * 128, ABSOLUTE);			/* XXX */
	read (datfd, tsect, 128);				/* XXX */
	movmem (tsect, &scribrec, sizeof (scribrec));
	close (datfd);
	if (tabwidth != DEFAULT)
		for (itab = 0; itab < MAXTABS; ++itab)
			scribrec.tabcolumns[itab] = itab * tabwidth;
	for (iarg = 0; iarg < nfiles; ++iarg)
		if (PrintFile (files[iarg].fname, files[iarg].fntimes) == ABORTALL)
			break;
	menu((nfiles > 0 ? files[0].fname : ""));
	}


PrintFile (fname, ntimes)
	char *fname;
	int ntimes;
{
	char c;
	FLAG done;
	
	if (IOpen (fname, INPUT | 0x8000) < 0) {
		printf ("Can't open input file '%s'.\n", fname);
		return;
		}
	if (!quietp) {
		if (ntimes == 1)
			printf ("Printing '%s' -- OK? ", fname);
		else printf ("Printing %d copies of '%s' -- OK? ", ntimes, fname);
		fflush(stdout);					/* XXX */
		if (!Ask ("")) {
			puts (" -- skipping file.\n\n");
			return (ABORTFILE);
			}
		}
	PInit (devname, portname, !pausep);
	if (cleftmar == -1) leftmar = PUnMica (scribrec.sleft, HORIZONTAL);
	else leftmar = cleftmar * PCharH();
	if (crightmar == -1) rightmar = PUnMica (scribrec.sright, HORIZONTAL);
	else rightmar = crightmar * PCharH();
	if (PVPos() != 0) {
		FileHeader();
		PFF();
		}
	done = FALSE;
	while (ntimes-- > 0  &&  !done) {
		curpage = 0;
		NextPage();
		DoChar (CR);
		while (!done  &&  IChar() !=CPM_EOF) {
			DoChar (IChar());
			if (TKbRdy()) switch (c = TGetKb()) {
			
			case ABORTFILE:
				puts ("\nAborting this file.\n");
				done = c;
				break;
			case ABORTALL:
				puts ("\nAborting all files.\n");
				done = c;
				break;
			case EXIT:
				menu(fname);
			default:
				break;
				}
			INext();
			}
		IRew();
		PNewPage();
		}
	PFini();
	IClose();
	return (done);
	}


FileHeader()				/* print file header */
{
	int inch;
	
	inch = PUnMica (2540, HORIZONTAL);
	PMoveH (inch);
	PPrtStr (IName ());
	PMoveH (inch / 2);
	PPrtStr (title);
	PCR();
	PMoveV (PLineV());
	PMoveH (inch * 2);
	PPrtStr ("Perfect Typer ");	/* vsn of this prog. */
	PPrtStr (VERSION);
#ifdef ALPHA
	PPrtStr(ALPHA);
#endif
	PCR();
	}


NextPage()				/* process page boundary */
{
	int prevh;
	
	++curpage;
	if (!quietp) printf (" %d", curpage);
	prevh = PHPos();
	PCR();
	PNewPage();
	if (pausep) PagePause();
	if (headingp  &&  perfskip > 0) {
		if (perfskip >= 3) PLF();
		PageHeader();
		}
	PMoveV (perfskip * PLineV() - PVPos());
	PMoveH (prevh);
	}


DoChar (ochar)				/* process a char */
	char ochar;
{
	int itab;
	
	switch (ochar) {
	
	case BS:
		PMoveH (-PCharH());
		break;
	case TAB:
		for (itab = 0; itab < MAXTABS; ++itab)
			if (scribrec.tabcolumns[itab] * PCharH() + leftmar > PHPos()) {
				PMoveH (scribrec.tabcolumns[itab] * PCharH()
					   + leftmar - PHPos());
				break;
				}
		if (itab >= MAXTABS) PMoveH (PCharH());
		break;
	case FF:
		PFF();
		NextPage();
		break;
	case CR:
		PCR();
		PMoveH (leftmar);
		break;
	case LF:
		PLF();
		if (PVPos() >= PPageV() - perfskip * PLineV()) NextPage();
		break;
	default:
		if (PHPos() + PWidChar (ochar) > PPageH() - rightmar) {
			DoChar (CR);
			DoChar (LF);
			}
		PPrtChar (ochar);
		break;
		}
	}


PageHeader()				/* print the page header */
{
	char str[80], *c;
	int len;
	
	PMoveH (leftmar);
	PSetAttr (UNDERSCORE, UNNBON);
	sprintf (str, "Page: %d", curpage);
	PPrtStr (str);
	PMoveH ((PPageH() - PWidStr (title) - rightmar + leftmar) / 2 - PHPos());
	PPrtStr (title);
	sprintf (str, "File: %s", IName());
	PMoveH (PPageH() - PWidStr (str) - rightmar - PHPos());
	PPrtStr (str);
	PSetAttr (UNDERSCORE, FALSE);
	PCR();
	}


/* End of pt.C  --  print a standard ASCII file */
