[comp.sources.unix] v12i003: CRC Graphics Package Patch#1

rsalz@uunet.UU.NET (Rich Salz) (10/10/87)

Submitted-by: rsk@j.cc.purdue.edu (Whitewater Wombat)
Posting-number: Volume 12, Issue 3
Archive-name: crc.pch

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	README
#	gd.c
#	gp.c
#	gplp.c
#	hpd.c
#	font-mods
cat << \SHAR_EOF > README
This patch contains two different items: first, the four drivers omitted
from the original release.  This was a botch on my part--we don't use these
drivers, and so when I packed up the sources to ship them out, I didn't
include them.  The drivers are supposed to handle Printronix, Versatec,
Grinnel, Comtal, and HP devices.

The second item, "font-mods", is some recent work done by Malcolm
Slaney which allows the font used by this package to be kept in memory.
It's not in "patch" format--I'm enclosing exactly what I received.

Finally, I have received some correspondence from various folks about
this package...which I'm in the process of answering.  However, please
note that I do NOT officially support this package, and so I can only
put a little bit of time into this.
-- 
Rich Kulawiec, rsk@s.cc.purdue.edu, s.cc.purdue.edu!rsk
SHAR_EOF
cat << \SHAR_EOF > gd.c
/*
	gd - graphics driver for the Comtal and the Grinnel

	The CRC graphics package

	Carl Crawford
	Purdue University
	W. Lafayette, IN 47907

	September 1981


	Cleaned up to support the new improved Grinnell
	Malcolm Slaney
	October 1983
*/

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <netinet/in.h>

#define L       (512 / sizeof(short))
#define M       (16384 / L)

#define	COMTAL		0
#define	GRINNELL	1

#define	IMAGE		0
#define	OVERLAY		1

#define	Grinnell	"/dev/Gr/"
#define	Comtal		"/dev/ct"
#define	Overlay		"gov"

char	OutputDevice[BUFSIZ];
char    buf[512],bb[512],*bf,*cf;
unsigned short ibuf[L*M],kbuf[L*M];
unsigned short *pp,*qq;

int	Device = COMTAL;			/* Comtal or Grinnell */
int	Mode = OVERLAY;				/* Overlay or Image Plane */
int	Number = 0;				/* Device Number */

int     blank;          /* 1=don't blank device */

FILE	*fdi, *fdo, *fd;/* file descriptors */
FILE	*ifd, *popen();
char    *ifn;           /* input file name */
char    *pname;         /* program name */
char	fill[256*8];	/* speed buffer for comtal image and grinnel */
char	*cp,*po;	/* character pointers */
int	net = 1;	/* 1 send output across network */
char	host[10] = "arpa"; /* last resort host */
int	ks;
int	nleft, nread;

char	*table[] = {
		"if",
		0
	};

