[net.sources] rastermorph: vtroff to almost anything converter

mark@umcp-cs.UUCP (09/23/83)

: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting rasterblast.6'
sed 's/^X//' <<'//go.sysin dd *' >rasterblast.6
X.TH RASTERBLAST 6L local
X.UC 4
X.SH NAME
Rasterblast \- Raster graphics for Tektronix 4025 Terminal
X.SH SYNOPSIS
rasterblast [options] [file1 file2 . . .]
X.SH DESCRIPTION
X.LP
The input files contain graphics information in raster format.
The input file is interpreted bit-serial; the high order bit of the
first byte  is the first bit of the first line of the image, the next
bit is the second bit of the first line, and so forth.
The program assumes that each line of the image is 80 bytes (640 bits)
wide, as this is the width of the Tektronix screen, but this width
may be overriden.  Output is automagically piped through
teksync (see man 6 teksync).
X.SH OPTIONS
X.IP '-f'
Each image gets the full workspace, which is 80 * 8 bits wide and
53 * 14 bits high.   The terminal does not have enough graphics
capacity to display densly packed graphics on the entire workspace,
but most images actually encountered will work nicely.  This is the
default.
X.IP '-h'
Each image gets half the workspace, which is 80 * 8 bits wide and
26 * 14 bits high.  This is about one screen of data.
X.IP '-q'
Each image gets one quarter of the workspace, which is 80 * 8 bits wide
and 13 * 14 bits high.  This is enough for most rastermorph
output.
X.IP '-e'
Each image gets one eighth of the workspace, which is 40 * 8 bits wide and
13 * 14 bits high.  This is often enough for rastermorph output.
X.IP '-w <n>'
Changes the width of input lines to <n>.  If n is greater than 80, the
image will be truncated.
X.IP '-c'
Hardcopy.   This only works on the Tektronix terminal in the VAX room.
REMEMBER:  If you are not in the AI group, check with someone who
is first, and always log your
copies.  Always let the hardcopy unit warm up for 5 minutes before using
it, and assume the first hardcopy will be bad.
X.SH INPUT FILES
X.LP
If no input files are specified, input for a single image will
come from stdin.  If input files are specified,
they will be blasted onto the tektronix in sequence.  If
the half, quarter, or eighth screen options (above) are specified,
images will be put in successive portions of the screen. 
If the number of input files is greater than the number of
divisions of the workspace, as many as will fit are put in
successive workspaces.
X.LP
If hard copy is specified, a copy will be made of
successive workspaces.  Thus, if you specified
half screen images, hard copy, and three input files, the first
two images would go into the workspace, then a hard copy would
be made, then the workspace would be cleared; finally the last
image would be placed in the workspace and copied.
X.SH SEE ALSO
X.DL
rastermorph
troff
vcat
teksync
X.SH DIAGNOSTICS
If the file ends with an incomplete line, it
is truncated, and an error message is printed.
X.SH BUGS
If the image is too wide or too tall, the output is silently truncated.
X.SH AUTHOR
Craig Stanfill
University of Maryland
X.SH SOURCE FILES
Reside in /usr/cam/tektronix/rasterblast
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 rasterblast.6
	/bin/echo -n '	'; /bin/ls -ld rasterblast.6
fi
/bin/echo 'Extracting rasterblast.c'
sed 's/^X//' <<'//go.sysin dd *' >rasterblast.c
#include <stdio.h>
#define DEFAULTLEN 80
#define LINE	1
#define SPACE   2
#define BIT(bytes, x) (01 & (bytes[(x) / 8]) >> (7 - ((x) % 8)))

#define FULL	1
#define HALF	2
#define QUARTER 4
#define EIGHTH	8

#define TRUE	1
#define FALSE	0

FILE *popen();

