[comp.sources.unix] v14i024: 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 24
Archive-name: vplot/part19

#! /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 19 (of 24)."
# Wrapped by rsalz@fig.bbn.com on Fri Mar 25 11:47:31 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Vplot_Kernel/Documentation/hacker.doc.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Vplot_Kernel/Documentation/hacker.doc.1'\"
else
echo shar: Extracting \"'Vplot_Kernel/Documentation/hacker.doc.1'\" \(25049 characters\)
sed "s/^X//" >'Vplot_Kernel/Documentation/hacker.doc.1' <<'END_OF_FILE'
Hacker's guide to the innards of the Pen programs,
X					or
What you need to know to support a new device well
X
X
Joe Dellinger and Charles R. Karish
X
Stanford University School of Earth Sciences
X
INTRODUCTION
The pen software package, developed by students in the Geophysics department
at Stanford University over many years, allows graphical data produced by
computer programs to be displayed on a wide variety of output devices,
including terminals and hard copy devices. Both vector and raster output
are supported. The filters allow the user to control the size, aspect ratio,
and position on the page independent of the program which produces the data.
Pen programs read files written in the vplot graphics metalanguage and
write commands appropriate to the various output devices.
The pen programs are all filters, and can be run in pipelines without
loss of function. Only rudimentary provisions for interaction are provided.
X
Terminals now supported include color Tektronix and
emulators (4105), monochrome Tektronix and emulators (4010)
X(GraphOn, Selanar, Retrographics), Envision, DEC Regis (Gigi, VT125, VT220),
Imagen, PostScript (e. g., Apple LaserWriter), Printronix printer,
suntools, X, NEWS, and Rastertek.
X
FILES
The source for the pen filters is located in .../vplot/filters and
subdirectories. All include files (files ending in .h) are kept in
X.../vplot/filters/include. Fonts are kept in
X.../vplot/filters/include/vplotfonts. Each pen filter has an associated
X device-dependent subroutine library, which is kept in a subdirectory of
X.../vplot/filters. For example, the Envision pen filter ``envipen'' uses
the directory .../vplot/filters/envilib.
X
PROGRAM STRUCTURE
The philosophy behind vplot and pen has been to have users' programs write
output in a device-independent language, and to present the results in a
compatible manner on all devices. All the filters share a common
user/operating system interface routine, called frontend, and a common
vplot command interpreter, dovplot.c. Frontend consists of 3 parts:
main_vplot, init_vplot, and proc_vplot. The routines in utillib.a
are mostly low-level and device independent. Genlib.a is a set of generic
routines which is capable of providing all or almost all of the functions
needed to support a GKS vector output package. The programmer is free
to use these routines in a device driver, or to substitute calls to
high-level hardware capabilities. Loclib.a contains a subset of the 
seplib library, including routines for writing/reading vplot and for
receiving parameters from the command line and initialization
files.
X
The heart of the device support system is the file <dev>conf.c
where <dev> is the name of the device. Inspired by the file
X/usr/sys/machine/conf.c which configures the UNIX operating system
to accept peripheral devices, this file is composed of three parts:
X1)	Declaration of the variables necessary to do self-documentation:
X	char name[] = "Filter name";
X	char *documentation[] = {...documentation...};
X	int doclength = {sizeof documentation / sizeof documentation[0] };
X
X	You may wish to include ``gendoc.h'' as part of your
X	documentation string.
X
X2)	Declaration of the routines which have been chosen/written
X	to provide the various functions.
X	All the routines named in part 3 must be declared, as well as all the
X	routines which they may call.
X
X3)	Initialization of a structure of pointers to the routines which do
X	the work. Since this structure is read directly by dovplot.c,
X	it is vital that the all entries be filled in order.
X	Each subroutine name can be one of three types:
X
X	a) A device-specific subroutine name such as ``envipoint''.
X	(Note the first 4 characters of the name are a unique identifier
X	for the device, and the rest of the name tells which routine in the
X	table this is. The 4 letter identifier is usually tacked onto
X	``pen'' to give the pen filter name (such as ``envipen'') and onto
X	``lib'' to give the subdirectory name (such as ``envilib'').)
X
X	b) A generic subroutine name such as ``genpoint''.
X	Generic subroutines simplify the device's work by handling
X	things in software. They in turn call other, simpler, device
X	routines. Generic routines are useful because by using them it
X	is very easy to rapidly support all the primitives on a device.
X	If the device can do things in hardware, however, it is usually
X	preferable to write a device-specific routine to use that capability
X	since that is much more efficient.
X
X	c) The do-nothing subroutine ``nulldev''.
X	Nulldev is an all-purpose generic subroutine that simply
X	returns. It can either be used as a place holder for routines
X	your device doesn't use, or it can be used in cases where there
X	is simply no reasonable way to handle that particular primitive
X	on that device.
X
The usual procedure for creating a new driver has been to steal as
much code as possible from a driver for a similar device,
or from the generic library. For a Tektronix emulator, this can be as
simple as checking that the mode changes are handled properly by dev.open
and dev.close, and writing a devconf.c with the proper subroutine names.
For a start, it should be possible to get a less-standard device going
with devopen, devclose, and devplot routines, relying on generic routines
for all other functions. Figure 1 contains the device structure for the
Envision 220.
X
X---------------------------------------------------------------------------
X
struct device   dev =
X{
X /* control routines */
X    enviopen,		/* open */
X    envireset,		/* reset */
X    envimessage,	/* message */
X    envierase,		/* erase */
X    enviclose,		/* close */
X
X /* high level output */
X    genvector,		/* vector */
X    genmarker,		/* marker */
X    gentext,		/* text */
X    genarea,		/* area */
X    genraster1,		/* raster */
X    envipoint,		/* point */
X    enviattributes,	/* attributes */
X
X /* input */
X    envigetpoint,	/* getpoint */
X    geninteract,	/* interact */
X
X /* low level output */
X    enviplot,		/* plot */
X    envistartpoly,	/* startpoly */
X    envimidpoly,	/* midpoly */
X    enviendpoly		/* endpoly */
X};
X
Figure 1: device structure for envipen
X-----------------------------------------------------------------------------
X
VARIABLES
The following variables are used to communicate information between
dovplot and the device routines.
X
These variables must be initialized in either dev.open or dev.reset:
X
int dev_xmax, dev_ymax, dev_xmin, dev_ymin;
X
X	These variables should give the device coordinates of the lower-leftmost
X	and upper-rightmost pixels on the device screen. It is assumed that
X	the device X axis is horizontal and the device Y axis is vertical,
X	and that dev_xmax > dev_xmin and dev_ymax > dev_ymin. If this is not
X	true for your device, it is up to the device routines to transform
X	the device coordinate system so it is true. (Examples of devices that
X	do this are gigipen and ipen.)
X
float pixels_per_inch, aspect_ratio;
X
X	Pixels_per_inch gives the number of pixels per inch on the device
X	in the horizontal direction. Aspect_ratio gives the height to width
X	ratio of the pixels. (Aspect_ratio > 1 means that the pixels are tall
X	and skinny, and thus that the resolution is less in the vertical
X	direction than in the horizontal direction.)
X
int num_col;
X
X	Num_col is the number of settable colors that the device has.
X	Colors that can't be reset from the host don't count.
X	Currently num_col can be at most 256, because this is all
X	the raster routines can handle (due to use of unsigned char's).
X	If mono=y is set, init_vplot will set num_col to zero.
X
X-------------------
X
These variables are set by dovplot but may be reset in
dev.open (NOT dev.reset) if the default
value is not appropriate. For the most part, resetting these variables
is for the purpose of making a device-dependent default;
the user is given a chance to override the value the device sets them to.
X
int mono=NO;
X
X	If mono=NO, then the device is assumed to have color EVEN IF num_col is
X	zero. If mono=YES, then the device is monochrome. (The user cannot
X	override mono=YES, but can mono=NO.) See comments about the effects
X	of mono and num_col on color in dev.attributes below, and on raster
X	in dev.raster. Mono=YES forces num_col=0.
X
int invras=YES;
X
X	This variable is only used in the utility routine ``dither.c'', which
X	dithers raster. Raster is only dithered if mono=YES and dither>0.
X	Normally such devices draw in black on a white page, which is the
X	reverse of what is normal for screen devices, and so invras=YES.
X	If the background color is BLACK then invras should be NO.
X
int dither=1;
X
X	Default dithering style to use for this device. See vplotraster(9)
X	for the different values to be explained.
X 
float greyc=1.;
X 
X	This variable is used only when dithering is being performed,
X	and really should only be used for hardcopy devices. It alters
X 	the grey scale so that grey rasters come out on paper with the
X	same nonlinear appearance that is perceived on display devices.
X	See vplotraster(9) for a discussion of the parameter and how to
X	use it.
X 
float pixc=1.;
X 
X	This variable is used only when dithering is being performed,
X	and also should only be used for hardcopy devices. It alters the
X	grey scale to correct for pixel overlap on the device, which 
X	(if uncorrected) causes grey raster images to come out much darker
X	on paper than on graphics displays. See vplotraster(9) for a 
X	discussion of the parameter and how to use it.
X
int txfont=DEFAULT_FONT, txprec=DEFAULT_PREC;
X
X	Default text font, precision, and overlay mode. Text fonts of less
X	than NUMGENFONT are reserved for genvector fonts. If you want the
X	device to by default use some nice hardware font, you can reset
X	txfont to the appropriate device-dependent font number.
X	Alternatively, if the device is one in which plotting speed is not
X	a problem, txfont can be set to DEFAULT_HARDCOPY_FONT.
X	Txprec is pretty much ignored by genvector. Fancy output devices should
X	set txprec to DEFAULT_HARDCOPY_PREC to enable ligatures. Txprec may
X	be used by device-dependent text routines. Txprec must be in the range
X	0 through 2.
X
float hshift=0., vshift=0.; int rotate=0;
X
X	These values are in addition to whatever the user may set from the
X	command line. This provides a way for a device to rotate or translate
X	all plots.
X
int shade=YES;
X
X	If shade=NO, then no attempt will be made by vplot to ask the device to
X	shade the interiors of polygons due to the vplot `a' and `A' commands.
X	Instead it will just outline them with vectors whenever it tries to
X	fill a polygon. This option is for devices that CAN fill but are
X	very slow to do so.
X
int wantras=YES;
X
X	If wantras=NO, then no attempt will be made by vplot to ask the
X	device to handle raster due to the vplot `r' and `R' commands.
X	Instead it will just shade the raster area solid white using dev.area.
X	This option is for devices that CAN do raster but are very slow to
X	do it.
X
float fatmult=1., patternmult=1.;
X
X	If fat lines are too slow, you can set fatmult=0. and disable line
X	fattening. The user can still turn it on again by overriding with
X	fatmult=1 from the command line. Patternmult can be used to scale up
X	or down patterns by default on a specific device.
X
int endpause=NO;
X
X	If the device needs a pause at the end of the plot
X	(via dev.close(CLOSE_PAUSE) and then dev.interact(INT_F_PAUSE))
X	then endpause should be set to YES.
X
int allowecho=?;
X
X	Allowecho controls whether echoing is turned off for the duration of
X	plotting. Allowecho=NO turns off echoing.
X	If the dev.open sets allowecho, dovplot assumes that it knows what it's
X	doing and leaves it alone. Otherwise,
X	dovplot tries to decide whether allowecho should be YES or NO depending
X	on where the output stream pltout goes. If after calling dev.open
X	pltout and stderr point to the same place, then it assumes that
X	allowecho should be NO. The user can force allowecho to be YES
X	from the command line if the device or dovplot set it to be NO,
X	but the user cannot force it to be NO.
X
int (*message)()=genmessage;
X
X	Dovplot decides where to send messages (such as error messages, for
X	example) in the same way that it decides how to set allowecho.
X	Before dev.open has been called, the device is not open and dev.message
X	cannot be called. Instead, it is assumed that it is safe to send all
X	messages to stderr by calling genmessage instead. After dev.open has
X	been called, dovplot checks to see whether stderr and pltout point to
X	the same place. If they do, then from then on all messages are routed to
X	dev.message. However, if they do NOT point to the same place, then it is
X	assumed that it is still safe to route them to stderr and messages are
X	still handled by genmessage. If this logic is incorrect for your device
X	you will need to reset this variable to dev.message in dev.open. So
X	far the only devices for which dovplot's logic has been wrong have
X	been virtual ones. The user cannot determine where messages are to
X	be sent.
X
X----------------
X
These variables can usually be left at their default values, but may
have to be reset for some devices. They cannot be changed by the user.
X
int need_end_erase=NO;
X
X	Some devices use the ``erase'' routine to do things such as write out
X	a rasterized plot image as well as for erasing. For such devices it
X	is convenient to have dev.erase called one last time before the device
X	is closed (via dev.erase(ERASE_END)). To get this, set need_end_erase=YES.
X
int buffer_output=YES;
X
X	If for some reason buffering the output to your device is a bad thing to
X	do, set buffer_output=NO. This only applies if you use the FILE *pltout
X	that dovplot provides.
X
int smart_clip=NO;
X
X	If smart_clip=NO, then dovplot should do all clipping for you. If you
X	can do your own clipping, then set smart_clip=YES. You must then
X	handle dev.attributes(SET_WINDOW)!
X
int smart_raster=NO;
X
X	If you can stretch AND clip your own raster, then set smart_raster=YES.
X	It is then up to you to do all the stretching and clipping (and possibly
X	dithering) of raster in the dev.raster routine, as dovplot will not then
X	do it for you.
X
X-------------------
X
These variables may be useful to refer to in dev.open, so that one pen filter
can support multiple devices:
X
char callname[]="filename";
char wstype[]="default";
X
X	Callname gives the name the person invoked to run this pen filter.
X	(The leading path is stripped for you if present.) If the person
X	has ``wstype=work_station_type'' as a command line option, then
X	wstype will be set to the string "work_station_type". Otherwise,
X	it will be set to "default". Note that the only routine that
X	REALLY has to be defined in dev.conf is dev.open, and the only
X	routines that REALLY have to be defined in dev.open are dev.close,
X	dev.reset and dev.message. However, by the time dev.reset returns
X	everything had better be defined. Thus you can decide inside
X	dev.open which subroutines to plug into the device table, after
X	looking at wstype and callname to tell you which device you are
X	supporting.
X
X------------------------------------------------------------------------------
X
SUBROUTINES
All sizes and locations are in device units unless stated otherwise.
Dovplot() uses its notions of the vplot environment (resolution, origin)
and the device resolution (pixel size and shape) to call with the appropriate
values. Subroutines may write to the external FILE *pltout which dovplot
initializes, which may be a terminal, a pipe, or a text file, or
they may open their own output file if pltout is not appropriate.
In general, if the user is redirecting stdout, then that's where the
output should go and no plot should actually appear anywhere.
If the user is not redirecting stdout, then the user wants a plot to appear
on the appropriate device. Pen filters should not easily be made to
dump binary garbage out onto your screen!
X
We will list each routine in the device table in order. We will also
list all associated generic and utility routines at the same time.
X
Control routines
X
X===========================
X
dev.open()
X
Initialize device-dependent variables (see above)
and emit hardware initialization strings.
This routine is guaranteed to be the first called, and it is only
called once.
X
X===========================
X
dev.reset()
X
Reset the terminal. It is guaranteed that this will be called once
after the first call to dev.open before any other routine is called.
The one exception is in case of certain errors, in which case dev.reset
is never called and instead dev.close(NOTHING) followed by dev.close(DONE)
are the only other calls after the initial dev.open call. (This is the
X``No input?'' error, which you've probably seen.)
X
X===========================
X
dev.message(command, string)
int command;
char string[];
X
Choose a command from mesgcom.h to position the cursor, set the proper
text mode, and print out a message.  Displaying a message will
require several calls to dev.message, one per command.
The meanings of the various commands are given by comments inside
mesgcom.h.
X
Generic routines: genmessage.c
Genmessage prints all messages to stderr. It doesn't try to do anything
at all fancy, although it does beep as the best available completely
device-independent way of ``highlighting text''. It beeps twice because
some devices silently eat single beeps.
X
X===========================
X
dev.erase(command)
int command;
X
Choose an erase mode from erasecom.h, and erase the screen.
The meanings of the various commands are given by comments inside
erasecom.h.
X
X===========================
X
dev.close(status)
int status;
X
Choose a close status from closestat.h, and close the workstation.
The meanings of the various commands are given by comments inside
closestat.h.
X
High level output routines
X
X===========================
X
dev.vector(x1, y1, x2, y2, nfat, dashon)
int x1, y1, x2, y2, nfat, dashon;
X{
X/* These can be declared by including extern.h */
extern float dashsum, dashpos;
extern float dashes[/* dashon*2 */];
X
Draw a (possibly) fat (possibly) dashed line from device coordinate
X(x1,y1) to (x2,y2). The fatness of the line is given by nfat. Nfat=0
means the thinnest possible line. Each increase of 1 means to fatten
the line by one device pixel WIDTH (the height could be quite different,
depending on the value of aspect_ratio). Nfat < 0 should be checked for,
and no vector should be drawn at all in that case.
X
If dashon>0 then a dashed line should be drawn. The pattern consists
of dashon dash-gap pairs. The pattern is defined in the array
dashes[2*dashon]. (ie, dashes[0] is the first dash length, dashes[1]
is the first gap length, dashes[2] is the second dash length, etc.)
Dovplot will call dev.attributes(NEW_DASH,...) whenever the values
in this array are changed. Note that just because a dashed pattern
has been put in effect does not mean it will always be used on all
calls to dev.vector. Dev.vector can still be asked to draw continuous
lines (ie, those for which dashon=0) without warning at any time.
Dashsum gives the total length of the dash-gap pattern
X(ie, dashsum = summation i=0;i<dashon*2;i++ of dashes[i]).
The position in the dash pattern at the start of the vector is given
in dashpos (it is the responsibility of dev.vector to update dashpos
after each vector is drawn. The only time dovplot ever touches it is to
reset it back to zero.) Dashpos, dashsum, and dashes are all measured
in INCHES. (You should get the same size dash pattern on different
devices even if they have different-sized screens!) If you are not
sure whether you have supported dashed lines correctly, try using
dashvec (described below) to do the dashing and see if the results
are compatible.
X
Just as in the case of dashing, dev.attributes(NEW_FAT,...) warns
when the "current fatness" has been changed. But dev.vector can
still be asked to draw a line with a different fatness (such as for
a polygon border) without warning at any time.
X
Utility routines associated with dev.vector:
X	These routines are meant to be called from a device-dependent
dev.vector routine as utility functions.
X
fatvec(x1, y1, x2, y2, nfat, dashon)
int x1, y1, x2, y2, nfat, dashon;
X
Fatvec should ONLY be called if nfat>0. Fatvec will apply Glenn Kroeger's
line-fattening algorithm to the given fat vector, replacing it with several
non-fat vectors. Fatvec will thus repeatedly call dev.vector with nfat=0.
X(That's why it is important that your routine only call fatvec if nfat>0!)
Fatvec ignores the dashon argument.
X
dashvec(x1, y1, x2, y2, nfat, dashon)
int x1, y1, x2, y2, nfat, dashon;
X
Dashvec should ONLY be called if dashon>0. Dashvec will apply Joe Dellinger
and Steve Cole's line-dashing algorithm to the given dashed vector, replacing
it with several non-dashed vectors. Dashvec will thus repeatedly call
dev.vector with dashon=0. (That's why it is important that your routine
only call dashvec if dashon>0!) Dashvec ignores the nfat argument.
X
Note that if both dashvec and fatvec are called, dashvec must be called
FIRST.
X
int clip(x1, y1, x2, y2)
int *x1, *y1, *x2, *y2;
X
Clip will clip the vector {(x1,y1),(x2,y2)} to the bounds set by
X{(xwmin,ywmin),(xwmax,ywmax)}. If the line is completely out of
bounds and is clipped away to nothing, clip returns 1. Otherwise,
clip returns 0. The standard way of using clip is:
X
X	if(clip(&x1,&y1,&x2,&y2)) return;
X
Generic routines for dev.vector: genvector.c
This routine will do all required clipping, fattening, and dashing.
It will also keep track of the previous position, and breaks up strings
of vectors for you into moves and draws. (It does this in a tricky way,
re-ordering the incoming vectors and even discarding moves that can be done
with draws. The idea is to make the plot come out as efficiently as possible
on the device.) It calls dev.plot(x,y,flag). No other routine calls
dev.plot, so if you do not use genvector then dev.plot should be nulldev.
X
X===========================
X
dev.marker(npts, mtype, msize, coor)
int npts, type, size;
int coor[/* npts*2 */];
X
Draw npts symbols centered at device coordinates (coor[0],coor[1]),
X(coor[2],coor[3]),...,(coor[npts*2-2],coor[npts*2-1]).
X
Mtype is an integer from 0 to whatever, defining the type of symbol to
draw. Mtype of 0 through 5 is defined as in GKS:
X0,1: Smallest possible dot on the device.
X2: Plus sign
X3: Asterisk
X4: Circle
X5: Cross
X6-19: Reserved by GKS, but currently undefined.
These are as used in Vplot:
X20: Square
X21: Triangle (flat side on bottom)
X22: Diamond
X23: 5-pointed Star
X
For values that make sense as ASCII, something that looks like the
corresponding ASCII character should be used.
For ridiculous values of mtype, at least plot a point.
X
Msize is the vertical height of the symbol in VERTICAL device units.
X(Ie, msize says how many pixels tall the letter `A' should be.)
X
Generic routines: genmarker.c
Genmarker calls dev.point, dev.text, or gentext.c as needed to produce
the desired symbols. For ASCII symbols the current font is used, which
could either be a device-dependent font or a gentext font depending on the
font number. Marker types 2 through 23 are drawn using the MATH and
MISC gentext fonts.
X
X===========================
X
dev.text(string, pathx, pathy, upx, upy);
char *string;
float pathx, pathy, upx, upy;
X{
X/* These can be defined by including vplot.h and extern.h */
extern int txfont, txprec, txovly;
struct txalign {int hor; int ver;};
extern struct txalign txalign;
extern int fat;
extern int xold, yold;
X
Print the text in string at the point (xold,yold) in device coordinates.
Upon return, xold and yold should be reset to point to the END of the text.
X(IE, for the normal text justification mode (TH_LEFT, TV_BASE), if the
dev.text routine is called twice in a row the two printed strings should
fit together nicely, as if produced by one call to dev.text with the two
strings concatenated.)
X
The text should have fatness `fat', as defined in the section for
dev.vector above.
X
The text should be justified according to the values of txalign.hor
X(for horizontal alignment) and txalign.ver (for vertical alignment.)
See vplot.h and vplottext.mn for descriptions of how text justification
should work and to enumerate the various justification modes. (Our modes
follow GKS, but with a couple of extensions thrown in to handle symbols
and mid-text font and size changes.)
X
The text font value to use is given by txfont. Device-dependent text fonts
start at font number NUMGENFONT. For txfont less than this, dovplot will
NOT automatically call gentext. Device-dependent text routines, except
for certain special cases, should begin by:
X
X	if (txfont < NUMGENFONT)
X	{
X	gentext(...pass on all arguments here...);
X	return;
X	}
X
The text precision value can be used by device-dependent text routines
to control the quality of text produced. (You should either follow the
GKS conventions or simply produce good text and ignore this parameter.)
The three different precisions are enumerated in vplot.h
X
The text overlay value controls whether or not an area is shaded out
under the text before it is drawn, and whether or not a box should be
drawn around it. The shading should be to the current background color,
END_OF_FILE
if test 25049 -ne `wc -c <'Vplot_Kernel/Documentation/hacker.doc.1'`; then
    echo shar: \"'Vplot_Kernel/Documentation/hacker.doc.1'\" unpacked with wrong size!
fi
# end of 'Vplot_Kernel/Documentation/hacker.doc.1'
fi
if test -f 'Vplot_Kernel/filters/init_vplot.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Vplot_Kernel/filters/init_vplot.c'\"
else
echo shar: Extracting \"'Vplot_Kernel/filters/init_vplot.c'\" \(23118 characters\)
sed "s/^X//" >'Vplot_Kernel/filters/init_vplot.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:   ./filters/init_vplot.c
X *
X * Joe Dellinger (SEP), Feb 18 1988
X *	Inserted this sample edit history entry.
X *	Please log any further modifications made to this file:
X *
X * Joe Dellinger, Feb 20 1988
X *	#define GETPAR to be fetch if SEPlib version.
X *
X * Joe Dellinger Feb 24 1988
X * 	Moved gen_do_dovplot to genlib, where it belongs.
X *	txfont, txprec, txovly, overlay defaults remembered.
X * Joe Dellinger Feb 28 1988
X *	Changed fatness to scale with size of screen and scale,
X *	like any regular geometric attribute.
X * Joe Dellinger Mar 4 1988
X *	Fixed slight bug with fatness scaling and style=old.
X */
X
X#include	<stdio.h>
X#include	<math.h>
X#include	<sys/ioctl.h>
X#include	<sys/types.h>
X#include	<sys/stat.h>
X#include	<sgtty.h>
X#include	<ctype.h>
X#include	<strings.h>
X
X#include	<vplot.h>
X
X#include	"./include/params.h"	/* for machine dependencies */
X#include	"./include/enum.h"
X#include	"./include/err.h"
X#include	"./include/attrcom.h"
X#include	"./include/intcom.h"
X#include	"./include/mesgcom.h"
X#include	"./include/erasecom.h"
X#include	"./include/closestat.h"
X#include	"./include/pat.h"
X#include	"./include/vertex.h"
X#include	"./include/round.h"
X#include	"./include/extern.h"
X
X#ifdef SEP
X#define		GETPAR	fetch
X#else
X#define		GETPAR	getpar
X#endif SEP
X
struct sgttyb   tty_clean_state;
struct sgttyb   tty_plot_state;
int             tty_clean_local_mode;
int             tty_plot_local_mode;
X
X/* 
X * The following variables must ALWAYS
X * be set in the device open or device reset file.
X * All their defaults are set to absurd values so that
X * we'll crash quickly it they're not set as required.
X */
X/* Screen dimensions */
int             dev_xmax = 0, dev_ymax = 0, dev_xmin = 0, dev_ymin = 0;
X/* Number of pixels per inch in the horizontal (X) direction on the device */
float           pixels_per_inch = 0.;
X/* vertical height (on screen) / horizontal width for a single pixel */
float           aspect_ratio = 0.;
X/*
X * Number of SETTABLE COLORS that the device has.
X * Non settable colors don't count.
X */
int             num_col = -1;
X
X/*
X * Other things that may need to be reset in dev.open
X * (Can't reset them some of them in dev.reset, because the user may
X * override from the command line.)
X */
X/* Does device need erase at end? */
int             need_end_erase = NO;
X/* should the output be buffered? */
int             buffer_output = YES;
X/* should the input be buffered? */
int             buffer_input = YES;
X/* should pipes be allowed for input? */
int             allow_pipe = YES;
X/* Can the device do its own clipping? (of vectors and polygons.) */
int             smart_clip = NO;
X/* Can the device stretch AND clip its own raster? */
int             smart_raster = NO;
X
X/*
X * These may be reset to device-dependent defaults.
X */
float           fatmult = 1.;
float           patternmult = 1.;
X
X/*
X * Look in extern.h for a better-organized list of the preceding.
X * Here I have left things which are also filter options with the
X * other filter options, even though they also belong in the above
X * categories.
X */
X
X/*
X * flags and variables
X */
char            wstype[25];
char            callname[25];
int             xcenterflag, ycenterflag;
int             ever_called = NO;
int             first_time = YES;
int             device_open = NO;	/* used by ERR */
int             out_isatty = YES;	/* If NO, output is a file or pipe */
int             nplots = 0;	/* number of plots made */
X
X/*
X * coordinate variables
X */
int             xwmax, xwmin, ywmax, ywmin;	/* window */
int             xnew, ynew;	/* new pen location */
int             xold, yold;	/* old pen location */
int             xorigin = 0, yorigin = 0;	/* global "origin" */
char           *txbuffer;
int             txbuflen, vxbuflen;
struct vertex  *vxbuffer;
int             xret, yret;
float           mxx, mxy, myx, myy;
X/*
X * This is so the device can throw in a coordinate transformation
X * for its convenience ON TOP OF whatever transformation the user
X * wants.
X */
int             default_rotate = 0, default_hshift = 0, default_vshift = 0;
X
X/*
X * attribute variables
X */
int             linestyle;
int             cur_color = DEFAULT_COLOR;
int             pat_color = DEFAULT_COLOR + 1;
int             next_color;
struct txalign  txalign;
X
int             txfont = DEFAULT_FONT;
int             txprec = DEFAULT_PREC;
int             txovly = OVLY_NORMAL;
int             default_txfont, default_txprec, default_txovly;
int             fat = 0;
int             afat = 0;
int             ipat = 0;	/* currently loaded pattern */
struct pat      pat[NPAT + 1];
float           dashsum = 0.;
int             dashon = NO;	/* Dashed lines? */
float           dashes[MAXDASH * 2];
float           dashpos = 0.;	/* Position in current dashing pattern */
int             color_set[MAX_COL + 1][_NUM_PRIM];
extern int      greycorr ();
int             num_col_8;
X
X
X/*
X * filter options - flags
X */
X/* Monochrome device? */
int             mono = NO;
X/*
X * Invras determines the polarity of dithered raster.
X * invras=n means raster works the same way as vectors; what is normally
X * WHITE on most devices is BLACK on a hardcopy black and white device.
X * invras=y is the proper default to make dithered images not come out as negatives
X */
int             invras = YES;
int             window = YES;
int             shade = YES;
int             brake = NO;
int             framewindows = NO;
int             endpause = NO;
int             allowecho = NEVER_SET;
X/*
X * setting allowecho NO (which may get done
X * in dev.open) means that the output device
X * is the user's terminal and echoing chars
X * back at the user would insert nonsense
X * into the plot stream.  In this case we
X * explicitly shut down echoing and output
X * translation until the end of the job.
X * Arguably, output translation should be
X * set/unset in dev.open or dev.reset as we may
X * be plotting on a terminal not our own or
X * the device filter may have built in
X * workarounds for known output translation
X * effects. I use it here as a safety measure.
X */
int             wantras = YES;
X
X/*
X * filter options - enumerated
X */
int             style = NO_STYLE_YET;
int             default_style = STYLE;
int             rotate;
int             size = RELATIVE;
int             erase = FORCE_INITIAL | DO_LITERALS;
X
X/*
X * filter options - valued
X */
int             xcenter, ycenter;	/* Vplot of point to force as center */
int             fatbase = 0;
int             epause = 0;	/* time to pause before erasing screen */
int             overlay = 0;	/* 1=overlay 0=replace */
int             default_overlay;
X
X/*
X * 0 = none
X * 1 = random
X * 2 = Ordered
X * 3 = Floyd-Steinberg
X */
int             dither = 1;	/* Dithering type */
X
int             xWmax, xWmin, yWmax, yWmin;
float           hshift, vshift;	/* Allow global translation of plot */
float           scale;	/* global scale */
float           xscale;	/* global x-scale */
float           yscale;	/* global y-scale */
float           hdevscale;	/* Vplot units to device units for x */
float           vdevscale;	/* Vplot units to device units for y */
float           txscale;/* global text scale */
float           mkscale;/* global marker scale */
float           dashscale;	/* global dashed line scale */
char            interact[MAXFLEN + 1] = "";	/* Where to store coordinate
X						 * file */
float           greyc = 1.;	/* Nonlinear correction */
float           pixc = 1.;	/* Pixel overlap correction */
X
X/* filter options - resettable between plots */
int             user_rotate;
float           user_txscale;
float           user_mkscale;
float           user_dashscale;
float           user_scale;
float           user_xscale;
float           user_yscale;
int             user_size;
float           user_hshift;
float           user_vshift;
int             user_xwmax_flag;
float           user_xwmax;
int             user_ywmax_flag;
float           user_ywmax;
int             user_xwmin_flag;
float           user_xwmin;
int             user_ywmin_flag;
float           user_ywmin;
X
int             ifat = 0;
float           fatmult_orig;
X
X/*
X * file and terminal control variables
X */
int             pltoutfd, stderrfd, controlfd;
extern int      genmessage ();
int             (*message) () = genmessage;
struct stat     stderrstat;
struct stat     pltoutstat;
FILE           *pltout, *pltin;
FILE           *fopen ();
FILE           *fdopen ();
FILE           *controltty;
char            outbuf[BUFSIZ];
char           *getenv ();
char           *malloc ();
char           *realloc ();
char            group_name[MAXFLEN + 1];
int             group_number = 0;
FILE           *pltinarray[MAXIN];
char            pltinname[MAXIN][MAXFLEN + 1];
char            pltname[MAXFLEN + 1] = "";
int             infileno = 0;
extern int      gen_do_dovplot ();
int             (*genreader) () = gen_do_dovplot;
X
X/*
X * Initialize and declare global variables.
X * Use getpar and getenv to search for command-line options.
X */
X
init_vplot ()
X{
char           *stringptr;
int             ii;
char            string[MAXFLEN + 1];
float           ftemp;
X
X
X    txbuffer = malloc (TXBUFLEN);
X    txbuflen = TXBUFLEN;
X/*
X * Sun III lint complains about "pointer alignment problem" here,
X * although the documentation makes it sound like that shouldn't
X * be possible.
X */
X    vxbuffer = (struct vertex *) malloc (sizeof (struct vertex) * VXBUFLEN);
X    vxbuflen = VXBUFLEN;
X
X    /*
X     * If the device can't do color, it can set mono to YES If device is
X     * mono, this overrides the user's insistence that it isn't. So GETPAR
X     * before we call dev.open. 
X     */
X    GETPAR ("mono", "1", &mono);
X
X    strcpy (wstype, "default");
X    if ((stringptr = getenv ("WSTYPE")) != NULL)
X	strcpy (wstype, stringptr);
X    /*
X     * Don't want to accidentally get this from a history file. Must come for
X     * the command line, so getpar, not GETPAR 
X     */
X    getpar ("wstype", "s", wstype);
X
X    /*
X     * Initialize all patterns to be undefined. (device can create a
X     * device-dependent default set if it wishes) 
X     */
X    for (ii = 0; ii <= NPAT; ii++)
X    {
X	pat[ii] .patbits = NULL;
X    }
X
X/*
X * The device-independent code MAY NOT actually read from
X * the terminal itself. However, these variables are 
X * declared so that the device-dependent routines can use
X * them if they wish as a courtesy.
X */
X    controlfd = open ("/dev/tty", 0);
X    controltty = fdopen (controlfd, "r");
X
X    /*
X     * Call device open before doing anything else. this finalizes pltout 
X     */
X    dev.open ();
X    device_open = YES;
X
X/*
X * Beware trying to print out error messages until
X * we've figured out where to connect the "message" routine!
X */
X
X    if (buffer_output)
X	setbuf (pltout, outbuf);
X    else
X	setbuf (pltout, (char *) NULL);
X
X    /*
X     * If graphics output going to control terminal, disable echoing and
X     * arrange for use of device's message routine 
X     */
X    pltoutfd = fileno (pltout);
X    stderrfd = fileno (stderr);
X    out_isatty = isatty (pltoutfd);
X
X    if (allowecho == NEVER_SET)
X    {
X	allowecho = YES;
X	if (out_isatty)
X	{
X	    fstat (pltoutfd, &pltoutstat);
X	    fstat (stderrfd, &stderrstat);
X#ifdef SEP
X	    if ((pltoutstat.st_dev == stderrstat.st_dev))
X		/*
X		 * Something in seplib makes the next 2 tests not work, I
X		 * don't know why. Unfortunately, this means the SEP versions
X		 * aren't as good about detecting the case of sending the
X		 * output to a different terminal than the one you're logged
X		 * in at. We should probably get this fixed sometime. - Joe
X		 * D. 
X		 */
X#else
X	    if ((pltoutstat.st_dev == stderrstat.st_dev) &&
X		(pltoutstat.st_ino == stderrstat.st_ino) &&
X		(pltoutstat.st_rdev == stderrstat.st_rdev))
X#endif SEP
X	    {
X		allowecho = NO;
X		message = dev.message;
X	    }
X	}
X    }
X
X    /*
X     * process YES or NO option arguments. GETPAR means it could have come
X     * from a seplib history file, getpar means it had to come from the
X     * command line. Use "getpar" when having the right value of the
X     * parameter is critical because setting the value overrides frontend's
X     * judgement. 
X     */
X    getpar ("echo", "1", &allowecho);
X    if (!allowecho)
X    {
X	ioctl (pltoutfd, TIOCGETP, (char *) (&tty_clean_state));
X	bcopy ((char *) (&tty_clean_state), (char *) (&tty_plot_state),
X	       sizeof (struct sgttyb));
X	ioctl (pltoutfd, TIOCLGET, (char *) (&tty_clean_local_mode));
X	tty_plot_local_mode = tty_clean_local_mode | LLITOUT;
X	ioctl (pltoutfd, TIOCLSET, (char *) (&tty_plot_local_mode));
X	tty_plot_state.sg_flags &= (~ECHO);
X	tty_plot_state.sg_flags &= (~LCASE);
X	tty_plot_state.sg_flags |= (CBREAK);
X	ioctl (pltoutfd, TIOCSETN, (char *) (&tty_plot_state));
X    }
X    getpar ("endpause", "1", &endpause);
X    GETPAR ("break", "1", &brake);
X    GETPAR ("shade", "1", &shade);
X    GETPAR ("wantras", "1", &wantras);
X    GETPAR ("window", "1", &window);
X    GETPAR ("frame", "1", &framewindows);
X    GETPAR ("overlay", "1", &overlay);
X    default_overlay = overlay;
X    GETPAR ("invras", "1", &invras);
X
X/*
X * Valued arguments
X */
X
X    getpar ("dither", "d", &dither);
X    getpar ("greyc", "f", &greyc);
X    getpar ("pixc", "f", &pixc);
X
X    GETPAR ("txfont", "d", &txfont);
X    GETPAR ("txprec", "d", &txprec);
X    GETPAR ("txovly", "d", &txovly);
X    default_txfont = txfont;
X    default_txprec = txprec;
X    default_txovly = txovly;
X
X    if (GETPAR ("erase", "s", string))
X    {
X	if ((string[0] == 'n') || (string[0] == 'N'))
X	    erase = NO;
X	else
X	if ((string[0] == 'o') || (string[0] == 'O'))
X	    erase = FORCE_INITIAL;
X	else
X	if ((string[0] == 'l') || (string[0] == 'L'))
X	    erase = DO_LITERALS;
X	else
X	    erase = FORCE_INITIAL | DO_LITERALS;
X    }
X
X    xcenter = 0;
X    ycenter = 0;
X    xcenterflag = NO;
X    ycenterflag = NO;
X    if (GETPAR ("xcenter", "f", &ftemp))
X    {
X	xcenterflag = YES;
X	xcenter = ROUND (ftemp * RPERIN);
X    }
X    if (GETPAR ("ycenter", "f", &ftemp))
X    {
X	ycenterflag = YES;
X	ycenter = ROUND (ftemp * RPERIN);
X    }
X
X    if ((stringptr = getenv ("PATTERNMULT")) != NULL)
X    {
X	sscanf (stringptr, "%f", &patternmult);
X    }
X    GETPAR ("patternmult", "f", &patternmult);
X
X    GETPAR ("interact", "s", interact);
X    GETPAR ("pause", "d", &epause);
X
X    if (interact[0] != '\0')
X    {
X	epause = 0;		/* interact makes it own sort of pausing */
X	endpause = NO;
X    }
X
X    /*
X     * Find the default style 
X     */
X    stringptr = NULL;
X    if (GETPAR ("style", "s", string))
X	stringptr = string;
X    else
X	stringptr = getenv ("PLOTSTYLE");
X    if (stringptr != NULL)
X    {
X	if ((stringptr[0] == 'r') || (stringptr[0] == 'R') ||
X	    (stringptr[0] == 'm') || (stringptr[0] == 'M'))
X	    default_style = ROTATED;
X	else
X	if ((stringptr[0] == 'o') || (stringptr[0] == 'O'))
X	    default_style = OLD;
X	else
X	if ((stringptr[0] == 'a') || (stringptr[0] == 'A'))
X	    default_style = ABSOLUTE;
X	else
X	    default_style = STANDARD;
X    }
X
X/*
X * Options changeable between calls to dovplot
X * (By calling reset_parameters or reset())
X * Dovplot calls reset every time it starts. It only calls
X * reset_parameters the first time.
X *
X * Things in this category:
X * user_*
X * fatmult_orig, fatbase
X */
X
X    if ((stringptr = getenv ("FATMULT")) != NULL)
X    {
X	sscanf (stringptr, "%f", &fatmult);
X    }
X    GETPAR ("fatmult", "f", &fatmult);
X    fatmult_orig = fatmult;
X
X    user_rotate = 0;
X    GETPAR ("rotate", "d", &user_rotate);
X
X    user_txscale = 1.0;
X    user_mkscale = 1.0;
X    user_dashscale = 1.0;
X    GETPAR ("txscale", "f", &user_txscale);
X    GETPAR ("mkscale", "f", &user_mkscale);
X    GETPAR ("dashscale", "f", &user_dashscale);
X
X    user_scale = 1.0;
X    user_xscale = 1.0;
X    user_yscale = 1.0;
X    GETPAR ("scale", "f", &user_scale);
X    GETPAR ("xscale", "f", &user_xscale);
X    GETPAR ("yscale", "f", &user_yscale);
X
X    user_size = size;
X    if (GETPAR ("size", "s", string))
X    {
X	if ((string[0] == 'a') || (string[0] == 'A'))
X	    user_size = ABSOLUTE;
X	else
X	    user_size = RELATIVE;
X    }
X
X    user_hshift = 0.;
X    GETPAR ("hshift xshift", "f", &user_hshift);
X    user_vshift = 0.;
X    GETPAR ("vshift yshift", "f", &user_vshift);
X
X    user_xwmax_flag = GETPAR ("xwmax", "f", &user_xwmax);
X    user_ywmax_flag = GETPAR ("ywmax", "f", &user_ywmax);
X    user_xwmin_flag = GETPAR ("xwmin", "f", &user_xwmin);
X    user_ywmin_flag = GETPAR ("ywmin", "f", &user_ywmin);
X
X    GETPAR ("fat", "d", &fatbase);
X
X
X
X/*
X *  These parameters can simply be changed at any time with no
X *  need for re-initialization of anything else:
X *
X *  shade, wantras
X *
X */
X
X}
X
init_colors ()
X{
int             ii;
X
X    /*
X     * Set up the default color table 
X     */
X
X/*
X * First 7 colors are assumed to map to the standard 7 pen colors
X * on ALL devices, even those with no settable colors!
X */
X    for (ii = 0; ii < 8; ii++)
X    {
X	color_set[ii][STATUS] = SET;
X	color_set[ii][_RED] = MAX_GUN * ((ii & 2) / 2);
X	color_set[ii][_GREEN] = MAX_GUN * ((ii & 4) / 4);
X	color_set[ii][_BLUE] = MAX_GUN * ((ii & 1) / 1);
X	color_set[ii][_GREY] = greycorr ((int) ((MAX_GUN * ii) / 7));
X    }
X
X    if (mono)
X    {
X	/* Monochrome devices are assumed to have no settable colors */
X	num_col = 0;
X    }
X
X    num_col_8 = (num_col > 8) ? num_col : 8;
X
X    if (mono)
X    {
X	color_set[0][MAP] = 0;
X	for (ii = 1; ii <= MAX_COL; ii++)
X	{
X	    color_set[ii][MAP] = 7;
X	}
X	for (ii = num_col_8; ii < 256; ii++)
X	{
X	    color_set[ii][_GREY] = color_set[((ii - 8) % 7) + 1][_GREY];
X	}
X	/* Put a grey scale in the upper half of the color table */
X	for (ii = 256; ii <= MAX_COL; ii++)
X	{
X	    color_set[ii][_GREY] = greycorr (ii - 256);
X	}
X    }
X    else
X    {
X	/*
X	 * Unmapped colors shouldn't be mapped; ie, they map to themselves 
X	 */
X	for (ii = 0; ii < num_col_8; ii++)
X	{
X	    color_set[ii][MAP] = ii;
X	}
X	/*
X	 * Colors outside the range of this terminal map cyclically back into
X	 * colors 1 through 7 
X	 */
X	for (ii = num_col_8; ii <= MAX_COL; ii++)
X	{
X	    color_set[ii][MAP] = ((ii - 8) % 7) + 1;
X	}
X    }
X}
X
setstyle (new_style)
X    int             new_style;
X{
X    /*
X     * Check to see if the style has changed 
X     */
X    if (new_style == style)
X	return;
X
X    style = new_style;
X    reset_parameters ();
X}
X
reset_parameters ()
X{
float           inches;	/* scaling base for y axis */
float           screenheight, screenwidth;	/* true size of the screen */
int             ix, iy;
X
X    xorigin = 0;
X    yorigin = 0;
X
X    rotate = default_rotate;
X    rotate += user_rotate;
X
X    txscale = user_txscale;
X    mkscale = user_mkscale;
X    dashscale = user_dashscale;
X
X    scale = user_scale;
X    xscale = user_xscale;
X    yscale = user_yscale;
X
X    fatmult = fatmult_orig;
X
X    size = user_size;
X
X    switch (style)
X    {
X/*
X * The old standard on the machine erebus.
X * Pretty much dead now. Still useful for some old programs nobody's
X * wanted to update.
X */
X    case OLD:
X	txscale /= 3.;
X	fatmult /= 3.;
X	scale *= 3.;
X	inches = STANDARD_HEIGHT;
X	break;
X/*
X * The old standard on the machine mazama. A useful coordinate system
X * for geological sorts of plots. 
X * The Y axis goes the long way, across the screen, which is the device's
X * horizontal axis.
X */
X    case ROTATED:
X	rotate += 90;
X	inches = ROTATED_HEIGHT;
X	break;
X    case ABSOLUTE:
X	size = ABSOLUTE;
X    case STANDARD:
X    default:
X	inches = STANDARD_HEIGHT;
X	break;
X    }
X
X    if (rotate >= 0)
X	rotate = rotate % 360;
X    else
X	rotate = ((rotate % 360) + 360) % 360;
X
X    mxx = cos (2. * 3.14159 * rotate / 360.);
X    myy = cos (2. * 3.14159 * rotate / 360.);
X    mxy = sin (2. * 3.14159 * rotate / 360.);
X    myx = -sin (2. * 3.14159 * rotate / 360.);
X
X    if (size == ABSOLUTE)
X    {
X	vdevscale = pixels_per_inch / (float) (RPERIN * aspect_ratio);
X	hdevscale = pixels_per_inch / (float) RPERIN;
X    }
X    else
X    {
X	/*
X	 * Fit the inches x inches unit square into a displayable box with
X	 * aspect ratio SCREEN_RATIO 
X	 */
X	screenwidth = (dev_xmax - dev_xmin) * pixels_per_inch;
X	screenheight =
X	 (dev_ymax - dev_ymin) * pixels_per_inch * aspect_ratio;
X	if ((screenheight / screenwidth) > SCREEN_RATIO)
X	{
X	    vdevscale = (SCREEN_RATIO * ((dev_xmax - dev_xmin) / aspect_ratio)) /
X	     (inches * RPERIN);
X	    hdevscale = vdevscale * aspect_ratio;
X	}
X	else
X	{
X	    vdevscale = (dev_ymax - dev_ymin) / (inches * RPERIN);
X	    hdevscale = vdevscale * aspect_ratio;
X	}
X    }
X
X    hshift = default_hshift;
X    vshift = default_vshift;
X
X    if (style == ROTATED)
X    {
X	vshift += dev_ymax - dev_ymin;
X    }
X
X    yscale *= scale;
X    xscale *= scale;
X    mkscale *= scale;
X
X/*
X * Set up fatness multiplication factor
X */
X    fatmult *= scale * hdevscale * RPERIN / FATPERIN;
X
X    /*
X     * The point (xcenter,ycenter) in vplot coordinates is to be centered in
X     * the screen. 
X     */
X    if (xcenterflag || ycenterflag)
X    {
X	vptodevxy (xcenter, ycenter, &ix, &iy);
X	if (xcenterflag)
X	{
X	    hshift += (dev_xmax + dev_xmin) / 2 - ix;
X	}
X	if (ycenterflag)
X	{
X	    vshift += (dev_ymax + dev_ymin) / 2 - iy;
X	}
X    }
X
X    hshift += user_hshift * pixels_per_inch;
X    vshift += user_vshift * pixels_per_inch / aspect_ratio;
X
X/* plot window parameters defaulted */
X/* to maximum size */
X
X    devtovpw (dev_xmin, dev_ymin, dev_xmax, dev_ymax,
X	      &xWmin, &yWmin, &xWmax, &yWmax);
X
X    if (user_xwmax_flag)
X	xWmax = ROUND (user_xwmax * RPERIN);
X    if (user_ywmax_flag)
X	yWmax = ROUND (user_ywmax * RPERIN);
X    if (user_xwmin_flag)
X	xWmin = ROUND (user_xwmin * RPERIN);
X    if (user_ywmin_flag)
X	yWmin = ROUND (user_ywmin * RPERIN);
X
X    vptodevw (xWmin, yWmin, xWmax, yWmax, &xWmin, &yWmin, &xWmax, &yWmax);
X
X    wlimit (dev_xmin, dev_xmax, &xWmin, &xWmax);
X    wlimit (dev_ymin, dev_ymax, &yWmin, &yWmax);
X
X    xwmax = xWmax;		/* plot window parameters defaulted */
X    xwmin = xWmin;		/* to maximum size 		 */
X    ywmax = yWmax;
X    ywmin = yWmin;
X    reset_windows ();
X}
X
add_a_cor (filename, xcor, ycor)
X    char           *filename;
X    int             xcor, ycor;
X{
static int      first_time = YES;
static FILE    *outfp;
X
X    if (first_time == YES)
X    {
X	outfp = fopen (filename, "w");
X	if (outfp == NULL)
X	{
X	    ERR (FATAL, name, "Can't open interact output file %s!", filename);
X	}
X	first_time = NO;
X    }
X    fprintf (outfp, "%f\t%f\n", (float) xcor / RPERIN, (float) ycor / RPERIN);
X}
X
wlimit (min, max, xmin, xmax)
X    int             min, max;
X    int            *xmin, *xmax;
X{
X    if (*xmin < min)
X	*xmin = min;
X
X    if (*xmax > max)
X	*xmax = max;
X}
X
END_OF_FILE
# end of 'Vplot_Kernel/filters/init_vplot.c'
fi
echo shar: End of archive 19 \(of 24\).
cp /dev/null ark19isdone
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.