main(argc,argv)
	int     argc;
	char    **argv;
{
	register i,j;
	int k;
	char    c;

	/* parse command line */

	pname = *argv;
	while(argv++ , --argc){
		if(argv[0][0] == '-')while(c = *++*argv)switch(c){

			case 'b':       /* blank */
				blank = 1;
				break;
			case 'G':       /* Grinnell */
				Device = GRINNELL;;
				break;
			case 'c':
			case 'C':	/* Comtal */
				Device = COMTAL;
				break;
			case 'i':
				Mode = IMAGE;
				break;
			case 'o':
				Mode = OVERLAY;
				break;
			case '0':	/* device 0 */
			case '1':
			case '2':
			case '3':
			case '4':
				Number = c;
				break;
			case 'm':	/* override machine */
				strcpy(host,*argv+1);
				net = 1;
				goto noption;
			default:
				fprintf(stderr,"bad flag: -%c\n",c);
				exit(1);
			}
		else
			switch(comm(*argv)){

			case 1:
				ifn = *argv + 3;
				break;
		}
noption:
	;
	}

	/* find out where to send output to */

	if((ifd = fopen((Device == COMTAL ? "/usr/lib/graphics/gd.site.Ct" :
					    "/usr/lib/graphics/gd.site.Gr"),
					    "r")) != NULL) {
		fgets(host,10,ifd);
		fclose(ifd);
		host[strlen(host)-1] = 0;
		if(strcmp(host,"local") == 0){
			net = 0;
		}else{
			net = 1;
		}
	}

	if(ifn){
		if((fd = fopen(ifn,"r")) == NULL)
			err("can't open: ",ifn);
	}else{
		fd = stdin;
	}

	/* send to remote machine if necessary */

	if(net){
		short s;
		sprintf(buf,"exec %s %s %s /usr/lib/graphics/gd -%s%s%c%s",
			Device == GRINNELL ? "/usr/ucb/rsh" : "/usr/ecn/ns",
			host,
			Device == GRINNELL ? "" : "-S",
			Device == GRINNELL ? "G" : "C",
			Mode == IMAGE ? "i" : "o",
			Number ? Number : '0',
			blank ? "b" : "");
			
		if((fdo = popen(buf,"w")) == NULL){
			fprintf(stderr,"can't execute pipe to '%s'\n",
				Device == GRINNELL ? "rsh" : "ns");
			exit(1);
		}
		gdread(fileno(fd), ibuf, sizeof(short)*L*M);
		s = 1;
		if (Mode == OVERLAY && htons(s) != s
		    && strcmp(host, "dipl") == 0) {
			unsigned short *sp;
			int i;
			for (i = L*M, sp = ibuf ; i > 0 ; i--, sp++)
				*sp = htons(*sp);
		}
		write(fileno(fdo), ibuf, sizeof(short)*L*M);
		if(pclose(fdo)){
			fprintf(stderr,"%s:/usr/lib/graphics/ngd died\n",host);
			exit(1);
		}
		exit(0);
	}

	/*  use local devices */

	/* find name of machine */
	bzero(host, sizeof(host));
	gethostname(host, sizeof(host)-1);

	sprintf(OutputDevice,"%s%s%c",
		Device == GRINNELL ? Grinnell : Comtal,
		Mode == OVERLAY ? Overlay : "",
		Number ? Number : '0');

	if (Mode == OVERLAY){
		if(blank)if((fdi = fopen(OutputDevice,"r")) == NULL){
			fprintf(stderr,"can't open: %s:%s\n",host,OutputDevice);
			exit(1);
		}
		if((fdo = fopen(OutputDevice,"w")) == NULL){
			fprintf(stderr,"can't open: %s:%s\n",host,OutputDevice);
			exit(1);
		}
		gdread(fileno(fd), ibuf, sizeof(short)*M*L);
		if (blank) {
			gdread(fileno(fdi), kbuf, sizeof(short)*M*L);
			for(j = 0, pp = ibuf, qq = kbuf ; j < M * L ; j++)
				*pp++ |= *qq++;
		}
		write(fileno(fdo), ibuf, sizeof(ibuf));
	}
	else {
		if(Device == COMTAL && !Number){
			if((fdi = fopen("/dev/ct/tc","r")) == NULL){
				fprintf(stderr,"can't open: %s!/dev/ct/tc\n",
					host);
				exit(1);
			}
			fread(buf,sizeof(char),512,fdi);
			fclose(fdi);
			Number = ((buf[4]>>1)&3)+'0';
			sprintf(OutputDevice,"%s%s%c",
				Device == GRINNELL ? Grinnell : Comtal,
				Mode == OVERLAY ? Overlay : "",
				Number ? Number : '0');
		}
		if(blank)if((fdi = fopen(OutputDevice,"r")) == NULL){
			fprintf(stderr,"can't open: %s!%s\n",host,OutputDevice);
			exit(1);
		}
		if((fdo = fopen(OutputDevice,"w")) == NULL){
			fprintf(stderr,"can't open: %s!%s\n",host,OutputDevice);
			exit(1);
		}
		for(i=0,cp=fill;i<256;i++){
			if(i & 0200) *cp++ = 255; else *cp++ = 0;
			if(i & 0100) *cp++ = 255; else *cp++ = 0;
			if(i & 0040) *cp++ = 255; else *cp++ = 0;
			if(i & 0020) *cp++ = 255; else *cp++ = 0;
			if(i & 0010) *cp++ = 255; else *cp++ = 0;
			if(i & 0004) *cp++ = 255; else *cp++ = 0;
			if(i & 0002) *cp++ = 255; else *cp++ = 0;
			if(i & 0001) *cp++ = 255; else *cp++ = 0;
		}
		for(k = 0 ; k < 512 ; k++){
			bf = buf;
			if(fread(ibuf,sizeof(short),32,fd) != 32)
				err("unexpected EOF","");
			for( j = 0,cp = (char *)ibuf ; j < 32 ; j++){
				po = fill + ((0377 &(int)*(cp+1)) << 3);
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				po = fill + ((0377 &(int)*cp) << 3);
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				*bf++ = *po++;
				cp += 2;
			}
			if(blank){
				fread(bb,sizeof(char),512,fdi);
				for(j=0,bf=buf,cf=bb;j<512;j++)*bf++ |= *cf++;
			}
			fwrite(buf,sizeof(char),512,fdo);
		}
		if(blank)
			fclose(fdi);
		fclose(fdo);
	}
}

comm(s)
	char	*s;
{
	register	int	i,j,r;

	for(i=0;table[i];i++){
		for(j=0;(r=table[i][j]) == s[j] && r;j++);
		if(r == 0 && s[j] == '=' && s[j+1] )return(i+1);
	}
	fprintf(stderr,"bad option: %s\n",s);
	exit(1);
}

err(s1,s2)
	char    *s1,*s2;
{
	fprintf(stderr,"%s: %s%s\n",pname,s1,s2);
	exit(1);
}

gdread(fd, buf, nleft)
int fd;
char *buf;
int nleft;
{
	int nread;
	for ( ; nleft > 0 ; ) {
		nread = read(fd, buf, nleft);
		if (nread <= 0) 
			err("unexpected EOF","");
		buf += nread;
		nleft -= nread;
	}
}
SHAR_EOF
cat << \SHAR_EOF > gp.c
/*
	gp - print bit planes on the Versatec

	The CRC graphics package

	Carl Crawford 
	Purdue University
	West Lafayette, IN 47901

	October 1981

*/