main(argc, argv)
int argc;
char **argv;
{
	FILE *output;
	int count;
	int size = FULL;
	int argn = 1;
	int hardcopy = FALSE;
	int len = DEFAULTLEN;

	while ((argn < argc) && (argv[argn][0] == '-'))
		{
		if (strcmp("-f", argv[argn]) == 0)
			size = FULL;
		else if (strcmp("-h", argv[argn]) == 0)
			size = HALF;
		else if (strcmp("-q", argv[argn]) == 0)
			size = QUARTER;
		else if (strcmp("-e", argv[argn]) == 0)
			size = EIGHTH;
		else if (strcmp("-c", argv[argn]) == 0)
			hardcopy = TRUE;
		else if (strcmp("-w", argv[argn]) == 0)
			{
			if(1 != sscanf(argv[argn+1], "%d", &len))
				{
				fprintf(stderr,
					"usage: rasterblast -w <number>\n"
					);
				exit(1);
				}
			argn++;
			}
		else	{
			fprintf(stderr, "usage: rasterblast");
			fprintf(stderr, "[-f][-h][-q][-e] files ...\n");
			exit(1);
			}
		argn++;
		}

	output = popen("/usr/local/teksync", "w");

	if(argv[argn][0] == '\000')
		blast_raster("", 0, size, hardcopy, len, output);

	for(count = 0; argv[count+argn][0] != '\000'; count++)
		blast_raster(argv[count+argn],
			     count, size, hardcopy, len, output
			     );

	if(hardcopy && ((count % size) != 0))
		make_copy(output);
	pclose(output);
	}

blast_raster(infile, count, size, hardcopy, len, output)
FILE *output;
char *infile;
int  count, size, hardcopy;
int len;
	{
	int x,y;
	int lastx;
	int mode;
	int byte[4000];

	FILE *input;

	graphic(size, count, output);

	if(infile[0] == '\000')
		input = stdin;
	else
		{
		if(NULL == (input = fopen(infile, "r")))
			{
			fprintf(stderr, "could not open %s\n", infile);
			exit(1);
			}
		}
	for (y = 0; !feof(input); y++)
		{
		for(x = 0; x < len; x++) byte[x] = 0;
		for (x = 0; x < len; x++)
			{
			byte[x] = getc(input);
			if ((x != len - 1) && (feof(input)))
			    {
			    fprintf(output, "\033mon\n");
			    fprintf(output, "Last line too short; truncated\n");
			    byte[x] = 0;
			    break;
			    }
			}

		lastx = 0;
		mode  = SPACE;
		for (x = 0; x < len * 8; x++)
			{
			if ((mode == LINE) && ! BIT(byte, x))
				{
				mode = SPACE;
				vector(lastx, y, x-1, y, size, output);
				}
			else if ((mode == SPACE) && BIT(byte, x))
				{
				mode = LINE;
				lastx = x;
				}
			}
		if (mode == LINE)
			vector(lastx, y, len * 8 - 1, y, size, output);
		}
	if(hardcopy && ((count % size) == size-1))
		make_copy(output);
	}


graphic(size, count, output)
int size;
int count;
FILE *output;
{
	int row, col, height, width;
	if((count % size) == 0)
		fprintf(output, "\033wor 30\n");
	
	switch (size) {
		case HALF:	row = (count % 2) * 26 + 1;
				col = 1;
				height = 26;
				width  = 80;
				break;

		case QUARTER:	row = (count % 4) * 13 + 1;
				col = 1;
				height = 13;
				width = 80;
				break;

		case EIGHTH:	row = ((count / 2) % 4) * 13 + 1;
				col = (count % 2) * 40 + 1;
				height = 13;
				width = 40;
				break;


		case FULL:
		default:
				row = 1, col = 1;
				height = 53; width = 80;
				break;
		}

	fprintf(output, "\033gra %d %d %d %d\n", row, row + height - 1,
					col, col + width  - 1
					);
	fprintf(output, "\033wor\n\033jum %d %d\n\033mon\n", row, col);
	}


		



