[comp.sources.misc] v06i088: BOOK 4/10/89

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (04/24/89)

Posting-number: Volume 6, Issue 88
Submitted-by: tneff@lll-crg.llnl.gov@l.UUCP (Tom Neff)
Archive-name: book.lj

[By this time, everyone ought to have getopt -- it's in *both* Unix sources
group archives.

WARNING!!!  Feeding printed pages through a LaserJet a second time is a good
way to screw up its innards.  The first pass's printing tends to melt off onto
the rollers, which results in dark bands on the page... and an expensive bill
to get it cleaned; after doing this a few times you'll find it's cheaper to
get the new LaserJet which prints both sides.  Use this at your own risk.
++bsa]

One thing the README doesn't mention is that the following
uses getopt(3C).  My apologies to anyone who doesn't
have it, I plead laziness on little cusps like this. -- TMN

----------cut here----------cut here----------cut here----------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	Makefile
#	README
#	book.c
# This archive created: Mon Apr 10 13:25:25 1989
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
XCFLAGS=-O
XDESTDIR=/usr/local/bin
X
Xbook: book.c
X	cc $(CFLAGS) -o book book.c 
X	cp book $(DESTDIR)
X	strip $(DESTDIR)/book
SHAR_EOF
fi
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
XREADME
X
XThis is the 4/10/89 version of BOOK, a program to print documents in 
X"manual" style on an HP LaserJet Series II printer. BOOK uses both 
Xsides of the paper, two pages per side in "landscape" mode using the 
Xline printer font. The first pass prints one side of the paper, then 
Xyou remove the printed sheets from the "out" tray and stick them back 
Xinto the "in" tray for a second pass to print the other side. When 
Xyou're done you can fold and staple the listing to make a book, or 
Xcut and hole punch it for use in a standard 9" x 6" ring binder. 
X
XThe syntax is
X
X	book [ -t nnn ] [ -o file ] file [...]
X
Xwith these switches:
X
X	-t nnn	Sets logical tab width to nnn (default 8).  BOOK
X		expands tabs to spaces rather than relying on the
X		LaserJet's tabbing.
X
X	-o file	Directs output to the specified file.  The default
X		is the standard output.
X
XYou can specify as many files as you want - BOOK will prompt you 
Xbetween each file so you can remove the previous listing from the 
X"out" tray. 
X
XIf a document is one page or less in length, BOOK will not pause 
Xbetween the first and second passes, but will simply print the one 
Xside and go on to the next file (if any). 
X
XThere have been several of these programs published in the past year 
Xfor MS-DOS systems, but I hadn't seen anything for generic C and UNIX 
Xso I decided to write my own. BOOK was written to compile and run on 
XSystem V - if someone wants to patch it for BSD please mail the patch 
Xto me at tneff@well.UUCP and I'll publish a dual compatible version. 
X
XBOOK was inspired by Vern Buerg's MS-DOS utility LJBOOK, and I want to 
Xexpress my gratitude to him for all his excellent stuff. 
X
X--
XTom Neff			tneff@well.UUCP
SHAR_EOF
fi
if test -f 'book.c'
then
	echo shar: "will not over-write existing file 'book.c'"