#include	<stdio.h>

#define L    32
#define M    512

FILE    *ofd,*ifd[20],*popen();
FILE	*fd;		/* for getting site name */
short buf[L],ibuf[L],obuf[132];
int nf;			/* number of inout files */
int	form[3] = {3,0,020}; /* stty stuff for some Versatecs */
int     silent;         /* 1=don't print output message */
char	host[10] = "a";	/* last resort site */
int	outlen;		/* size of versatec line */
int	net = 1;	/* 1=go across network */
int     full;           /* 1= 4:1 0= 2:1 */
char gov[] = "/dev/ct/gov0";
char	cbuf[100];	/* character buffer for site determination */
int	dumb;		/* 1=dumb Versatec */

main(argc, argv)
	int     argc;
	char    **argv;
{
	char    c;
	short   map(),map2();
	int     i;
	register        j;
	register short  *p,*q;

	if(argc == 1)synerr();

/* the file /u/lib/graphics/gp.site contains information about which
versatec to use. it two fields: "host # ". the host is the network
machine where graphics will be sent to. the # is the length of the
line. 100 for normal versatecs and 132 for the old one at APPA. if
host is 'local' then the versatec connected directly to the machine
will be used. care should be used so that loops do not occur by
sending output back and forth between machines. */

	if((fd = fopen("/usr/lib/graphics/gp.site","r")) != NULL){
		fgets(host,10,fd);
		for(i=0;i<10;i++){
			if(host[i] == ' ' || host[i] == '\n'){
				host[i] = 0;
				break;
			}
		}
		outlen = atoi(host + i + 1);
		if(outlen == 132 ) dumb = 1;
		fclose(fd);
		if(strcmp(host,"local") == 0){
			net = 0;
		}else{
			net = 1;
		}
	}

	while(argv++ , --argc){
		if(**argv == '-')while(c = *++*argv)switch(c){

		case 'h':       /* 2:1 scaling */
			full = 0;
			break;
		case 'f':       /* 4:1 scaling */
			full = 1;
			break;
		case 'i':       /* standard input */
			ifd[nf++] = stdin;
			break;
		case 's':       /* silent mode */
			silent = 1;
			break;
		case 'm':	/* set up machine */
			strcpy(host,*argv+1);
			net = 1;
			goto nloop;
		default:
			fprintf(stderr,"bad flag: -%c\n",c);
			exit(1);
		}else{
			if(dumb){
				if(**argv >= '0' && **argv <= '2' && !*(*argv + 1)){
					gov[11] = **argv;
					ifd[nf++] = fopen(gov,"r");
					*argv = gov;
				}else{
				ifd[nf++] = fopen(*argv,"r");
				}
			}else{
				ifd[nf++] = fopen(*argv,"r");
			}
			if(ifd[nf-1] == NULL){
				fprintf(stderr,"can't open: %s\n",*argv);
				exit(1);
			}
		}
nloop:
	;
	}

	if(!nf)synerr();
	if(!dumb)full = 0;

	if(net){
		sprintf(cbuf,"exec ns  %s -S  gp -i",host);
		if(silent)strcat(cbuf," -s");
		if(full)strcat(cbuf,"-f");
		silent = 1;
		if((ofd = popen(cbuf,"w")) == NULL){
			fprintf(stderr,"can't execute pipe to '%s'\n",host);
			exit(1);
		}


	}else{
		if((fd=fopen("/etc/cpu","r")) != NULL){
			fgets(host,10,fd);
			host[strlen(host)-1] = 0;
			fclose(fd);
		}
		if( (ofd = fopen("/dev/vc","w")) == NULL){
			fprintf(stderr,"Versatec in use on '%s'\n",host);
			exit(1);
		}
	}
	if(!net && !dumb)stty(fileno(ofd),form);

	for(i=0;i<M;i++){
		input();
		if(net){
			fwrite(ibuf,sizeof(short),L,ofd);
		}else{
			p = ibuf;
			q = obuf + 20;
			if(full)q -= 18;
			for(j=0;j<L;j++){
				if(full){
					*q++ = map(12, *p);
					*q++ = map(8, *p);
					*q++ = map(4, *p);
					*q++ = map(0, *p++);
				}else{
					*q = map2(8, *p) << 8;
					*q++ |= map2(12, *p);
					*q = map2(0, *p) << 8;
					*q++ |= map2(4, *p++);
				}
			}
			for(j=0;j<(2<<full);j++){
				fwrite(obuf,sizeof(short),outlen,ofd);
			}
		}
	}

	if(!net){
		if(!dumb){
			stty(fileno(ofd),form);
		}else{
			for(i=0;i<outlen;obuf[i++] = 0);
			for(i=0;i<1500;i++)fwrite(obuf,sizeof(short),outlen,ofd);
		}
	}else{
		pclose(ofd);
	}
	if(!silent)fprintf(stderr,"output at '%s'\n",host);
}