vector(x1, y1, x2, y2, size, output)
int x1, y1, x2, y2;
int size;
FILE *output;
{
	int max;

	switch (size) {
		case FULL:
		case HALF:
		case QUARTER:
			max = (53 * 14) / size - 8;
			break;
		case EIGHTH:
			max = (53 * 14) / 4 - 8;
			}

	fprintf(output, "\033vec %d %d %d %d\n", x1+1, max-y1, x2+1, max-y2);
	}

make_copy(output)
FILE *output;
{
	fprintf(output, "\033wor\033jum\n\033hco w\n\033mon\n");
	}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 rasterblast.c
	/bin/echo -n '	'; /bin/ls -ld rasterblast.c
fi
/bin/echo 'Extracting rastermorph.6'
sed 's/^X//' <<'//go.sysin dd *' >rastermorph.6
X.TH RASTERMORPH 6L
X.SH NAME
rastermorph \- draw a raster picture on a tek 4025, printer, etc.
X.SH SYNOPSIS
X.B rastermorph
[ options ] <inputraster >outputraster
X.SH DESCRIPTION
X.I Rastermorph
is a program to transform a raster for output on various devices.
The raster must be represented by a stream of bytes, with a fixed
number of bytes representing each horizontal raster line.
The stream is interpreted bit-serial; the high order bit of the
first byte is the first bit of the first line of the image, the next
bit is the second bit of the first line, and so forth.
The three output devices currently supported are the tektronix 4025, the
printronix printer in plot mode, and an arbitrary ordinary device.
The default settings are correct for sending vcat'ed output
from troff to the tektronix or printronix.
X.PP
Because output from 
X.I rastermorph 
with the 
X.BI \-D tek
option is a bit serial byte stream,
X.I rastermorph
output with the 
X.BI \-D tek
option can be used as new rastermorph input.
For example, if file 
X.I temp
was created with the command:
X.br
X.ti +5
rastermorph -o80 -Dtek < input > temp
X.br
then the following command causes 
X.I temp2
to be identical to 
X.I temp :
X.br
X.ti +5
rastermorph -i80 -b -v -Dtek < temp > temp2
X.br
Other examples are below.
X.PP
X.SH OPTIONS
X.TP
X.BI \-D device
X.I device
is one of 'term', 'tek', or 'print', specifying output in a form
suitable for a terminal, a tektronix 4025, or the printronix in
plot mode, 
respectively.  Output for a terminal represents 'on' bits
with asterisks, 'off' bits with blanks.  
Output for the tektronix is in the input format expected by
X.I rasterblast .
X.TP
X.BI \-v
Turn off skipping of the vcat header.  Use this option for
non-vcat input.
If 
X.I \-v
is not specified, then the following action is taken:
the first three bytes in the file are skipped, followed
by any characters up to the first zero byte.  The
character fudge (see the
X.I -f
option, below) is then applied to the remainder of the input file. 
X.TP
X.BI \-b
Turn off skipping of initial input lines of all zero bytes.
This skipping is normally applied after the vcat header and character 
fudge options.
X.TP
X.BI \-r
Give no raster output: only report the number of raster lines 
in the image.  This will include initial empty lines if the 
X.I -b
option is also specified.  It never includes trailing empty lines.
This option allows an intelligent choice for the 
X.I \-l
argument (see below), which can significantly speed up processing and reduce
file space.
X.TP
X.BI \-f num
X.I num
is the number of extra characters to fudge from the front of the file.
X.B Rastermorph 
assumes that the input is divided into fixed length records
of length specified by the -i option.
The -f option is good for shifting a picture left or right.
The default is 25.
X.TP
X.BI \-i num
X.I num
is the number of characters in each input record.
X.I Num
times 8 is the horizontal bit resolution of the input raster.
The default is 264.
X.TP
X.BI \-o num
X.I num
is the number of characters in each output record.
X.I Num
times 8 is the horizontal bit resolution of the output raster.
The default is 80.
X.TP
X.BI \-l num
X.I num
is the maximum number of lines in the output.  The default is a very large
number.
Empty lines at the beginning of a picture are automatically
skipped (but see the
X.I \-b
option, above).
Use the
X.I \-l
option to skip trailing empty lines.
The 
X.I -r 
option is useful for setting 
X.IR -l .
X.SH EXAMPLES
X.br
X.nf 
X.na
troff -t | /usr/lib/vcat -t | rastermorph -Dtek | rasterblast
X.fi 
X.ad
X.sp
troff -t | /usr/lib/vcat -t | rastermorph -Dtek >temp 
rastermorph -r < tekdemo | awk '{print $$3}' > numlines
rastermorph -b -v -Dtek -l`cat demolines` < temp > tekdemo
rm temp
X.sp
troff -t | /usr/lib/vcat -t | rastermorph -Dprint | lpr
X.SH SEE\ ALSO
rasterblast
X.br
unexpand - to speed up output when outputing to a terminal.
X.SH AUTHOR
Mark Weiser
X.SH BUGS
The
X.I -f
option is intended to be used as a picture shift, but actually is 
a picture rotate.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 rastermorph.6
	/bin/echo -n '	'; /bin/ls -ld rastermorph.6
