home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume24
/
gnuplot3
/
part20
< prev
next >
Wrap
Text File
|
1991-10-28
|
49KB
|
1,872 lines
Newsgroups: comp.sources.misc
From: gershon%gr@cs.utah.edu (Elber Gershon)
Subject: v24i042: gnuplot3 - interactive function plotting utility, Part20/26
Message-ID: <1991Oct29.030924.3984@sparky.imd.sterling.com>
X-Md4-Signature: 8626dc11a59b66e8d5d5a2cf7da53f48
Date: Tue, 29 Oct 1991 03:09:24 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: gershon%gr@cs.utah.edu (Elber Gershon)
Posting-number: Volume 24, Issue 42
Archive-name: gnuplot3/part20
Environment: UNIX, MS-DOS, VMS
Supersedes: gnuplot2: Volume 11, Issue 65-79
#!/bin/sh
# this is Part.20 (part 20 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file gnuplot/term/apollo.trm continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 20; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping gnuplot/term/apollo.trm'
else
echo 'x - continuing file gnuplot/term/apollo.trm'
sed 's/^X//' << 'SHAR_EOF' >> 'gnuplot/term/apollo.trm' &&
X
X Ray Lischner (uunet!mntgfx!lisch)
X 4 October 1989 file created for GNUplot 1.1
X 26 March 1990 updated for GNUplot 2.0
*/
X
#include <apollo/base.h>
#include <apollo/error.h>
#include <apollo/pad.h>
#include <apollo/gpr.h>
X
/* default tick sizes for small windows */
#define APOLLO_VTIC 6
#define APOLLO_HTIC 6
X
/* issue an error message, using additional text "s" */
#define apollo_error(s) error_$print_name(status, (s), strlen(s))
X
/* if "status" indicates an error, then issue an error message */
#define apollo_check(s) if (status.all != status_$ok) apollo_error(s)
X
static ios_$id_t stream = -1; /* the stream for the pad */
static gpr_$bitmap_desc_t screen_desc; /* the screen's bitmap */
static gpr_$bitmap_desc_t bitmap_desc; /* the graphics bitmap */
static gpr_$attribute_desc_t attr; /* attribute block for saved bitmap */
static short draw_width; /* default GPR draw width */
static name_$long_pname_t font_name; /* font path name */
static int APOLLO_XMAX, APOLLO_YMAX; /* window size */
static boolean use_bitmap; /* use a separate bitmap? */
X
/* return whether stdout is a DM pad */
apollo_isa_pad()
{
X status_$t status;
X pad_$isa(1, &status);
X return (status.all == status_$ok);
}
X
/*
X Find out what the default font is for the pad, and save the
X character height and width information.
X
X Note that we must save the font file name because we need
X to reload the font file everytime the window changes size.
*/
static void apollo_font_info(struct termentry* tbl, char* fname)
{
X short fwidth, fheight, flen;
X status_$t status;
X
X /* get the font size & update the termentry table */
X pad_$inq_font(stream, &fwidth, &fheight, fname, name_$long_pnamlen_max,
X &flen, &status);
X apollo_check("inq_font");
X fname[flen] = '\0';
X
X tbl->v_char = fheight;
X tbl->h_char = fwidth;
}
X
/*
X Initialize all the GPR stuff. To save time, we draw into a separate
X bitmap, and then blt it onto the screen all at once. This results
X in 5-10 times speed-up in the graphics, with only a little
X complication. Most of the complication is right here, making sure
X we allocate the right bitmaps, etc., in the right order. The rest
X is in APOLLO_text(), where we actually BLT the bitmap onto the screen.
X Everything else is the same.
X
X The bitmaps have the same size as the window. If the window changes
X size, then the bitmaps retain the same size, so the user sees part
X of the plot or a lot of space around the plot. Drawing a new plot,
X or replotting the previous one causes APOLLO_graphics() to see if
X the window has changed size, in which case the GPR is terminated,
X and this routine is called again. Thus, make sure any changes
X preserve this ability. Anything that should only be done once
X to the pad should be handled by APOLLO_init().
X
X By the way, we save the current draw width, to be used later
X for drawing extra wide lines. This way we don't need to know
X anything about the current output device characteristics;
X we can just draw the default width, or twice the default width, etc.
*/
static void apollo_gpr_init(struct termentry* tbl, pad_$window_desc_t* window)
{
X gpr_$offset_t size;
X short fontid;
X status_$t status;
X
X size.x_size = APOLLO_XMAX = tbl->xmax = window->width;
X size.y_size = APOLLO_YMAX = tbl->ymax = window->height;
X
X /* now initialize GPR */
X gpr_$init(gpr_$frame, stream, size, 1, &screen_desc, &status);
X apollo_check("gpr_$init");
X
X if (use_bitmap)
X {
X /* allocate the bitmap and its attribute block */
X gpr_$allocate_attribute_block(&attr, &status);
X apollo_check("allocate_attribute_block");
X
X gpr_$allocate_bitmap(size, 1, attr, &bitmap_desc, &status);
X apollo_check("allocate_bitmap");
X
X gpr_$set_bitmap(bitmap_desc, &status);
X apollo_check("set_bitmap");
X }
X
X /* set the font file */
X gpr_$load_font_file(font_name, strlen(font_name), &fontid, &status);
X apollo_check(font_name);
X
X gpr_$set_text_font(fontid, &status);
X apollo_check("set_text_font");
X
X gpr_$inq_draw_width(&draw_width, &status);
X apollo_check("inq_draw_width");
}
X
/*
X Determine the tick sizes to be used for labelling borders.
X By default, we use 1/50 of the window size, which looks nice to me.
X If this makes the ticks too small, however, we use a minimum
X size, to make sure they are visible. The minimum size was also
X determined experimentally.
X
X Feel free to changes the sizes to something you feel looks better.
X
X This routine must be called after apollo_gpr_init(), because we
X need to know the window size, as stored in the termentry table.
*/
static void apollo_tic_sizes(struct termentry* tbl)
{
X /* base the tick size on the window size */
X tbl->v_tic = tbl->ymax / 50;
X if (tbl->v_tic < APOLLO_VTIC)
X tbl->v_tic = APOLLO_VTIC;
X tbl->h_tic = tbl->xmax / 50;
X if (tbl->v_tic < APOLLO_HTIC)
X tbl->v_tic = APOLLO_HTIC;
}
X
/*
X Terminate the GPR. This is called whenever the window size
X changes, and we need to reinitialize the GPR. I assume that
X calling gpr_$terminate() also deallocates the bitmaps and
X attribute blocks because deallocating the screen's bitmap
X causes terminate() to think GPR has already been terminated.
X
X Since this can be called many times, make sure nothing
X drastic is done here, like closing the stream to the pad.
X The only actions should be those that will be reinitialized
X by apollo_gpr_init().
*/
static void apollo_gpr_terminate()
{
X status_$t status;
X
X gpr_$terminate(false, &status);
X apollo_check("terminate");
}
X
/*
X Initialize the graphics. This is called once, so we do things
X here that should be done exactly once, such as opening the window.
X I like to give windows names, so it is obvious what the window's
X contents are, but this causes a transcript to be kept in a file
X whose name is the window's name. This might be nice in some
X circumstances, but to me it is a nuisance, so the file is
X deleted immediately. The name is unlikely to appear normally,
X so there should be little interference with users' normal files.
X If the user has explicitly set the output file, however, then
X we use that name, and do not delete the file. Thus, the
X user can get a metafile of the plot. We can tell if the
X output file has been set because outstr is "STDOUT". Otherwise,
X outstr is the filename, in single quotes. We need to strip
X the quotes to make the file name.
X
X The DM defaults are used for window sizes and positions. If
X the user doesn't like it, he or she can change is and issue
X a replot command (assuming a plot has already been generated).
X
X Note, also, that we must call pad_$set_scale() or else
X pad_$inq_windows() returns scaled values, which is not what
X we want. Setting the scale to one (1) turns off the scaling,
X so we get real pixel sizes.
X
X Finally, we get the name and size of the default font. The
X name is kept, as explained earlier. Then we can initialize
X the GPR stuff.
X
X Note that there is a way that APOLLO_init() gets called more
X than once. If the user issues the "set terminal apollo" command
X more than once, then this is called, so we need to make sure
X that we do not keep creating windows.
X
X An alternative strategy would be to interpret multiple "set term
X apollo"s to mean create multiple windows. The user could only
X access the most recent window because GNUplot has no concept of
X multiple terminals. The user would, in fact, have no way of
X removing old windows because they are still active. We could try
X catching keyboard events to see if the user presses EXIT, but I do
X not want to start getting into that mess. If the user really
X wants this kind of functionality, then he or she can run gnuplot
X multiple times. I think that is a lot cleaner, don't you?
*/
APOLLO_init()
{
X /* only initialize once */
X if (stream == -1)
X {
X extern char outstr[];
X struct termentry* tbl;
X pad_$window_desc_t window;
X name_$long_name_t wname;
X short wnum; /* junk needed by pad_$inq_windows() */
X boolean unlink_wname;
X status_$t status;
X
X tbl = &term_tbl[term];
X
X /* make the window name unique, with "gnuplot" in the label */
X if (strcmp(outstr, "STDOUT") == 0)
X {
X sprintf(wname, "gnuplot-%d", getpid());
X unlink_wname = true;
X }
X else
X {
X /* strip the single quotes around the file name */
X strcpy(wname, outstr + 1);
X wname[strlen(wname) - 1] = '\0';
X unlink_wname = false;
X }
X
X use_bitmap = unlink_wname;
X
X /* use the default window position and size */
X window.top = window.left = window.width = window.height = 0;
X pad_$create_window(wname, strlen(wname), pad_$transcript, 1, window,
X &stream, &status);
X apollo_check("create_window");
X
X /* if this is not the user's name, then delete the file */
X if (unlink_wname)
X unlink(wname);
X
X /* remove all scaling, to revert to pixel units, not char. units */
X pad_$set_scale(stream, 1, 1, &status);
X apollo_check("set_scale");
X
X /* get rid of the window when the program exits */
X pad_$set_auto_close(stream, 1, true, &status);
X apollo_check("set_auto_close");
X
X /* now determine the window size & update the termentry table */
X pad_$inq_windows(stream, &window, 1, &wnum, &status);
X apollo_check("inq_windows");
X
X /* the order of the next three calls is important */
X apollo_font_info(tbl, font_name);
X apollo_gpr_init(tbl, &window);
X apollo_tic_sizes(tbl);
X }
}
X
/*
X Prepare for graphics output. Since this is what the user wants to
X do when preparing a new plot, this is a meaningful time to see if
X the window has changed size. Thus, we avoid mucking about with
X asynchronous traps, and we avoid the bigger problem of dealing
X with a half-finished plot when the window changes size.
X
X Simply put, get the current window size, and if it has changed,
X then get rid of the old bitmaps, etc., and allocate new ones at
X the new size. We also need to update the termentry table.
X If the window stays the same size, then just clear it.
*/
static void apollo_redo_window(pad_$window_desc_t* window)
{
X struct termentry* tbl = &term_tbl[term];
X status_$t status;
X
X /* the order of the following calls is important */
X apollo_gpr_terminate();
X apollo_gpr_init(tbl, window);
X apollo_tic_sizes(tbl);
}
X
APOLLO_graphics()
{
X pad_$window_desc_t window;
X short wnum;
X status_$t status;
X
X pad_$inq_windows(stream, &window, 1, &wnum, &status);
X apollo_check("inq_windows");
X
X if (window.width != APOLLO_XMAX || window.height != APOLLO_YMAX)
X apollo_redo_window(&window);
X else
X {
X gpr_$clear(0, &status);
X apollo_check("clear");
X }
}
X
/* set a line type:
X -2 heavy, solid (border)
X -1 heavy, dotted (axis)
X 0 solid (normal)
X 1 dots (other curves)
X 2 short dash
X 3 long dash
X 4 dash dot
X
X Apparently, GPUplot draws a lot of short line segments, and each
X one starts a new pattern. This makes the patterns somewhat useless,
X but one can still tell the difference between solid, dotted, and
X dashed lines. The utility of fancier styles is limited, however.
X
X On a color workstation, we should use different colors, but I
X don't have one.
*/
X
/*
X To draw different line styles on an Apollo, we use two different
X parameters. One is a line thickness, which is just an integral
X multiple of the default line thickness. The second is a 16-bit
X pattern that is repeated. We could use fancier patterns, since
X GPR supports up to 64-bits, but, as I explained earlier, this
X really does not buy us anything.
X
X I used patterns that do not start with all bits on because
X GNUplot seems to use lots of short line segments to draw
X a curve, and this might make a very curvey plot seem like
X a solid line, regardless of pattern. I don't want to start
X with too many zeros, however, or else the curve might not
X appear at all! All the patterns, therefore, start with one
X bit on. The rest of the bits determine the true pattern.
X
X By examining graphics.c, we see that linetype -2 is used exclusively
X for the border, -1 for the axes, and the non-negative integers for
X the curves. We use heavy lines for the border and axes, and normal
X width lines for the curves.
X
X Since C arrays start at zero, make sure all the offsets are correct,
X so that it is easy to access the array with -2...n linetypes.
*/
X
typedef struct {
X short width;
X short pattern;
} APOLLO_LINE;
X
static APOLLO_LINE apollo_lines[] = {
X { 2, ~0 }, /* heavy, solid */
X { 2, 0x6666 }, /* heavy, dotted */
X { 1, ~0 }, /* normal */
X { 1, 0xAAAA }, /* dotted */
X { 1, 0xC3C3 }, /* short dash */
X { 1, 0xE01F }, /* long dash */
X { 1, 0x87F8 }, /* dash dot */
X { 1, 0x6666 }, /* big dots */
};
X
#define BITS_PER_LINETYPE 16
X
/* apollo_line(-2) is the border style, etc. */
#define apollo_line(x) apollo_lines[(x)+2]
#define apollo_pattern(x) &apollo_line(x).pattern
#define apollo_width(x) apollo_line(x).width
X
#define APOLLO_MIN_LINE (-2)
#define APOLLO_MAX_LINE (sizeof(apollo_lines)/sizeof(*apollo_lines)-2)
X
/* set the line style */
APOLLO_linetype(ltype)
int ltype;
{
X status_$t status;
X
X if (ltype < APOLLO_MIN_LINE)
X ltype = APOLLO_MIN_LINE;
X if (ltype >= APOLLO_MAX_LINE)
X ltype %= APOLLO_MAX_LINE;
X
X gpr_$set_line_pattern(1, apollo_pattern(ltype), BITS_PER_LINETYPE, &status);
X apollo_check("set_line_pattern");
X
X gpr_$set_draw_width(draw_width * apollo_width(ltype), &status);
X apollo_check("set_draw_width");
}
X
/* issue an error message that includes an (x, y) coordinate */
static void apollo_xy_error(char* s, int x, int y, status_$t status)
{
X char buffer[128];
X
X sprintf(buffer, "%s(%d, %d)", s, x, y);
X apollo_error(buffer);
}
X
#define apollo_xy_check(s) \
X if (status.all != status_$ok) apollo_xy_error((s), x, y, status)
X
/*
X Note that GNUplot and GPR have reversed ideas of where the Y origin is.
X This means subtracting the Y coordinate from Y max.
*/
#define plot_to_gpr(y) (APOLLO_YMAX - (y))
X
/* move to a new position */
APOLLO_move(unsigned int x, unsigned int y)
{
X status_$t status;
X
X gpr_$move((gpr_$coordinate_t) x, plot_to_gpr(y), &status);
X apollo_xy_check("move");
}
X
/* draw a line to a new position */
APOLLO_vector(unsigned int x, unsigned int y)
{
X status_$t status;
X
X gpr_$line((gpr_$coordinate_t) x, plot_to_gpr(y), &status);
X apollo_xy_check("line");
}
X
/*
X On terminals, this switches to text mode. The real meaning,
X however, is that the graphics are finished. This means we can
X now display the saved bitmap.
*/
APOLLO_text()
{
X if (use_bitmap)
X {
X static gpr_$position_t pos; /* always zero */
X gpr_$window_t window;
X status_$t status;
X
X /* bitblt the entire bitmap to the entire window */
X window.window_base.x_coord = 0;
X window.window_base.y_coord = 0;
X window.window_size.x_size = APOLLO_XMAX;
X window.window_size.y_size = APOLLO_YMAX;
X
X gpr_$set_bitmap(screen_desc, &status);
X apollo_check("set_bitmap(screen_desc)");
X
X gpr_$pixel_blt(bitmap_desc, window, pos, &status);
X apollo_check("bitblt");
X
X gpr_$set_bitmap(bitmap_desc, &status);
X apollo_check("set_bitmap(bitmap_desc)");
X }
}
X
APOLLO_text_angle(ang)
int ang;
{
X status_$t status;
X
X gpr_$set_text_path(ang ? gpr_$up : gpr_$right, &status);
X apollo_check("set_text_path");
X return TRUE;
}
X
static enum JUSTIFY apollo_text_mode;
X
APOLLO_justify_text(mode)
enum JUSTIFY mode;
{
X apollo_text_mode = mode;
X return TRUE;
}
X
/*
X Write "str" right justified on row "row". A row is assumed to
X have whatever height the current text has. Make sure the
X text does not cover the tick marks.
*/
APOLLO_put_text(x, y, str)
unsigned int x, y;
char str[];
{
X gpr_$offset_t size;
X status_$t status;
X
X gpr_$inq_text_extent(str, strlen(str), &size, &status);
X apollo_check("inq_text_extent");
X
X y -= size.y_size / 2; /* center around "y" */
X switch (apollo_text_mode)
X {
X case LEFT:
X break;
X case CENTRE:
X x -= size.x_size / 2;
X break;
X case RIGHT:
X x -= size.x_size;
X break;
X }
X APOLLO_move(x, y);
X
X gpr_$text(str, strlen(str), &status);
X apollo_check("put_text");
}
X
/* reset the graphics state and terminate */
APOLLO_reset()
{
X if (stream != -1)
X {
X apollo_gpr_terminate();
X stream = -1;
X }
}
SHAR_EOF
echo 'File gnuplot/term/apollo.trm is complete' &&
chmod 0644 gnuplot/term/apollo.trm ||
echo 'restore of gnuplot/term/apollo.trm failed'
Wc_c="`wc -c < 'gnuplot/term/apollo.trm'`"
test 17013 -eq "$Wc_c" ||
echo 'gnuplot/term/apollo.trm: original size 17013, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gnuplot/term/impcodes.h ==============
if test -f 'gnuplot/term/impcodes.h' -a X"$1" != X"-c"; then
echo 'x - skipping gnuplot/term/impcodes.h (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gnuplot/term/impcodes.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gnuplot/term/impcodes.h' &&
/*
X * Copyright (c) 1985 Regents of the University of California.
X * All rights reserved. The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X *
X * @(#)imPcodes.h 5.1 (Berkeley) 9/21/85
X */
X
#define imP_SP 128
#define imP_SP1 129
#define imP_OLD_MMOVE 130
#define imP_MPLUS 131
#define imP_MMINUS 132
#define imP_MMOVE 133
#define imP_SMOVE 134
X
#define imP_SET_ABS_H 135
#define imP_SET_REL_H 136
#define imP_SET_ABS_V 137
#define imP_SET_REL_V 138
X
#define imP_SRULE 192
#define imP_BRULE 193
X
#define imP_SET_HPOS 195
#define imP_SET_VPOS 196
#define imP_CRLF 197
#define imP_SGLY 198
#define imP_BGLY 199
#define imP_DELG 200
#define imP_DELC 201
#define imP_DELF 202
X
#define imP_SET_HV_SYSTEM 205
#define imP_SET_ADV_DIRS 206
#define imP_SET_FAMILY 207
#define imP_SET_IL 208
#define imP_SET_BOL 209
#define imP_SET_SP 210
#define imP_PUSH 211
#define imP_POP 212
#define imP_PAGE 213
#define imP_SET_PUSH_MASK 214
#define imP_ENDPAGE 219
X
#define imP_CREATE_FAMILY_TABLE 221
#define imP_CREATE_MAP 222
X
#define imP_CREATE_PATH 230
#define imP_SET_TEXTURE 231
#define imP_SET_PEN 232
#define imP_FILL_PATH 233
#define imP_DRAW_PATH 234
#define imP_BITMAP 235
#define imP_SET_MAGN 236
X
#define imP_EOF 255
X
X
SHAR_EOF
chmod 0666 gnuplot/term/impcodes.h ||
echo 'restore of gnuplot/term/impcodes.h failed'
Wc_c="`wc -c < 'gnuplot/term/impcodes.h'`"
test 1260 -eq "$Wc_c" ||
echo 'gnuplot/term/impcodes.h: original size 1260, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gnuplot/parse.c ==============
if test -f 'gnuplot/parse.c' -a X"$1" != X"-c"; then
echo 'x - skipping gnuplot/parse.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gnuplot/parse.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gnuplot/parse.c' &&
/* GNUPLOT - parse.c */
/*
X * Copyright (C) 1986, 1987, 1990, 1991 Thomas Williams, Colin Kelley
X *
X * Permission to use, copy, and distribute this software and its
X * documentation for any purpose with or without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and
X * that both that copyright notice and this permission notice appear
X * in supporting documentation.
X *
X * Permission to modify the software is granted, but not the right to
X * distribute the modified code. Modifications are to be distributed
X * as patches to released version.
X *
X * This software is provided "as is" without express or implied warranty.
X *
X *
X * AUTHORS
X *
X * Original Software:
X * Thomas Williams, Colin Kelley.
X *
X * Gnuplot 2.0 additions:
X * Russell Lang, Dave Kotz, John Campbell.
X *
X * Gnuplot 3.0 additions:
X * Gershon Elber and many others.
X *
X * Send your comments or suggestions to
X * pixar!info-gnuplot@sun.com.
X * This is a mailing list; to join it send a note to
X * pixar!info-gnuplot-request@sun.com.
X * Send bug reports to
X * pixar!bug-gnuplot@sun.com.
X */
X
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <errno.h>
#include <math.h>
#include "plot.h"
X
#ifndef vms
#ifndef __ZTC__
extern int errno;
#endif
#endif
X
extern int num_tokens,c_token;
extern struct lexical_unit token[];
extern char c_dummy_var[MAX_NUM_VAR][MAX_ID_LEN+1]; /* name of current dummy vars */
extern struct udft_entry *dummy_func; /* pointer to dummy variable's func */
X
struct value *pop(),*integer(),*complex();
struct at_type *temp_at(), *perm_at();
struct udft_entry *add_udf();
struct udvt_entry *add_udv();
union argument *add_action();
X
struct at_type at;
static jmp_buf fpe_env;
X
#define dummy (struct value *) 0
X
#ifdef __TURBOC__
void fpe()
#else
#ifdef __ZTC__
void fpe(an_int)
int an_int;
#else
#ifdef _CRAY
void fpe(an_int)
int an_int;
#else
fpe()
#endif
#endif
#endif
{
#ifdef PC /* thanks to lotto@wjh12.UUCP for telling us about this */
X _fpreset();
#endif
X (void) signal(SIGFPE, fpe);
X undefined = TRUE;
X longjmp(fpe_env, TRUE);
}
X
X
#ifdef apollo
#include <apollo/base.h>
#include <apollo/pfm.h>
#include <apollo/fault.h>
X
/*
X On an Apollo, the OS can signal a couple errors that are not mapped
X into SIGFPE, namely signalling NaN and branch on an unordered
X comparison. I suppose there are others, but none of these are documented,
X so I handle them as they arise.
X
X Anyway, we need to catch these faults and signal SIGFPE.
*/
X
pfm_$fh_func_val_t apollo_sigfpe(pfm_$fault_rec_t& fault_rec)
{
X kill(getpid(), SIGFPE);
X return pfm_$continue_fault_handling;
}
X
apollo_pfm_catch()
{
X status_$t status;
X pfm_$establish_fault_handler(fault_$fp_bsun, pfm_$fh_backstop,
X apollo_sigfpe, &status);
X pfm_$establish_fault_handler(fault_$fp_sig_nan, pfm_$fh_backstop,
X apollo_sigfpe, &status);
}
#endif
X
X
evaluate_at(at_ptr,val_ptr)
struct at_type *at_ptr;
struct value *val_ptr;
{
X double temp, real();
X
X undefined = FALSE;
X errno = 0;
X reset_stack();
X if (setjmp(fpe_env))
X return; /* just bail out */
X (void) signal(SIGFPE, fpe); /* catch core dumps on FPEs */
X
X execute_at(at_ptr);
X
X (void) signal(SIGFPE, SIG_DFL);
X
X if (errno == EDOM || errno == ERANGE) {
X undefined = TRUE;
X } else {
X (void) pop(val_ptr);
X check_stack();
X }
/* At least one machine (ATT 3b1) computes Inf without a SIGFPE */
X temp = real(val_ptr);
X if (temp > VERYLARGE || temp < -VERYLARGE) {
X undefined = TRUE;
X }
}
X
X
struct value *
const_express(valptr)
struct value *valptr;
{
register int tkn = c_token;
X if (END_OF_COMMAND)
X int_error("constant expression required",c_token);
X evaluate_at(temp_at(),valptr); /* run it and send answer back */
X if (undefined) {
X int_error("undefined value",tkn);
X }
X return(valptr);
}
X
X
struct at_type *
temp_at() /* build a static action table and return its pointer */
{
X at.a_count = 0; /* reset action table !!! */
X express();
X return(&at);
}
X
X
/* build an action table, put it in dynamic memory, and return its pointer */
X
struct at_type *
perm_at()
{
register struct at_type *at_ptr;
register unsigned int len;
X
X (void) temp_at();
X len = sizeof(struct at_type) -
X (MAX_AT_LEN - at.a_count)*sizeof(struct at_entry);
X at_ptr = (struct at_type *) alloc(len, "action table");
X (void) memcpy(at_ptr,&at,len);
X return(at_ptr);
}
X
X
#ifdef NOCOPY
/*
X * cheap and slow version of memcpy() in case you don't have one
X */
memcpy(dest,src,len)
char *dest,*src;
unsigned int len;
{
X while (len--)
X *dest++ = *src++;
}
#endif /* NOCOPY */
X
X
express() /* full expressions */
{
X xterm();
X xterms();
}
X
xterm() /* ? : expressions */
{
X aterm();
X aterms();
}
X
X
aterm()
{
X bterm();
X bterms();
}
X
X
bterm()
{
X cterm();
X cterms();
}
X
X
cterm()
{
X dterm();
X dterms();
}
X
X
dterm()
{
X eterm();
X eterms();
}
X
X
eterm()
{
X fterm();
X fterms();
}
X
X
fterm()
{
X gterm();
X gterms();
}
X
X
gterm()
{
X hterm();
X hterms();
}
X
X
hterm()
{
X unary(); /* - things */
X iterms(); /* * / % */
}
X
X
factor()
{
register int value;
X
X if (equals(c_token,"(")) {
X c_token++;
X express();
X if (!equals(c_token,")"))
X int_error("')' expected",c_token);
X c_token++;
X }
X else if (isnumber(c_token)) {
X convert(&(add_action(PUSHC)->v_arg),c_token);
X c_token++;
X }
X else if (isletter(c_token)) {
X if ((c_token+1 < num_tokens) && equals(c_token+1,"(")) {
X value = standard(c_token);
X if (value) { /* it's a standard function */
X c_token += 2;
X express();
X if (!equals(c_token,")"))
X int_error("')' expected",c_token);
X c_token++;
X (void) add_action(value);
X }
X else {
X int call_type = (int )CALL;
X value = c_token;
X c_token += 2;
X express();
X if (equals(c_token, ",")) {
X c_token += 1;
X express();
X call_type = (int )CALL2;
X }
X if (!equals(c_token,")"))
X int_error("')' expected",c_token);
X c_token++;
X add_action(call_type)->udf_arg = add_udf(value);
X }
X }
X else {
X if (equals(c_token,c_dummy_var[0])) {
X c_token++;
X add_action(PUSHD1)->udf_arg = dummy_func;
X }
X else if (equals(c_token,c_dummy_var[1])) {
X c_token++;
X add_action(PUSHD2)->udf_arg = dummy_func;
X }
X else {
X add_action(PUSH)->udv_arg = add_udv(c_token);
X c_token++;
X }
X }
X } /* end if letter */
X else
X int_error("invalid expression ",c_token);
X
X /* add action code for ! (factorial) operator */
X while (equals(c_token,"!")) {
X c_token++;
X (void) add_action(FACTORIAL);
X }
X /* add action code for ** operator */
X if (equals(c_token,"**")) {
X c_token++;
X unary();
X (void) add_action(POWER);
X }
X
}
X
X
X
xterms()
{ /* create action code for ? : expressions */
X
X if (equals(c_token,"?")) {
X register int savepc1, savepc2;
X register union argument *argptr1,*argptr2;
X c_token++;
X savepc1 = at.a_count;
X argptr1 = add_action(JTERN);
X express();
X if (!equals(c_token,":"))
X int_error("expecting ':'",c_token);
X c_token++;
X savepc2 = at.a_count;
X argptr2 = add_action(JUMP);
X argptr1->j_arg = at.a_count - savepc1;
X express();
X argptr2->j_arg = at.a_count - savepc2;
X }
}
X
X
aterms()
{ /* create action codes for || operator */
X
X while (equals(c_token,"||")) {
X register int savepc;
X register union argument *argptr;
X c_token++;
X savepc = at.a_count;
X argptr = add_action(JUMPNZ); /* short-circuit if already TRUE */
X aterm();
X argptr->j_arg = at.a_count - savepc;/* offset for jump */
#if defined(AMIGA_LC_5_1) || defined(AMIGA_AC_5)
X (void) add_action(ABOOL);
#else
X (void) add_action(BOOL);
#endif
X }
}
X
X
bterms()
{ /* create action code for && operator */
X
X while (equals(c_token,"&&")) {
X register int savepc;
X register union argument *argptr;
X c_token++;
X savepc = at.a_count;
X argptr = add_action(JUMPZ); /* short-circuit if already FALSE */
X bterm();
X argptr->j_arg = at.a_count - savepc;/* offset for jump */
#if defined(AMIGA_LC_5_1) || defined(AMIGA_AC_5)
X (void) add_action(ABOOL);
#else
X (void) add_action(BOOL);
#endif
X }
}
X
X
cterms()
{ /* create action code for | operator */
X
X while (equals(c_token,"|")) {
X c_token++;
X cterm();
X (void) add_action(BOR);
X }
}
X
X
dterms()
{ /* create action code for ^ operator */
X
X while (equals(c_token,"^")) {
X c_token++;
X dterm();
X (void) add_action(XOR);
X }
}
X
X
eterms()
{ /* create action code for & operator */
X
X while (equals(c_token,"&")) {
X c_token++;
X eterm();
X (void) add_action(BAND);
X }
}
X
X
fterms()
{ /* create action codes for == and != operators */
X
X while (TRUE) {
X if (equals(c_token,"==")) {
X c_token++;
X fterm();
X (void) add_action(EQ);
X }
X else if (equals(c_token,"!=")) {
X c_token++;
X fterm();
X (void) add_action(NE);
X }
X else break;
X }
}
X
X
gterms()
{ /* create action code for < > >= or <= operators */
X
X while (TRUE) {
X /* I hate "else if" statements */
X if (equals(c_token,">")) {
X c_token++;
X gterm();
X (void) add_action(GT);
X }
X else if (equals(c_token,"<")) {
X c_token++;
X gterm();
X (void) add_action(LT);
X }
X else if (equals(c_token,">=")) {
X c_token++;
X gterm();
X (void) add_action(GE);
X }
X else if (equals(c_token,"<=")) {
X c_token++;
X gterm();
X (void) add_action(LE);
X }
X else break;
X }
X
}
X
X
X
hterms()
{ /* create action codes for + and - operators */
X
X while (TRUE) {
X if (equals(c_token,"+")) {
X c_token++;
X hterm();
X (void) add_action(PLUS);
X }
X else if (equals(c_token,"-")) {
X c_token++;
X hterm();
X (void) add_action(MINUS);
X }
X else break;
X }
}
X
X
iterms()
{ /* add action code for * / and % operators */
X
X while (TRUE) {
X if (equals(c_token,"*")) {
X c_token++;
X unary();
X (void) add_action(MULT);
X }
X else if (equals(c_token,"/")) {
X c_token++;
X unary();
X (void) add_action(DIV);
X }
X else if (equals(c_token,"%")) {
X c_token++;
X unary();
X (void) add_action(MOD);
X }
X else break;
X }
}
X
X
unary()
{ /* add code for unary operators */
X if (equals(c_token,"!")) {
X c_token++;
X unary();
X (void) add_action(LNOT);
X }
X else if (equals(c_token,"~")) {
X c_token++;
X unary();
X (void) add_action(BNOT);
X }
X else if (equals(c_token,"-")) {
X c_token++;
X unary();
X (void) add_action(UMINUS);
X }
X else
X factor();
}
SHAR_EOF
chmod 0644 gnuplot/parse.c ||
echo 'restore of gnuplot/parse.c failed'
Wc_c="`wc -c < 'gnuplot/parse.c'`"
test 10144 -eq "$Wc_c" ||
echo 'gnuplot/parse.c: original size 10144, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gnuplot/makefile.msc ==============
if test -f 'gnuplot/makefile.msc' -a X"$1" != X"-c"; then
echo 'x - skipping gnuplot/makefile.msc (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gnuplot/makefile.msc (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gnuplot/makefile.msc' &&
# Make file for use with Microsoft C Version 5.10
# and Microsoft Program Maintenance Utility Version 4.07
#
X
# where to place gnuplot.gih helpfile
HELPFILE = gnuplot.gih
X
# /c means don't link
# /AL means large memory model (large code, large data)
# /DPC means define symbol PC
CFLAGS = /c /AL /DPC #/DMSDOS #/Zi #/Od
X
# see other terminal defines in term.h
TERMFLAGS =
X
# /NOE means NO EXTernal Dictionary
# /EX means pack EXE file
# /ST:10000 means stack size 10000 bytes
LINKFLAGS = /NOE /EX /ST:10000 #/codeview
X
OBJS = bitmap.obj command.obj contour.obj eval.obj graphics.obj graph3d.obj \
X help.obj internal.obj misc.obj parse.obj plot.obj readline.obj \
X scanner.obj setshow.obj standard.obj term.obj util.obj version.obj \
X pcgraph.obj hrcgraph.obj corgraph.obj
X
CSOURCE5 = term\aed.trm term\cgi.trm term/dumb.trm term/dxf.trm term\dxy.trm \
X term\eepic.trm term\epson.trm term\fig.trm term\hp26.trm \
X term\hp2648.trm term\hpgl.trm term\hpljii.trm
CSOURCE6 = term\impcodes.h term\imagen.trm term\object.h \
X term\iris4d.trm term\kyo.trm term\latex.trm term\pc.trm
CSOURCE7 = term\post.trm term\qms.trm term\regis.trm term\sun.trm \
X term\t410x.trm term\tek.trm term\unixpc.trm term\unixplot.trm \
X term\v384.trm term\x11.trm
CSOURCE8 = contour.c
X
# default rules
.c.obj:
X cl $(CFLAGS) $*.c
X
.asm.obj:
X masm $*;
X
pcgraph.obj: pcgraph.asm header.mac lineproc.mac
X
corgraph.obj: corgraph.asm header.mac lineproc.mac
X
hrcgraph.obj: hrcgraph.asm header.mac lineproc.mac
X
bitmap.obj: bitmap.c bitmap.h plot.h
X
command.obj: command.c plot.h setshow.h help.h
X cl $(CFLAGS) /DHELPFILE=\"$(HELPFILE)\" command.c
X
contour.obj: contour.c plot.h
X
eval.obj: eval.c plot.h
X
graphics.obj: graphics.c plot.h setshow.h
X
graph3d.obj: graphics.c plot.h setshow.h
X
help.obj: help.c plot.h help.h
X
internal.obj: internal.c plot.h
X
misc.obj: misc.c plot.h setshow.h
X
parse.obj: parse.c plot.h
X
plot.obj: plot.c plot.h setshow.h
X
readline.obj: readline.c
X
scanner.obj: scanner.c plot.h
X
setshow.obj: setshow.c plot.h setshow.h
X
standard.obj: standard.c plot.h
X
term.obj: term.c term.h plot.h setshow.h bitmap.h $(CSOURCE5) $(CSOURCE6) $(CSOURCE7)
X cl $(CFLAGS) $(TERMFLAGS) /Iterm term.c
X
util.obj: util.c plot.h
X
version.obj: version.c
X
# convert gnuplot.doc to gnuplot.gih
doc2gih.exe: docs\doc2gih.c
X cl docs\doc2gih.c
X
$(HELPFILE): doc2gih.exe docs\gnuplot.doc
X doc2gih docs\gnuplot.doc $(HELPFILE)
X
# Object files in link command line are ordered to avoid far jumps.
# use linkopt.msc to avoid command-line overflow
X
gnuplot.exe: $(OBJS)
X link $(LINKFLAGS) @linkopt.msc
SHAR_EOF
chmod 0644 gnuplot/makefile.msc ||
echo 'restore of gnuplot/makefile.msc failed'
Wc_c="`wc -c < 'gnuplot/makefile.msc'`"
test 2572 -eq "$Wc_c" ||
echo 'gnuplot/makefile.msc: original size 2572, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gnuplot/copyright ==============
if test -f 'gnuplot/copyright' -a X"$1" != X"-c"; then
echo 'x - skipping gnuplot/copyright (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gnuplot/copyright (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gnuplot/copyright' &&
/*
X * Copyright (C) 1986, 1987, 1990, 1991 Thomas Williams, Colin Kelley
X *
X * Permission to use, copy, and distribute this software and its
X * documentation for any purpose with or without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and
X * that both that copyright notice and this permission notice appear
X * in supporting documentation.
X *
X * Permission to modify the software is granted, but not the right to
X * distribute the modified code. Modifications are to be distributed
X * as patches to released version.
X *
X * This software is provided "as is" without express or implied warranty.
X *
X *
X * AUTHORS
X *
X * Original Software:
X * Thomas Williams, Colin Kelley.
X *
X * Gnuplot 2.0 additions:
X * Russell Lang, Dave Kotz, John Campbell.
X *
X * Gnuplot 3.0 additions:
X * Gershon Elber and many others.
X *
X * Send your comments or suggestions to
X * pixar!info-gnuplot@sun.com.
X * This is a mailing list; to join it send a note to
X * pixar!info-gnuplot-request@sun.com.
X * Send bug reports to
X * pixar!bug-gnuplot@sun.com.
X */
SHAR_EOF
chmod 0644 gnuplot/copyright ||
echo 'restore of gnuplot/copyright failed'
Wc_c="`wc -c < 'gnuplot/copyright'`"
test 1114 -eq "$Wc_c" ||
echo 'gnuplot/copyright: original size 1114, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= gnuplot/graph3d.c ==============
if test -f 'gnuplot/graph3d.c' -a X"$1" != X"-c"; then
echo 'x - skipping gnuplot/graph3d.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting gnuplot/graph3d.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gnuplot/graph3d.c' &&
/* GNUPLOT - graph3d.c */
/*
X * Copyright (C) 1986, 1987, 1990, 1991 Thomas Williams, Colin Kelley
X *
X * Permission to use, copy, and distribute this software and its
X * documentation for any purpose with or without fee is hereby granted,
X * provided that the above copyright notice appear in all copies and
X * that both that copyright notice and this permission notice appear
X * in supporting documentation.
X *
X * Permission to modify the software is granted, but not the right to
X * distribute the modified code. Modifications are to be distributed
X * as patches to released version.
X *
X * This software is provided "as is" without express or implied warranty.
X *
X *
X * AUTHORS
X *
X * Original Software:
X * Gershon Elber and many others.
X *
X * Send your comments or suggestions to
X * pixar!info-gnuplot@sun.com.
X * This is a mailing list; to join it send a note to
X * pixar!info-gnuplot-request@sun.com.
X * Send bug reports to
X * pixar!bug-gnuplot@sun.com.
X */
X
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include <time.h>
#include "plot.h"
#include "setshow.h"
X
extern char *strcpy(),*strncpy(),*strcat(),*ctime(),*tdate;
#ifdef AMIGA_AC_5
extern time_t dated;
#else
#ifdef VMS
extern time_t dated,time();
#else
extern long dated,time();
#endif
#endif
X
static plot3d_impulses();
static plot3d_lines();
static plot3d_points();
static plot3d_dots();
static cntr3d_impulses();
static cntr3d_lines();
static cntr3d_points();
static cntr3d_dots();
static update_extrema_pts();
static draw_parametric_grid();
static draw_non_param_grid();
static draw_bottom_grid();
static draw_3dxtics();
static draw_3dytics();
static draw_3dztics();
static draw_series_3dxtics();
static draw_series_3dytics();
static draw_series_3dztics();
static draw_set_3dxtics();
static draw_set_3dytics();
static draw_set_3dztics();
static xtick();
static ytick();
static ztick();
X
#ifndef max /* Lattice C has max() in math.h, but shouldn't! */
#define max(a,b) ((a > b) ? a : b)
#endif
X
#ifndef min
#define min(a,b) ((a < b) ? a : b)
#endif
X
#define inrange(z,min,max) ((min<max) ? ((z>=min)&&(z<=max)) : ((z>=max)&&(z<=min)) )
X
#define apx_eq(x,y) (fabs(x-y) < 0.001)
#define abs(x) ((x) >= 0 ? (x) : -(x))
#define sqr(x) ((x) * (x))
X
/* Define the boundary of the plot
X * These are computed at each call to do_plot, and are constant over
X * the period of one do_plot. They actually only change when the term
X * type changes and when the 'set size' factors change.
X */
static int xleft, xright, ybot, ytop, xmiddle, ymiddle, xscaler, yscaler;
X
/* Boundary and scale factors, in user coordinates */
/* x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d are local to this
X * file and are not the same as variables of the same names in other files
X */
static double x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d;
static double xscale3d, yscale3d, zscale3d;
static double real_z_min3d, real_z_max3d;
static double min_sy_ox,min_sy_oy; /* obj. coords. for xy tics placement. */
static double min_sx_ox,min_sx_oy; /* obj. coords. for z tics placement. */
X
typedef double transform_matrix[4][4];
static transform_matrix trans_mat;
X
/* (DFK) Watch for cancellation error near zero on axes labels */
#define SIGNIF (0.01) /* less than one hundredth of a tic mark */
#define CheckZero(x,tic) (fabs(x) < ((tic) * SIGNIF) ? 0.0 : (x))
#define NearlyEqual(x,y,tic) (fabs((x)-(y)) < ((tic) * SIGNIF))
X
/* And the functions to map from user to terminal coordinates */
#define map_x(x) (int)(x+0.5) /* maps floating point x to screen */
#define map_y(y) (int)(y+0.5) /* same for y */
X
/* And the functions to map from user 3D space into normalized -1..1 */
#define map_x3d(x) ((x-x_min3d)*xscale3d-1.0)
#define map_y3d(y) ((y-y_min3d)*yscale3d-1.0)
#define map_z3d(z) ((z-z_min3d)*zscale3d-1.0)
X
static mat_unit(mat)
transform_matrix mat;
{
X int i, j;
X
X for (i = 0; i < 4; i++) for (j = 0; j < 4; j++)
X if (i == j)
X mat[i][j] = 1.0;
X else
X mat[i][j] = 0.0;
}
X
static mat_trans(tx, ty, tz, mat)
double tx, ty, tz;
transform_matrix mat;
{
X mat_unit(mat); /* Make it unit matrix. */
X mat[3][0] = tx;
X mat[3][1] = ty;
X mat[3][2] = tz;
}
X
static mat_scale(sx, sy, sz, mat)
double sx, sy, sz;
transform_matrix mat;
{
X mat_unit(mat); /* Make it unit matrix. */
X mat[0][0] = sx;
X mat[1][1] = sy;
X mat[2][2] = sz;
}
X
static mat_rot_x(teta, mat)
double teta;
transform_matrix mat;
{
X double cos_teta, sin_teta;
X
X teta *= Pi / 180.0;
X cos_teta = cos(teta);
X sin_teta = sin(teta);
X
X mat_unit(mat); /* Make it unit matrix. */
X mat[1][1] = cos_teta;
X mat[1][2] = -sin_teta;
X mat[2][1] = sin_teta;
X mat[2][2] = cos_teta;
}
X
static mat_rot_y(teta, mat)
double teta;
transform_matrix mat;
{
X double cos_teta, sin_teta;
X
X teta *= Pi / 180.0;
X cos_teta = cos(teta);
X sin_teta = sin(teta);
X
X mat_unit(mat); /* Make it unit matrix. */
X mat[0][0] = cos_teta;
X mat[0][2] = -sin_teta;
X mat[2][0] = sin_teta;
X mat[2][2] = cos_teta;
}
X
static mat_rot_z(teta, mat)
double teta;
transform_matrix mat;
{
X double cos_teta, sin_teta;
X
X teta *= Pi / 180.0;
X cos_teta = cos(teta);
X sin_teta = sin(teta);
X
X mat_unit(mat); /* Make it unit matrix. */
X mat[0][0] = cos_teta;
X mat[0][1] = -sin_teta;
X mat[1][0] = sin_teta;
X mat[1][1] = cos_teta;
}
X
/* Multiply two transform_matrix. Result can be one of two operands. */
void mat_mult(mat_res, mat1, mat2)
transform_matrix mat_res, mat1, mat2;
{
X int i, j, k;
X transform_matrix mat_res_temp;
X
X for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) {
X mat_res_temp[i][j] = 0;
X for (k = 0; k < 4; k++) mat_res_temp[i][j] += mat1[i][k] * mat2[k][j];
X }
X for (i = 0; i < 4; i++) for (j = 0; j < 4; j++)
X mat_res[i][j] = mat_res_temp[i][j];
}
X
/* And the functions to map from user 3D space to terminal coordinates */
static int map3d_xy(x, y, z, xt, yt)
double x, y, z;
int *xt, *yt;
{
X int i,j;
X double v[4], res[4], /* Homogeneous coords. vectors. */
X w = trans_mat[3][3];
X
X v[0] = map_x3d(x); /* Normalize object space to -1..1 */
X v[1] = map_y3d(y);
X v[2] = map_z3d(z);
X v[3] = 1.0;
X
X for (i = 0; i < 2; i++) { /* Dont use the third axes (z). */
X res[i] = trans_mat[3][i]; /* Initiate it with the weight factor. */
X for (j = 0; j < 3; j++) res[i] += v[j] * trans_mat[j][i];
X }
X
X for (i = 0; i < 3; i++) w += v[i] * trans_mat[i][3];
X if (w == 0) w = 1e-5;
X
X *xt = ((int) (res[0] * xscaler / w)) + xmiddle;
X *yt = ((int) (res[1] * yscaler / w)) + ymiddle;
}
X
/* Test a single point to be within the xleft,xright,ybot,ytop bbox.
X * Sets the returned integers 4 l.s.b. as follows:
X * bit 0 if to the left of xleft.
X * bit 1 if to the right of xright.
X * bit 2 if above of ytop.
X * bit 3 if below of ybot.
X * 0 is returned if inside.
X */
static int clip_point(x, y)
int x, y;
{
X int ret_val = 0;
X
X if (x < xleft) ret_val |= 0x01;
X if (x > xright) ret_val |= 0x02;
X if (y < ybot) ret_val |= 0x04;
X if (y > ytop) ret_val |= 0x08;
X
X return ret_val;
}
X
/* Clip the given line to drawing coords defined as xleft,xright,ybot,ytop.
X * This routine uses the cohen & sutherland bit mapping for fast clipping -
X * see "Principles of Interactive Computer Graphics" Newman & Sproull page 65.
X */
static void draw_clip_line(x1, y1, x2, y2)
int x1, y1, x2, y2;
{
X int x, y, dx, dy, x_intr[2], y_intr[2], count, pos1, pos2;
X register struct termentry *t = &term_tbl[term];
X
X pos1 = clip_point(x1, y1);
X pos2 = clip_point(x2, y2);
X if (pos1 || pos2) {
X if (pos1 & pos2) return; /* segment is totally out. */
X
X /* Here part of the segment MAY be inside. test the intersection
X * of this segment with the 4 boundaries for hopefully 2 intersections
X * in. If non found segment is totaly out.
X */
X count = 0;
X dx = x2 - x1;
X dy = y2 - y1;
X
X /* Find intersections with the x parallel bbox lines: */
X if (dy != 0) {
X x = (ybot - y2) * dx / dy + x2; /* Test for ybot boundary. */
X if (x >= xleft && x <= xright) {
X x_intr[count] = x;
X y_intr[count++] = ybot;
X }
X x = (ytop - y2) * dx / dy + x2; /* Test for ytop boundary. */
X if (x >= xleft && x <= xright) {
X x_intr[count] = x;
X y_intr[count++] = ytop;
X }
X }
X
X /* Find intersections with the y parallel bbox lines: */
X if (dx != 0) {
X y = (xleft - x2) * dy / dx + y2; /* Test for xleft boundary. */
X if (y >= ybot && y <= ytop) {
X x_intr[count] = xleft;
X y_intr[count++] = y;
X }
X y = (xright - x2) * dy / dx + y2; /* Test for xright boundary. */
X if (y >= ybot && y <= ytop) {
X x_intr[count] = xright;
X y_intr[count++] = y;
X }
X }
X
X if (count == 2) {
X int x_max, x_min, y_max, y_min;
X
X x_min = min(x1, x2);
X x_max = max(x1, x2);
X y_min = min(y1, y2);
X y_max = max(y1, y2);
X
X if (pos1 && pos2) { /* Both were out - update both */
X x1 = x_intr[0];
X y1 = y_intr[0];
X x2 = x_intr[1];
X y2 = y_intr[1];
X }
X else if (pos1) { /* Only x1/y1 was out - update only it */
X if (dx * (x2 - x_intr[0]) + dy * (y2 - y_intr[0]) > 0) {
X x1 = x_intr[0];
X y1 = y_intr[0];
X }
X else {
X x1 = x_intr[1];
X y1 = y_intr[1];
X }
X }
X else { /* Only x2/y2 was out - update only it */
X if (dx * (x_intr[0] - x1) + dy * (y_intr[0] - x1) > 0) {
X x2 = x_intr[0];
X y2 = y_intr[0];
X }
X else {
X x2 = x_intr[1];
X y2 = y_intr[1];
X }
X }
X
X if (x1 < x_min || x1 > x_max ||
X x2 < x_min || x2 > x_max ||
X y1 < y_min || y1 > y_max ||
X y2 < y_min || y2 > y_max) return;
X }
X else
X return;
X }
X
X (*t->move)(x1,y1);
X (*t->vector)(x2,y2);
}
X
/* Two routine to emulate move/vector sequence using line drawing routine. */
static int move_pos_x, move_pos_y;
X
static void clip_move(x,y)
int x,y;
{
X move_pos_x = x;
X move_pos_y = y;
}
X
static void clip_vector(x,y)
int x,y;
{
X draw_clip_line(move_pos_x,move_pos_y, x, y);
X move_pos_x = x;
X move_pos_y = y;
}
X
/* And text clipping routine. */
static void clip_put_text(x, y, str)
int x,y;
char *str;
{
X register struct termentry *t = &term_tbl[term];
X
X if (clip_point(x, y)) return;
X
X (*t->put_text)(x,y,str);
}
X
/* (DFK) For some reason, the Sun386i compiler screws up with the CheckLog
X * macro, so I write it as a function on that machine.
X */
#ifndef sun386
/* (DFK) Use 10^x if logscale is in effect, else x */
#define CheckLog(log, x) ((log) ? pow(10., (x)) : (x))
#else
static double
CheckLog(log, x)
X BOOLEAN log;
X double x;
{
X if (log)
X return(pow(10., x));
X else
X return(x);
}
#endif /* sun386 */
X
static double
LogScale(coord, islog, what, axis)
X double coord; /* the value */
X BOOLEAN islog; /* is this axis in logscale? */
X char *what; /* what is the coord for? */
X char *axis; /* which axis is this for ("x" or "y")? */
{
X if (islog) {
X if (coord <= 0.0) {
X char errbuf[100]; /* place to write error message */
X (void) sprintf(errbuf,"%s has %s coord of %g; must be above 0 for log scale!",
X what, axis, coord);
X (*term_tbl[term].text)();
X (void) fflush(outfile);
X int_error(errbuf, NO_CARET);
X } else
X return(log10(coord));
X }
X return(coord);
}
X
/* borders of plotting area */
/* computed once on every call to do_plot */
static boundary3d(scaling)
X BOOLEAN scaling; /* TRUE if terminal is doing the scaling */
{
X register struct termentry *t = &term_tbl[term];
X xleft = (t->h_char)*2 + (t->h_tic);
X xright = (scaling ? 1 : xsize) * (t->xmax) - (t->h_char)*2 - (t->h_tic);
X ybot = (t->v_char)*5/2 + 1;
X ytop = (scaling ? 1 : ysize) * (t->ymax) - (t->v_char)*5/2 - 1;
X xmiddle = (xright + xleft) / 2;
X ymiddle = (ytop + ybot) / 2;
X xscaler = (xright - xleft) / 2;
X yscaler = (ytop - ybot) / 2;
}
X
static double dbl_raise(x,y)
double x;
int y;
{
register int i;
double val;
X
X val = 1.0;
X for (i=0; i < abs(y); i++)
X val *= x;
X if (y < 0 ) return (1.0/val);
X return(val);
}
X
X
SHAR_EOF
true || echo 'restore of gnuplot/graph3d.c failed'
fi
echo 'End of part 20'
echo 'File gnuplot/graph3d.c is continued in part 21'
echo 21 > _shar_seq_.tmp
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.