#define K0	0000000
#define K4	0000017
#define K8	0000360
#define K1	0007400
#define K2	0170000

short tab[] = {
	(K0),
	(K1),
	(K2),
	(K1|K2),
	(K4),
	(K4|K1),
	(K4|K2),
	(K4|K2|K1),
	(K8|K0),
	(K8|K1),
	(K8|K2),
	(K8|K1|K2),
	(K8|K4),
	(K8|K4|K1),
	(K8|K4|K2),
	(K8|K4|K2|K1)
};

short   map(n,d)
	int     n;
	short   d;
{
	return( tab[ (d>>n)&017 ] );
}

#undef K0
#undef K1
#undef K2
#undef K4
#undef K8
#define K0	0000000
#define K1	0000003
#define K2	0000014
#define K4	0000060
#define K8	0000300

short tab2[] = {
	(K0),
	(K1),
	(K2),
	(K1|K2),
	(K4),
	(K4|K1),
	(K4|K2),
	(K4|K2|K1),
	(K8|K0),
	(K8|K1),
	(K8|K2),
	(K8|K1|K2),
	(K8|K4),
	(K8|K4|K1),
	(K8|K4|K2),
	(K8|K4|K2|K1)
};

short   map2(n,d)
	int     n;
	short   d;
{
	return( tab2[ (d>>n)&017 ] );
}


input()
{
	register int i, j;

	fread(ibuf,sizeof(short),L,ifd[0]);
	i = 1;
	while(i < nf){
		fread(buf,sizeof(short),L,ifd[i++]);
		for(j=0; j<L; j++)
			ibuf[j] |= buf[j];
	}
}

synerr()
{
	fprintf(stderr,"syntax: gp [-ifhsm] file1 file2 ... filen\n");
	exit(1);
}
SHAR_EOF
cat << \SHAR_EOF > gplp.c
#include	<stdio.h>

/*
	gplp - print bit planes on a Printronix line-printer

	syntax: gplp [-XX] [-i] file1 file2 ... filen

	The CRC graphics package

	carl crawford
	purdue university
	w. lafayette, in 47907

	july 1979


	*****************************************************************

	Modified by Tony Andrews : July, 1982

	Added "-s" option to compensate for different vertical and 
	horizontal pixed densities on the printronix. Define "NSQ" to
	delete the changes making the code identical to the original.

	The compensation is a simple compression so characters will be
	distorted somewhat.

	To avoid a major overhaul of the argument processing, the "-s"
	must come after the "-i" (if present) and before any file names.

*/

#define L       32
#define M       512

FILE	*ofd;			/* output file descriptor */
FILE	*fd;			/* input file descriptor */
char    PLOT    =    005;
char    ENDLINE =    012;
int     nfile;
char	swtab[64];
char	site[10] = "-ep";	/* last resort line-printer */

#ifndef NSQ
int     sflag   =   0;
short   mask[16];

#define MASK(x)  (((short)0x0001) << (15-x))
#endif