fi
/bin/echo 'Extracting rastermorph.c'
sed 's/^X//' <<'//go.sysin dd *' >rastermorph.c
#include <stdio.h>
#define TEK 1
#define TERM 2
#define PRINT 3
int	outdev=0,
	num_col_in=264,
	column_fudge=25,
	num_col_out=79,
	max_lines=2000000000,
	report = 0,
	blankskip=1,
	vcat = 1;
char *rast;
xmain()
{
printprint(0x1d);
printprint(0x50);
printprint(0xff);
printprint(0xaa);
printprint(0);
}
main(argc,argv)
char **argv;
	{
	register char c;
	int foundchar,i,j,k,colmax,rowmax;
	char *calloc();

	for (i=1; i<argc; i++)
		{
		if (argv[i][0] == '-')
			{
			/* options:
			   i,o,f,l,v,b
			   -b     -  turns off initial blank line skip.
			   -v     -  turns off skip of vcat header.
			   -inum  -  num = number of chars per input line.
			   -onum  -  num = number of chars per output line.
			   -lnum  -  num = maximum number of output lines.
			   -fnum  -  num = number of extra chars to fudge 
					   from the front of the file.
					   (This is applied after the first
					   zero char is found.)
					   
			*/
			switch(argv[i][1])
				{
				case 'i':
				   {
				   num_col_in = atol(&argv[i][2]);
				   break;
				   }
				case 'f':
				   {
				   column_fudge = atol(&argv[i][2]);
				   break;
				   }
				case 'o':
				   {
				   num_col_out = atol(&argv[i][2]) - 1;
				   break;
				   }
				case 'l':
				   {
				   max_lines = atol(&argv[i][2]);
				   break;
				   }
				case 'v':
				   {
				   vcat = 0;
				   break;
				   }
				case 'b':
				   {
				   blankskip = 0;
				   break;
				   }
				case 'r':
				   {
				   report = 1;
				   break;
				   }
				case 'D':
				   {
				   if (! strcmp(&argv[i][2],"term"))
				      outdev = TERM;
				   else if (! strcmp(&argv[i][2],"tek"))
				      outdev = TEK;
				   else if (! strcmp(&argv[i][2],"print"))
				      outdev = PRINT;
				   else
				      {
				      fprintf(stderr,"Output device '%s' not recognized.\n",argv[i]);
				      fprintf(stderr,"Please use one of 'tek', 'term', or 'print'.\n");
				      exit(1);
				      }
				   break;
				   }
				default:
				   {
				   fprintf(stderr,"Parameter '%s' was ignored.\n",argv[i]);
				   break;
				   }
				}
			}
		else
			{
			fprintf(stderr,"Parameter '%s' was ignored.\n",argv[i]);
			}
		}
	if (! outdev)
	   {
	   fprintf(stderr,"Output device not specified: '-Dterm' assumed.\n");
	   outdev = TERM;
	   }
	
#ifdef DEBUG
fprintf(stderr,"outdev %d, num_col_in %d, column_fudge %d, num_col_out %d, max_lines %d.\n",outdev,num_col_in,column_fudge,num_col_out,max_lines);
#endif
	rast=(char *)calloc(num_col_in,sizeof(char));
	colmax = 0;
	if (vcat)
		{
		/* Special processing for the vcat header:
		   skip a few chars */
		getchar(); getchar(); getchar();
		/* look for the end of the nl's */
		while ((c=getchar()) != 0)
			;
		ungetc(c,stdin);
		}
	for(j=0; j<column_fudge; j++) 
		getchar();
	foundchar = 0;
	if (! blankskip)
		foundchar = 1;
	rowmax = -1;
	for (j=0; j<max_lines; j = foundchar ? j+1 : 0)
		{
		colmax = -1;
		for (i=0; i<num_col_in; i++)
			{
			if ((c = getchar()) == EOF)
				goto done;
			rast[i] = c;
			if (c != 0)
			   {
			   if (i > colmax)
				colmax = i;
			   if (i <= num_col_out)
				rowmax = j;
				foundchar = 1;
			   }
			}
		if (!report && foundchar)
			{
			rasterout(rast,colmax);
			}
		}
done:
	if (report)
		{
		printf("Picture was %d lines long.\n",rowmax+1);
		}
	}

