/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*  page [-h<h>] [-f<f>] [-p<p>] [file]...
*
* Paginate a text into pages of <p> lines each, with a <h>-line header
* and a <f>-line footer on each page.  Note that page length refers to
* the number of lines of text on a page, not the  total  page  length.
* The total page length will be <h>+<p>+<f>.
*
* The options may start with a '+', meaning:
*    +h  means an initial header on the first page.
*    +f  means a final footer on the last page.
*    +p  means an initial page eject for the first page.
*
* The defaults are:
*    +h5
*    -f5
*    +p56
*
* BUGS:
*   This program doesn't understand the  concept  of  wraparound  (for
*   long lines), and so long lines may screw up its output for devices
*   that do wraparound.  To fix this properly, we  need  to  add  such
*   things as a page-width option and a way to set tab stops.
*
* AUTHOR: John Chambers
*   <jc@trillian.mit.edu>
*/
#include "V.h"

#define INBUF 1000

char inbuf[INBUF];

int files = 0;	/* Files processed so far (including current file) */
int pages = 0;	/* Pages written so far */
int lines = 0;	/* Lines written to the current page */

int flength= 5;	/* Length of footer */
int hlength= 5;	/* Length of header */
int plength= 5;	/* Length of page */

int finalf = 0;	/* Final footer */
int inithf = 1;	/* Initial header */
int initpf = 1;	/* Initial page */

void onefile();

main(ac,av)
	char**av;
{	int   a;

#if DEBUG > 0
	Vinit(ac,av);
#endif
	for (a=1; a<ac; a++) {
		switch (av[a][0]) {
		  case '-':
		  case '+':
			switch (av[a][1]) {
#if DEBUG > 0
			  case 'd':
			  case 'D':
				Vopt(av[a]+2);
				V2 "Debug   level:%3d.",Vlvl D;
				break;
#endif
			  case 'f':
			  case 'F':
				if (sscanf(av[a]+2,"%d",&flength) < 1)
					flength = 5;
				finalf = (av[a][0] == '+');
#if DEBUG > 0
				V2 "Footer length:%3d.",flength D;
#endif
				break;
			  case 'h':
			  case 'H':
				if (sscanf(av[a]+2,"%d",&hlength) < 1)
					hlength = 5;
				inithf = (av[a][0] == '+');
#if DEBUG > 0
				V2 "Header length:%3d.",hlength D;
#endif
				break;
			  case 'p':
			  case 'P':
				if (sscanf(av[a]+2,"%d",&plength) < 1)
					plength = 66;
				initpf = (av[a][0] == '+');
#if DEBUG > 0
				V2 "Page   length:%3d.",plength D;
#endif
				break;
			  default:
				fprintf(stderr,"Unknown option \"%s\" ignored.\n",av[a]);
				break;
			}
			break;
		  default:
			onefile(av[a]);
			break;
		}
	}
	if (files <= 0)
		onefile(0);
	exit(0);
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*	Process one file.  If no name is given, we read standard input.
*	All output goes to standard output.
*/
void onefile(fname)
	char *fname;
{	FILE *fp;
	int   i;

	++files;
	if (fname) {
		if (!(fp = fopen(fname,"r"))) {
			fprintf(stderr,"Can't read \"%s\"\n",fname);
			return;
		}
#if DEBUG > 0
		V3 "Read \"%s\"",fname D;
#endif
	} else {
#if DEBUG > 0
		V3 "Read standard input." D;
#endif
		fp = stdin;
	}
	if (initpf) {
		putchar('\f');				/* First page eject */
		pages++;
		lines = 0;
	}
	for (i=0; i<hlength; i++)		/* First header */
		putchar('\n');
	while (fgets(inbuf,INBUF,fp)) {
		if (++lines > plength) {	/* Full page? */
			for (i=0; i<flength; i++)
				putchar('\n');		/* Footer */
			putchar('\f');			/* Page eject */
			pages++;
			lines = 1;
			for (i=0; i<hlength; i++)
				putchar('\n');		/* Header */
		}
		fputs(inbuf,stdout);
	}
	if (finalf) {
		for (i=0; i<flength; i++)
			putchar('\n');			/* Final footer */
		lines += flength;
	}
	fclose(fp);
}