main(argc,argv)
	int	argc;
	char	**argv;
{
	FILE    *ifd[20];
	short ibuf[33],buf[33];
	char    obuf[100],*ob;
	register int     i,j,k;
	char    swap();
	FILE	*popen();

	ibuf[32] = 0;	/* clear last byte in vector */
#ifndef NSQ
	for(i=0;i<16;i++)               /* used to speed up masking later */
		mask[i] = MASK(i);
#endif
	if((fd = fopen("/usr/lib/graphics/gplp.site","r")) != NULL){
		fgets(site,10,fd);
		fclose(fd);
		site[strlen(site) - 1] = 0;
	}

	if(argv[1][0] == '-' && argv[1][1] && argv[1][2] && !argv[1][3]){
		if(argv[1][1] != 'p' || argv[1][2] != 'l'){
			site[1] = argv[1][1];
			site[2] = argv[1][2];
			site[3] = 0;
		}
		argc--;
		argv++;
	}
	if(argv[1][0] == '-' && argv[1][1] && argv[1][2] && argv[1][3] && !argv[1][4]){
		if(argv[1][1] != 'p' || argv[1][2] != 'l'){
			site[1] = argv[1][1];
			site[2] = argv[1][2];
			site[3] = argv[1][3];
			site[4] = 0;
		}
		argc--;
		argv++;
	}

	if(argv[1][0] == '-' && argv[1][1] == 'i' && argv[1][2] == '\0'){
		ifd[nfile++] = stdin;
		argv++;
		argc--;
	}
#ifndef NSQ
	if(argv[1][0] == '-' && argv[1][1] == 's' && argv[1][2] == '\0'){
		sflag++;
		argv++;
		argc--;
	}
#endif
	if(argc == 1 && !nfile)synerr();
	while(--argc){
		if((ifd[nfile++] = fopen(argv[1],"r")) == NULL){
			fprintf(stderr,"gplp: can't open: %s\n",argv[1]);
			exit(1);
		}
		++argv;
	}
	if (site[0] == '-')
		strcpy(&site[0],&site[1]);

	sprintf(obuf,"exec lpr -l -P%s", site);
	if((ofd = popen(obuf,"w")) == NULL){
		fprintf(stderr,"gplp: can't pipe to lpr\n");
		exit(1);
	}

	for(i=0;i<64;i++)swtab[i] = swap((char) i);
	for(j=0;j<M;j++){
		if(fread(ibuf,sizeof(short),L,ifd[0]) != L){
			fprintf(stderr,"gplp: unexpected EOF\n");
			exit(1);
		}
		i = 0;
		while(++i < nfile){
			if(fread(buf,sizeof(short),L,ifd[i]) != L){
				fprintf(stderr,"gplp: unexpected EOF\n");
				exit(1);
			}
			for(k=0;k<L;k++)ibuf[k] |= buf[k];
		}
#ifndef NSQ
		if(sflag) adjust(ibuf);
#endif
		ob = obuf;
		*ob++ = PLOT;
		for(i=0;i<L;i += 3){
			*ob++ = swtab[(ibuf[i] >> 10) & 077];
			*ob++ = swtab[(ibuf[i] >>4) & 077];
			*ob++ = swtab[((ibuf[i+1] >> 14) & 03) | ((ibuf[i] << 2) & 074)];
			*ob++ = swtab[(ibuf[i+1] >> 8) & 077];
			*ob++ = swtab[(ibuf[i+1] >> 2) & 077];
			*ob++ = swtab[((ibuf[i+2] >> 12) & 017) | ((ibuf[i+1] << 4) & 060)];
			*ob++ = swtab[(ibuf[i+2] >> 6) & 077];
			*ob++ = swtab[ibuf[i+2] & 077];
		}
		while(*(--ob) == 0100);
		*(++ob) = ENDLINE;
		fwrite(obuf,1,ob - obuf + 1,ofd);
	}
	fputc('\f',ofd);         /* eject page */
	pclose(ofd);
	wait(0);
}
char    swap(cc)
	char    cc;
{
	register        int     i;
	register char tmp;

	tmp = 0;
	for(i=0;i<6;i++){
		cc <<= 1;
		tmp |= (cc & 0100);
		tmp >>= 1;
	}
	return(tmp | 0100);
}
synerr()
{
	fprintf(stderr,"syntax: gplp [-XX] [-i] file1 file2 ... filen\n");
	exit(1);
}
#ifndef NSQ
adjust(buf)
short *buf;
{
	register int i;
	short tbuf[33];

	for(i=0; i<L ;i++)              /* clear output buffer */
		tbuf[i] = 0;

	for(i=0; i<M ;i++)
		if(biton(buf,i))
			setbit(tbuf,(int) ( (60.0/72.0) * (float) i));

	for(i=0; i<L ;i++)              /* move adjusted buffer back    */
		buf[i] = tbuf[i];       /* into the original            */
}
biton(b,n)
short *b;
int n;
{
	register int index,offset;

	index = n >> 4;
	offset= n & 0x000f;
	return(b[index] & mask[offset]);
}
setbit(b,n)
short *b;
int n;
{
	register int index,offset;

	index = n >> 4;
	offset= n & 0x000f;
	b[index] |= mask[offset];
}
#endif
SHAR_EOF
cat << \SHAR_EOF > hpd.c
#define OLDHP
/*
	hpd - HP daemon program

	The CRC graphics package

	Carl Crawford
	Purdue University
	W. Lafayette, IN 47907

	March 1980
*/

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


#ifdef	vax
#include	<sys/file.h>
#endif	vax

#define	ETX	3	/* <etx> */
#define	ESC	27	/* <esc> */

#ifndef OLDHP
#include <sgtty.h>
struct sgttyb Tty,tty;
char pbuf[BUFSIZ];
#endif

int     flag,tickle;
char    ansbuff[32];	/* return from HP */
int     fd,fdi;		/* HP file descriptors */
char    buf[512];	/* input buffer */
char	name[100];	/* path to device */
int	c;		/* input character */
FILE	*ifd;		/* input to program */
int	net = 1;	/* 1=send output across network */
char	host[10] = "a";	/* last resort plotter site */