rasterout(rast,colmax)
char *rast;
	{
	int i,k;
	for (i=0; i<=colmax; i++)
	   {
	   switch(outdev)
		{
		case PRINT:
			{	
			printprint(rast[i]);
			break;
			}
		case TEK:
			{
			printf("%c",rast[i]); 
			break;
			}
		case TERM:
			{
			starprint(rast[i]);
			break;
			}
	   	}
	   }
	switch(outdev)
		{
		case PRINT:
		     {	
		     put_pixel(-1);
		     break;
		     }
		case TEK:
		     {
		     for (k=colmax+1; k<80; k++)
			     printf("%c",0);
		     break;
		     }
		case TERM:
		     {
		     printf("\n");
		     break;
		     }
		}
	}

printprint(c)
char c;
	{
	int i;
	for (i=7; i>=0; i--)
		{
		put_pixel((c >> i) & 1);
		}
	}

int byte=64,count=0;

put_pixel(pixel)
register int pixel;
{
	if(pixel<0)
	{
		if(count)putc(byte,stdout);
		byte=64;
		count=0;
		putc(5,stdout);
		putc('\n',stdout);
		return;
	}
	byte|=pixel<<(count++);
	if(count>5)
	{
		putc(byte,stdout);
		byte=64;
		count=0;
	}
}



starprint(c)
char c;
	{
	int mask;
	mask = 0x80;
	for(mask=0x80; mask!=0; mask = mask >> 1)
	   {
	   if ((mask & c) == 0)
		{printf(" ");}
	   else
		{printf("*");};
	   }
	}