else
sed 's/^X//' << \SHAR_EOF > 'book.c'
X/*
X *	book.c		April 10, 1989
X *
X *	Print documents on 5.5" by 8.5" pages both sides of the
X *	paper, using an HP Laserjet Series II.
X *
X *	Author: Tom Neff
X *
X *	Written for UNIX System V.
X *
X *		To compile:
X *
X *			cc -O book.c -o book
X *
X *	Inspired by Vern Buerg's LJBOOK.
X *
X *	 4/10/89	change default tabs to 8;
X *				handle one-page docos without pausing
X */
X
X#include <string.h>
X#include <stdio.h>
X
X#define FF '\014'
X#define MAXPAGES 1000
X#define MAXROWS 66
X#define MAXCOLS 128
X#define DEFAULTTABS 8
X
X#define tolpt(x) fputs(x, lpt)
X
Xstatic FILE *docf;
Xstatic FILE *lpt = stdout;
X
Xstatic long pagebrks[MAXPAGES];
Xstatic char linbuf[MAXCOLS];
X
Xstatic int nsheets, nhalves, ndocpgs;
Xstatic int row;
Xstatic int lpage, rpage;
X
Xstatic int tabsize=DEFAULTTABS;
X
Xstatic char *PINIT="\033&l1ol8d1e67f5.5C\033(s0p16.66h8.5v0d0b0t1Ci\r";
Xstatic char *PRIGHT="\0339\033&a1r96l178M\r";
Xstatic char *PLEFT="\0339\033&a1ra0la89M\r";
X
X	/*  Send a filtered line to the output stream  */
X
Xljline(source)
Xchar *source;
X{
X	char *s = source;
X	int col = 0;
X	register char c;
X	char dest[MAXCOLS], *d = dest;
X
X#define give(c)	*d++=c, col++
X
X	do
X	{
X		c=*s++;
X
X		if (c=='\n')
X		{
X			give('\r');
X			give('\n');
X		}
X		else if ((c=='\b') && (col > 0))
X			d--, col--;
X		else if (c=='\t')
X		{
X			give(' ');
X			while ((col % tabsize) != 0)
X				give(' ');
X		}
X		else if (c >= ' ')
X			give(c);
X	} while (c != '\0');
X
X	*d++=0;
X	tolpt(dest);
X}
X
X	/*  Send a page of text to the left or right page  */
X
Xdopage(page, inits)
Xint page;
Xchar *inits;
X{
X	char *p;
X
X	tolpt(inits);
X	if (page >= ndocpgs)
X		return;
X
X	fseek(docf, pagebrks[page], 0);
X	for (row=0; row < MAXROWS; row++)
X	{
X		if (fgets(linbuf, sizeof(linbuf), docf) == NULL)
X			break;
X
X		while ((p=strchr(linbuf, FF)) != NULL)
X			*p = (char) ' ';			/*  filter formfeeds  */
X
X		if (strchr(linbuf, '\r') == NULL)		/*  Add CR's  */
X		{
X			if ((p = strchr(linbuf, '\n')) != NULL)
X			{
X				*p = '\r';
X				*++p = '\n';
X				*++p = '\0';
X			}
X		}
X
X		ljline(linbuf);
X	}
X}
X
X	/*  Print an entire file in two passes.  */
X
Xbookfile(path)
Xchar *path;
X{
X	fprintf(stderr, "\nReady to print %s\n", path);
X
X	/*  make a pass and learn where the page breaks are  */
X
X	if ((docf = fopen(path, "r")) == NULL)
X	{
X		fprintf(stderr, "Error opening %s!\n", path);
X		return;
X	}
X
X	fseek(docf, 0, 0);
X	ndocpgs = 0;
X
X	while ((!feof(docf)) && (ndocpgs < MAXPAGES))
X	{
X		row = 0;
X		pagebrks[ndocpgs] = ftell(docf);
X		ndocpgs++;
X
X		while (row++ < MAXROWS)
X		{
X			if (fgets(linbuf, sizeof(linbuf), docf) == NULL)
X				break;
X
X			if (strchr(linbuf, FF) != NULL)
X				break;
X		}
X
X		if (feof(docf))
X			break;
X	}
X
X	nsheets = (ndocpgs+3)/4;
X	nhalves = nsheets*4;
X
X	fprintf(stderr, "%d sheets to print...\n", nsheets);
X
X	/*  Now let's print the first pass  */
X
X	tolpt(PINIT);
X
X	for (rpage=0, lpage=nhalves-1;
X		rpage < lpage;
X		rpage+=2, lpage-=2)
X	{
X		dopage(lpage, PLEFT);
X		dopage(rpage, PRIGHT);
X
X		fputc(FF, lpt);
X	}
X
X	if (nhalves > 1)
X	{
X		fflush(lpt);
X
X		fprintf(stderr,"\nReady to print the other side.\n");
X		fprintf(stderr,"\nRemove paper and place it back in the in-tray.\n");
X		fprintf(stderr,"Press ENTER when ready: ");
X		gets(linbuf);
X
X		/*  The second pass  */
X
X		tolpt(PINIT);
X
X		for (rpage=nhalves/2, lpage=rpage-1; lpage >= 0; rpage+=2, lpage-=2)
X		{
X			dopage(lpage, PLEFT);
X			dopage(rpage, PRIGHT);
X
X			fputc(FF, lpt);
X		}
X	}
X
X	/*  Done with this file  */
X
X	fclose(docf);
X	fflush(lpt);
X
X	fprintf(stderr,"Done printing %s\n", path);
X}
X
X	/*  The command mainline. */
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	int c;
X	int errflg = 0;
X
X	extern char *optarg;
X	extern int optind;
X
X	/*  Collect option switches  */
X
X	while ((c=getopt(argc, argv, "o:t:?")) != -1)
X		switch (c) 
X		{
X		case 'o':
X			if ((lpt=fopen(optarg, "w")) == NULL)
X			{
X				fprintf(stderr, "Error opening %s\n", optarg);
X				exit(1);
X			}
X			break;
X		case 't':
X			if ((tabsize=atoi(optarg)) == 0)
X				errflg++;
X			break;
X		default:
X			errflg++;
X		}
X
X	/*  Validate args and print usage message if bad  */
X
X	if (argc < 2)
X		errflg++;
X
X	if (errflg)
X	{
X		fprintf(stderr, "Usage: book [-o outfile] [-t tabsize] file ...\n");
X		exit(1);
X	}
X
X	/*  Now read file args and print them  */
X
X	for ( ; optind < argc; optind++)
X	{
X		bookfile(argv[optind]);
X
X		if (optind+1 < argc)
X		{
X			fprintf(stderr,"Press ENTER when ready for next file: ");
X			gets(linbuf);
X		}
X	}
X}
SHAR_EOF
fi
exit 0
#	End of shell archive
-- 
Tom Neff                  tneff@well.UUCP
                       or tneff@dasys1.UUCP