main(argc,argv)
	int     argc;
	char    **argv;
{
	register i,j;
	char *p;
	int	clean(),timeout();

#ifdef OLDHP
	/* find out default host for plotter */

	if((ifd = fopen("/usr/lib/graphics/hpd.site","r")) != NULL){
		fgets(host,10,ifd);
		fclose(ifd);
		host[strlen(host)-1] = 0;
		if(strcmp(host,"local") == 0){
			net = 0;
		}else{
			net = 1;
		}
	}

	/* see if -mHOST is on the command line */

	if(argc >= 2){
		if(argv[1][0] == '-' && argv[1][1] == 'm' && argv[1][2]){
			strcpy(host,argv[1]+2);
			net = 1;
			argc--;
			argv++;
		}
	}

	/* see if path to plotter is specified */

	if(argc == 2){
		strcpy(name,argv[1]);
	}else{
		strcpy(name,"/dev/plt0");
	}

	/* pipe to another machine if necessary */

	if(net){
		execl("/bin/ns","ns",host,"-S","/usr/lib/graphics/hpd",name,0);
		execl("/usr/bin/ns","ns",host,"-S","/usr/lib/graphics/hpd",name,0);
		execl("/usr/ecn/ns","ns",host,"-S","/usr/lib/graphics/hpd",name,0);
		fprintf(stderr,"hpd: can't exec ns\n");
		exit(1);
	}

	/* drive plotter local to this machine */

	/* find out name of machine */

	if((ifd=fopen("/etc/cpu","r")) != NULL){
		fgets(host,10,ifd);
		host[strlen(host)-1] = 0;
		fclose(ifd);
	}

	/* open plotter for input and output */

	fdi = open(name,0);
	if(fdi == -1)noplot();
	fd = open(name,1);
	if(fd == -1)noplot();

#ifdef	vax
	flock(fdi,LOCK_EX);
#endif	vax
#endif OLDHP

#ifndef OLDHP
	setbuf(stdout,pbuf);
	fdi = fd = 1;
	gtty(fd,&Tty);
	tty = Tty;
	tty.sg_flags &= ~ECHO;
	stty(fd,&tty);
#endif
	/* catch interrupts and reset plotter */

	if (signal(SIGHUP,SIG_IGN) != SIG_IGN)
		signal(SIGHUP,clean);
	if (signal(SIGINT,SIG_IGN) != SIG_IGN)
		signal(SIGINT,clean);
	if (signal(SIGQUIT,SIG_IGN) != SIG_IGN)
		signal(SIGQUIT,clean);

	i = 0;
	while(1){
		if((c = getchar()) != EOF)buf[i++] = c;
		if(i == 512 || c == EOF || c == '}'){

			if (write(fd,buf,i) < 0) {
				perror("hpd: write failed");
				exit(69);
			}

			flag = 1;
			alarm(180);	/* have driver time out */
			signal(SIGALRM,timeout);
			/* wait for buffer to empty out */

			while(flag){
				tickle = '\05';

				if (write(fd,&tickle,1) < 0) {
					perror("hpd: write failed"); 
					exit(69);
				}

				if ((i = read(fdi,ansbuff,30)) < 0) {
					perror("hpd: read failed");
					exit(69);
				}

				p = ansbuff;
				for(j = 0;j < i;j++)if(*p++ == 'G')flag = 0;
#ifdef OLDHP
				if(c == EOF && !flag)exit(1);
#else
				if(c == EOF && !flag)clean();
#endif
			}
				
			alarm(0);
			i = 0;
		}
	}
}

noplot()
{
	fprintf(stderr,"Can't open HP plotter on %s!%s\n",host,name);
	exit(1);
}

clean()
{
	int i = 0;

	/* reset plotter and put the pen back */

#ifdef OLDHP
	buf[i++] = ESC;
	buf[i++] = '.';
	buf[i++] = 'K';
#endif
	buf[i++] = ETX;
	buf[i++] = '}';
	buf[i++] = 'v';
	buf[i++] = 0100;
#ifndef OLDHP
	buf[i++] = ESC;
	buf[i++] = '.';
	buf[i++] = ')';
#endif
	write(fd,buf,i);

#ifndef OLDHP
	stty(fd,&Tty);
#endif

	exit(1);
}

timeout()
{
	fprintf(stderr,"Time out HP running on %s!%s\n",host,name);
	clean();
}
SHAR_EOF
cat << \SHAR_EOF > font-mods
The following changes, WHICH I HAVE NOT TESTED, are designed to all
the font that qplot/plot3d uses to be kept in memory, rather than on
disk.  The original package kept the font on disk, because it was
designed to run on a PDP-11...but most machines around today shouldn't
have a problem keeping the font in memory, and should enjoy a performance
increase as a result.  I will be installing and testing these changes
shortly (I hope) so I'll be able to judge for myself. :-)

These changes were done by Malcolm Slaney, who comments:

OK....I think only two files have changed.  They are charfont/genfont.c
and lib/symbol.c.  They are appended to this letter.  When these changes
are installed you can get rid of the font.5x7 that must be kept in a well
known place.   Oh, yes, there is a change to the charfont/Makefile.

----------------------------  charfont/genfont.c ---------------------
/*
	genfont - generate character font files

	The CRC graphics package

	Carl Crawford 
	Purdue University
	W. Lafayette, IN 47907

	October 1981
*/