char **
malloc2d(first,last,elsize)
{
char **out,*calloc();
int i;
out = (char **)calloc(first,sizeof(char *));
for(i=0; i<first; i++)
	out[i]=calloc(last,elsize);
return(out);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 rastermorph.c
	/bin/echo -n '	'; /bin/ls -ld rastermorph.c
fi
/bin/echo 'Extracting teksync.6'
sed 's/^X//' <<'//go.sysin dd *' >teksync.6
X.TH TEKSYNC 6L local 
X.UC 4
X.SH DESCRIPTION
teksync - synchronize communication with tektronix 4025 terminals.
X.SH SYNOPSIS
teksync [file]
X.SH EXPLANATION
The tektronix terminals buffer their input.  Under some circumstances,
(such as when plotting massive amounts of data), the buffer overflows
and the terminal crashes.  Teksync prevents this.
Input comes from the single argument (defaults to standard input).
Output goes to standard output, which must be a terminal.  When this
is going on, echo is turned off.
X.SH AUTHOR
Craig Stanfill
X.SH BUGS
It is not possible to specify the terminal as (for instance) a second
argument.  I tried to make it work, but it wouldn't.
X.SH SEE ALSO
tektronix(6), plot(1G)
X.SH FILES
X/usr/local/lib/teksync.run
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 teksync.6
	/bin/echo -n '	'; /bin/ls -ld teksync.6
fi
/bin/echo 'Extracting teksync.c'
sed 's/^X//' <<'//go.sysin dd *' >teksync.c
#include <stdio.h>
#define COMMAND_CHAR '\033'
#define SYNCFREQUENCY 2000

main(argc, argv)
int argc;
char *argv[];
{
	FILE *out,*in,*sync;
	char c;
	int charcount;
	int in_command, in_vec, in_int, intcount;
	int old1, old2;


	if (argc == 1)
		{
		in = stdin;
		out= stdout;
		/*
		if(!isatty(1))
			{
			printf("teksync must be last element of pipe\n");
			exit(1);
			}
			*/
		sync = fopen("/dev/tty", "r");
		}
	else if (argc == 2)
		{
		if(NULL == (in = fopen(argv[1], "r")))
			{
			printf("could not open %s\n", argv[1]);
			exit(1);
			}
		out = stdout;
		if(!isatty(1))
			{
			printf("teksync must be last element of pipe\n");
			exit(1);
			}
		sync = fopen(ttyname(1), "r");
		}	
	else
		{
		printf("usage tekwrite [file]\n");
		exit(1);
		}
	charcount = 0;
	in_command= 0;
	while (EOF != (c = getc(in)))
		{
		charcount++;
		if (charcount > SYNCFREQUENCY)
			{
			if (!in_command)
				{
				fprintf(out, "%crep 00\n", COMMAND_CHAR);
				while (';' != getc(sync));
				charcount = 0;
				}
			/* else if (in_vec && ! in_int && (intcount % 2 == 0))
				{
				fprintf(out, "%crep 00\n", COMMAND_CHAR);
				while (';' != getc(sync));
				charcount = 0;
				fprintf(out, "%cvec %d %d ", 
					COMMAND_CHAR,
					old2,
					old1
					);
				}
				*/
			}
		putc(c, out);
		switch (c) {
		   case COMMAND_CHAR : in_command = 1;break;
		   case 'V':
		   case 'v': if (in_command == 1) in_command++;
			     else in_command = 5;
			     break;
		   case 'E':
		   case 'e': if (in_command == 2) in_command++;
			     else in_command = 5;
			     break;
		   case 'C':
		   case 'c': if (in_command == 3)
				{
				in_vec = 1;
				in_int = 0;
				intcount = 0;
				}
			     else in_command = 5;
			     break;
		   case '\n':
		   case ';':
		   case '\015': in_command = 0; in_vec = 0; break;
		   default:  if ( ! in_vec) break;
			     if (('0' <= c) && (c <= '9'))
				{
				if ( ! in_int) 
					{
					in_int = 1;
					old2 = old1;
					old1 = 0;
					}
				old1 = old1 * 10 + (c - '0');
				}
			     else
				{
				if (in_int)
					{
					in_int = 0;
					intcount++;
					}
				}
		   }
		}
	}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 teksync.c
	/bin/echo -n '	'; /bin/ls -ld teksync.c
fi
-- 
spoken:	mark weiser
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!mark
CSNet:	mark@umcp-cs
ARPA:	mark.umcp-cs@UDel-Relay