[comp.sources.unix] REPOST v14i020: Device-independant graphics system, with drivers

rsalz@bbn.com (Rich Salz) (04/06/88)

Submitted-by: Joe Dellinger <joe@hanauma.STANFORD.EDU>
Posting-number: Volume 14, Issue 20
Archive-name: vplot/part15

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 15 (of 24)."
# Wrapped by rsalz@fig.bbn.com on Fri Mar 25 11:47:25 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Virtual_device/vplib/vppen.mn' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Virtual_device/vplib/vppen.mn'\"
else
echo shar: Extracting \"'Virtual_device/vplib/vppen.mn'\" \(9204 characters\)
sed "s/^X//" >'Virtual_device/vplib/vppen.mn' <<'END_OF_FILE'
X.TH Vppen 9 "February 12 1988"
X.SH NAME
vppen \- VPLOT filter for VPLOT
X.PP
X.SH SYNOPSIS
vppen  plot_file1 [plot_file2 ...] [options] > vplot_out
X.PP
Seplib version: Vppen < Plot1.h [Plot2.h ...] [options] > Vplot_out.h
X.PP
X.SH DESCRIPTION
All
X.B pen
filters accept input in the
X.B vplot
graphical metalanguage.
X.B Vppen
is the filter for the ``virtual vplot device''.
Both its input and output are vplot. Why is this useful?
The full set of pen options allows you
to rotate, combine, clip, scale, shift, etc, plots. At some point you may
make something on your screen using these options which
you would really like to have as a single
file. How to do this? Simply use the same set of options with vppen.
Vppen will draw the same picture, but will save the picture as a vplot file.
You can then rotate, combine, clip, etc this new plot.
X.PP
Vppen also has options to do useful things such as centering, making
arrays of plots, and finding plot statistics.
X.PP
X.SH VIRTUAL DEVICE DESCRIPTION
The virtual vplot device has a screen 10.24 inches (STANDARD_HEIGHT in <vplot.h>)
high, with a height/width ratio of 3/4 (SCREEN_RATIO in <vplot.h>). It has
X600 pixels to the inch (RPERIN), and has 256 colors, all settable.
It knows how to do its own clipping and has ``hardware text'', etc.
This is the device that vppen ``plots'' on.
X.PP
Ideally vplot coming into
vppen with no options set should be passed on through completely unchanged.
This is true (except for a few exceptions like polygon fill patterns and such)
if both the input and output are absolute style. (If you don't know what
terms like ``absolute style'' mean, read the other vplot documentation.)
For this reason, vppen by default uses ``size=absolute'' and outputs absolute style
output. This is convenient if you are repeatedly sending files through
vppen, but you may want to override it otherwise.
X.PP
X.SH GENERIC OPTIONS
X.PP
For a list of all generic
pen options, which also apply to vppen, do ``man pen''.
Generic options that you may find particularly useful are:
X.PP
X.TP
X.B erase
The erase=once option is useful when combining several plots into one.
X(Otherwise you're likely to have the entire screen cleared before each plot.)
X.PP
X.TP
X.B xshift, yshift
These options are useful for positioning a plot.
X.PP
X.TP
X.B scale
The scale options are useful in getting a plot the right size.
X.PP
X.TP
X.B frame
Useful for putting a box around the edge of the clipping window.
X.PP
X.TP
X.B xwmin, xwmax, ywmin, ywmax
Useful for clipping out just the part of the plot you want.
X.PP
X.TP
X.B rotate
Useful for rotating a plot, usually by 90 degrees.
X.PP
Remember that ALL generic pen options apply, not just the ones listed
above.
Only vppen-specific options will be covered in the next section.
X.PP
X.SH VPPEN-SPECIFIC OPTIONS
X.PP
X.TP 
X.B gridnum=0 gridsize= grid=-1
These commands are provided as a quick way to make a grid of plots.
Gridnum=X,Y divides the output screen into X rectangles
horizontally and Y rectangles vertically. If Y is not specified, then
it is set equal to X. If X is zero, then gridding is not done.
Gridsize=X,Y sets the X and Y dimensions of each rectangle
in inches.
If the gridsize is not set, then the array of rectangles will be sized to
fill the screen.
Grid sets the fatness of a white border drawn around each rectangle.
If it is negative, no border will be drawn.
Each rectangle is its own miniature device screen. Clipping is set
to the edges of this screen just as it is for the full-sized screen.
All generic commands such as rotate, xshift, etc, will apply to each
rectangle and NOT to the plot as a whole.
Each rectangle contains one (or zero) plot. When an erase command is received,
nothing will be erased but instead plotting will begin in the next rectangle,
and a ``break'' command will be output.
The rectangles are filled left to right and then top to bottom. It is not
an error to have more plots that you have room for, the rectangles will
march right off the bottom of the page, but they will still be there.
If you have less plots than you have room for some of the rectangles will
be empty. Normally the generic pen option ``size'' defaults to ``absolute''
in vppen, as it does on most hardcopy devices. This doesn't work very well
if your screen is a few inches on a side, so if the gridnum option is used
X``size'' will instead default to the normal screen-device default ``relative''.
For similar reasons, the gridnum option will also change the default options
to ``big=n'' and ``vpstyle=n''.
You may find it useful to use size=relative when plotting a gridded vplot file.
X.PP
X.TP
X.B big=y
If big=y, the output screen is expanded to the entire range of possible
vplot coordinates, -54.6 to +54.6 inches (VP_MAX in <vplot.h>) in each
direction. A coordinate shift is thrown in to move the origin back to (0,0)
where it belongs. This has some good effects and some bad effects.
The chief good effect is that nothing is clipped at the edge of the
screen, since the ``screen'' contains all possible vplot coordinates.
X(It is still possible for things to be clipped, but only at
the edge of the vplot coordinate system.)
The chief bad effect is that rotated style objects will be positioned at the
top of the expanded screen, which is to say 54 inches away from the origin
and right at the edge of the largest coordinates vplot can handle.
Thus big=y with rotated style input is an all around bad idea; the
solution is to make one pass through vppen with big=n to turn it
into non-rotated style. Another bad thing to do is to try to mix big=y
with size=relative. You get a very big plot indeed!
X.PP
X.TP
X.B stat=n
If stat=y, no vplot will be written to standard out. Instead vppen will find
the largest and smallest coordinates used in each input file and print
out a summary of the height, width, etc, information. Statistics are also
kept for all the input plots together as a whole.
X.PP
X.TP
X.B align=uu
This option is used to left, right, top, bottom, or center justify a plot.
The format is align=xy, where ``x'' controls the left-right justification
and ``y'' controls the up-down justification. ``X'' is one of:
X.br
X	l	for left justified
X.br
X	r	for right justified
X.br
X	c	for centered
X.br
X	u	for unaligned, (no shifting done)
X.br
and ``Y'' is one of:
X.br
X	b	for bottom justified
X.br
X	t	for top justified
X.br
X	c	for centered
X.br
X	u	for unaligned, (no shifting done)
X.br
X
The align point is set to have coordinate (0,0). Note that points shifted
into negative coordinates are still there, they just may be off the
screen. (Use the big=y option to avoid clipping problems.)
The ``xcenter=0, ycenter=0'' option is very handy to use when
plotting ``aligned'' files.
X.PP
X.TP
X.B vpstyle=y
Normally vppen inserts a ``set style absolute'' vplot command at the beginning
of every plot frame. If vpstyle=n, it does not do this.
X.PP
X.TP
X.B dumb=n
If dumb=y, then all output will be digested down to the bare essentials -
color changes, erases, moves, draws, and nothing else.
X.PP
X.TP
X.B blast=y bit=0
If blast=n, then raster output will be compacted as much as possible as it
is being written. This is slower, but the resulting file may be substantially
smaller. If bit=integer > 0, then bit raster will be used, with the integer
giving the color number of the ``on'' pixels.
X.PP
X.SH COMMENTS
X.PP
Some options (stat, align) will not work with piped input, as they involve
making repeated passes through the input vplot files.
X.PP
Beware letting vppen dump raw binary vplot to your screen!
X.PP
Vppen outputs an initial erase only if an initial erase is forced from the
command line (erase=yes (the default) or erase=once).
X.PP
Set the text font, precision, etc, that you want on your first pass
through vppen, because it will be hardwired after that.
X.PP
Some vplot commands as yet have no corresponding command in libvplot, and
so vppen currently eats these. Provisions are made in the code for the
day when these commands will exist; they just have to be uncommented out.
X.PP
Vppen has four uses. One is as a sort of cheap vplot editor. The second
is as a filter for digesting complicated things into the bare essential
moves and draws. The third is that it provides a library of routines
that can be linked into other vplot filters (perhaps an interactive vplot
editor), so that they can easily ``dump a hardcopy of the screen''.
X(The code has been carefully written with this in mind.)
Lastly, it provides an example of how to do several tricky things:
First, how to support a device that can do
EVERYTHING in ``hardware'', and so needs to have the highest possible
level of support. Second, how to do multiple passes through the vplot
input (again something paving the way for a vplot editor).
Third, how to find the length of
a text string without actually drawing it.
X.PP
X.SH SEE ALSO
pen, libvplot, vplot
X.PP
X.SH COPYRIGHT
The Vplot source is copyrighted. Please read the copyright which can be
found in the accompanying Vplot manual page.
X.PP
X.SH AUTHOR
Joe Dellinger
X.PP
X.SH BUGS
It is not clear how options such as ``stat'', ``align'', and ``gridnum''
behave when used in combination. Absolute sizing can be a pain.
There are still rotated style plots in common use, which have problems
with big=y.
END_OF_FILE
if test 9204 -ne `wc -c <'Virtual_device/vplib/vppen.mn'`; then
    echo shar: \"'Virtual_device/vplib/vppen.mn'\" unpacked with wrong size!
fi
# end of 'Virtual_device/vplib/vppen.mn'
fi
if test -f 'Vplot_Kernel/Documentation/vplotraster.mn' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Vplot_Kernel/Documentation/vplotraster.mn'\"
else
echo shar: Extracting \"'Vplot_Kernel/Documentation/vplotraster.mn'\" \(9882 characters\)
sed "s/^X//" >'Vplot_Kernel/Documentation/vplotraster.mn' <<'END_OF_FILE'
X.TH vplot_raster 9 "4 June 1987"
X.SH "NAME"
vplot raster \- A guide to using raster plotting commands in vplot graphics
X
X.SH "DESCRIPTION"
Despite the name
X.B vplot
X(where the `v' once stood for `vector')
the vplot metalanguage includes raster plotting capability.
This document describes more detailed aspects of raster plotting
than are included in the
X.B vplot
manual page.
X.PP
A raster is a rectangular array of bytes.
The value stored in each byte
determines the number of the color that is to be displayed
at the corresponding location in the raster.
The mapping of array values to colors
is set up by the programmer by calling the
X.B vp_coltab()
routine, which may be found in
X.B libvplot.a.
To define a color using
X.B vp_coltab(),
the red, green, and blue components of the color are each specified
as floats from 0. to 1., with 1. being fully on and 0. being fully off.
The corresponding `grey level' for grey-scale
devices is given by the formula
floor((4 * green + 2 * red + blue + 6)/7).
X.PP
Each device has a number of settable colors (call this number N).
Calling
X.B vp_coltab()
for colors 0 through N-1 will redefine the desired color.
If you attempt to define a color X outside of the range 0 through N-1,
X.B vplot
will pick the color number in the range 0 through N-1 that is closest
to color X in color and map all requests for color X to that color number. 
Whenever any color in the range 0 through N-1 is changed,
all the mappings will be recalculated
X(although of course what is already drawn cannot be changed).
Note that color 0 is the background color.
Other colors will be mapped to color 0 only if the match is exact.
X.PP
As an example, consider the common case where an eight bit per pixel
raster is to be displayed using a grey scale, ranging from black to white,
and various colors are to be used to display labels on the plot.
The calling program should call
X.B vp_coltab
to allocate the first few color numbers to the label colors,
then fill the remainder of the lower half of the color scale
X(up to color 255)
with the needed grey scale colors.
Because different devices have different numbers of settable colors,
it is important to order the grey scale colors so that the most important
ones such as black (0, 0, 0), white (1, 1, 1), and medium grey
X(.5, .5, .5) come first.
Then whatever the number of settable colors,
the raster reproduction will be as good as possible.
More explicitly,
the calling program should repeatedly cover the 0 to 1 range
with a decreasing step size,
taking care not to repeat colors, i.e.,
X(0, 0, 0),
X(1, 1, 1),
X(.5, .5, .5),
X(.25, .25, .25),
X(.75, .75, .75),
X(.125, .125, .125),
X(.375, .375, .375),
etc.
Then in the upper half of the color scale (colors 256 through 511),
the calling program can define the grey scale colors
corresponding to the raster array values,
setting, for example,
color 256 to (0, 0, 0),
color 257 to (1./255., 1./255., 1./255.),
color 258 to (2./255., 2./255., 2./255.),..., and
color 511 to (1, 1, 1).
The 
X.B offset
parameter in
X.B vp_raster
is used to reference these colors.
For this example,
X.B offset=256
would be the appropriate specification.
Then for each value in the raster array,
X.B vplot
adds 256 to it to find the grey scale color defined for that value,
then (using the mapping to available colors) uses the available color
that best matches the requested color to plot that raster element.
X.PP
Monochrome devices such as plotters are unable to give a good
representation of grey rasters because of the lack of definable colors.
For such devices,
X.B vplot
can dither the image to simulate a grey or continuous-tone image.
Briefly, dithering methods represent
a continuous-tone image on a bilevel display
by varying the threshold value that determines
whether a given output pixel is set to `on' or `off'
given its value on input. 
Consider the above example of an eight bit per pixel raster.
This means that, on an appropriate graphics display,
each pixel can take on any of 256 different intensity levels.
The task of dithering is to represent such an image
on a device that has only two different intensity levels.
A crude way of transforming from continuous-tone to bilevel form
would be to divide the continuous-tone intensity range in half,
and set input intensities 0-.5 to `off' and .5-1 to `on'. 
But this would neglect most of the continuous-tone information.
Vplot has four better ways of performing this transformation built in.
X.PP
X.B Random dither
randomly selects a threshold value for determining whether a given output
pixel is set to `on' or `off'.
This preserves much of the continuous-tone information,
but gives a rather `noisy' image,
since within a constant-intensity region of the raster,
some pixels will be set to both `on' and `off' due to the random thresholds.
X.PP
X.B Ordered dither
applies a sixteen by sixteen matrix of threshold values to the input
image in checkerboard fashion.
This gives a much more regular appearance on output. 
X.PP
The
X.B minimized average error method 
or
X.B Floyd-Steinberg algorithm 
takes the `error' in converting a single pixel to bilevel form
into account when converting neighbors,
with the goal of minimizing the difference
between the continuous-tone and bilevel images.
This method generally produces the best representation of the original image,
though it is the slowest of the four algorithms.
X.PP
X.B Digital halftoning
is an ordered-dither scheme that is designed for images that are
going to be reproduced photographically. The high-frequency alternation
of black and white samples that is used to produce grey levels in
ordered dither is not reproduced faithfully by photocopiers.
This algorithm uses lower-frequency alternation of samples to produce
the same grey level. While the resulting image has a coarser texture,
it will be reproduced accurately. This method is only recommended for
images that will be reproduced photographically.
X.PP
The dithering method can be selected by use of the 
X.B dither 
parameter with any
X.B pen
filter.
The available dithering methods are:
X 
X.br
X             0    No dither (0=off, anything else=on)
X.br
X             1    Random Dither
X.br
X             2    Ordered Dither
X.br
X             3    Minimized Average Error Method
X.br
X             4    Digital Halftoning
X.PP
Dithered output can be displayed on polytone or color devices by specifying 
X.B mono=y 
in the
X.B pen
filter call.
X.PP
On a typical graphics display, a linear grey scale has a nonlinear
appearance.  The transition from black to white is more rapid than expected,
leaving the scale clipped at both ends.  This perceived nonlinearity is
due to the characteristics of the human eye, which sees a linear change
in brightness as a logarithmic change, as well as to the display characteristics
of the device being used.  When a grey scale is displayed on paper using
the dithering methods described above, the nonlinearity is no longer
present.  Such images seem to have a washed out appearance because of
the relative scarcity of pure black and white shades.  The nonlinearity
of display devices seems to be a useful feature that one might wish to
duplicate on paper.  The pen filter parameter
X.B greyc
X(short for `grey correction') modifies the grey scale used to display a
raster to simulate the nonlinearity of displays.  The grey scale is
multiplied by a cubic polynomial with greyc determining the exact shape
of the polynomial.  The function has been constructed such that the ends
and middle of the grey scale are left undisturbed, but on either side of
the middle the grey scale is skewed towards the end of the scale (black or
white).  Greyc=1. leaves the grey scale undisturbed, and values smaller than
X1. skew the scale as described above.  We have found greyc=-0.5 to yield
plots on our Imagen laser printer that are very similar to images displayed
on our Rastertek graphics display.  Some experimentation is undoubtedly
required for other devices.  Once a desirable value has been obtained for
a particular device, that value should be made the default for the particular
device.
X.PP
A further complication with plotting raster images is the dot size used
by the plotter.  In displaying a linear grey scale on our laser printer,
we found the result to be much darker than expected, especially in the
darker half of the scale.  Our hypothesis is that the plotter causes
adjacent dots to overlap.  When the image is mostly white (as in the white
end of the grey scale), this overlap is not very important, since it is
rare that a given empty spot is surrounded by black dots.  However, in the
black half of the grey scale, white places in the plotted
image are usually surrounded by black dots, and the overlap causes the
white space to be much smaller than expected.  Hence the plot is darker
than expected. 
X.PP
From this hypothesis, we have constructed a function that alters the
grey scale to compensate for dot or pixel overlap.  The
X.B pixc
X(short for `pixel correction') parameter controls this alteration of the
grey scale.  Pixc=1. leaves the grey scale undisturbed.  Values smaller
than 1. shift all the grey values toward white in such a way as to
compensate for the
darkening that results from pixel overlap.  The shift is larger for the
dark half of the grey scale, since (from the above discussion) it is more
seriously affected by pixel overlap.  We have found pixc=0.6 to be an
appropriate value for our Imagen laser printer.  This value gives accurate
reproduction of a linear grey scale.
X.PP
As with the greyc parameter, once a suitable value has been obtained for
a particular printer, the appropriate value should be made the default
for that device.
X.SH COPYRIGHT
The Vplot source code is copyrighted. Please read the copyright notice which
can be found in the Vplot manual page.
X.SH "SEE ALSO"
pen vplotlib vplot vplothacker
X.SH "AUTHOR"
Joe Dellinger and Steve Cole
END_OF_FILE
if test 9882 -ne `wc -c <'Vplot_Kernel/Documentation/vplotraster.mn'`; then
    echo shar: \"'Vplot_Kernel/Documentation/vplotraster.mn'\" unpacked with wrong size!
fi
# end of 'Vplot_Kernel/Documentation/vplotraster.mn'
fi
if test -f 'Vplot_Kernel/util/plas.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Vplot_Kernel/util/plas.c'\"
else
echo shar: Extracting \"'Vplot_Kernel/util/plas.c'\" \(11419 characters\)
sed "s/^X//" >'Vplot_Kernel/util/plas.c' <<'END_OF_FILE'
X/*
X * Copyright 1987 the Board of Trustees of the Leland Stanford Junior
X * University. Official permission to use this software is included in
X * the documentation. It authorizes you to use this file for any
X * non-commercial purpose, provided that this copyright notice is not
X * removed and that any modifications made to this file are commented
X * and dated in the style of my example below.
X */
X
X/*
X *
X *  source file:   ./util/plas.c
X *
X * Joe Dellinger (SEP), June 11 1987
X *	Inserted this sample edit history entry.
X *	Please log any further modifications made to this file:
X */
X
char           *documentation[] =
X{
X "",
X "",
X "NAME",
X "		plas 	(PLot ASsembler) -- deformat vector plot commands",
X "SYNOPSIS",
X "		plas < asciifile > binaryfile",
X "------------------------------------------------------------------------",
X "	Reads stdin; writes stdout.  Complement to 'pldb'.",
X "	Converts vplot-language files in ascii (human-readable) form",
X "	into the hybrid ascii/binary form that the 'pen' filters understand.",
X "",
X "   A backslash at the end of a line of text allows multi-line text strings.",
X "Options",
X "      -v: Use vplot units (the default)",
X "      -i: Use inches",
X "      -c: Use centimeters",
X "  Note that these options apply to ALL geometric attributes,",
X "  including line width and character height scale factors.",
X "",
X "The default may be set within the file by having as the first line",
X "#plas: X",
X "where X is one of V, C, or I for Vplot, Cm, or Inches",
X "SEE ALSO",
X "	manual entries for vplot, pen;  self-documentation for pldb."
X};
int             doclength =
X{
X sizeof documentation / sizeof documentation[0]
X};
X
X#include	<stdio.h>
X#include	<sys/ioctl.h>
X#include	<sgtty.h>
X#include	<ctype.h>
X#include	<vplot.h>
X#include	"params.h"
X#include	"round.h"
X
X#define MAXLINE 24*84
X#define NL  '\n'
X
struct sgttyb   ttystat;
FILE           *
fopen (), *fdopen ();
X
main (argc, argv)
X    int             argc;
X    char           *argv[];
X{
int             xargc;
char          **xargv;
char           *cptr;
char            c, a;
int             npat, ix, iy, iz, npts, mtype, orient, col_tab_no, maskx, masky, col;
int             nmul, nx, ny, ipat, i, j;
float           x, y, msize, size, fat, red, green, blue, off, rep;
float           xmin, ymin, xmax, ymax;
int             piped_in;
char            line[MAXLINE];
float           scale, txvecscale, txscale, fatscale, colscale, hscale;
float           xcor, ycor, xvplot, yvplot;
int             count;
int             xpix, ypix, num_pat, num_byte;
int             ibyte, byte, num_rep;
int             ras_offset, ras_orient;
int             line_count;
X
X    npat = 0;
X
X    /*
X     * If no arguments, and not in a pipeline, self document 
X     */
X    piped_in = ioctl ((fileno (stdin)), TIOCGETP, &ttystat);
X    if (argc == 1 && !piped_in)
X    {
X	for (i = 0; i < doclength; i++)
X	    printf ("%s\n", documentation[i]);
X	exit (0);
X    }
X
X/*
X * Default to vplot units
X */
X    fatscale = 1.;
X    txvecscale = 1.;
X    txscale = 1.;
X    scale = 1.;
X    colscale = 1.;
X    hscale = 1.;
X
X    xargc = argc;
X    xargv = argv;
X    for (xargc--, xargv++; xargc; xargc--, xargv++)
X    {
X	cptr = *xargv;
X	if (*cptr == '-')
X	{
X	    while (*(++cptr))
X	    {
X		switch (*cptr)
X		{
X		case 'v':
X/*
X * Vplot units
X */
X		    fatscale = 1.;
X		    txvecscale = 1.;
X		    txscale = 1.;
X		    scale = 1.;
X		    colscale = 1.;
X		    hscale = 1;
X		    break;
X		case 'c':
X/*
X * Centimeters
X */
X		    fatscale = FATPERIN / 2.54;
X		    txvecscale = TEXTVECSCALE;
X		    txscale = TXPERIN / 2.54;
X		    scale = RPERIN / 2.54;
X		    colscale = MAX_GUN;
X		    hscale = RPERIN / 2.54;
X		    break;
X		case 'i':
X/*
X * Inches
X */
X		    fatscale = FATPERIN;
X		    txvecscale = TEXTVECSCALE;
X		    txscale = TXPERIN;
X		    scale = RPERIN;
X		    colscale = MAX_GUN;
X		    hscale = RPERIN;
X		    break;
X		default:
X		    break;
X		}
X	    }
X	}
X    }
X
X/* main switch loop	*/
X
X    line_count = 0;
X    while (fgets (line, MAXLINE, stdin) != NULL)
X    {
X	c = line[0];
X	line_count++;
X	switch (c)
X	{
X	case '#':
X	    if (line_count == 1)
X	    {
X		if (strncmp (line, "#plas: ", 7) == 0)
X		{
X		    switch (line[7])
X		    {
X		    case 'V':
X		    case 'v':
X			fatscale = 1.;
X			txvecscale = 1.;
X			txscale = 1.;
X			scale = 1.;
X			colscale = 1.;
X			hscale = 1;
X			break;
X		    case 'I':
X		    case 'i':
X			fatscale = FATPERIN;
X			txvecscale = TEXTVECSCALE;
X			txscale = TXPERIN;
X			scale = RPERIN;
X			colscale = MAX_GUN;
X			hscale = RPERIN;
X			break;
X		    case 'C':
X		    case 'c':
X			fatscale = FATPERIN / 2.54;
X			txvecscale = TEXTVECSCALE;
X			txscale = TXPERIN / 2.54;
X			scale = RPERIN / 2.54;
X			colscale = MAX_GUN;
X			hscale = RPERIN / 2.54;
X			break;
X		    }
X		}
X	    }
X	    break;
X	case VP_MESSAGE:
X	    putc (c, stdout);
X	    text ();
X	    break;
X	case VP_SETSTYLE:
X	    sscanf (line, "%*c %c", &a);
X	    putc (c, stdout);
X	    putc (a, stdout);
X	    break;
X	case VP_ERASE:
X	case VP_PURGE:
X	case VP_BREAK:
X	case VP_NOOP:
X	    putc (c, stdout);
X	    break;
X	case VP_TXALIGN:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %d %d", &ix, &iy);
X	    puth (ix, stdout);
X	    puth (iy, stdout);
X	    break;
X	case VP_ORIGIN:
X	case VP_MOVE:
X	case VP_DRAW:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %f %f", &x, &y);
X	    puth (ROUND (x * scale), stdout);
X	    puth (ROUND (y * scale), stdout);
X	    break;
X	case VP_TXFONTPREC:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %d %d %d", &ix, &iy, &iz);
X	    puth (ix, stdout);
X	    puth (iy, stdout);
X	    puth (iz, stdout);
X	    break;
X	case VP_PLINE:
X	case VP_SETDASH:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %d", &npts);
X	    puth (npts, stdout);
X	    while (npts--)
X	    {
X		gets (line);
X		sscanf (line, "%f %f", &x, &y);
X		puth (ROUND (x * scale), stdout);
X		puth (ROUND (y * scale), stdout);
X	    }
X	    break;
X	case VP_PMARK:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %d %d %f", &npts, &mtype, &msize);
X	    puth (npts, stdout);
X	    puth (mtype, stdout);
X	    puth (ROUND (msize * txscale), stdout);
X	    while (npts--)
X	    {
X		gets (line);
X		sscanf (line, "%f %f", &x, &y);
X		puth (ROUND (x * scale), stdout);
X		puth (ROUND (y * scale), stdout);
X	    }
X	    break;
X	case VP_BEGIN_GROUP:
X	    putc (c, stdout);
X	    text ();
X	    break;
X	case VP_END_GROUP:
X	    putc (c, stdout);
X	    break;
X	case VP_OLDTEXT:
X	case VP_TEXT:
X	    putc ((char) VP_TEXT, stdout);
X	    sscanf (line, "%*c %f %d", &size, &orient);
X	    puth (ROUND (size * txscale), stdout);
X	    if (c == VP_OLDTEXT)
X		orient *= 90;
X	    puth (orient, stdout);
X	    text ();
X	    break;
X	case VP_GTEXT:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %f %f %f %f", &x, &y, &xcor, &ycor);
X	    puth (ROUND (x * scale * txvecscale), stdout);
X	    puth (ROUND (y * scale * txvecscale), stdout);
X	    puth (ROUND (xcor * scale * txvecscale), stdout);
X	    puth (ROUND (ycor * scale * txvecscale), stdout);
X	    text ();
X	    break;
X	case VP_COLOR:
X	case VP_OVERLAY:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %d", &ix);
X	    puth (ix, stdout);
X	    break;
X	case VP_SET_COLOR_TABLE:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %d %f %f %f",
X		    &col_tab_no, &red, &green, &blue);
X	    puth (col_tab_no, stdout);
X	    puth (ROUND (red * colscale), stdout);
X	    puth (ROUND (green * colscale), stdout);
X	    puth (ROUND (blue * colscale), stdout);
X	    break;
X	case VP_FAT:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %f", &fat);
X	    puth (ROUND (fat * fatscale), stdout);
X	    break;
X	case VP_WINDOW:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %f %f %f %f", &xmin, &ymin, &xmax, &ymax);
X	    puth (ROUND (scale * xmin), stdout);
X	    puth (ROUND (scale * ymin), stdout);
X	    puth (ROUND (scale * xmax), stdout);
X	    puth (ROUND (scale * ymax), stdout);
X	    break;
X	case VP_OLDAREA:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %d", &npts);
X	    fgets (line, MAXLINE, stdin);
X	    sscanf (line, "%f %d %d", &fat, &maskx, &masky);
X	    puth (npts, stdout);
X	    puth (ROUND (fat * fatscale), stdout);
X	    puth (maskx, stdout);
X	    puth (masky, stdout);
X	    for (i = 0; i < npts; i++)
X	    {
X		fgets (line, MAXLINE, stdin);
X		sscanf (line, "%f %f", &x, &y);
X		puth (ROUND (x * scale), stdout);
X		puth (ROUND (y * scale), stdout);
X	    }
X	    break;
X	case VP_AREA:
X	    putc (c, stdout);
X	    sscanf (line, "%*c %d", &npts);
X	    puth (npts, stdout);
X	    for (i = 0; i < npts; i++)
X	    {
X		fgets (line, MAXLINE, stdin);
X		sscanf (line, "%f %f", &x, &y);
X		puth (ROUND (scale * x), stdout);
X		puth (ROUND (scale * y), stdout);
X	    }
X	    break;
X	case VP_PATLOAD:
X	    npat++;
X	    ipat = 0;
X	    sscanf (line, "%*c %d %d %d %d", &nmul, &nx, &ny, &ipat);
X	    putc (c, stdout);
X	    puth (nmul, stdout);
X	    puth (nx, stdout);
X	    puth (ny, stdout);
X	    if (ipat == 0)
X	    {
X		ipat = npat;
X	    }
X	    puth (ipat, stdout);
X
X	    if (nx != -1)
X	    {
X		for (i = 0; i < nx; i++)
X		{
char           *ptr;
X		    fgets (line, MAXLINE, stdin);
X
X		    for (j = 0, ptr = line; j < ny; j++, *ptr++)
X		    {
X			if (*ptr == NULL || *ptr == NL)
X			    fprintf (stderr, "null/nl");
X			if (*ptr >= '0' && *ptr <= '9')
X			{
X			    ipat = (*ptr) - '0';
X			}
X			else
X			{
X			    ipat = (*ptr) - 'A' + 10;
X			}
X			puth (ipat, stdout);
X		    }
X		}
X	    }
X	    else
X	    {
X		for (i = 0; i < ny * 2; i++)
X		{
X		    fgets (line, MAXLINE, stdin);
X		    sscanf (line, "%f %d %f %f", &fat, &col, &off, &rep);
X		    puth (ROUND (fat * fatscale), stdout);
X		    puth (col, stdout);
X		    puth (ROUND (off * hscale), stdout);
X		    puth (ROUND (rep * hscale), stdout);
X		}
X	    }
X	    break;
X	case VP_BYTE_RASTER:
X	case VP_BIT_RASTER:
X	    {
X
X		sscanf (line, "%*c %d %d", &ras_orient, &ras_offset);
X		putc (c, stdout);
X		puth (ras_orient, stdout);
X		puth (ras_offset, stdout);
X		fgets (line, MAXLINE, stdin);
X		sscanf (line, "%f %f", &xcor, &ycor);
X		puth (ROUND (xcor * scale), stdout);
X		puth (ROUND (ycor * scale), stdout);
X		fgets (line, MAXLINE, stdin);
X		sscanf (line, "%f %f", &xvplot, &yvplot);
X		puth (ROUND (scale * xvplot), stdout);
X		puth (ROUND (scale * yvplot), stdout);
X		fgets (line, MAXLINE, stdin);
X		sscanf (line, "%d %d", &xpix, &ypix);
X		puth (xpix, stdout);
X		puth (ypix, stdout);
X
X		for (j = 0; j < ypix;)
X		{
X		    count = 0;
X		    fgets (line, MAXLINE, stdin);
X		    count = 0;
X		    sscanf (line, "%d", &num_rep);
X		    if (num_rep < 1)
X			fprintf (stderr, "Bad Raster repetition factor\n");
X		    puth (num_rep, stdout);
X	    more_line:fgets (line, MAXLINE, stdin);
X		    sscanf (line, "%d %d", &num_pat, &num_byte);
X		    puth (num_pat, stdout);
X		    puth (num_byte, stdout);
X		    for (i = 0; i < num_byte; i++)
X		    {
X			fgets (line, MAXLINE, stdin);
X			sscanf (line, "%d", &byte);
X			if (c == VP_BYTE_RASTER)
X			{
X			    putc ((char) byte, stdout);
X			}
X			else
X			{
X			    if (i % 8 == 0)
X				ibyte = 0;
X			    ibyte |= ((byte != 0) << (7 - (i % 8)));
X			    if (i % 8 == 7 || i == num_byte - 1)
X				putc ((char) ibyte, stdout);
X			}
X		    }
X		    count += num_byte * num_pat;
X		    if (count < xpix)
X			goto more_line;
X		    j += num_rep;
X		}
X	    }
X	    break;
X	default:
X	    ;			/* Treat unknown charactors as comments */
X	}
X    }
X}
X
text ()
X{
char            c;
X    do
X    {
X	c = getc (stdin);
X	if (c == '\\')
X	{
X	    if ((c = getc (stdin)) != '\n')
X	    {
X		putc ('\\', stdout);
X	    }
X	    else
X		continue;
X	}
X	else
X	if (c == '\n')
X	    break;
X	putc (c, stdout);
X    } while (1);
X    putc ('\0', stdout);
X}
END_OF_FILE
if test 11419 -ne `wc -c <'Vplot_Kernel/util/plas.c'`; then
    echo shar: \"'Vplot_Kernel/util/plas.c'\" unpacked with wrong size!
fi
# end of 'Vplot_Kernel/util/plas.c'
fi
if test -f 'Vplot_Kernel/util/pldb.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Vplot_Kernel/util/pldb.c'\"
else
echo shar: Extracting \"'Vplot_Kernel/util/pldb.c'\" \(10150 characters\)
sed "s/^X//" >'Vplot_Kernel/util/pldb.c' <<'END_OF_FILE'
X/*
X * Copyright 1987 the Board of Trustees of the Leland Stanford Junior
X * University. Official permission to use this software is included in
X * the documentation. It authorizes you to use this file for any
X * non-commercial purpose, provided that this copyright notice is not
X * removed and that any modifications made to this file are commented
X * and dated in the style of my example below.
X */
X
X/*
X *
X *  source file:   ./util/pldb.c
X *
X * Joe Dellinger (SEP), June 11 1987
X *	Inserted this sample edit history entry.
X *	Please log any further modifications made to this file:
X */
X
char           *documentation[] =
X{
X "",
X "",
X "NAME",
X "		 pldb -- (PLot DeBugger) ",
X "SYNOPSIS",
X "		pldb < binaryfile > asciifile",
X "-------------------------------------------------------------------------",
X "	Reads the standard input stream, writes standard out",
X "",
X "	Input: 	vplot metafile format (mixed ASCII and binary)",
X "	Output:	Human-readable representations of vplot vector plot",
X "		commands",
X "	plas returns pldb output to vplot format.",
X "	Useful with pen output filters.",
X "OPTIONS:",
X "      -v: use vplot units (default)",
X "      -i: use inches",
X "      -c: use centimeters",
X "  Note that these options apply to ALL geometric attributes,",
X "  including line width and character height.",
X "SEE ALSO",
X "	 manual entries for 'vplot' and 'pen'; selfdoc for 'plas'."
X};
int             doclength =
X{
X sizeof documentation / sizeof documentation[0]
X};
X
X/*
X *  Various portions of this program were written by
X *  Jon Claerbout (Long long ago!),
X *  Jeff Thorson (1980-81?),  Michel Debiche (1982-84),
X *  Chuck Karish (1985),  and Joe Dellinger (1986-1987)
X *  of the Stanford University
X *  Departments of Geophysics and Geology.
X *
X *  Anybody want to clean this mess up?
X */
X
X#include	<stdio.h>
X#include	<sys/ioctl.h>
X#include	<sgtty.h>
X#include	<ctype.h>
X#include	<vplot.h>
X#include	"params.h"
X
struct sgttyb   ttystat;
FILE           *
fopen (), *fdopen ();
X
main (argc, argv)
X    int             argc;
X    char           *argv[];
X{
int             xargc;
char          **xargv;
char           *cptr;
char            c, a;
int             ix, iy, iz, npts, mtype, orient, col_tab_no, xmask, ymask, col;
int             nmul, nx, ny, ipat, i, j, ii, key, pos, bit;
float           x, y, msize, size, fat, red, green, blue, off, rep;
float           xmin, ymin, xmax, ymax;
int             piped_in;
float           scale, txvecscale, txscale, fatscale, colscale, hscale;
float           xcor, ycor, xvplot, yvplot;
int             xpix, ypix, num_pat, num_byte;
int             ibyte, byte, num_rep;
int             ras_offset, ras_orient;
int             which_units;
int             retstat = 0;
X
X    /*
X     * If no arguments, and not in a pipeline, self document 
X     */
X    piped_in = ioctl ((fileno (stdin)), TIOCGETP, &ttystat);
X    if (argc == 1 && !piped_in)
X    {
X	for (i = 0; i < doclength; i++)
X	    printf ("%s\n", documentation[i]);
X	exit (0);
X    }
X
X/*
X * Default to vplots
X */
X    fatscale = 1.;
X    txvecscale = 1.;
X    txscale = 1.;
X    scale = 1.;
X    colscale = 1.;
X    hscale = 1.;
X    which_units = 'v';
X
X    xargc = argc;
X    xargv = argv;
X    for (xargc--, xargv++; xargc; xargc--, xargv++)
X    {
X	cptr = *xargv;
X	if (*cptr == '-')
X	{
X	    while (*(++cptr))
X	    {
X		switch (*cptr)
X		{
X		case 'v':
X/*
X * Vplot units
X */
X		    fatscale = 1.;
X		    txvecscale = 1.;
X		    txscale = 1.;
X		    scale = 1.;
X		    colscale = 1.;
X		    hscale = 1;
X		    which_units = 'v';
X		    break;
X		case 'c':
X/*
X * Centimeters
X */
X		    fatscale = 1. / (FATPERIN / 2.54);
X		    txvecscale = 1. / TEXTVECSCALE;
X		    txscale = 1. / (TXPERIN / 2.54);
X		    scale = 1. / (RPERIN / 2.54);
X		    colscale = 1. / MAX_GUN;
X		    hscale = 1. / (RPERIN / 2.54);
X		    which_units = 'c';
X		    break;
X		case 'i':
X/*
X * Inches
X */
X		    fatscale = 1. / FATPERIN;
X		    txvecscale = 1. / TEXTVECSCALE;
X		    txscale = 1. / TXPERIN;
X		    scale = 1. / RPERIN;
X		    colscale = 1. / MAX_GUN;
X		    hscale = 1. / RPERIN;
X		    which_units = 'i';
X		    break;
X		default:
X		    break;
X		}
X	    }
X	}
X    }
X
X    switch (which_units)
X    {
X    case 'v':
X	printf ("#plas: Vplot units used in this file\n");
X	break;
X    case 'c':
X	printf ("#plas: Centimeters used in this file\n");
X	break;
X    case 'i':
X	printf ("#plas: Inches used in this file\n");
X	break;
X    }
X
X    /* main switch statement */
X
X    while ((c = getc (stdin)) != EOF)
X    {
X	switch (c)
X	{
X	case VP_MESSAGE:
X	    printf ("%c\n", c);
X	    text ();
X	    break;
X	case VP_SETSTYLE:
X	    a = getchar ();
X	    printf ("%c %c\n", c, a);
X	    break;
X	case VP_ERASE:
X	case VP_BREAK:
X	case VP_PURGE:
X	case VP_NOOP:
X	    printf ("%c\n", c);
X	    break;
X	case VP_ORIGIN:
X	case VP_MOVE:
X	case VP_DRAW:
X	    x = scale * geth (stdin);
X	    y = scale * geth (stdin);
X	    printf ("%c %g %g\n", c, x, y);
X	    break;
X	case VP_TXALIGN:
X	    ix = geth (stdin);
X	    iy = geth (stdin);
X	    printf ("%c %d %d\n", c, ix, iy);
X	    break;
X	case VP_TXFONTPREC:
X	    ix = geth (stdin);
X	    iy = geth (stdin);
X	    iz = geth (stdin);
X	    printf ("%c %d %d %d\n", c, ix, iy, iz);
X	    break;
X	case VP_PLINE:
X	case VP_SETDASH:
X	    npts = geth (stdin);
X	    printf ("%c %d\n", c, npts);
X	    while (npts--)
X	    {
X		x = scale * geth (stdin);
X		y = scale * geth (stdin);
X		printf ("%g %g\n", x, y);
X	    }
X	    break;
X	case VP_PMARK:
X	    npts = geth (stdin);
X	    mtype = geth (stdin);
X	    msize = txscale * geth (stdin);
X	    printf ("%c %d %d %g\n", c, npts, mtype, msize);
X	    while (npts--)
X	    {
X		x = scale * geth (stdin);
X		y = scale * geth (stdin);
X		printf ("%g %g\n", x, y);
X	    }
X	    break;
X	case VP_BEGIN_GROUP:
X	    printf ("%c\n", c);
X	    text ();
X	    break;
X	case VP_END_GROUP:
X	    printf ("%c\n", c);
X	    break;
X	case VP_GTEXT:
X	    x = scale * txvecscale * geth (stdin);
X	    y = scale * txvecscale * geth (stdin);
X	    xcor = scale * txvecscale * geth (stdin);
X	    ycor = scale * txvecscale * geth (stdin);
X	    printf ("%c %g %g %g %g\n", c, x, y, xcor, ycor);
X	    text ();
X	    break;
X	case VP_OLDTEXT:
X	    key = geth (stdin);
X	    size = txscale * (key & 037);
X	    orient = (key & 0140) >> 5;
X	    printf ("%c %g %d\n", VP_TEXT, size, 90 * orient);
X	    text ();
X	    break;
X	case VP_TEXT:
X	    size = txscale * geth (stdin);
X	    orient = geth (stdin);
X	    printf ("%c %g %d\n", c, size, orient);
X	    text ();
X	    break;
X	case VP_OVERLAY:
X	case VP_COLOR:
X	    ix = geth (stdin);
X	    printf ("%c %d\n", c, ix);
X	    break;
X	case VP_SET_COLOR_TABLE:
X	    col_tab_no = geth (stdin);
X	    red = colscale * geth (stdin);
X	    green = colscale * geth (stdin);
X	    blue = colscale * geth (stdin);
X	    printf ("%c %d %g %g %g\n", c, col_tab_no, red, green, blue);
X	    break;
X	case VP_FAT:
X	    fat = fatscale * geth (stdin);
X	    printf ("%c %g\n", c, fat);
X	    break;
X	case VP_WINDOW:
X	    xmin = scale * geth (stdin);
X	    ymin = scale * geth (stdin);
X	    xmax = scale * geth (stdin);
X	    ymax = scale * geth (stdin);
X	    printf ("%c %g %g %g %g\n", c, xmin, ymin, xmax, ymax);
X	    break;
X	case VP_BIT_RASTER:
X	case VP_BYTE_RASTER:
X	    ras_orient = geth (stdin);
X	    ras_offset = geth (stdin);
X	    printf ("%c %d %d\n", c, ras_orient, ras_offset);
X	    xcor = scale * geth (stdin);
X	    ycor = scale * geth (stdin);
X	    printf ("%g %g\n", xcor, ycor);
X	    xvplot = scale * geth (stdin);
X	    yvplot = scale * geth (stdin);
X	    printf ("%g %g\n", xvplot, yvplot);
X	    xpix = geth (stdin);
X	    ypix = geth (stdin);
X	    printf ("%d %d\n", xpix, ypix);
X	    for (i = 0; i < ypix; i += num_rep)
X	    {
X		pos = 0;
X		num_rep = geth (stdin);
X		printf ("     %d  ------ lines %d to %d\n",
X			num_rep, i, i + num_rep - 1);
X	new_line:num_pat = geth (stdin);
X		num_byte = geth (stdin);
X		printf ("%d %d  -- start byte %d in y_line %d\n",
X			num_pat, num_byte, pos, i);
X		if (num_pat < 0 || num_byte < 0)
X		{
X		    fprintf (stderr, "Error in raster field\n");
X		    exit (1);
X		}
X		pos += num_byte * num_pat;
X		if (pos > xpix)
X		{
X		    fprintf (stderr, "Error in raster field\n");
X		    exit (1);
X		}
X
X		if (c == VP_BYTE_RASTER)
X		{
X		    for (ii = 0; ii < num_byte; ii++)
X		    {
X			byte = (int) getc (stdin);
X			if (byte == EOF)
X			{
X			    fprintf (stderr, "Error in raster field\n");
X			    exit (1);
X			}
X			printf ("%d\n", byte);
X		    }
X		}
X		else
X		{
X		    for (ii = 0; ii < num_byte; ii++)
X		    {
X			if (ii % 8 == 0)
X			{
X			    ibyte = (int) getc (stdin);
X			}
X			else
X			{
X			    ibyte <<= 1;
X			}
X			printf ("%d\n", ((ibyte >> 7) & 001));
X		    }
X		}
X		if (pos < xpix)
X		    goto new_line;
X	    }
X	    break;
X	case VP_AREA:
X	    {
X		npts = geth (stdin);
X		printf ("%c %d\n", c, npts);
X		for (i = 0; i < npts; i++)
X		{
X		    x = scale * geth (stdin);
X		    y = scale * geth (stdin);
X		    printf ("%g %g\n", x, y);
X		}
X	    }
X	    break;
X	case VP_PATLOAD:
X	    nmul = geth (stdin);
X	    nx = geth (stdin);
X	    ny = geth (stdin);
X	    ipat = geth (stdin);
X	    printf ("%c %d %d %d %d\n",
X		    c, nmul, nx, ny, ipat);
X	    if (nx == -1)
X	    {
X		for (i = 0; i < ny * 2; i++)
X		{
X		    fat = fatscale * geth (stdin);
X		    col = geth (stdin);
X		    off = hscale * geth (stdin);
X		    rep = hscale * geth (stdin);
X		    printf ("%g %d %g %g\n",
X			    fat, col, off, rep);
X		}
X	    }
X	    else
X	    {
X		for (i = 0; i < nx; i++)
X		{
X		    for (j = 0; j < ny; j++)
X		    {
X			bit = geth (stdin);
X			if (bit >= 0 && bit <= 9)
X			{
X			    putc (bit + '0', stdout);
X			}
X			else
X			{
X			    putc (bit + 'A' - 10, stdout);
X			}
X		    }
X		    putc ('\n', stdout);
X		}
X	    }
X	    break;
X	case VP_OLDAREA:
X	    {
X		npts = geth (stdin);
X		printf ("%c %d\n", c, npts);
X		fat = fatscale * geth (stdin);
X		xmask = geth (stdin);
X		ymask = geth (stdin);
X		printf ("%g %d %d\n", fat, xmask, ymask);
X		for (i = 0; i < npts; i++)
X		{
X		    x = scale * geth (stdin);
X		    y = scale * geth (stdin);
X		    printf ("%g %g\n", x, y);
X		}
X	    }
X	    break;
X	default:
X	    printf ("******unknown command %c %o\n", c, c);
X	    retstat = 1;
X	}
X    }
X    exit (retstat);
X}
X
text ()
X{
char            c;
X
X    while ((c = getc (stdin)))
X	printf ("%c", c);
X    printf ("\n");
X}
END_OF_FILE
if test 10150 -ne `wc -c <'Vplot_Kernel/util/pldb.c'`; then
    echo shar: \"'Vplot_Kernel/util/pldb.c'\" unpacked with wrong size!
fi
# end of 'Vplot_Kernel/util/pldb.c'
fi
echo shar: End of archive 15 \(of 24\).
cp /dev/null ark15isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 24 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.