rsalz@bbn.com (Rich Salz) (04/07/88)
Submitted-by: Joe Dellinger <joe@hanauma.STANFORD.EDU> Posting-number: Volume 14, Issue 27 Archive-name: vplot/part22 #! /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 22 (of 24)." # Wrapped by rsalz@fig.bbn.com on Fri Mar 25 11:47:34 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Vplot_Kernel/Documentation/hacker.doc.2' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Vplot_Kernel/Documentation/hacker.doc.2'\" else echo shar: Extracting \"'Vplot_Kernel/Documentation/hacker.doc.2'\" \(29413 characters\) sed "s/^X//" >'Vplot_Kernel/Documentation/hacker.doc.2' <<'END_OF_FILE' color 0. The box should be of the same color and fatness as the text. Which value of txovly corresponds to what action is defined in vplot.h. It is up to the device to decide how big a box around the text is appropriate for a given font. (It is probably a good idea to follow gentext's example in this.) X Pathx, pathy, upx, and upy define the size, shape, and orientation of the text. Pathx and upx are in HORIZONTAL device units, and pathy and upy are in VERTICAL device units. (This distinction is important if your device does not have aspect_ratio=1..) Note that all 4 values are FLOATS, not ints. X The vector (pathx,pathy) defines the text path, and the vector (upx,upy) defines the character up vector. (This is just like in the GKS text notation conventions.) To understand the meaning of these two vectors, consider normal horizontal text with a height of 100 pixels. (We'll assume our device has square pixels for the moment.) For this text, (pathx,pathy) = (100.,0.) and (upx,upy) = (0.,100.). Now the position of any point on this text can be expressed as a linear combination of the path vector and the up vector. This is how dev.text should represent all text internally. In this way, if we linearly transform just the path vector and the up vector, then we do the transform to every point of the text too. If we rotate both the path and up vectors, the text rotates. if we multiply both the path and up vectors by two, the text gets twice as big. If the path and up vectors are not orthogonal, the text gets sheared. X To test a device-dependent text routine, try switching between a device-dependent font and one of the gentext fonts (txfont<NUMGENFONT). If your device-dependent test routine is correctly working, the text should always appear the same as far as height, direction, and position in both cases. X Generic routines: gentext.c Gentext.c produces text by mixing vectors and filled areas. It calls dev.vector, dev.area, and dev.attributes. It also recognizes many special escape sequences in the text. Gentext is documented in vplottext(9). X X=========================== X X#include "vertex.h" X#include "pat.h" dev.area(npts, verlist) int npts; struct vertex *verlist; X{ X/* These can be defined by including extern.h */ extern int xwmin, xwmax, ywmin, ywmax; extern int ipat; extern struct pat pat[]; X Dev.area fills a polygon with a user-defined pattern. Npts is the number of vertices of the polygon. The coordinates of the vertices themselves are stored in the doubly linked list verlist. X Here is vertex.h: X struct vertex X{ X int x; /* X coordinate of vertex */ X int y; /* Y coordinate of vertex */ X struct vertex *next; /* pointer to next vertex */ X struct vertex *last; /* pointer to last vertex */ X struct vertex *soft; /* pointer to some other vertex */ X}; X The coordinates are in device units. It is up to the device to clip the polygon! The lower-leftmost displayable point is (xwmin,ywmin) and the upper-rightmost displayable point is (xwmax,ywmax). X The pattern to fill with is given in the external pat[ipat], which is a structure of type pat. Here is pat.h: X struct pat X{ X int ydim; /* Slow dimension */ X int xdim; /* Fast dimension */ X int ydim_orig; X int xdim_orig; X int patbits[/*xdim*ydim*/]; /* Array of color numbers */ X}; X Pat.patbits is an array of pat.xdim by pat.ydim color values, with one element in the array for each device pixel. The pattern is repeated to fill the polygon. The position of the origin of the pattern does not matter, but should not depend on the particular polygon. (In other words, if two polygons tiled with the same pattern overlap, the pattern should be continuous across the two.) X The horizontal dimension of the pattern is length pat.xdim. This is the fast axis. The vertical dimension of the pattern is length pat.ydim. This is the slow axis. The pattern is scanned on the screen TV-style. X(In other words, pat.patbits[0] is at the upper-left hand corner, pat.patbits[pat.xdim-1] is the upper-right hand corner, and pat.patbits[pat.ydim*pat.xdim-1] is the lower right hand corner.) X If either pat.xdim or pat.ydim is 0 for a given polygon, dev.area is never even called and so no filling is done. If your device cannot fill with an arbitrary pattern, it is OK to fill solidly with the current color instead. X Dovplot will use a 1 by 1 pattern for polygons generated by the VP_OLDAREA command if the device uses color, regardless of the requested pattern (this is part of the definition of the VP_OLDAREA command). XXdim_orig and ydim_orig contain the values that xdim and ydim would have had if the device had been black and white. This is provided so that no information needed to reconstruct the original vplot command is lost. X Dovplot will call dev.attributes(NEW_PAT,ipat) whenever the pattern defined by pat[ipat] is loaded or updated. X Generic routines: vecarea.c, genarea.c, genpatarea.c Vecarea fills the polygon with the current color by drawing vertical and horizontal vectors. It shows the size of the pattern by the line spacing. Vecarea calls dev.vector and dev.attributes. X Genarea clips the given polygon (if smart_clip=NO), possibly generating more than one polygon out of the pieces. It then calls dev.startpoly, dev.midpoly, and dev.endpoly to do the actual filling of the polygons. X Genpatarea fills the polygon with the correct pattern one raster line at a time by calling dev.raster. It uses the ``dumb'' format for dev.raster, so you cannot use genpatarea if smart_raster=YES. X X=========================== X Dev.raster has 2 formats, depending on the value of smart_raster. X If smart_raster=NO, then the raster will be stretched to device coordinates, clipped (regardless of the value of smart_clip), color mapped, dithered (if appropriate), and broken up into individual scan lines. Dev.raster will be called once for each scan line of the raster image. X If smart_raster=YES, then the raster will be read in and color mapped, but nothing else. It is up to the device to dither it (if appropriate), stretch it, and clip it. The entire block of raster will be passed with one call to dev.raster. X X/* Dumb format, smart_raster=NO */ dev.raster(count, out_of, xpos, ypos, rlength, orient, raster, dummy1, dummy2) int count, out_of, xpos, ypos, rlength, orient, dummy1, dummy2; unsigned char raster[/*rlength*/]; X Draw a line of raster, starting at the point (xpos,ypos) and extending for a total of length pixels in a direction determined by orient. Orient is measured in units of 90 degrees clockwise from the device's XX (horizontal) axis. Thus for orient=0 you draw the line right, for orient=1 you draw down, for orient=2 left, and for orient=3 up. X The line of raster itself is in the array raster, which is of dimension rlength. Each element of the array is a color number which determines the color of one device pixel. X Some devices may be able to handle more than one line of raster at a time. The variables count and out_of are provided so that the device can know how many dev.raster calls will be made in a row. Count is zero for the first call, and increases by 1 each time until it reaches out_of-1 on the last call. (Thus out_of is the total number of raster lines.) X Scanning is done TV-style. (Thus, for orient=0, ypos decrements by 1 for each call; for orient=1, xpos decrements by 1 for each call; for orient=2, ypos increments by 1 for each call; for orient=3, xpos increments by 1 for each call.) Genraster1 gives you a good example of how to write a routine that builds up blocks of raster over several calls. X Dummy1 and dummy2 are not used; they are provided only so that both forms of the command have the same string of arguments. X Generic routines, dumb format: genraster.c, genraster1.c Genraster does vector draws along scan lines to produce raster output. It does one raster line at a time. Some fast but stupid devices can actually do raster reasonably fast this way. Genraster calls dev.attributes (to set the colors) and dev.vector. X Genraster1 attempts to be a little smarter than genraster. It saves up many lines worth of raster at a time, and sorts the vectors by color and length. It does all the vectors of one color at a time, so as to save on calls to dev.attribute to change the color. It also finds the parts of the image that can be more efficiently drawn via dev.point, and makes a second pass for those. (If the device has a point mode this is considerably more efficient.) Genraster1 calls dev.attributes, dev.vector, and dev.point. X X/* Smart format, smart_raster=YES */ dev.raster (xpix, ypix, xmin, ymin, xmax, ymax, X raster_block, orient, dither_it) int xpix, ypix, xmin, ymin, xmax, ymax, orient, dither_it; unsigned char raster_block[/*xpix*ypix*/]; X{ X/* Including "extern.h" defines these. */ extern int xwmin, xwmax, ywmin, ywmax; X Draw the block of raster in the array raster_block. If dither_it=NO, raster_block is an array of color numbers. If dither_it=YES, raster_block is an array of grey levels X(0 is black, 255 is white). X Raster_block has dimensions xpix times ypix, with xpix the fast axis. If orient=0, the raster is painted on the screen TV-style. The first array value is the upper-leftmost point. Each line of raster (xpix long) fills from left to right. Each new line of raster (ypix lines in all) is below the previous one. X If orient=1, we rotate the raster 90 degrees clockwise. Thus the first value is the upper rightmost point, and the raster fills in top to bottom and then right to left. For orient=2 we rotate another X90 degrees and fill in right to left and then bottom to top. For orient=3 we fill the raster in bottom to top and then left to right. X The lower-leftmost pixel in the raster image should appear on the screen at device coordinate (xmin, ymin) (assuming it isn't clipped, of course). The raster image should be (xmax-xmin) horizontal device units wide and (ymax-ymin) vertical device units tall. Thus, the pixel (xmax,ymax) is not the upper-rightmost pixel in the raster image, but is the first pixel above and to the right of the one that is. (I know this sounds strange. But when you actually code this up you'll see that it makes sense to do it this way, and that this is probably what you actually would have done even if I had told you to make sure that the point X(xmax,ymax) was in the image.) X Finally, the resulting image must be clipped so that (xwmin,ywmin) is the lower-leftmost pixel that can appear, and (xwmax,ywmax) is the upper-rightmost pixel that can appear. (Note that this time the corner IS in the image. Just trying to be confusing.) X Generic routines: NONE X X=========================== X dev.point(x1, y1) int x1, y1; X Change the pixel at device coordinate (x1,y1) to the current color. X Generic routines: genpoint.c Genpoint calls dev.vector with zero length. Somethings wrong with the dev.vector for your device if it doesn't do anything in this case. X X=========================== X dev.attributes(command, value, v1, v2, v3) int command, value, v1, v2, v3; X Set various attributes (color table, current color, clipping window, etc) using device-specific routines. Commands are defined and documented in include file attrcom.h. Value and v[1-3] are used to pass parameters as needed. Sometimes some of the 4 will be dummy arguments. X Comments about color: X The device tells dovplot how many colors it has by setting num_col and mono. Num_col is the number of settable colors. The color for color table numbers num_col and up will never attempt to be defined by dovplot. If num_col is zero, the device has no settable colors, and dev.attributes(SET_COLOR_TABLE,...) will never be called at all. X X Devices with no settable colors can still have color. If mono=NO, dovplot assumes that colors 0 through 7 correspond to the standard Vplot colors (as listed in vplot.h). Dovplot will not attempt to set the current color outside of the range 0 through 7 if num_col=0. X(There is no provision for devices with more than 8 colors but no settable colors.) X X Rather than forcing people to change the colors on their terminal to have vplot's colors come out right, you should map the color numbers dovplot asks for onto the correct device color numbers so that the factory default setting gives the correct colors. (Don't forget to similarly map the color table numbers too.) X X Calls to dev.attributes(SET_COLOR,...) by dovplot will only set colors in the range 0 through MAX(7,num_col-1). X X If mono=YES, dovplot will force num_col=0 and will only ever try to set the current color to be either 0 (meaning background) or 7 (meaning NOT background). X X Calls to device routines should NEVER upset the current color. If for some reason they should change it, they should always put it back again when they are done. (Dovplot keeps track of the current color, and only calls dev.attributes(SET_COLOR,...) when necessary.) Calls to generic routines are guaranteed to never (permanently) change the current color. X X Color tables should usually be set to factory default settings at the beginning of every plot, if it is possible to do this in such a way that the former settings can be restored again afterwards. X X Every device should AT LEAST keep track of whether or not the current drawing color is color 0 or not. Color 0 always defines the background color. If the device cannot draw (or rather undraw) in the background color, then it SHOULDN'T DRAW AT ALL when the current color is 0. X Generic routines: NONE X X------------------------------------------------------------- X Input routines X X============================== X int dev.getpoint(termout, x, y) FILE *termout; int *x, *y; X{ int status; X return status; X} X Turn on the cursor and let the user pick a point. Return the device coordinate of the picked point in (*x,*y), and return 0. If the user indicated that he doesn't want to pick any more points, return 1. X(The value in (*x,*y) is then considered to be junk by dovplot.) Returned values should be in the normal range of device coordinates. If (*x,*y) is returned unchanged, this will also indicate that no point was picked and no more points should be picked. X Termout is a stream pointer reading from ``/dev/tty''. You can use it if it is convenient and correct to do so, or ignore it. X Generic routines: nulldev Linking in nulldev for this routine will simulate a user that always declines to enter any points at all, since (*x,*y) is returned unchanged. X X============================== X dev.interact(command, termout, string) int command; FILE *termout; char string[]; X This routine handles string input from the user and pausing. The various possible commands are described in X".../vplot/filters/include/intcom.h". X Generic routines: nulldev, geninteract Linking in nulldev will rudely zoom past all prompts to the user without waiting. This is a reasonable thing to do for hardcopy devices. X Geninteract will read the required input from termout, which is connected to read from "/dev/tty". X X-------------------------------------------------------------------------- X Low level output routines --- only called by certain generic routines X X================================= X int lost = YES; dev.plot(x, y, draw) int x, y, draw; X Move or draw to device coordinate (x,y). Draw=0 for move, 1 for draw. X This routine MUST declare the global flag ``lost''. It is the responsibility of all the device routines to set this to YES whenever anything happens that may cause genvector's idea of the ``current device pen position'' to be wrong. (For example, printing an error message, doing hardware text, filling a polygon, etc.) Generic routines do not present a difficulty, since they can't output anything directly to the device. X When lost is set to YES, it is guaranteed that the next call to dev.plot will by a move, and not a draw. X When genvector's idea of the current position is correct again (for example when dev.plot has been called) lost should be set to NO. This is important; genvector only looks at the value of lost, it doesn't set it. Leaving lost YES all the time will greatly slow down plotting by forcing one move for each draw! X Generic routines: nulldev Link in nulldev here as a placeholder if you didn't use genvector as your vector routine. X X================================= X dev.startpoly(npts) int npts; X dev.midpoly(x,y) int x, y; X dev.endpoly(last) int last; X Polygon-drawing routines called only by genarea. X Dev.startpoly is called once at the beginning of every polygon. Npts gives the number of points in the polygon. After dev.startpoly has been called, then dev.midpoly is called once for each point in the polygon. (x,y) gives the device coordinate of the vertex. X Dev.endpoly is called once at the end of each polygon. Genarea may fragment one polygon into several. If this polygon just defined is the last polygon in a set of polygons that were fragmented from one, then last will be 1. If there are more fragments in this set to go, last will be 0. It is guaranteed that no other routines but these three will be called after the first dev.startpoly call and before dev.endpoly(last=YES) is called. X The genarea algorithm will fail for certain very complicated crossed polygons, unless the multiple polygons fragmented from the one original one are shaded as a unit. Some devices such as the Tek4105 allow this to be done. That is why the ``last'' flag is provided. There is no great harm in shading each polygon as it comes. Occasionally interior voids will be filled twice instead of not filled at all, that's all. X If the device can fill with an arbitrary pattern, it should do so. The pattern is available to these routines in the same way as described under dev.area. If the device cannot fill with a user-defined pattern, filling solidly with the current color is the next best thing. X Generic routines: nulldev.c If you did not use genarea as your dev.area routine, then none of these routines are ever called so you just need to put in nulldev as a placeholder. X X------------------------------------------------------------------------- HANDLING ERRORS: Device routines SHOULD NOT simply exit when they get a fatal error! All errors should be handled via the provided utility routine "ERR"! X X#include "err.h" ERR (type, filter, fmt, a1, a2, a3) int type; char *filter; char *fmt; double a1, a2, a3; X X"Type" is one of the possibilities from "err.h". Currently there are three possibilities: COMMENT, WARN, FATAL. Case COMMENT is just for making remarks, not really error messages per se. Case WARN should be used when something is wrong, but the filter can take reasonable corrective action. Case FATAL is for errors that should cause abnormal termination of the program. Calls to ERR with type FATAL will not return. X X"Filter" should be the name of the filter generating the error or comment as you want it to appear in the message. Normally this should just be the variable "name" defined in <dev>conf.c. X From here on ERR has the same syntax as "printf", except that ERR will automatically throw a carriage-return line-feed on for you (so you don't want to end with "\n"). X After ERR has been called with type FATAL, dovplot and frontend will do necessary cleaning up, in the process calling dev.close. Device-dependent cleaning up should be done by that routine at that time. X The define ERR is used so that conflicts with other subroutines named X"error", "err", etc, can be avoided. Currently "ERR" is defined to be X"filtererror", a name we haven't had any trouble with. X X------------------------------------------------------------------------- BEING TRICKY ABOUT THE ORDER THINGS ARE PLOTTED X The external variable extern int (*genreader) (); can be changed in dev.open to point to your own routine for processing input files. You should only need to change this variable if for some reason you want to be able to change the order or way in which input files are handled, or if you want to know the actual file names of the input plot files. (You might find this handy if you are creating an interactive vplot editor, for example.) X The default input file handling routine, which is what you get if you ignore this section of the documentation, is the following. Frontend already does the job of finding all the input files, verifying that they exist, and opening them for reading. X gen_do_dovplot (nn, inpltin, innames) int nn; FILE ** inpltin; char innames[][MAXFLEN+1]; X{ X int ii; X X for (ii = 0; ii < nn; ii++) X { X pltin = inpltin[ii]; X strcpy (pltname, innames[ii]); X dovplot (); X fclose (pltin); X } X} X X"Nn" is the number of input files. "Inpltin" is an array of nn stream pointers each of which point to an open (but unread-upon) input stream. X"Innames" is the corresponding array of strings giving the associated name of the input file for each of the streams in inpltin. X The external integer "buffer_input" can be set to NO in dev.open to assure that all the input streams are unbuffered. The external integer X"allow_pipe" can be set to NO in dev.open to assure that all the input streams are seekable on. X It is possible to change most variables set by command line arguments between calls to dovplot without ill effect. There are comments in init_vplot at the end of the section of code where command line arguments are processed listing which variables have been explicitly set up to be changeable in this way. X Variables controlling the mapping between the device's and vplot's coordinate system can also be changed, but the subroutine X"reset_parameters()" in frontend must be called afterwards to reinitialize all the related variables that may need it. X X./filters/vplib/vpdovplot.c is an example of a routine that makes X2 passes through a vplot file, doing things differently the second time around. X X------------------------------------------------------------------------- THINGS THAT GET RESET BETWEEN FRAMES (AND THINGS THAT DON'T) X Vplot has many "global" parameters. Some of these get reset between frames (or between input files); a few don't. X The following parameters get reset (by reset()) at the start of every new frame: clipping windows, drawing fatness, current drawing color, text alignment mode, text font, text precision, text overlay mode, raster overlay mode, dash line pattern. X The plot style also gets reset at the start of every new frame, but it is handled separately. X The following DO NOT GET RESET AT ALL: color tables, current pen position X The global vplot origin command is another special case. Generally, this command is only used when you are creating a figure "by hand" using plas. It is reset when reset_parameters() is called, but is global otherwise. It has no libvplot command on purpose. X X------------------------------------------------------------------------- GROUPS X The begin-end group commands are provided so that a "MacDraw"-like vplot editor may be created. The device knows when groups are opened and closed, and their positions within the current plot file, via the dev.attributes(BEGIN_GROUP,...) and dev.attributes(END_GROUP,...) calls. You can use fseek to reposition the plot stream to the beginning of a desired group, and then call dovplot to plot the group again. When the group open (number one, not zero) command is processed, the device gets a chance to reset global attributes from their "initialized" values. X(For example, to change the color.) When the group close (number one) command is processed, the device gets a chance to to reposition pltin to the end of the file and so cause dovplot to think it's done and return. X It is possible for the user to violate the grouping laws, ie: begin-group and end-group commands must be paired within a file, erases may not be contained within a group. Dovplot will warn the user if this happens. How the device handles such an error, however, is up to it. Caveat user. X A group number 0 is generated by dovplot itself for each plot frame, and consists of everything in the plot frame excepting erases. Erases lie between groups. Initial erase and style commands are not contained in the first group numbered 0. Groups generated by the begin-end group commands in the vplot file are numbered from 1 on up. X The external integer "group_number" gives the number of currently open groups. X X------------------------------------------------------------------------- SEPLIB TRICKS X If you don't use the seplib versions of the filters, you can ignore this section. X Pen filters have to do some tricky things with SEPlib since the standard defaults are inappropriate. Normally seplib wants to send the header to standard out. Since the output of Pen filters are usually not redirected, this would dump the header on your screen and possibly interfere with your plot. By the same token, the data output usually SHOULD go to your screen, instead of being saved in a file or sent down a pipe. The normal SEPlib method of self-documenting also has to be subverted in order to be consistent between the SEP and non-SEP versions of the programs. X To accomplish this, several things are done: X A library "tseplib" is provided that contains routines for which the standard seplib versions had to be modified. This should be linked AHEAD of seplib so that the modified versions get taken. The routines are documented as to how they differ and why. X X"OUT" and "HEAD" are defined to be the external variables "sepoutwhere" and "sepheadwhere", respectively. These are normally "/dev/tty" and X"/dev/null". (These values are grabbed from the routine "sepwhere" in tseplib.) If these values are inappropriate for your filter (unlikely to be the case for most filters; see Vppen for an example of one) you can create your own version of this routine and make sure it gets linked in ahead of tseplib. X If head=/dev/null and this was the default in sepheadwhere and standard out is redirected, then it is assumed the user really wants some sort of header despite the fact that the Pen filter killed the real one and so a "fake" one will be created for them by frontend. Frontend will only actually write something into it if "out" is not standard out (to avoid mixing header and data). The device-dependent code may do so if it wishes, though (see Raspen for an example). The device should only use "Puthead" to write to the header, to make sure everything is done properly. The "fake" header has the advantage that information can be added to it at any time. Normal SEPlib headers must be closed before any data can be written. Thus only fake headers can have "n3=number_of_frames" added onto the header. (This is why Raspen uses fake headers.) X X------------------------------------------------------------------------- FRONTEND, and DOING IT YOURSELF X The system-user interface is split among three routines, which together are called the "frontend". X Main_vplot is responsible for finding the input files and opening them, deciding where the output should go for devices that aren't strong-willed enough to insist on figuring it out for themselves, setting up signal catching, interfacing with SEPlib, and doing self-documentation. It also calls the other 2 routines, init_vplot and proc_vplot. X Init_vplot initializes all variables and calls dev.open to open the device. X Proc_vplot processes the input files. X It is possible to skip main_vplot and call init_vplot and proc_vplot yourself directly. However, init_vplot and proc_vplot expect certain things to be set before they are called. X Init_vplot expects: X XXargc and xargv are just copies of main's argc and argv, but declared globally so that other routines (namely getpar) have access to them. XXargc and xargv should be declared in the calling program. X Callname is a string which gives the "pen filter name" of the set of device-dependent routines you want. It should have the path stripped. The device-dependent code may want to know callname in order to pick between similar devices. Callname should be declared external. X Pltout is just a copy of stdout. It is an external FILE *. X Proc_vplot expects: X Infileno gives the number of input files. It is an external integer. X Pltinname[infileno] gives the names of the input files. It is an external array of pointers to chars. X Pltinarray[infileno] gives the already-open stream pointers for the afore-mentioned files. It is an external array of FILE *'s. X That's it. It is also possible to bypass even calling proc_vplot. See sample.c in .../vplot/filters for an example of how to do this. X X------------------------------------------------------------------------- AUTHORS The present generation of pen filters were created by Joe Dellinger. The original pen programs were written by Jeff Thorson and Rob Clayton. Glenn Kroeger and Michel Debiche cleaned up the organization of the code. Wes Monroe, Chuck Karish, Rick Ottolini, Doug Wilson, and Jean-Luc Guiziou have added support for new devices. Steve Cole added dithering. Stew Levin has found and fixed obscure bugs. X COPYRIGHT Vplot is copyrighted. Please read the copyright in the accompanying X"Vplot" manual page. The copyright is not very restrictive. If you want to include vplot (or derivatives thereof) as part of some other X"public domain" or "nearly public domain" package, we can probably work something out. The desired effect of the copyright is to permit widespread distribution without somebody trying to grab control of it for themselves or trying to sell it. X SEE ALSO vplot(L) pen(L) plas(L) pldb(L) seplib(L) getpar(L) END_OF_FILE if test 29413 -ne `wc -c <'Vplot_Kernel/Documentation/hacker.doc.2'`; then echo shar: \"'Vplot_Kernel/Documentation/hacker.doc.2'\" unpacked with wrong size! fi # end of 'Vplot_Kernel/Documentation/hacker.doc.2' fi echo shar: End of archive 22 \(of 24\). cp /dev/null ark22isdone 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.