/*
     The file generated by 'genfont' used to have the following format:

short  height     Default character height.
short  size       Bytes of core required to hold coordinates.
short  pnt[256]   Indexes to 1st coordinate of each symbol.
short  crd[size]  Coordinates of symbols

Where each crd[i] has the following format:

  EVSXXXXXXSYYYYYY   (a 'short' is assumed to be 16 bits)
  III     IIIIIIII
  III     I   I----- Y coordinate (sign magnitude format)
  IIIIIIIII
  II   I----- X coordinate (sign magnitude format)
  II----- Line segment visible flag (0=invisible, 1=visible)
  I----- 1=more coordinates; 0=last coordinate

The new output of this program is a file that can be included directly
into a C program.  Back in the days of PDP 11's it was important to
keep the program small.  Now it is better to reduce the amount of IO
needed and to make maintance easier by removing the character description
file.........................................Malcolm.... May 1987.

  The file used as input to 'genfont' as the following format:

  \n/x0,y0,v0/x1,y1,v2/.../xm,ym,vm<cr>
  .
  .
  .

  where:
	  'n' is the character in octal.
	  xi, i=1,2,..m is the x coordinate of the i'th segment
	  yi, i=1,2,..m is the x coordinate of the i'th segment
	  vi, i=1,2,..m is the visible indicator of the i'th segment
		v = 0 => invisible
		  = 1 => visible

*/

#include <stdio.h>

FILE	*ifd;			/* input file descriptor */
char	InputBuffer[512];	/* input character buffer */
short	OutputBuffer[512];	/* output buffer for packed coords. */
int	OutputBufferPointer;	/* Current position in output buffer */
int	FilePosition;		/* position within file */
int	XPosition;		/* x position */
int	YPosition;		/* y position */
int	VisibFlag;		/* visib flag */
short	PackedChar;		/* formed coordinate */
int	CharIndex;		/* character number */
struct{			/* header structure */
	short  height;
	short  coordsz;
	short  pntrlst[256];
}fontcom;

main(argc, argv)
	int  argc;
	char  **argv;
{
	int	i;

	if(argc != 2)
		synerr();
	if((ifd = fopen(argv[1],"r"))==NULL)
		err("can't open: ",argv[1]);

	for (i=0; i<256; i++)
		fontcom.pntrlst[i] = -1;

	/* get height of font */

	if(gread())
		err("can't read height","");
	fontcom.height = atoi(InputBuffer);

	printf("short pntcoord[] = {\n");
	/* loop through all the entries */
	OutputBufferPointer = 0;
	while(!gread()){
		if (*InputBuffer == '\\') {
			WriteCharacter(CharIndex);

			CharIndex = atoi(InputBuffer+1);
			CharIndex = (CharIndex/100*64) + 
					(((CharIndex/10)%10)*8) + 
					CharIndex%10;
			if (CharIndex<0 || CharIndex>255)
				err("invalid character number ",InputBuffer+1);
			fontcom.pntrlst[CharIndex] = FilePosition;
		}else{
			XPosition = atoi(InputBuffer);
			if(gread())err("incomplete coordinate specified","");
			YPosition = atoi(InputBuffer);
			if(gread())err("incomplete coordinate specified","");
			VisibFlag = atoi(InputBuffer)&&01;
			PackedChar = (VisibFlag<<14) | 
					((abs(XPosition)%128)<<7) | 
					(abs(YPosition)%128);
			if(XPosition < 0)
				PackedChar |= 0020000;
			if(YPosition < 0)
				PackedChar |= 0100;
			OutputBuffer[OutputBufferPointer++] = PackedChar;
			FilePosition++;
		}
	}

	/* clean up last character */
	WriteCharacter(CharIndex);

	/* write header */

	printf("};\n");
	printf("struct {\n");
	printf("	short	height;\n");
	printf("	short	pntrlst[257];\n");
	printf("} fontcom = { %d,", fontcom.height);
	for (i=0;i<256;i++){
		if (i%8 == 0)
			printf("\n	");
		printf("%d, ",fontcom.pntrlst[i]);
	}
	printf("0};\n");
	exit(0);
}

WriteCharacter(Index)
int	Index;
{
	int	i;
	if (OutputBufferPointer){
		printf("/* %c(0%03o) */\n",CharIndex, CharIndex);

		OutputBuffer[OutputBufferPointer-1] |= 0100000;
		for (i=0;i<OutputBufferPointer;i++)
			printf("%d,",OutputBuffer[i]);

		printf("\n");
		OutputBufferPointer = 0;
	}
}

gread()
{
	char	*c;

	c = InputBuffer;
	while((*c = fgetc(ifd)) != EOF){
		if(*c == ',' || *c == '/' || *c == '\n')return(0);
		c++;
	}
	return(1);
}

err(s1,s2)
	char	*s1,*s2;
{
	fputs(s1,stderr);
	fputs(s2,stderr);
	fputc('\n',stderr);
	exit(1);
}

synerr(){
	err("syntax: genfont <output file> <input file>","");
}

---------------------------  lib/symbol.c ---------------------
/*
	symbol - plot strings

	The CRC graphics package

	Carl Crawford
	Purdue University
	W. Lafayette, IN 47907

*/

#include	"crc.h"

