Ultrix-3.1/src/cmd/lpr/ulf.c

Compare this file to the similar file:
Show the results in this format:


/**********************************************************************
 *   Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.    *
 *   All Rights Reserved. 					      *
 *   Reference "/usr/src/COPYRIGHT" for applicable restrictions.      *
 **********************************************************************/


static char Sccsid[] = "@(#)ulf.c	3.0	4/21/86";
/*
 *
 * ulf -- Universal Lineprinter Filter
 *	  Written by Cliff Matthews, on April 7th, 1983 at the
 *	  University of New Mexico
 *
 * Supports:  diablo and dumb (LA180, LA120) "lineprinters"
 *
 * This program uses a "line_structure" that is a linked list of arrays to
 * hold enough characters for one physical line on the lineprinter.  The
 * first array contains the characters of the line, and all subsequent arrays
 * hold overprinting characters.  Blanks are left as zero's, so that they
 * don't have to be printed, just move the printhead whatever way is easiest.
 *
 */

#include	<stdio.h>
#include	<ctype.h>
#include	<errno.h>
#include	<sgtty.h>
#include	"lp.local.h"
#include	"globals.h"

#define	CONTROL		20	/* How many tolerable control characters */
#define	RPRINT		"\0336"	/* Make diablo print backword esc 6 */
#define	FPRINT		"\0335"	/* Make diablo print forward  esc 5 */

struct	line_s {
	char	*line;
	struct	line_s *next;
};

struct	line_s *makeline();

main(argc,argv)
int argc;
char *argv[];
{

	char c;				/* last character read */
	struct line_s *linepointer;	/* chars to print later */
	int loc;			/* current printing location */

	init(argv);
	linepointer = makeline();

	while ( (c = getchar()) != EOF ) {
		switch (c) {
		case ' ':			/* Space */
			loc++;
			break;

		case '\b':			/* Backspace */
			loc--;
			break;

		case '\t':			/* Tab */
			loc += 8 - (loc % 8);
			break;

		case '\n':			/* New Line */
			dumplines( linepointer );
			loc = 0;
			break;

		case '\r':			/* Carriage Return */
			loc = 0;
			break;

		case '\f':			/* Form Feed */
			dumplines( linepointer );
			loc = 0;
			throwpage();
			break;

		default:
			c &= 0177;			/* Turn off parity */
			if ((!isprint(c)) && NC )
				tossout();		/* Not Printable */
			else
				if (( loc >= 0) && ( loc <= width - 1))
					place( c, loc++, linepointer );
				else
					loc++;			/* off page */
		}
	}
	bill(user);
}

struct line_s *
makeline()	/* malloc up some memory for a line_structure */
{
	struct line_s *s;	/* memory allocated for the new line */
	char *cp;		/* scratch char pointer */
	char *end;		/* last legal array position for while loop */

	s = (struct line_s *) malloc(sizeof(struct line_s));
	if ( s == 0 )
		outofmemory();
	else {
		s->next = NULL;
		cp = s->line = malloc(width + 1);
		if ( s->line == 0)
			outofmemory();
		else {
			end = s->line + width;
			while ( cp < end )
				*cp++ = ' ';
			*cp = 0;
		}
	}
	return (s);
}

/* tossout: used to keep count of how many control
 * characters were being printed, and would puke if
 * too many were attempted, now just returns without
 * printing.  Doesn't keep count anymore.
 */
tossout()
{
	return;
}

place(c, location, p)	/* add a new character to a line_structure */
char c;			/* character to place */
struct line_s *p;	/* structure to put character in */
int location;		/* where in the line the character should go */
{
	char *cp;

	if (*(cp = (p->line + location)) != ' ') {
		if (p->next == NULL)
			p->next = makeline();
		place(c, location, p->next);
	} else
		*cp = c;
}

dumplines(p)		/* dump the top-level line_structure */
struct line_s *p;
{
	char *cp, *end;	/* scratch, and last legit array element */

	if (p->next != NULL)
		rdumpl(p->next);
	qprint(p->line);
	printf("\n");

	linenum++;
	if (linenum == length) {
		npages++;
		linenum = 0;
	}

	cp = p->line;
	end = cp + width;
	while ( cp < end )
		*cp++ = ' ';

	p->next = NULL;
}


rdumpl(p)		/* recursively dump the overprints */
struct line_s *p;
{
	if (p->next != NULL)
		rdumpl(p->next);
	qprint(p->line);
	free(p->line);
	free(p);
}

outofmemory()
{
	printf("%s: Out of Memory\n",invoke);
	exit(ENOMEM);
}

qprint(line)		/* print a line efficiently */
char *line;
{
	char *cp;		/* scratch character pointer */
/*	char *end; NOTUSED	/* last legitimate array position */
	int r,l;		/* right most character, leftmost */
	int i,j;		/* temporary values */

	cp = line + width - 1;
	while ( cp >= line && *cp == ' ')
		--cp;

	if ( cp < line )
		return;

	if (diablo) {
		r = cp - line;
/* NOTUSED	end = line + width;	*/
		cp = line;
		while ( *cp++ == ' ' );
		l = cp - line - 1;
		i = abs(printhead - l) + (2 * ((direction == FORWARD) ? 1 : -1));
		j = abs(printhead - r);
		if ( (printhead < l) || (i < j) ) {
			spaceto(l,FORWARD);
			pr(line,l,r);
		} else {
			spaceto(r,BACKWARD);
			pr(line,r,l);
		}

	} else {
		*++cp = '\0';
		printf("%s\r", line);
	}
}

spaceto( where, dir)
int where;			/* which column */
int dir;			/* which way to go afterward */
{
	if (where == 0) {
		putchar('\r');
		direction = FORWARD;	/* where else should we go */
	} else {
		if ( direction != dir ) {
			printf("%s", ( dir == FORWARD ) ? FPRINT : RPRINT );
			direction = dir;
		}
		if (printhead != where) {
			putchar('\033');	/* <esc><tab># gets you to # */
			putchar('\t');
			putchar((char)where+1);
		}
	}
	printhead = where;
}

pr(line,start,stop)	/* prints the characters from start to stop */
int start;		/* array index of first character */
int stop;		/* array index of last character */
char *line;		/* line to play with */
{
	char *end;		/* last character location to access */
	char *cp;		/* scratch character position */

	end = line + stop;
	cp = line + start;
	if (start < stop) {
		while ( cp <= end )
			putchar( *cp++ );
		printhead = stop+1;
	} else {
		while ( cp >= end )
			putchar( *cp-- );
		if ( printhead < 0 )
			printhead = 0;
		printhead = stop-1;
	}
}

throwpage()		/* toss a page */
{
	printf("%s",ff);
	npages++;
	linenum = 0;
}