/*
 *	$Source: /usr/src/local/packages/djlpf/RCS/djlpf.c,v $
 *	$Author: jtk $
 *	$Id: djlpf.c,v 1.9 1994/02/24 00:05:50 jtk Exp $
 */

#ifndef lint
static
#ifdef __STDC__
const
#endif
char rcsid_djlpf_c[] = "$Id: djlpf.c,v 1.9 1994/02/24 00:05:50 jtk Exp $";
#endif /* lint */

/*
 * Copyright (c) 1983 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1983 Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)lpf.c	5.4 (Berkeley) 6/1/90";
#endif /* not lint */

/*
 * 	filter which reads the output of nroff and converts lines
 *	with ^H's to overwritten lines.  Thus this works like 'ul'
 *	but is much better: it can handle more than 2 overwrites
 *	and it is written with some style.
 *	modified by kls to use register references instead of arrays
 *	to try to gain a little speed.
 */
/*
 *	Hacked to pieces by John Kohl <jtk@kolvir.blrc.ma.us> to
 *	convert into fancy filter for Hewlett-Packard DeskJet 500
 *	(should also work for other HP PCL printers, except perhaps
 *	for the 'text scale' thing below (see portrait code below)

(much of the text width/length stuff inspired by printcap hackery from
	blknowle@frodo.jdssc.dca.mil (Brad L. Knowles)
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif

#define MAXWIDTH  210
#define MAXREP    10

char	buf[MAXREP][MAXWIDTH];
int	maxcol[MAXREP] = {-1};
int	lineno;
int	width = 132;	/* default line length */
int	length = 66;	/* page length */
int	indent;		/* indentation length */
int	npages = 0;
int	literal;	/* print control characters */
char	*name;		/* user's login name */
char	*host;		/* user's machine name */
char	*acctfile;	/* accounting information file */