symbol(x,y,height,str,angle)
	float x,y,angle;
	float height;
	char *str;
{
	int f,vis;
	int charfont();
	float xx,yy,t1,t2,ca,sa,d2r;
	static	float	oangle,oheight;
	static	int	first	= 1;	/* ==1 if first call	*/
	int	dollar;
	char    cc;

	if(DEV == TEK && DEVN == 2 && index(str,'$') == 0) {
	    register	int	i;
	    plot(x,y,3);
	    if(oangle != angle || first) {
		plotp(ESC);	/* Graphic text rotation	*/
		plotp('M');
		plotp('R');
		tint((int) angle); tint(0);
		oangle = angle;
		}
	    if(oheight != height || first) {
		plotp(ESC);	/* Graphic test size		*/
		plotp('M');
		plotp('C');
		tint((int)(190*height));
		tint((int)(265*height));
		tint((int)( 75*height));
		oheight = height;
		}
	    first = 0;
	    plotp(ESC);	/* Output graphic string	*/
	    plotp('L');
	    plotp('T');
	    tint(strlen(str));
	    for(i=0; str[i]; i++)
		plotp(str[i]);
	    return;
	    }

	d2r = 4.0 * atan(1.0) / 180.0;
	dollar = 0;
	angle *= d2r;
	sa = sin(angle);
	ca = cos(angle);
	plot(x,y,3);

	while(cc = *str){
		if(cc == '$' && dollar == 0){
			dollar = 1;
			str++;
		}
		else{
			if(dollar == 1){
				dollar = 0;
				cc += 0200;
			}

/*				/* kludge bad font defintition for '.' */
/*			if(cc == '.' && DEV <= MBIT)
/*				cc = ',';
 */
			do{
				f = charfont(cc,height,&xx,&yy,&vis);
				t1 = ca * xx - sa * yy;
				t2 = sa * xx + ca *yy;
				plot(t1+x,t2+y,3-vis);
			}
			while(f);
			x += t1;
			y += t2;
			str++;
		}
	}
}

/*   Charfont is a program that looks up the end points  of  line
segments  for  plotting  characters.   Each  time  'charfont'  is
called, it returns the relative coordinates, which when added  to
the  current  location yields the final end point for a line seg-
ment.  The initial point of the line segment is the current loca-
tion.   Whether the line segment is to be visible or not is indi-
cated by the returned value in "visflg". */

#include	"font.5x7.h"

charfont(symbol,height,x,y,visflg)
	char  symbol;
	float  height, *x, *y;
	int  *visflg;
{
	int  i;
	static short *pntr;
	static float  scale;
	register int  temp;

	/* find coordinate of first point */

	if (pntr == 0) {
		if ( (i=fontcom.pntrlst[symbol&0377]) == -1) {

			/* assume space if can't find it */

			if ( (i=fontcom.pntrlst[' ']) == -1) {

				/* set if no space */

				*x = 0.0;
				*y = 0.0;
				*visflg = 0;
				return(0);
			}
		}
		pntr = pntcoord+i;
		scale = height/fontcom.height;
	}
	temp = *pntr++;
	
	/* get X coordiante */

	*x = ((temp>>7)&077)*scale;
	if (temp&0020000)*x = (-(*x));

	/* get Y coordinate */

	*y = (temp&077)*scale;
	if (temp&0100)*y = (-(*y));

	/* get visib flag */

	*visflg = (temp&040000)>>14;

	/* check for last coordinate */

	if (temp < 0) {
		pntr = 0;
		return(0);
	}
	return(1);
}

/*  The font file used by 'fontinit' to read  in  the  data  for
	'charfont' has the following format:

short  height     Default character height.
short  pnt[256]   Indexes to 1st coordinate of each symbol.
short  crd[size]  Coordinates of symbols

Where each crd[i] has the following format:

  EVSXXXXXXSYYYYYY
  III     IIIIIIII
  III     I   I----- Y coordinate (sign magnitude format)
  IIIIIIIII
  II   I----- X coordinate (sign magnitude format)
  II----- Line segment visible flag (0=invisible, 1=visible)
  I----- 1=more coordinates; 0=last coordinate

*/


tint(i)
	int i;
{
	int negative,lo,hi1,hi2;
	negative = 1;
	if(i < 0){
		i = -i;
		negative = 0;
		}
	lo = (i % 16) + 32;
	if(negative)lo += 16;
	i /= 16;
	hi1 = (i % 64) + 64;
	i /= 64;
	hi2 = (i % 64) + 64;
	if(hi2 == 64){
		if(hi1 == 64){
			plotp(lo);
			return;
			}
		plotp(hi1); plotp(lo);
		return;
		}
	plotp(hi2); plotp(hi1); plotp(lo);
}

--------------------------- charfont/Makefile --------------------
CFLAGS=-O
GLIBDIR=/usp0/malcolm/crc/lib/graphics

all:		genfont font.5x7

font.5x7:	ifont.5x7 genfont
		genfont ifont.5x7 > font.5x7

genfont:	genfont.c
		cc $(CFLAGS) genfont.c -o genfont

install:	font.5x7
		cp font.5x7 ../lib/font.5x7.h
clean:
		rm -f font.5x7 genfont

SHAR_EOF
#	End of shell archive
exit$