🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: net.text
Article #790

Re: Looking for nroff tables for HP LaserJet

#790
From: Wayne A. Christopher
Date: Mon, 24 Feb 1986 18:29
1477 lines
29565 bytes
I have ditroff width tables for the Times Roman cartridge -- I hope you can
make use of them.  I measured the characters by hand, so I don't have anything
for the other cartidges (it's a lot of trouble).  I'm also including a
simple-minded ditroff filter for the laserjet, and other things that should
be all you need to set up a laserjet, software-wise... This stuff is full
of bugs which I don't have time to fix, so I would be happy to get any bug
fixes.

The diff file is for /usr/src/usr.lib/lpr/filters/lpf.c.

	Wayne

--

# The rest of this file is a shell script which will extract:
# Makefile ljf.c.diff ljfd.c width.c pagereverse.c DESC R I B
echo x - Makefile
cat >Makefile <<'!Funky!Stuff!'
# Makefile for ljfd and ljf

CC =		cc

CFLAGS =	-g

CFILES =	ljfd.c ljf.c width.c pagereverse.c

OFILES =	ljfd.o ljf.o width.o pagereverse.o

HFILES =

all:		ljf ljfd desc/DESC.out pagereverse

ljfd:           ljfd.o width.o
		$(CC) $(CFLAGS) ljfd.o width.o -o ljfd

ljf:		ljf.o
		$(CC) $(CFLAGS) ljf.o -o ljf

pagereverse:	pagereverse.o
		$(CC) $(CFLAGS) pagereverse.o -o pagereverse

desc/DESC.out:	desc/DESC desc/I desc/R desc/B
		(cd desc; ./devconfig DESC; cd ..)

ctags:
		ctags $(CFILES) $(HFILES)

!Funky!Stuff!
echo x - ljf.c.diff
cat >ljf.c.diff <<'!Funky!Stuff!'
18,20d17
<  *
<  * >>>  This version is modified for the HP laserjet, and does tab
<  * >>>  expansion and page reversal.
29,32d25
< #define PAGEREVERSE "/usr/local/pagereverse"
< 
< #define NLINES 66	/* This is bad, but that's life. */
< 
49,50c42
< 	register FILE *p = stdin, *o = stdout, *tf;
< 	FILE *fopen();
---
> 	register FILE *p = stdin, *o = stdout;
55d46
< 	char *mktemp(), *tempf = "/tmp/ljXXXXXX";
91,96d81
< 	tempf = mktemp(tempf);
< 	if (!(tf = fopen(tempf, "w"))) {
< 		/* Well, let's not die horribly... */
< 		tf = stdout;
< 	}
< 	initlj();
172,176c157
< 				if (*cp == '\n') {
< 					putc('\r', tf);
< 					putc('\n', tf);
< 				} else
< 					putc(*cp, tf);
---
> 				putc(*cp, o);
179,185c160,163
< 			if (i < maxrep) {
< 				putc('\r', tf);
< 			} else if (ch == '\n') {
< 				putc('\r', tf);
< 				putc('\n', tf);
< 			} else
< 				putc(ch, tf);
---
> 			if (i < maxrep)
> 				putc('\r', o);
> 			else
> 				putc(ch, o);
187c165
< 				fflush(tf);
---
> 				fflush(o);
194,200c172,174
< 
< 	/* Now take the temp file and run it through pagereverse. */
< 	if (tf != stdout) {
< 		fclose(tf);
< 		sprintf(buf, "%s < %s", PAGEREVERSE, tempf);
< 		system(buf);
< 		unlink(tempf);
---
> 	if (lineno) {		/* be sure to end on a page boundary */
> 		putchar('\f');
> 		npages++;
202d175
< 
209,226d181
< 
< /* Initialize the laserjet -- make sure that the lpr font is current. */
< 
< initlj()
< {
< 	/* Get the right font.  */
< 	printf("\033E\033&l0O\033(8U\033(s0p10h12v0s0b3T");
< 
< 	/* Set page length -- see page 4-28 of the lj manual. */
< 	printf("\033&l14c1e7.64c66F");
< 
< 	/* Set the left margin. */
< 	printf("\033&a2L");
< 
< 	fflush(stdout);
< 	return;
< }
< 
!Funky!Stuff!
echo x - ljfd.c
cat >ljfd.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: 1.1 $ on $Date: 85/10/29 14:44:27 $
 *           $Source: /cad4/faustus/src/laserjet/RCS/ljfd.c,v $
 * Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * Ditroff driver for the hp laserjet. Much of this is generic, and for
 * many printers only a few lines in each routine need be changed to
 * get something that works...
 */

#include <stdio.h>
#include <ctype.h>

extern char *tmalloc(), *copy();

#define eq(a,b)     (!strcmp((a), (b)))
#define prefix(p, s)    (!strncmp((p), (s), strlen(p)))
#define alloc(strname)  ((struct strname *) tmalloc(sizeof(struct strname)))

int pagereverse = 0;

struct command {
	char *c_line;			/* NULL terminated, no newline. */
	struct command *c_next;
	struct command *c_prev;
	struct command *c_nextpage;	/* If this is a 'p' line... */
	struct command *c_prevpage;
} ;

/* Stuff to describe the state of the page. */

int hpos, vpos;
int hmax, vmax;
int curfont, cursize;
int maxfont, maxsize;
int curpage;
int debug = 0;
int wordspace = 0;

main(ac, av)
	char **av;
{
	char buf[BUFSIZ];
	struct command *coms, *cc, *tr = NULL, *lp = NULL, *readcoms();

	if (eq(av[1], "-d"))
		debug = 1;
	else if (eq(av[1], "-D"))
		debug = 2;

	startup();

	/* Gather up all the commands first. */
	coms = readcoms(stdin);

	/* if (debug) printcoms((int) coms); */

	/* Do commands until we get to a 'p' line... */
	for (cc = coms; cc && (*cc->c_line != 'p'); cc = cc->c_next)
		doline(cc->c_line);

	/* Now print the pages out in the proper order. */
	if (pagereverse) {
		while (cc->c_nextpage)
			cc = cc->c_nextpage;
		do {
			doline(cc->c_line);
			lp = cc;
			cc = cc->c_next;
			while (cc && (*cc->c_line != 'p') &&
					!prefix("x trailer", cc->c_line)) {
				doline(cc->c_line);
				cc = cc->c_next;
			}
			if (prefix("x trailer", cc->c_line))
				tr = cc;
			cc = lp;
			if (cc)
				cc = cc->c_prevpage;
			else
				break;
		} while (cc);
		if (tr)
			while (tr) {
				doline(tr->c_line);
				tr = tr->c_next;
			}
		else
			fprintf(stderr, "Warning: no x trailer!\n");
	} else {
		while (cc) {
			doline(cc->c_line);
			cc = cc->c_next;
		}
	}

	cleanup();
	exit(0);
}

/* Read in commands, filtering out comments and breaking up multiple
 * commands on one line. This is really bad -- ditroff should be more
 * nice to us.
 */

struct command *
readcoms(fp)
	FILE *fp;
{
	struct command *comm = NULL, *last = NULL, *prevpage = NULL;
	char *s, *getcom();

	while (s = getcom(fp)) {
		if (comm) {
			last->c_next = alloc(command);
			last->c_next->c_prev = last;
			last = last->c_next;
		} else {
			last = comm = alloc(command);
		}
		last->c_line = s;
		if (*s == 'p') {
			/* Link this one and prevpage together. */
			if (prevpage) {
				prevpage->c_nextpage = last;
				last->c_prevpage = prevpage;
			}
			prevpage = last;
		}
	}
	return (comm);
}

char *
getcom(fp)
	FILE *fp;
{
	static char buf[BUFSIZ] = "";
	char wbuf[BUFSIZ];
	static int i = 0;
	register char *s, *t;
	register int j = 0;

new:	while (!buf[i] || (buf[0] == '#')) {
		if (!fgets(buf, BUFSIZ, fp))
			return (NULL);
		i = 0;
	}
	while (isspace(buf[i]))
		i++;
	if (!buf[i])
		goto new;

	switch (buf[i]) {
		case 's':
		case 'f':
		case 'H':
		case 'V':
		case 'h':
		case 'v':
		case 'p':
			/* Grab the next number. */
			wbuf[j++] = buf[i++];
			while (isdigit(buf[i]))
				wbuf[j++] = buf[i++];
			wbuf[j] = '\0';
			break;
		case 'w':
			wbuf[0] = buf[i++];
			wbuf[1] = '\0';
			break;
		case 'c':
			wbuf[0] = buf[i++];
			wbuf[1] = buf[i++];
			wbuf[2] = '\0';
			break;
		case 'C':
			while (buf[i] && !isspace(buf[i]))
				wbuf[j++] = buf[i++];
			wbuf[j] = '\0';
			break;
		case 'n':
			while (!isspace(buf[i]))
				wbuf[j++] = buf[i++];
			while (buf[i] && isspace(buf[i]))
				wbuf[j++] = buf[i++];
			while (!isspace(buf[i]))
				wbuf[j++] = buf[i++];
			wbuf[j] = '\0';
			break;
		default:
			if (isdigit(buf[i])) {
				wbuf[0] = buf[i++];
				wbuf[1] = buf[i++];
				wbuf[2] = buf[i++];
				wbuf[3] = '\0';
			} else {
				while (buf[i] && (buf[i] != '\n'))
					wbuf[j++] = buf[i++];
				wbuf[j] = '\0';
			}
			;
	}
	return (copy(wbuf));
}

/* Execute one ditroff command, not necessarily a whole line. */

doline(line)
	char *line;
{
	if (debug == 2) {
		fprintf(stderr, "> %s\n", line);
		return;
	}
	switch (*line) {
		case 's':	/* Set point size to num. */
			setsize(atoi(line + 1));
			break;
		case 'f':	/* Set font to num. */
			setfont(atoi(line + 1));
			break;
		case 'c':	/* Write one character. */
			writechar(line[1]);
			break;
		case 'C':	/* Write a special character. */
			writespec(line + 1);
			break;
		case 'H':	/* Go to hpos num. */
			hgoto(atoi(line + 1));
			break;
		case 'V':	/* Go to vpos num. */
			vgoto(atoi(line + 1));
			break;
		case 'h':	/* Move relative num horiz. */
			hmove(atoi(line + 1));
			break;
		case 'v':	/* Move relative num vert. */
			vmove(atoi(line + 1));
			break;
		case 'n':	/* End of line. */
			break;
		case 'w':	/* Paddable word space. */
			wordspace = 1;
			break;
		case 'p':	/* New page. */
			newpage(atoi(line + 1));
			break;
		case 'x':	/* Device control... */
			devcontrol(line);
			break;
		case 'D':	/* Drawing function. */
			drawfunc(line);
			break;
		default:	/* NNc. */
			if (!isdigit(line[0]) || !isdigit(line[1])) {
				fprintf(stderr, "Error: bad line %s\n", line);
				return;
			}
			hmove((line[0] - '0') * 10 + (line[1] - '0'));
			writechar(line[2]);
	}
	return;
}

/* Parse an 'x' control line. */

devcontrol(l)
	char *l;
{
	char *line = l + 1;
	char *getword(), *command;
	char *s;
	int i;

	command = getword(&line);
	switch (*command) {
		case 'i':	/* Initialize printer. */
			initprinter();
			break;
		case 'T':	/* The name of the typesetter... */
			break;	/* Who cares? */
		case 'r':	/* Resolution... We know this... */
			break;
		case 'p':	/* Pause... */
			/*** What do we do? */
			break;
		case 's':	/* Quit. */
			cleanup();
			exit(0);
		case 't':	/* Trailer? */
			break;
		case 'f':	/* Make font n be s. */
			s = getword(&line);
			if (!*s) {
				fprintf(stderr, "Error: bad line %s\n", l);
				return;
			}
			i = atoi(s);
			s = getword(&line);
			loadfont(i, s);
			break;
		case 'H':	/* Set character height. */
			s = getword(&line);
			if (!*s) {
				fprintf(stderr, "Error: bad line %s\n", l);
				return;
			}
			i = atoi(s);
			setheight(i);
			break;
		case 'S':	/* Set character slant. */
			s = getword(&line);
			if (!*s) {
				fprintf(stderr, "Error: bad line %s\n", l);
				return;
			}
			i = atoi(s);
			setslant(i);
			break;
		default:
			fprintf(stderr, "Error: bad device control line %s\n",
					l);
			return;
	}
	return;
}

drawfunc(line)
	char *line;
{
	/* This remains to be implemented... */
	return;
}

/* This returns static data... */

char *
getword(s)
	char **s;
{
	static char buf[BUFSIZ];
	int i = 0;

	while (isspace(**s))
		(*s)++;
	while (**s && !isspace(**s))
		buf[i++] = *(*s)++;
	buf[i] = '\0';
	return (buf);
}

/* Create a copy of a string. */

char *
copy(str)
	char *str;
{
	char *p, *tmalloc();
	
	p = tmalloc(strlen(str) + 1);
	strcpy(p, str);
	return(p);
}

/* Malloc num bytes and initialize to zero. Fatal error if the space can't
 * be malloc'd.
 */

char *
tmalloc(num)
	register int num;
{
	register char *s;
	char *malloc();

	if (!(s = malloc((unsigned) num))) {
		fprintf(stderr, "malloc: can't allocate %d bytes.\n", num);
		exit(1);
	}
	bzero(s, num);
	return(s);
}

/* Diagnostic... */

printcoms(i)
	int i;
{
	struct command *c = (struct command *) i;

	while (c) {
		if (*c->c_line == 'p')
			printf("%s [%0x%x, pp = 0x%x, np = 0x%x]\n",
					c->c_line, (int) c, c->c_prevpage,
					c->c_nextpage);
		else
			printf("%s\n", c->c_line);
		c = c->c_next;
	}
	return;
}

/* Everything above this point is completely generic stuff, so lazy people
 * can just change things in the following routines.
 * ======================================================================
 */

startup()
{
	/* The laserjet spits out pages in reverse order. */
	pagereverse = 1;
	hmax = 2500;
	vmax = 3000;
	cursize = 10;
	maxfont = 4;
	return;
}

cleanup()
{
	/* Reset the font, etc on the laserjet. lpd should do this really.  */

	printf("\033E\033&l0O\033(8U\033(s0p10h12v0s0b3T");	/* Font. */
#ifdef notdef
	printf("\033&l14c1e7.64c66F");			/* Page length.  */
	printf("\033&a2L");				/* Left margin. */
#endif

	return;
}

writechar(c)
	char c;
{
	char *curfontname();

	putchar(c);
	hmove(- askwidth(c, curfontname()));
	return;
}

/* Here is the table of special charactrs that can be made with other
 * characters. Acknowledgements to Ron Saad for some of the codes.
 * The widths are for 10 point Tms Rmn.
 */

struct asctab {
	char *a_name;
	char *a_seq;
	int a_width;
} asctab[] = {
	{ "\\|",	"\033&a+3H",			6 } ,
	{ "\\^",	"\033&a+2H",			2 } ,
	{ "em",		"-",				23 } ,
	{ "hy",		"-",				23 } ,
	{ "\\-",	"-",				23 } ,
	{ "dg",		"|\033&a-30H-",			23 } ,
	{ "aa",		"'",				16 } ,
	{ "ga",		"`",				12 } ,
	{ "en",		"-",				23 } ,
	{ "l.",		".",				12 } ,
	{ "br",		"|",				8 } ,
	{ "vr",		"|",				8 } ,
	{ "fm",		"'",				16 } ,
	{ "or",		"|",				8 } ,
	/*
	{ "fi",		"f\033&a-25Hi",			30 } ,
	{ "ff",		"f\033&a-25Hf",			30 } ,
	{ "fl",		"f\033&a-25Hl",			30 } ,
	{ "Fi",		"f\033&a-30Hf\033&a-25Hi",	30 } ,
	{ "Fl", 	"f\033&a-30Hf\033&a-25Hl",	30 } ,
	{ "ce",		"\277",				30 } ,
	*/
	{ "ci",		"O",				33 } ,
	{ "ul",		"_",				35 } ,
	{ "ru",		"_",				35 }
} ;

writespec(s)
	char *s;
{
	int i, nascs = sizeof (asctab) / sizeof (struct asctab);

	for (i = 0; i < nascs; i++)
		if (eq(s, asctab[i].a_name))
			break;
	if (i == nascs) {
		fprintf(stderr, "Error: can't print character '%s'...\n", s);
		return;
	}
	fputs(asctab[i].a_seq, stdout);
	hmove( - asctab[i].a_width);
	return;
}

/* The laserjet uses decipoints, with one decipoint = 720 / 300 pixels. */

#define pixtodec(num)	(((num) * 720) / 300)

hgoto(num)
{
	if ((num < 0) || (num > hmax)) {
		fprintf(stderr, "Error: can't hgoto %d\n", num);
		return;
	}
	hpos = num;
	printf("\033&a%dH", pixtodec(num));
	return;
}

/* This is strange -- ditroff seems to send vgoto's beyond the end of the 
 * page when it wants to go to the end of the page.
 */

vgoto(num)
{
	if ((num < 0) || (num > vmax)) {
		/* fprintf(stderr, "Error: can't vgoto %d\n", num); */
		/* return; */
		num = vmax - 25;	/* Fudge... */
	}
	vpos = num;
	printf("\033&a%dV", pixtodec(num));
	return;
}

hmove(num)
{
	if ((hpos + num < 0) || (hpos + num > hmax)) {
		fprintf(stderr, "Error: can't hmove %d\n", num);
		return;
	}
	hpos += num;
	printf("\033&a%c%dH", (num > 0) ? '+' : '-', pixtodec(abs(num)));
	return;
}

vmove(num)
{
	if ((vpos + num < 0) || (vpos + num > vmax)) {
		fprintf(stderr, "Error: can't vmove %d\n", num);
		return;
	}
	vpos += num;
	printf("\033&a%c%dV", (num > 0) ? '+' : '-', pixtodec(abs(num)));
	return;
}

newpage(num)
{
	curpage = num;
	printf("\n\f");
	return;
}

initprinter()
{
	/* Nothing to do. */
	return;
}

/* Here we assume that the 'B' TMS font cartridge is loaded. */

#define OR_LAND		1
#define OR_PORT		2

#define SY_ROMAN	1
#define SY_KANA		2
#define SY_USASCII	3
#define SY_LINE		4
#define SY_MATH		5

#define SP_FIXED	1
#define SP_PROP		2

#define ST_UPRIGHT	1
#define ST_ITALIC	2

#define SK_LIGHT	1
#define SK_MEDIUM	2
#define SK_BOLD		3

/* Don't change these -- see page 4-22 of the laserjet manual. */

#define TF_LINEPR	0
#define TF_PICA		1
#define TF_ELITE	2
#define TF_COURIER	3
#define TF_HELV		4
#define TF_TMSRMN	5
#define TF_GOTHIC	6
#define TF_SCRIPT	7
#define TF_PRESTIGE	8

struct hpfontinfo {
	char *fi_name;		/* What ditroff calls it. */
	int fi_cartridge;	/* The one-character cartridge name, 0 = res. */
	int fi_orientation;	/* OR_LAND or OR_PORT. */
	int fi_symbolset;	/* SY_ROMAN or SY_USASCII. */
	int fi_spacing;		/* SP_FIXED or SP_PROP. */
	float fi_pitch;
	float fi_point;
	int fi_style;		/* ST_UPRIGHT or ST_ITALIC. */
	int fi_stroke;		/* SK_LIGHT, SK_MEDIUM, or SK_BOLD. */
	int fi_typeface;	/* TF_*. */
	int fi_number;		/* The number given in 'f' commands. */
} carttab[] = {
	{ "", 0, OR_PORT, SY_ROMAN, SP_FIXED, 10.0, 12.0, ST_UPRIGHT,
			SK_MEDIUM, TF_COURIER, 0 } ,
	{ "", 'B', OR_PORT, SY_USASCII, SP_PROP, 0.0, 14.4, ST_UPRIGHT,
			SK_BOLD, TF_HELV , 0} ,
	{ "R", 'B', OR_PORT, SY_USASCII, SP_PROP, 0.0, 10.0, ST_UPRIGHT,
			SK_MEDIUM, TF_TMSRMN, 0 } ,
	{ "B", 'B', OR_PORT, SY_USASCII, SP_PROP, 0.0, 10.0, ST_UPRIGHT,
			SK_BOLD, TF_TMSRMN, 0 } ,
	{ "I", 'B', OR_PORT, SY_USASCII, SP_PROP, 0.0, 10.0, ST_ITALIC,
			SK_MEDIUM, TF_TMSRMN, 0 } ,
	{ "", 'B', OR_PORT, SY_USASCII, SP_PROP, 0.0, 8.0, ST_UPRIGHT,
			SK_LIGHT, TF_TMSRMN, 0 } ,
	{ "", 'B', OR_LAND, SY_ROMAN, SP_FIXED, 16.66, 8.5, ST_UPRIGHT,
			SK_LIGHT, TF_LINEPR, 0 } ,
	{ "", 0, OR_LAND, SY_ROMAN, SP_FIXED, 10.0, 12.0, ST_UPRIGHT,
			SK_MEDIUM, TF_COURIER, 0 }
} ;

loadfont(num, name)
	char *name;
{
	int i, nfonts = sizeof (carttab) / sizeof (struct hpfontinfo);

	for (i = 0; i < nfonts; i++)
		if (eq(name, carttab[i].fi_name))
			break;
	if (i == nfonts) {
		fprintf(stderr, "Error: no such font as '%s'...\n", name);
		return;
	}
	carttab[i].fi_number = num;
	return;
}

setfont(num)
{
	int i, nfonts = sizeof (carttab) / sizeof (struct hpfontinfo);

	for (i = 0; i < nfonts; i++)
		if (carttab[i].fi_number == num)
			break;
	if (i == nfonts) {
		fprintf(stderr, "Error: no such font numbered %d...\n", num);
		return;
	}
	curfont = num;

	/* Now set all the characteristics of this font. */
	switch (carttab[i].fi_orientation) {
		case OR_LAND:
			fputs("\033&l1O", stdout);
			break;
		case OR_PORT:
			fputs("\033&l0O", stdout);
			break;
		default:
			fprintf(stderr, "Error: bad orientation %d\n...",
					carttab[i].fi_orientation);
			return;
	}

	switch (carttab[i].fi_symbolset) {
		case SY_ROMAN:
			fputs("\033(8U", stdout);
			break;
		case SY_KANA:
			fputs("\033(8K", stdout);
			break;
		case SY_USASCII:
			fputs("\033(0U", stdout);
			break;
		case SY_LINE:
			fputs("\033(0B", stdout);
			break;
		case SY_MATH:
			fputs("\033(0A", stdout);
			break;
		default:
			fprintf(stderr, "Error: bad symbol set %d\n...",
					carttab[i].fi_symbolset);
			return;
	}

	switch (carttab[i].fi_spacing) {
		case SP_PROP:
			fputs("\033(s1P", stdout);
			break;
		case SP_FIXED:
			fputs("\033(s0P", stdout);
			break;
		default:
			fprintf(stderr, "Error: bad spacing %d\n...",
					carttab[i].fi_spacing);
			return;
	}

	if (carttab[i].fi_pitch > 0.0)
		printf("\033(s%.2fH", carttab[i].fi_pitch);

	if (carttab[i].fi_point > 0.0)
		printf("\033(s%.2fV", carttab[i].fi_point);

	switch (carttab[i].fi_style) {
		case ST_ITALIC:
			fputs("\033(s1S", stdout);
			break;
		case ST_UPRIGHT:
			fputs("\033(s0S", stdout);
			break;
		default:
			fprintf(stderr, "Error: bad style %d\n...",
					carttab[i].fi_style);
			return;
	}

	switch (carttab[i].fi_stroke) {
		case SK_LIGHT:
			fputs("\033(s-3B", stdout);
			break;
		case SK_MEDIUM:
			fputs("\033(s0B", stdout);
			break;
		case SK_BOLD:
			fputs("\033(s3B", stdout);
			break;
		default:
			fprintf(stderr, "Error: bad stroke weight %d\n...",
					carttab[i].fi_stroke);
			return;
	}
	
	printf("\033(s%dT", carttab[i].fi_typeface);

	return;
}

char *
curfontname()
{
	int i, nfonts = sizeof (carttab) / sizeof (struct hpfontinfo);

	for (i = 0; i < nfonts; i++)
		if (carttab[i].fi_number == curfont)
			break;
	if (i == nfonts)
		return (NULL);
	else
		return (carttab[i].fi_name);
}

setheight(num)
{
	/* Can't do this apart from setting font... */
	fprintf(stderr, "Error: can't set height...\n");
	return;
}

setslant(num)
{
	/* Can't do this apart from setting font... */
	fprintf(stderr, "Error: can't set slant...\n");
	return;
}

setsize(num)
{
	/* Can't do this apart from setting font... */
	if (num != cursize)
		fprintf(stderr, "Error: can't set size...\n");
	return;
}

!Funky!Stuff!
echo x - width.c
cat >width.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: $ on $Date: $
 *           $Source: $
 * Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * This is a hack to make up for the fact that the laserjet is strange...
 */

int R_width[] = {
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 12, 15, 29, 23, 35, 35, 16,
	15, 16, 21, 23, 14, 23, 12, 21,
	23, 23, 23, 23, 23, 23, 23, 23,
	23, 23, 10, 12, 24, 25, 24, 21,
	38, 35, 29, 31, 34, 30, 28, 36,
	35, 16, 20, 37, 30, 42, 35, 33,
	26, 33, 34, 22, 30, 37, 34, 38,
	36, 33, 31, 13, 21, 14, 24, 35,
	12, 21, 25, 21, 25, 21, 19, 23,
	25, 14, 17, 25, 13, 36, 25, 22,
	25, 24, 17, 17, 15, 25, 24, 34,
	24, 24, 20, 16, 8, 17, 25
} ;

int B_width[] = {
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 13, 18, 28, 24, 38, 34, 12,
	17, 19, 17, 24, 13, 23, 13, 22,
	24, 24, 24, 24, 24, 24, 24, 24,
	24, 24, 11, 11, 25, 26, 25, 21,
	41, 32, 31, 31, 32, 29, 27, 35,
	37, 18, 24, 33, 29, 41, 33, 34,
	28, 34, 32, 26, 30, 35, 33, 41,
	32, 31, 32, 13, 22, 14, 26, 33,
	12, 22, 24, 21, 24, 21, 19, 23,
	27, 14, 17, 26, 14, 36, 25, 22,
	24, 24, 18, 18, 16, 24, 20, 32,
	24, 23, 20, 16, 8, 17, 30
} ;

int I_width[] = {
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 0, 0, 0, 0, 0, 0, 0,
	0, 17, 17, 27, 23, 31, 31, 20,
	20, 20, 21, 21, 11, 22, 11, 31,
	22, 22, 22, 22, 22, 22, 22, 22,
	22, 22, 17, 17, 30, 25, 31, 21,
	50, 29, 29, 30, 33, 29, 29, 29,
	35, 19, 24, 30, 29, 40, 33, 33,
	28, 33, 32, 28, 30, 33, 31, 35,
	34, 29, 33, 24, 12, 24, 22, 33,
	9, 22, 24, 22, 25, 20, 21, 25,
	23, 14, 21, 24, 14, 36, 25, 21,
	24, 21, 17, 18, 14, 21, 19, 31,
	25, 23, 23, 21, 7, 21, 25
} ;

/* This routine returns the width of the character in the given font. It
 * should really read the device description file...
 */

askwidth(ch, ft)
	char *ft;
{
	if (!strcmp(ft, "R"))
		return (R_width[ch]);
	else if (!strcmp(ft, "B"))
		return (B_width[ch]);
	else if (!strcmp(ft, "I"))
		return (I_width[ch]);
}

!Funky!Stuff!
echo x - pagereverse.c
cat >pagereverse.c <<'!Funky!Stuff!'

/* RCS Info: $Revision: 1.1 $ on $Date: 85/10/29 14:44:13 $
 *           $Source: /cad4/faustus/src/laserjet/RCS/pagereverse.c,v $
 * Copyright (c) 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
 *	Permission is granted to do anything with this code except sell it
 *	or remove this message.
 *
 * Reverse the pages in a file. Usage is pagereverse [pagelength].
 */

#include <stdio.h>

#define MAXPAGES 10000

main(ac, av)
	char **av;
{
	register plen = 66, pnum = 0, line = 0, i = 0;
	long pages[MAXPAGES];	/* The beginning of each page. */
	char buf[BUFSIZ];
	char *mktemp(), *tempf = "/tmp/prXXXXXX";
	FILE *fopen(), *fp;

	if (ac == 2) {
		plen = atoi(av[1]);
		if ((plen <= 0) || (plen > 1000)) {
			fprintf(stderr, "Usage: %s [pagelen]\n");
			exit(1);
		}
	} else if (ac > 2) {
		fprintf(stderr, "Usage: %s [pagelen]\n");
		exit(1);
	}
	tempf = mktemp(tempf);
	if (!(fp = fopen(tempf, "w+"))) {
		perror(tempf);
		exit(1);
	}
	pages[0] = 0;

	/* Copy all the lines and figure out the page boundaries. */
	while (fgets(buf, BUFSIZ, stdin)) {
		if (line++ == plen - (pnum ? 1 : 0)) {
			pages[++pnum] = i;
			line = 0;
		}
		if (*buf == '\f') {
			/* Now we have to expand this as newlines. */
			while (line++ <= plen) {
				putc('\n', fp);
			}
			pages[++pnum] = ftell(fp);
			line = 0;
		} else {
			fputs(buf, fp);
		}
		i = ftell(fp);
	}
	fflush(fp);

	/* Now go back and output them in reversed order. */
	while (pnum >= 0) {
		fseek(fp, pages[pnum], 0);
		for (i = 0; i < plen; i++) {
			if (!fgets(buf, BUFSIZ, fp)) {
				/* Fill the last page with blank lines... */
				while (i++ < plen)
					putchar('\n');
				break;
			}
			fputs(buf, stdout);
		}
		pnum--;
	}
	fclose(fp);
	unlink(tempf);
	exit(0);
}

!Funky!Stuff!
echo x - DESC
cat >DESC <<'!Funky!Stuff!'
# Laserjet Ditroff Description file
fonts 3 R I B
sizes 10 0
unitwidth 10
# This should be res 300, but ditroff is so screwed up...
res 290
hor 2
vert 2
# This is evil -- ditroff ignores these two values completely.
paperwidth 2500
paperlength 2500
# I have yet to add the MSB-set characters that the lj accepts -- these
# are all simulated with ascii.
charset
Fi Fl \- \^ \| aa br ce ci dg em en ff fi fl fm ga hy l. or ru ul vr
!Funky!Stuff!
echo x - R
cat >R <<'!Funky!Stuff!'
# Tms Rmn 
name R
ligatures 0
# char	width	u/d	octal
charset
!	12	2	41
"	15	2	42
#	29	3	43
$	23	2	44
%	35	2	45
&	35	2	46
'	16	2	47
(	15	3	50
)	16	3	51
*	21	2	52
+	23	2	53
,	14	0	54
-	23	0	55
.	12	0	56
/	21	2	57
0	23	2	60
1	23	2	61
2	23	2	62
3	23	2	63
4	23	2	64
5	23	2	65
6	23	2	66
7	23	2	67
8	23	2	70
9	23	2	71
:	10	0	72
;	12	0	73
<	24	2	74
=	25	0	75
>	24	2	76
?	21	2	77
@	38	2	100
A	35	2	101
B	29	2	102
C	31	2	103
D	34	2	104
E	30	2	105
F	28	2	106
G	36	2	107
H	35	2	110
I	16	2	111
J	20	2	112
K	37	2	113
L	30	2	114
M	42	2	115
N	35	2	116
O	33	2	117
P	26	2	120
Q	33	2	121
R	34	2	122
S	22	2	123
T	30	2	124
U	37	2	125
V	34	2	126
W	38	2	127
X	36	2	130
Y	33	2	131
Z	31	2	132
[	13	3	133
\	21	2	134
]	14	3	135
^	24	0	136
_	35	0	137
`	12	2	140
a	21	0	141
b	25	2	142
c	21	0	143
d	25	2	144
e	21	0	145
f	19	2	146
g	23	1	147
h	25	2	150
i	14	2	151
j	17	3	152
k	25	2	153
l	13	2	154
m	36	0	155
n	25	0	156
o	22	0	157
p	25	1	160
q	24	1	161
r	17	0	162
s	17	0	163
t	15	2	164
u	25	0	165
v	24	0	166
w	34	0	167
x	24	0	170
y	24	1	171
z	20	0	172
{	16	3	173
|	8	3	174
}	17	3	175
~	25	0	176
\|	6	0	0
\^	2	0	0
em	23	0	0
hy	23	0	0
\-	0	0	0	xxx
ce	0	0	0	xxx
dg	0	0	0	xxx
aa	16	0	0
ga	12	0	0
en	23	0	0
l.	12	0	0
br	8	0	0
vr	8	0	0
fm	16	0	0
or	8	0	0
fi	30	0	0	xxx
ff	30	0	0	xxx
fl	30	0	0	xxx
Fi	30	0	0	xxx
Fl	30	0	0	xxx
ci	33	0	0
ul	35	0	0
ru	35	0	0
!Funky!Stuff!
echo x - I
cat >I <<'!Funky!Stuff!'
# Tms Rmn Italic
name I
ligatures 0
# char	width	u/d	octal
charset
!	17	2	41
"	17	2	42
#	27	3	43
$	23	2	44
%	31	2	45
&	31	2	46
'	20	2	47
(	20	3	50
)	20	3	51
*	21	2	52
+	21	2	53
,	11	0	54
-	22	0	55
.	11	0	56
/	31	2	57
0	22	2	60
1	22	2	61
2	22	2	62
3	22	2	63
4	22	2	64
5	22	2	65
6	22	2	66
7	22	2	67
8	22	2	70
9	22	2	71
:	17	0	72
;	17	0	73
<	30	2	74
=	25	0	75
>	31	2	76
?	21	2	77
@	50	2	100
A	29	2	101
B	29	2	102
C	30	2	103
D	33	2	104
E	29	2	105
F	29	2	106
Fi	30	0	0	xxx
Fl	30	0	0	xxx
G	29	2	107
H	35	2	110
I	19	2	111
J	24	2	112
K	30	2	113
L	29	2	114
M	40	2	115
N	33	2	116
O	33	2	117
P	28	2	120
Q	33	3	121
R	32	2	122
S	28	2	123
T	30	2	124
U	33	2	125
V	31	2	126
W	35	2	127
X	34	2	130
Y	29	2	131
Z	33	2	132
[	24	3	133
\	12	2	134
\-	0	0	0	xxx
\^	2	0	0
\|	6	0	0
]	24	3	135
^	22	0	136
_	33	0	137
`	9	2	140
a	22	0	141
aa	16	0	0
b	24	2	142
br	8	0	0
c	22	0	143
ce	0	0	0	xxx
ci	33	0	0
d	25	2	144
dg	0	0	0	xxx
e	20	0	145
em	23	0	0
en	23	0	0
f	21	3	146
ff	30	0	0	xxx
fi	30	0	0	xxx
fl	30	0	0	xxx
fm	16	0	0
g	25	1	147
ga	12	0	0
h	23	2	150
hy	23	0	0
i	14	2	151
j	21	3	152
k	24	2	153
l	14	2	154
l.	12	0	0
m	36	0	155
n	25	0	156
o	21	0	157
or	8	0	0
p	24	1	160
q	21	1	161
r	17	0	162
ru	35	0	0
s	18	0	163
t	14	2	164
u	21	0	165
ul	35	0	0
v	19	0	166
vr	8	0	0
w	31	0	167
x	25	0	170
y	23	1	171
z	23	0	172
{	21	3	173
|	7	3	174
}	21	3	175
~	25	0	176
!Funky!Stuff!
echo x - B
cat >B <<'!Funky!Stuff!'
# Tms Rmn Bold
name B
ligatures 0
# char	width	u/d	octal
charset
!	13	2	41
"	18	2	42
#	28	3	43
$	24	2	44
%	38	2	45
&	34	2	46
'	12	2	47
(	17	3	50
)	19	3	51
*	17	2	52
+	24	2	53
,	13	0	54
-	23	0	55
.	13	0	56
/	22	2	57
0	24	2	60
1	24	2	61
2	24	2	62
3	24	2	63
4	24	2	64
5	24	2	65
6	24	2	66
7	24	2	67
8	24	2	70
9	24	2	71
:	11	0	72
;	11	0	73
<	25	2	74
=	26	0	75
>	25	2	76
?	21	2	77
@	41	2	100
A	32	2	101
B	31	2	102
C	31	2	103
D	32	2	104
E	29	2	105
F	27	2	106
Fi	30	0	0	xxx
Fl	30	0	0	xxx
G	35	2	107
H	37	2	110
I	18	2	111
J	24	2	112
K	33	2	113
L	29	2	114
M	41	2	115
N	33	2	116
O	34	2	117
P	28	2	120
Q	34	2	121
R	32	2	122
S	26	2	123
T	30	2	124
U	35	2	125
V	33	2	126
W	41	2	127
X	32	2	130
Y	31	2	131
Z	32	2	132
[	13	3	133
\	22	2	134
\-	0	0	0	xxx
\^	2	0	0
\|	6	0	0
]	14	3	135
^	26	0	136
_	33	0	137
`	12	2	140
a	22	0	141
aa	16	0	0
b	24	2	142
br	8	0	0
c	21	0	143
ce	0	0	0	xxx
ci	33	0	0
d	24	2	144
dg	0	0	0	xxx
e	21	0	145
em	23	0	0
en	23	0	0
f	19	2	146
ff	30	0	0	xxx
fi	30	0	0	xxx
fl	30	0	0	xxx
fm	16	0	0
g	23	1	147
ga	12	0	0
h	27	2	150
hy	23	0	0
i	14	2	151
j	17	3	152
k	26	2	153
l	14	2	154
l.	12	0	0
m	36	0	155
n	25	0	156
o	22	0	157
or	8	0	0
p	24	1	160
q	24	1	161
r	18	0	162
ru	35	0	0
s	18	0	163
t	16	2	164
u	24	0	165
ul	35	0	0
v	20	0	166
vr	8	0	0
w	32	0	167
x	24	0	170
y	23	1	171
z	20	0	172
{	16	3	173
|	8	3	174
}	17	3	175
~	30	0	176
!Funky!Stuff!
Technical Details
Message-ID: <65@cad.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!linus!philabs!cmcl2!seismo!lll-crg!lll-lcc!ucdavis!ucbvax!cad!faustus
References: <1361@wucec2.UUCP>

Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: arc1-ca.pugleaf.net!utzoo!linus!philabs!cmcl2!seismo!lll-crg!lll-lcc!ucdavis!ucbvax!cad!faustus
From: faustus@cad.UUCP (Wayne A. Christopher)
Newsgroups: net.text
Subject: Re: Looking for nroff tables for HP LaserJet
Message-ID: <65@cad.UUCP>
Date: Mon, 24-Feb-86 13:29:27 EST
Article-I.D.: cad.65
Posted: Mon Feb 24 13:29:27 1986
Date-Received: Wed, 26-Feb-86 20:13:49 EST
References: <1361@wucec2.UUCP>
Organization: U. C. Berkeley CAD Group
Lines: 1477
Keywords: term(5) HP-LaserJet nroff tabhp.c