main(argc, argv) 
	int argc;
	char *argv[];
{
	register FILE *p = stdin, *o = stdout;
	register int i, col;
	register char *cp;
	int opt;
	int done, linedone, maxrep;
	char ch, *limit;
	int lq;
	
#define NAME argv[0]

	/* look at NAME to select anything weird */
	if (cp = strrchr(NAME, '/'))
	    cp++;
	else
	    cp = NAME;
	if (!strcmp(cp, "djlqpf"))	/* LQ == letter quality */
	    lq = 1;
	else
	    lq = 0;

	while ((opt = getopt(argc, argv, "n:h:w:l:i:c")) != EOF)
	    switch(opt) {
	    case 'n':
		name = optarg;
		break;
	    case 'h':
		host = optarg;
		break;
	    case 'w':
		i = atoi(optarg);
		if (i > 0) {
		    i = MIN(i, MAXWIDTH);
		    width = i;
		}
		break;
	    case 'l':
		length = atoi(optarg);
		break;
	    case 'i':
		indent = atoi(optarg);
		break;
	    case 'c':	/* Print control chars */
		literal++;
		break;
	    }
	argc -= optind;
	argv += optind;
	if (argc)
	    acctfile = argv[0];

	for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' ');
	done = 0;
	
	/* preamble:  send init string to printer to put into
	   our preferred font mode.
	   ESC E		reset
	   */

	fputs("\033E", o);
	if (literal) {
	    /* if we're being literal, just send the output along */
	    char line[BUFSIZ];
	    int cc;
	    npages++;			/* give up on counting... */
	    while ((cc = fread(line, sizeof(*line), sizeof(line)/sizeof(*line), p)) > 0) {
		fwrite(line, sizeof(*line), cc, o);
	    }
	} else {


	    if (length == 48) {
		/* ESC &l1O		landscape */
		/* ESC &l6D		6 li/in */
		/* ESC &l48P		48 li/pg */
		/* ESC &l0L		perf skip off */
		fputs("\033&l1o6d48p0L",o);
		if (width <= 51)
		    fputs("\033(s5H",o); /* 5 CPI=52 cols */
		else if (width > 51 && width <= 103)
		    /* nothing; printer default is 10 CPI */;
		else if (width > 103 && width <= 172)
		    fputs("\033(s16.67H",o); /* 16.67 CPI = 172 cols */
		else
		    fputs("\033(s20H",o);	/* 20 CPI = 210 cols */
	    } else {
		/* ESC &l0O		portrait */
		/* ESC &l6D		6 li/in */
		/* ESC &l66P		66 li/pg */
		/* ESC &l0L		perf skip off */
		/* ESC &k6W		text scaling mode to squeeze 66
		   			lines onto page */
		fputs("\033&l0o7D",o);
		if (length > 48 && length < 66)
		    /* can't fit more than 66 in portrait mode */
		    fprintf(o, "\033&l%dP", length);
		else
		    fputs("\033&l66P", o);
		fputs("\033&l0L", o);
		if (length > 63)
		    fputs("\033&k6W",o); /* text scaling mode */

		if (width <= 40)
		    fputs("\033(s5H",o); /* 5 CPI=40 cols */
		else if (width > 40 && width <= 80)
		    /* nothing; printer default is 10 CPI */;
		else if (width > 80 && width <= 96)
		    fputs("\033(s12h6T",o); /* 12 CPI = 96 cols;
					    use Letter Gothic */
		else if (width > 96 && width <= 132)
		    fputs("\033(s16.67H",o); /* 16.67 CPI = 132 cols */
		else
		    fputs("\033(s20H",o); /* 20 CPI = 160 cols */
	    }
	    /* ESC &k2G		carriage control (lf=crlf, cr=cr, ff=crff) */
	    fputs("\033&k2G", o);

	    if (lq)
		fputs("\033(s2Q",o);	/* ESC (s2Q	letter quality mode */
	    else {
		/* ESC (s1Q	draft quality mode */
		/* ESC &k1W		bidirectional (draft only) */
		fputs("\033(s1Q\033&k1W",o);
	    }
	
	    while (!done) {
		col = indent;
		maxrep = -1;
		linedone = 0;
		while (!linedone) {
		    switch (ch = getc(p)) {
		    case EOF:
			linedone = done = 1;
			ch = '\n';
			break;

		    case '\f':
			lineno = length;
		    case '\n':
			if (maxrep < 0)
			    maxrep = 0;
			linedone = 1;
			break;

		    case '\b':
			if (--col < indent)
			    col = indent;
			break;

		    case '\r':
			col = indent;
			break;

		    case '\t':
			col = ((col - indent) | 07) + indent + 1;
			break;

		    default:
			if (col >= width || !literal && ch < ' ') {
			    col++;
			    break;
			}
			cp = &buf[0][col];
			for (i = 0; i < MAXREP; i++) {
			    if (i > maxrep)
				maxrep = i;
			    if (*cp == ' ') {
				*cp = ch;
				if (col > maxcol[i])
				    maxcol[i] = col;
				break;
			    }
			    cp += MAXWIDTH;
			}
			col++;
			break;
		    }
		}

		/* print out lines */
		for (i = 0; i <= maxrep; i++) {
		    for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) {
			putc(*cp, o);
			*cp++ = ' ';
		    }
		    if (i < maxrep)
			putc('\r', o);
		    else
			putc(ch, o);
		    if (++lineno >= length) {
			fflush(o);
			npages++;
			lineno = 0;
		    }
		    maxcol[i] = -1;
		}
	    }
	    if (lineno && !literal) {
	        /* be sure to end on a page boundary */
		putchar('\f');
		npages++;
	    }
	}
	if (name && acctfile && access(acctfile, 02) >= 0 &&
	    freopen(acctfile, "a", stdout) != NULL) {
		printf("%7.2f\t%s:%s\n", (float)npages, host, name);
	}
	exit(0);
}
