Esempio n. 1
0
static void
do_cubic(
    struct curve_points *plot,	/* still containes old plot->points */
    spline_coeff *sc,		/* generated by cp_tridiag */
    int first_point,		/* where to start in plot->points */
    int num_points,		/* to determine end in plot->points */
    struct coordinate *dest)	/* where to put the interpolated data */
{
    double xdiff, temp, x, y;
    double xstart, xend;	/* Endpoints of the sampled x range */
    int i, l;
    struct coordinate GPHUGE *this_points;

    /* min and max in internal (eg logged) co-ordinates. We update
     * these, then update the external extrema in user co-ordinates
     * at the end.
     */
    double ixmin, ixmax, iymin, iymax;
    double sxmin, sxmax, symin, symax;	/* starting values of above */

    x_axis = plot->x_axis;
    y_axis = plot->y_axis;

    ixmin = sxmin = AXIS_LOG_VALUE(x_axis, X_AXIS.min);
    ixmax = sxmax = AXIS_LOG_VALUE(x_axis, X_AXIS.max);
    iymin = symin = AXIS_LOG_VALUE(y_axis, Y_AXIS.min);
    iymax = symax = AXIS_LOG_VALUE(y_axis, Y_AXIS.max);

    this_points = (plot->points) + first_point;

    l = 0;

    /* HBB 20010727: Sample only across the actual x range, not the
     * full range of input data */
#if SAMPLE_CSPLINES_TO_FULL_RANGE
    xstart = this_points[0].x;
    xend = this_points[num_points - 1].x;
#else
    xstart = GPMAX(this_points[0].x, sxmin);
    xend = GPMIN(this_points[num_points - 1].x, sxmax);

    if (xstart >= xend)
	int_error(plot->token,
		  "Cannot smooth: no data within fixed xrange!");
#endif
    xdiff = (xend - xstart) / (samples_1 - 1);

    for (i = 0; i < samples_1; i++) {
	x = xstart + i * xdiff;

	/* Move forward to the spline interval this point is in */
	while ((x >= this_points[l + 1].x) && (l < num_points - 2))
	    l++;

	/* KB 981107: With logarithmic x axis the values were
         * converted back to linear scale before calculating the
         * coefficients. Use exponential for log x values. */
	temp = AXIS_DE_LOG_VALUE(x_axis, x)
	    - AXIS_DE_LOG_VALUE(x_axis, this_points[l].x);

	/* Evaluate cubic spline polynomial */
	y = ((sc[l][3] * temp + sc[l][2]) * temp + sc[l][1]) * temp + sc[l][0];

	/* With logarithmic y axis, we need to convert from linear to
         * log scale now. */
	if (Y_AXIS.log) {
	    if (y > 0.)
		y = AXIS_DO_LOG(y_axis, y);
	    else
		y = symin - (symax - symin);
	}

	dest[i].type = INRANGE;
	STORE_AND_FIXUP_RANGE(dest[i].x, x, dest[i].type, ixmin, ixmax, X_AXIS.autoscale, NOOP, continue);
	STORE_AND_FIXUP_RANGE(dest[i].y, y, dest[i].type, iymin, iymax, Y_AXIS.autoscale, NOOP, NOOP);

	dest[i].xlow = dest[i].xhigh = dest[i].x;
	dest[i].ylow = dest[i].yhigh = dest[i].y;

	dest[i].z = -1;

    }

    UPDATE_RANGE(ixmax > sxmax, X_AXIS.max, ixmax, x_axis);
    UPDATE_RANGE(ixmin < sxmin, X_AXIS.min, ixmin, x_axis);
    UPDATE_RANGE(iymax > symax, Y_AXIS.max, iymax, y_axis);
    UPDATE_RANGE(iymin < symin, Y_AXIS.min, iymin, y_axis);

}
Esempio n. 2
0
static void
do_cubic(
    struct curve_points *plot,	/* still containes old plot->points */
    spline_coeff *sc,		/* generated by cp_tridiag */
    int first_point,		/* where to start in plot->points */
    int num_points,		/* to determine end in plot->points */
    struct coordinate *dest)	/* where to put the interpolated data */
{
    double xdiff, temp, x, y;
    double xstart, xend;	/* Endpoints of the sampled x range */
    int i, l;
    struct coordinate GPHUGE *this_points;

    /* min and max in internal (eg logged) co-ordinates. We update
     * these, then update the external extrema in user co-ordinates
     * at the end.
     */
    double ixmin, ixmax, iymin, iymax;
    double sxmin, sxmax, symin, symax;	/* starting values of above */

    x_axis = plot->x_axis;
    y_axis = plot->y_axis;

    ixmin = sxmin = X_AXIS.min;
    ixmax = sxmax = X_AXIS.max;
    iymin = symin = Y_AXIS.min;
    iymax = symax = Y_AXIS.max;

    this_points = (plot->points) + first_point;

    l = 0;

    /* HBB 20010727: Sample only across the actual x range, not the
     * full range of input data */
#if SAMPLE_CSPLINES_TO_FULL_RANGE
    xstart = this_points[0].x;
    xend = this_points[num_points - 1].x;
#else
    xstart = GPMAX(this_points[0].x, sxmin);
    xend = GPMIN(this_points[num_points - 1].x, sxmax);

    if (xstart >= xend) {
	/* This entire segment lies outside the current x range. */
	for (i = 0; i < samples_1; i++)
	    dest[i].type = OUTRANGE;
	return;
    }
#endif
    xdiff = (xend - xstart) / (samples_1 - 1);

    for (i = 0; i < samples_1; i++) {
	x = xstart + i * xdiff;

	/* Move forward to the spline interval this point is in */
	while ((x >= this_points[l + 1].x) && (l < num_points - 2))
	    l++;

	temp = x - this_points[l].x;

	/* Evaluate cubic spline polynomial */
	y = ((sc[l][3] * temp + sc[l][2]) * temp + sc[l][1]) * temp + sc[l][0];

	/* With logarithmic y axis, we need to convert from linear to log scale now */
	if (Y_AXIS.log && y <= 0)
		y = symin - (symax - symin);

	dest[i].type = INRANGE;
	STORE_AND_FIXUP_RANGE(dest[i].x, x, dest[i].type, ixmin, ixmax, X_AXIS.autoscale);
	STORE_AND_FIXUP_RANGE(dest[i].y, y, dest[i].type, iymin, iymax, Y_AXIS.autoscale);

	dest[i].xlow = dest[i].xhigh = dest[i].x;
	dest[i].ylow = dest[i].yhigh = dest[i].y;

	dest[i].z = -1;

    }

    UPDATE_RANGE(ixmax > sxmax, X_AXIS.max, ixmax);
    UPDATE_RANGE(ixmin < sxmin, X_AXIS.min, ixmin);
    UPDATE_RANGE(iymax > symax, Y_AXIS.max, iymax);
    UPDATE_RANGE(iymin < symin, Y_AXIS.min, iymin);

}
Esempio n. 3
0
void
mcs_interp(struct curve_points *plot)
{
    /* These track the original (pre-sorted) data points */
    int N = plot->p_count;
    struct coordinate *p = gp_realloc(plot->points, (N+1) * sizeof(coordinate), "mcs");
    int i;

    /* These will track the resulting smoothed curve */
    struct coordinate *new_points = gp_alloc((samples_1+1) * sizeof(coordinate), "mcs");
    double sxmin = AXIS_LOG_VALUE(plot->x_axis, X_AXIS.min);
    double sxmax = AXIS_LOG_VALUE(plot->x_axis, X_AXIS.max);
    double xstart, xend, xstep;

    xstart = GPMAX(p[0].x, sxmin);
    xend = GPMIN(p[N-1].x, sxmax);
    xstep = (xend - xstart) / (samples_1 - 1);

    /* Calculate spline coefficients */
#define DX	xlow
#define SLOPE	xhigh
#define C1	ylow
#define C2	yhigh
#define C3	z

    for (i = 0; i < N-1; i++) {
	p[i].DX = p[i+1].x - p[i].x;
	p[i].SLOPE = (p[i+1].y - p[i].y) / p[i].DX;
    }
    p[N-1].SLOPE = 0;

    p[0].C1 = p[0].SLOPE;
    for (i = 0; i < N-1; i++) {
	if (p[i].SLOPE * p[i+1].SLOPE <= 0) {
	    p[i+1].C1 = 0;
	} else {
	    double sum = p[i].DX + p[i+1].DX;
	    p[i+1].C1 = (3. * sum)
		    / ((sum + p[i+1].DX) /  p[i].SLOPE + (sum + p[i].DX) /  p[i+1].SLOPE);
	}
    }
    p[N].C1 = p[N-1].SLOPE;

    for (i = 0; i < N; i++) {
	double temp = p[i].C1 + p[i+1].C1 - 2*p[i].SLOPE;
	p[i].C2 = (p[i].SLOPE - p[i].C1 -temp) / p[i].DX;
	p[i].C3 = temp / (p[i].DX * p[i].DX);
    }

    /* Use the coefficients C1, C2, C3 to interpolate over the requested range */
    for (i = 0; i < samples_1; i++) {
	double x = xstart + i * xstep;
	double y;
	TBOOLEAN exact = FALSE;

	if (x == p[N-1].x) {	/* Exact value for right-most point of original data */
	    y = p[N-1].y;
	    exact = TRUE;
	} else {
	    int low = 0;
	    int mid; 
	    int high = N-1;
	    while (low <= high) {
		mid = floor((low + high) / 2);
		if (p[mid].x < x)
		    low = mid + 1;
		else if (p[mid].x > x)
		    high = mid - 1;
		else {		/* Exact value for some point in original data */
		    y = p[mid].y;
		    exact = TRUE;
		    break;
		}
	    }
	    if (!exact) {
		int j = GPMAX(0, high);
		double diff = x - p[j].x;
		y = p[j].y + p[j].C1 * diff + p[j].C2 * diff * diff + p[j].C3 * diff * diff * diff;
	    }
	}

	/* FIXME:  Log x?  autoscale x? */
	new_points[i].x = x;
	new_points[i].type = INRANGE;
	STORE_WITH_LOG_AND_UPDATE_RANGE(new_points[i].y, y, new_points[i].type,
		plot->y_axis, plot->noautoscale, NOOP, NOOP);
    }

    /* Replace original data with the interpolated curve */
    free(p);
    plot->points = new_points;
    plot->p_count = samples_1;
    plot->p_max = samples_1 + 1;

#undef DX
#undef SLOPE
#undef C1
#undef C2
#undef C3
}
Esempio n. 4
0
void
mcs_interp(struct curve_points *plot)
{
    /* These track the original (pre-sorted) data points */
    int N = plot->p_count;
    struct coordinate *p = gp_realloc(plot->points, (N+1) * sizeof(coordinate), "mcs");
    int i;

    /* These will track the resulting smoothed curve (>= 3X original count) */
    /* Larger number of samples gives smoother curve (no surprise!) */
    int Nsamp = (samples_1 > 2*N) ? samples_1 : 2*N;
    int Ntot = N + Nsamp;
    struct coordinate *new_points = gp_alloc((Ntot) * sizeof(coordinate), "mcs");
    double xstart = GPMAX(p[0].x, X_AXIS.min);
    double xend = GPMIN(p[N-1].x, X_AXIS.max);
    double xstep = (xend - xstart) / (Nsamp - 1);

    /* Load output x coords for sampling */
    for (i=0; i<N; i++)
	new_points[i].x = p[i].x;
    for ( ; i<Ntot; i++)
	new_points[i].x = xstart + (i-N)*xstep;
    /* Sort output x coords */
    qsort(new_points, Ntot, sizeof(struct coordinate), compare_points);
    /* Displace any collisions */
    for (i=1; i<Ntot-1; i++) {
	double delta = new_points[i].x - new_points[i-1].x;
	if (new_points[i+1].x - new_points[i].x < delta/1000.)
	    new_points[i].x -= delta/2.;
    }

    /* Calculate spline coefficients */
#define DX	xlow
#define SLOPE	xhigh
#define C1	ylow
#define C2	yhigh
#define C3	z

    for (i = 0; i < N-1; i++) {
	p[i].DX = p[i+1].x - p[i].x;
	p[i].SLOPE = (p[i+1].y - p[i].y) / p[i].DX;
    }
    p[N-1].SLOPE = 0;

    p[0].C1 = p[0].SLOPE;
    for (i = 0; i < N-1; i++) {
	if (p[i].SLOPE * p[i+1].SLOPE <= 0) {
	    p[i+1].C1 = 0;
	} else {
	    double sum = p[i].DX + p[i+1].DX;
	    p[i+1].C1 = (3. * sum)
		    / ((sum + p[i+1].DX) /  p[i].SLOPE + (sum + p[i].DX) /  p[i+1].SLOPE);
	}
    }
    p[N].C1 = p[N-1].SLOPE;

    for (i = 0; i < N; i++) {
	double temp = p[i].C1 + p[i+1].C1 - 2*p[i].SLOPE;
	p[i].C2 = (p[i].SLOPE - p[i].C1 -temp) / p[i].DX;
	p[i].C3 = temp / (p[i].DX * p[i].DX);
    }

    /* Use the coefficients C1, C2, C3 to interpolate over the requested range */
    for (i = 0; i < Ntot; i++) {
	double x = new_points[i].x;
	double y;
	TBOOLEAN exact = FALSE;

	if (x == p[N-1].x) {	/* Exact value for right-most point of original data */
	    y = p[N-1].y;
	    exact = TRUE;
	} else {
	    int low = 0;
	    int mid; 
	    int high = N-1;
	    while (low <= high) {
		mid = floor((low + high) / 2);
		if (p[mid].x < x)
		    low = mid + 1;
		else if (p[mid].x > x)
		    high = mid - 1;
		else {		/* Exact value for some point in original data */
		    y = p[mid].y;
		    exact = TRUE;
		    break;
		}
	    }
	    if (!exact) {
		int j = GPMAX(0, high);
		double diff = x - p[j].x;
		y = p[j].y + p[j].C1 * diff + p[j].C2 * diff * diff + p[j].C3 * diff * diff * diff;
	    }
	}

	xstart = X_AXIS.min;
	xend = X_AXIS.max;
	if (inrange(x, xstart, xend))
	    new_points[i].type = INRANGE;
	else
	    new_points[i].type = OUTRANGE;
	/* FIXME:  simpler test for outrange would be sufficient */
	STORE_AND_UPDATE_RANGE(new_points[i].y, y, new_points[i].type,
		plot->y_axis, plot->noautoscale, NOOP);
    }

    /* Replace original data with the interpolated curve */
    free(p);
    plot->points = new_points;
    plot->p_count = Ntot;
    plot->p_max = Ntot + 1;

#undef DX
#undef SLOPE
#undef C1
#undef C2
#undef C3
}
Esempio n. 5
0
/* plot a colour smooth box bounded by the terminal's integer coordinates
   [x_from,y_from] to [x_to,y_to].
   This routine is for non-postscript files, as it does an explicit loop
   over all thin rectangles
 */
static void
draw_inside_color_smooth_box_bitmap(FILE * out)
{
    int steps = 128; /* I think that nobody can distinguish more colours drawn in the palette */
    int i, j, xy, xy2, xy_from, xy_to;
    int jmin = 0;
    double xy_step, gray, range;
    gpiPoint corners[4];

    (void) out;			/* to avoid "unused parameter" warning */
    if (color_box.rotation == 'v') {
	corners[0].x = corners[3].x = color_box.bounds.xleft;
	corners[1].x = corners[2].x = color_box.bounds.xright;
	xy_from = color_box.bounds.ybot;
	xy_to = color_box.bounds.ytop;
	xy_step = (color_box.bounds.ytop - color_box.bounds.ybot) / (double)steps;
    } else {
	corners[0].y = corners[1].y = color_box.bounds.ybot;
	corners[2].y = corners[3].y = color_box.bounds.ytop;
	xy_from = color_box.bounds.xleft;
	xy_to = color_box.bounds.xright;
	xy_step = (color_box.bounds.xright - color_box.bounds.xleft) / (double)steps;
    }
    range = (xy_to - xy_from);

    for (i = 0, xy2 = xy_from; i < steps; i++) {

	/* Start from one pixel beyond the previous box */
	xy = xy2;
	xy2 = xy_from + (int) (xy_step * (i + 1));

	/* Set the colour for the next range increment */
	/* FIXME - The "1 +" seems wrong, yet it improves the placement in gd */
	gray = (double)(1 + xy - xy_from) / range;
	if (sm_palette.positive == SMPAL_NEGATIVE)
	    gray = 1 - gray;
	set_color(gray);

	/* If this is a defined palette, make sure that the range increment */
	/* does not straddle a palette segment boundary. If it does, split  */
	/* it into two parts.                                               */
	if (sm_palette.colorMode == SMPAL_COLOR_MODE_GRADIENT)
	    for (j=jmin; j<sm_palette.gradient_num; j++) {
		int boundary = xy_from + (int)(sm_palette.gradient[j].pos * range);
		if (xy >= boundary) {
		    jmin = j;
		} else {
		    if (xy2 > boundary) {
			xy2 = boundary;
			i--;
			break;
		    }
		}
		if (xy2 < boundary)
		    break;
	    }

	if (color_box.rotation == 'v') {
	    corners[0].y = corners[1].y = xy;
	    corners[2].y = corners[3].y = GPMIN(xy_to,xy2+1);
	} else {
	    corners[0].x = corners[3].x = xy;
	    corners[1].x = corners[2].x = GPMIN(xy_to,xy2+1);
	}
#ifdef EXTENDED_COLOR_SPECS
	if (supply_extended_color_specs)
	    corners[0].spec.gray = -1;	/* force solid color */
#endif
	/* print the rectangle with the given colour */
	if (default_fillstyle.fillstyle == FS_EMPTY)
	    corners->style = FS_OPAQUE;
	else
	    corners->style = style_from_fill(&default_fillstyle);
	term->filled_polygon(4, corners);
    }
}
Esempio n. 6
0
/*  sb_get:
 *  retrieve (wrapped) line buffer
 */
LPLB 
sb_get(LPSB sb, uint index)
{
    LPLB line = NULL;

    assert(sb != NULL); assert((index < sb->size) || (sb->wrap_at > 0));
    assert(sb->lb != NULL);

    if (sb->wrap_at == 0) {
	if (index < sb_internal_length(sb))
	    line = &(sb->lb[(sb->head + index) % sb->size]);
    } else {
	/* count number of wrapped lines */
	uint line_count;
	uint idx;
	uint internal_length = sb_internal_length(sb);

	if (sb->last_line <= index) {
	    /* use cached values */
	    line_count = sb->last_line;
	    idx = sb->last_line_index;
	} else {
	    line_count = 0;
	    idx = 0;
	}
	for ( ; (idx < internal_length); idx++) {
	    line_count += sb_lines(sb, sb_internal_get(sb, idx));
	    if (line_count > index) break;
	}

	if (idx < internal_length) {
	    uint wrapped_lines;
	    uint len;
	    LPLB lb;
	    uint start, count;

	    /* get last line buffer */
	    lb = sb_internal_get(sb, idx);
	    len = lb_length(lb);
	    wrapped_lines = sb_lines(sb, lb);
	    line_count -= wrapped_lines;

	    /* cache current index */
	    sb->last_line_index = idx;
	    sb->last_line = line_count;

	    /* index into current line buffer */
	    start = (index - line_count) * sb->wrap_at;
	    count = GPMIN(len - start, sb->wrap_at);

	    /* copy substring from current line buffer */
	    lb_init(sb->current_line);
	    if (lb->str) {
		sb->current_line->len = count;
		sb->current_line->str = lb->str + start;
		//lb_insert_str(sb->current_line, 0, lb->str + start, count);
	    }

	    /* return temporary buffer */
	    line = sb->current_line;
	}
    }
    return line;
}
Esempio n. 7
0
/* Given two points, both outside the plot, return
 * the points where an edge of the plot intersects the line segment defined
 * by the two points. There may be zero, one, two, or an infinite number
 * of intersection points. (One means an intersection at a corner, infinite
 * means overlaying the edge itself). We return FALSE when there is nothing
 * to draw (zero intersections), and TRUE when there is something to
 * draw (the one-point case is a degenerate of the two-point case and we do
 * not distinguish it - we draw it anyway).
 */
TBOOLEAN			/* any intersection? */
two_edge3d_intersect(
    struct coordinate GPHUGE *points,	/* the points array */
    int i,				/* line segment from point i-1 to point i */
    double *lx, double *ly, double *lz)	/* lx[2], ly[2], lz[2]: points where it crosses edges */
{
    int count;
    /* global axis_array[FIRST_{X,Y,Z}_AXIS].{min,max} */
    double ix = points[i - 1].x;
    double iy = points[i - 1].y;
    double iz = points[i - 1].z;
    double ox = points[i].x;
    double oy = points[i].y;
    double oz = points[i].z;
    double t[6];
    double swap;
    double x, y, z;		/* possible intersection point */
    double t_min, t_max;

    /* nasty degenerate cases, effectively drawing to an infinity point (?)
       cope with them here, so don't process them as a "real" OUTRANGE point

       If more than one coord is -VERYLARGE, then can't ratio the "infinities"
       so drop out by returning FALSE */

    count = 0;
    if (ix == -VERYLARGE)
	count++;
    if (ox == -VERYLARGE)
	count++;
    if (iy == -VERYLARGE)
	count++;
    if (oy == -VERYLARGE)
	count++;
    if (iz == -VERYLARGE)
	count++;
    if (oz == -VERYLARGE)
	count++;

    /* either doesn't pass through 3D volume *or*
       can't ratio infinities to get a direction to draw line, so simply return(FALSE) */
    if (count > 1) {
	return (FALSE);
    }

    if (ox == -VERYLARGE || ix == -VERYLARGE) {
	if (ix == -VERYLARGE) {
	    /* swap points so ix/iy/iz don't have a -VERYLARGE component */
	    x = ix;
	    ix = ox;
	    ox = x;
	    y = iy;
	    iy = oy;
	    oy = y;
	    z = iz;
	    iz = oz;
	    oz = z;
	}
	/* check actually passes through the 3D graph volume */

	if (ix > axis_array[FIRST_X_AXIS].max
	    && IN_AXIS_RANGE(iy, FIRST_Y_AXIS)
	    && IN_AXIS_RANGE(iz, FIRST_Z_AXIS)) {
	    lx[0] = axis_array[FIRST_X_AXIS].min;
	    ly[0] = iy;
	    lz[0] = iz;

	    lx[1] = axis_array[FIRST_X_AXIS].max;
	    ly[1] = iy;
	    lz[1] = iz;

	    return (TRUE);
	} else {
	    return (FALSE);
	}
    }
    if (oy == -VERYLARGE || iy == -VERYLARGE) {
	if (iy == -VERYLARGE) {
	    /* swap points so ix/iy/iz don't have a -VERYLARGE component */
	    x = ix;
	    ix = ox;
	    ox = x;
	    y = iy;
	    iy = oy;
	    oy = y;
	    z = iz;
	    iz = oz;
	    oz = z;
	}
	/* check actually passes through the 3D graph volume */
	if (iy > axis_array[FIRST_Y_AXIS].max
	    && IN_AXIS_RANGE(ix, FIRST_X_AXIS)
	    && IN_AXIS_RANGE(iz, FIRST_Z_AXIS)) {
	    lx[0] = ix;
	    ly[0] = axis_array[FIRST_Y_AXIS].min;
	    lz[0] = iz;

	    lx[1] = ix;
	    ly[1] = axis_array[FIRST_Y_AXIS].max;
	    lz[1] = iz;

	    return (TRUE);
	} else {
	    return (FALSE);
	}
    }
    if (oz == -VERYLARGE || iz == -VERYLARGE) {
	if (iz == -VERYLARGE) {
	    /* swap points so ix/iy/iz don't have a -VERYLARGE component */
	    x = ix;
	    ix = ox;
	    ox = x;
	    y = iy;
	    iy = oy;
	    oy = y;
	    z = iz;
	    iz = oz;
	    oz = z;
	}
	/* check actually passes through the 3D graph volume */
	if (iz > axis_array[FIRST_Z_AXIS].max
	    && IN_AXIS_RANGE(ix, FIRST_X_AXIS)
	    && IN_AXIS_RANGE(iy, FIRST_Y_AXIS)) {
	    lx[0] = ix;
	    ly[0] = iy;
	    lz[0] = axis_array[FIRST_Z_AXIS].min;

	    lx[1] = ix;
	    ly[1] = iy;
	    lz[1] = axis_array[FIRST_Z_AXIS].max;

	    return (TRUE);
	} else {
	    return (FALSE);
	}
    }
    /*
     * Quick outcode tests on the 3d graph volume
     */

    /* test z coord first --- most surface OUTRANGE points generated
     * between axis_array[FIRST_Z_AXIS].min and baseplane (i.e. when
     * ticslevel is non-zero)
     */
    if (GPMAX(iz, oz) < axis_array[FIRST_Z_AXIS].min
	|| GPMIN(iz, oz) > axis_array[FIRST_Z_AXIS].max)
	return (FALSE);

    if (GPMAX(ix, ox) < axis_array[FIRST_X_AXIS].min
	|| GPMIN(ix, ox) > axis_array[FIRST_X_AXIS].max)
	return (FALSE);

    if (GPMAX(iy, oy) < axis_array[FIRST_Y_AXIS].min
	|| GPMIN(iy, oy) > axis_array[FIRST_Y_AXIS].max)
	return (FALSE);

    /* Special horizontal/vertical, etc. cases are checked and
     * remaining slant lines are checked separately.
     *
     * The slant line intersections are solved using the parametric
     * form of the equation for a line, since if we test x/y/z min/max
     * planes explicitly then e.g. a line passing through a corner
     * point (x_min,y_min,z_min) actually intersects all 3 planes and
     * hence further tests would be required to anticipate this and
     * similar situations. */

    /* Can have case (ix == ox && iy == oy && iz == oz) as both points
     * OUTRANGE */
    if (ix == ox && iy == oy && iz == oz) {
	/* but as only define single outrange point, can't intersect
	 * 3D graph volume */
	return (FALSE);
    }

    if (ix == ox) {
	if (iy == oy) {
	    /* line parallel to z axis */

	    /* x and y coords must be in range, and line must span
	     * both FIRST_Z_AXIS->min and ->max.
	     * 
	     * note that spanning FIRST_Z_AXIS->min implies spanning
	     * ->max as both points OUTRANGE */

	    if (!IN_AXIS_RANGE(ix, FIRST_X_AXIS)
		|| !IN_AXIS_RANGE(iy, FIRST_Y_AXIS)) {
		return (FALSE);
	    }
	    if (inrange(axis_array[FIRST_Z_AXIS].min, iz, oz)) {
		lx[0] = ix;
		ly[0] = iy;
		lz[0] = axis_array[FIRST_Z_AXIS].min;

		lx[1] = ix;
		ly[1] = iy;
		lz[1] = axis_array[FIRST_Z_AXIS].max;

		return (TRUE);
	    } else
		return (FALSE);
	}
	if (iz == oz) {
	    /* line parallel to y axis */
	    if (!IN_AXIS_RANGE(ix, FIRST_X_AXIS)
		|| !IN_AXIS_RANGE(iz, FIRST_Z_AXIS)) {
		return (FALSE);
	    }
	    if (inrange(axis_array[FIRST_Y_AXIS].min, iy, oy)) {
		lx[0] = ix;
		ly[0] = axis_array[FIRST_Y_AXIS].min;
		lz[0] = iz;

		lx[1] = ix;
		ly[1] = axis_array[FIRST_Y_AXIS].max;
		lz[1] = iz;

		return (TRUE);
	    } else
		return (FALSE);
	}


	/* nasty 2D slanted line in a yz plane */
	if (!IN_AXIS_RANGE(ox, FIRST_X_AXIS))
	    return (FALSE);

	t[0] = (axis_array[FIRST_Y_AXIS].min - iy) / (oy - iy);
	t[1] = (axis_array[FIRST_Y_AXIS].max - iy) / (oy - iy);

	if (t[0] > t[1]) {
	    swap = t[0];
	    t[0] = t[1];
	    t[1] = swap;
	}
	t[2] = (axis_array[FIRST_Z_AXIS].min - iz) / (oz - iz);
	t[3] = (axis_array[FIRST_Z_AXIS].max - iz) / (oz - iz);

	if (t[2] > t[3]) {
	    swap = t[2];
	    t[2] = t[3];
	    t[3] = swap;
	}
	t_min = GPMAX(GPMAX(t[0], t[2]), 0.0);
	t_max = GPMIN(GPMIN(t[1], t[3]), 1.0);

	if (t_min > t_max)
	    return (FALSE);

	lx[0] = ix;
	ly[0] = iy + t_min * (oy - iy);
	lz[0] = iz + t_min * (oz - iz);

	lx[1] = ix;
	ly[1] = iy + t_max * (oy - iy);
	lz[1] = iz + t_max * (oz - iz);

	/* Can only have 0 or 2 intersection points -- only need test
	 * one coord */
	if (IN_AXIS_RANGE(ly[0], FIRST_Y_AXIS)
	    && IN_AXIS_RANGE(lz[0], FIRST_Z_AXIS)) {
	    return (TRUE);
	}
	return (FALSE);
    }

    if (iy == oy) {
	/* already checked case (ix == ox && iy == oy) */
	if (oz == iz) {
	    /* line parallel to x axis */
	    if (!IN_AXIS_RANGE(iy, FIRST_Y_AXIS)
		|| !IN_AXIS_RANGE(iz, FIRST_Z_AXIS)) {
		return (FALSE);
	    }
	    if (inrange(axis_array[FIRST_X_AXIS].min, ix, ox)) {
		lx[0] = axis_array[FIRST_X_AXIS].min;
		ly[0] = iy;
		lz[0] = iz;

		lx[1] = axis_array[FIRST_X_AXIS].max;
		ly[1] = iy;
		lz[1] = iz;

		return (TRUE);
	    } else
		return (FALSE);
	}
	/* nasty 2D slanted line in an xz plane */

	if (!IN_AXIS_RANGE(oy, FIRST_Y_AXIS))
	    return (FALSE);

	t[0] = (axis_array[FIRST_X_AXIS].min - ix) / (ox - ix);
	t[1] = (axis_array[FIRST_X_AXIS].max - ix) / (ox - ix);

	if (t[0] > t[1]) {
	    swap = t[0];
	    t[0] = t[1];
	    t[1] = swap;
	}
	t[2] = (axis_array[FIRST_Z_AXIS].min - iz) / (oz - iz);
	t[3] = (axis_array[FIRST_Z_AXIS].max - iz) / (oz - iz);

	if (t[2] > t[3]) {
	    swap = t[2];
	    t[2] = t[3];
	    t[3] = swap;
	}
	t_min = GPMAX(GPMAX(t[0], t[2]), 0.0);
	t_max = GPMIN(GPMIN(t[1], t[3]), 1.0);

	if (t_min > t_max)
	    return (FALSE);

	lx[0] = ix + t_min * (ox - ix);
	ly[0] = iy;
	lz[0] = iz + t_min * (oz - iz);

	lx[1] = ix + t_max * (ox - ix);
	ly[1] = iy;
	lz[1] = iz + t_max * (oz - iz);

	/*
	 * Can only have 0 or 2 intersection points -- only need test one coord
	 */
	if (IN_AXIS_RANGE(lx[0], FIRST_X_AXIS)
	    && IN_AXIS_RANGE(lz[0], FIRST_Z_AXIS)) {
	    return (TRUE);
	}
	return (FALSE);
    }
    if (iz == oz) {
	/* already checked cases (ix == ox && iz == oz) and (iy == oy
	   && iz == oz) */

	/* nasty 2D slanted line in an xy plane */

	if (!IN_AXIS_RANGE(oz, FIRST_Z_AXIS))
	    return (FALSE);

	t[0] = (axis_array[FIRST_X_AXIS].min - ix) / (ox - ix);
	t[1] = (axis_array[FIRST_X_AXIS].max - ix) / (ox - ix);

	if (t[0] > t[1]) {
	    swap = t[0];
	    t[0] = t[1];
	    t[1] = swap;
	}
	t[2] = (axis_array[FIRST_Y_AXIS].min - iy) / (oy - iy);
	t[3] = (axis_array[FIRST_Y_AXIS].max - iy) / (oy - iy);

	if (t[2] > t[3]) {
	    swap = t[2];
	    t[2] = t[3];
	    t[3] = swap;
	}
	t_min = GPMAX(GPMAX(t[0], t[2]), 0.0);
	t_max = GPMIN(GPMIN(t[1], t[3]), 1.0);

	if (t_min > t_max)
	    return (FALSE);

	lx[0] = ix + t_min * (ox - ix);
	ly[0] = iy + t_min * (oy - iy);
	lz[0] = iz;

	lx[1] = ix + t_max * (ox - ix);
	ly[1] = iy + t_max * (oy - iy);
	lz[1] = iz;

	/*
	 * Can only have 0 or 2 intersection points -- only need test one coord
	 */
	if (IN_AXIS_RANGE(lx[0], FIRST_X_AXIS) 
	    && IN_AXIS_RANGE(ly[0], FIRST_Y_AXIS)) {
	    return (TRUE);
	}
	return (FALSE);
    }
    /* really nasty general slanted 3D case */

    /*
       Solve parametric equation

       (ix, iy, iz) + t (diff_x, diff_y, diff_z)

       where 0.0 <= t <= 1.0 and

       diff_x = (ox - ix);
       diff_y = (oy - iy);
       diff_z = (oz - iz);
     */

    t[0] = (axis_array[FIRST_X_AXIS].min - ix) / (ox - ix);
    t[1] = (axis_array[FIRST_X_AXIS].max - ix) / (ox - ix);

    if (t[0] > t[1]) {
	swap = t[0];
	t[0] = t[1];
	t[1] = swap;
    }
    t[2] = (axis_array[FIRST_Y_AXIS].min - iy) / (oy - iy);
    t[3] = (axis_array[FIRST_Y_AXIS].max - iy) / (oy - iy);

    if (t[2] > t[3]) {
	swap = t[2];
	t[2] = t[3];
	t[3] = swap;
    }
    t[4] = (iz == oz) ? 0.0 : (axis_array[FIRST_Z_AXIS].min - iz) / (oz - iz);
    t[5] = (iz == oz) ? 1.0 : (axis_array[FIRST_Z_AXIS].max - iz) / (oz - iz);

    if (t[4] > t[5]) {
	swap = t[4];
	t[4] = t[5];
	t[5] = swap;
    }
    t_min = GPMAX(GPMAX(t[0], t[2]), GPMAX(t[4], 0.0));
    t_max = GPMIN(GPMIN(t[1], t[3]), GPMIN(t[5], 1.0));

    if (t_min > t_max)
	return (FALSE);

    lx[0] = ix + t_min * (ox - ix);
    ly[0] = iy + t_min * (oy - iy);
    lz[0] = iz + t_min * (oz - iz);

    lx[1] = ix + t_max * (ox - ix);
    ly[1] = iy + t_max * (oy - iy);
    lz[1] = iz + t_max * (oz - iz);

    /*
     * Can only have 0 or 2 intersection points -- only need test one coord
     */
    if (IN_AXIS_RANGE(lx[0], FIRST_X_AXIS) 
	&& IN_AXIS_RANGE(ly[0], FIRST_Y_AXIS)
	&& IN_AXIS_RANGE(lz[0], FIRST_Z_AXIS)) {
	return (TRUE);
    }
    return (FALSE);
}
Esempio n. 8
0
int
main(int argc_orig, char **argv)
#endif
{
    int i;

    /* We want the current value of argc to persist across a LONGJMP from int_error().
     * Without this the compiler may put it on the stack, which LONGJMP clobbers.
     * Here we try make it a volatile variable that optimization will not affect.
     * Why do we not have to do the same for argv?   I don't know.
     * But the test cases that broke with generic argc seem fine with generic argv.
     */
    static volatile int argc;
    argc = argc_orig;

#ifdef LINUXVGA
    LINUX_setup();		/* setup VGA before dropping privilege DBT 4/5/99 */
    drop_privilege();
#endif
/* make sure that we really have revoked root access, this might happen if
   gnuplot is compiled without vga support but is installed suid by mistake */
#ifdef __linux__
    if (setuid(getuid()) != 0) {
	fprintf(stderr,"gnuplot: refusing to run at elevated privilege\n");
	exit(EXIT_FAILURE);
    }
#endif

/* HBB: Seems this isn't needed any more for DJGPP V2? */
/* HBB: disable all floating point exceptions, just keep running... */
#if defined(DJGPP) && (DJGPP!=2)
    _control87(MCW_EM, MCW_EM);
#endif

#if defined(OS2)
    {
	int rc;
#ifdef OS2_IPC
	char semInputReadyName[40];

	sprintf(semInputReadyName, "\\SEM32\\GP%i_Input_Ready", getpid());
	rc = DosCreateEventSem(semInputReadyName, &semInputReady, 0, 0);
	if (rc != 0)
	    fputs("DosCreateEventSem error\n", stderr);
#endif
	rc = RexxRegisterSubcomExe("GNUPLOT", (PFN) RexxInterface, NULL);
    }
#endif

/* malloc large blocks, otherwise problems with fragmented mem */
#ifdef MALLOCDEBUG
    malloc_debug(7);
#endif


/* init progpath and get helpfile from executable directory */
#if defined(MSDOS) || defined(OS2)
    {
	char *s;

#ifdef __EMX__
	_execname(progpath, sizeof(progpath));
#else
	safe_strncpy(progpath, argv[0], sizeof(progpath));
#endif
	/* convert '/' to '\\' */
	for (s = progpath; *s != NUL; s++)
	    if (*s == DIRSEP2)
		*s = DIRSEP1;
	/* cut program name */
	s = strrchr(progpath, DIRSEP1);
	if (s != NULL)
	    s++;
	else
	    s = progpath;
	*s = NUL;
	/* init HelpFile */
	strcpy(HelpFile, progpath);
	strcat(HelpFile, "gnuplot.gih");
	/* remove trailing "bin/" from progpath */
	if ((s != NULL) && (s - progpath >= 4)) {
	    s -= 4;
	    if (strncasecmp(s, "bin", 3) == 0)
		*s = NUL;
	}
    }
#endif /* DJGPP */

#if (defined(PIPE_IPC) || defined(_WIN32)) && (defined(HAVE_LIBREADLINE) || (defined(HAVE_LIBEDITLINE) && defined(X11)))
    /* Editline needs this to be set before the very first call to readline(). */
    /* Support for rl_getc_function is broken for utf-8 in editline. Since it is only
       really required for X11, disable this section when building without X11. */
    rl_getc_function = getc_wrapper;
#endif

#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE)
    /* T.Walter 1999-06-24: 'rl_readline_name' must be this fix name.
     * It is used to parse a 'gnuplot' specific section in '~/.inputrc'
     * or gnuplot specific commands in '.editrc' (when using editline
     * instead of readline) */
    rl_readline_name = "Gnuplot";
    rl_terminal_name = getenv("TERM");
#if defined(HAVE_LIBREADLINE)
    using_history();
#else
    history_init();
#endif
#endif
#if defined(HAVE_LIBREADLINE) && !defined(MISSING_RL_TILDE_EXPANSION)
    rl_complete_with_tilde_expansion = 1;
#endif

    for (i = 1; i < argc; i++) {
	if (!argv[i])
	    continue;

	if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) {
	    printf("gnuplot %s patchlevel %s\n",
		    gnuplot_version, gnuplot_patchlevel);
	    return 0;

	} else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
	    printf( "Usage: gnuplot [OPTION] ... [FILE]\n"
#ifdef X11
		    "for X11 options see 'help X11->command-line-options'\n"
#endif
		    "  -V, --version\n"
		    "  -h, --help\n"
		    "  -p  --persist\n"
		    "  -s  --slow\n"
		    "  -d  --default-settings\n"
		    "  -c  scriptfile ARG1 ARG2 ... \n"
		    "  -e  \"command1; command2; ...\"\n"
		    "gnuplot %s patchlevel %s\n",
		    gnuplot_version, gnuplot_patchlevel);
#ifdef DEVELOPMENT_VERSION
	    printf(
#ifdef DIST_CONTACT
		    "Report bugs to "DIST_CONTACT"\n"
		    "            or %s\n",
#else
		    "Report bugs to %s\n",
#endif
		    bug_email);
#endif
	    return 0;

	} else if (!strncmp(argv[i], "-persist", 2) || !strcmp(argv[i], "--persist")
#ifdef _WIN32
		|| !stricmp(argv[i], "-noend") || !stricmp(argv[i], "/noend")
#endif
		) {
	    persist_cl = TRUE;
	} else if (!strncmp(argv[i], "-slow", 2) || !strcmp(argv[i], "--slow")) {
	    slow_font_startup = TRUE;
	} else if (!strncmp(argv[i], "-d", 2) || !strcmp(argv[i], "--default-settings")) {
	    /* Skip local customization read from ~/.gnuplot */
	    skip_gnuplotrc = TRUE;
	}
    }

#ifdef X11
    /* the X11 terminal removes tokens that it recognizes from argv. */
    {
	int n = X11_args(argc, argv);
	argv += n;
	argc -= n;
    }
#endif

    setbuf(stderr, (char *) NULL);

#ifdef HAVE_SETVBUF
    /* This was once setlinebuf(). Docs say this is
     * identical to setvbuf(,NULL,_IOLBF,0), but MS C
     * faults this (size out of range), so we try with
     * size of 1024 instead. [SAS/C does that, too. -lh]
     */
    if (setvbuf(stdout, (char *) NULL, _IOLBF, (size_t) 1024) != 0)
	(void) fputs("Could not linebuffer stdout\n", stderr);

    /* Switching to unbuffered mode causes all characters in the input
     * buffer to be lost. So the only safe time to do it is on program entry.
     * Do any non-X platforms suffer from this problem?
     * EAM - Jan 2013 YES.
     */
    setvbuf(stdin, (char *) NULL, _IONBF, 0);
#endif

    gpoutfile = stdout;

    /* Initialize pre-loaded user variables */
    /* "pi" is hard-wired as the first variable */
    (void) add_udv_by_name("GNUTERM");
    (void) add_udv_by_name("NaN");
    init_constants();
    udv_user_head = &(udv_NaN->next_udv);

    init_memory();

    interactive = FALSE;

    /* April 2017:  We used to call init_terminal() here, but now   */
    /* We defer initialization until error handling has been set up. */

# if defined(_WIN32) && !defined(WGP_CONSOLE)
    interactive = TRUE;
# else
    interactive = isatty(fileno(stdin));
# endif

    /* Note: we want to know whether this is an interactive session so that we can
     * decide whether or not to write status information to stderr.  The old test
     * for this was to see if (argc > 1) but the addition of optional command line
     * switches broke this.  What we really wanted to know was whether any of the
     * command line arguments are file names or an explicit in-line "-e command".
     */
    for (i = 1; i < argc; i++) {
# ifdef _WIN32
	if (!stricmp(argv[i], "/noend"))
	    continue;
# endif
	if ((argv[i][0] != '-') || (argv[i][1] == 'e') || (argv[i][1] == 'c') ) {
	    interactive = FALSE;
	    break;
	}
    }

    /* Need this before show_version is called for the first time */

    if (interactive)
	show_version(stderr);
    else
	show_version(NULL); /* Only load GPVAL_COMPILE_OPTIONS */

    update_gpval_variables(3);  /* update GPVAL_ variables available to user */

#ifdef VMS
    /* initialise screen management routines for command recall */
    {
    unsigned int ierror;
    if (ierror = smg$create_virtual_keyboard(&vms_vkid) != SS$_NORMAL)
	done(ierror);
    if (ierror = smg$create_key_table(&vms_ktid) != SS$_NORMAL)
	done(ierror);
    }
#endif /* VMS */

    if (!SETJMP(command_line_env, 1)) {
	/* first time */
	interrupt_setup();
	get_user_env();
	init_loadpath();
	init_locale();

	memset(&sm_palette, 0, sizeof(sm_palette));
	init_fit();		/* Initialization of fitting module */
#ifdef READLINE
	/* When using the built-in readline, we set the initial
	   encoding according to the locale as this is required
	   to properly handle keyboard input. */
	init_encoding();
#endif
	init_gadgets();

	/* April 2017: Now that error handling is in place, it is safe parse
	 * GNUTERM during terminal initialization.
	 * atexit processing is done in reverse order. We want
	 * the generic terminal shutdown in term_reset to be executed before
	 * any terminal specific cleanup requested by individual terminals.
	 */
	init_terminal();
	push_terminal(0);	/* remember the initial terminal */
	gp_atexit(term_reset);

	/* Execute commands in ~/.gnuplot */
	init_session();

	if (interactive && term != 0) {		/* not unknown */
#ifdef GNUPLOT_HISTORY
#if (defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE)) && !defined(_WIN32)
	    expanded_history_filename = tilde_expand(GNUPLOT_HISTORY_FILE);
#else
	    expanded_history_filename = gp_strdup(GNUPLOT_HISTORY_FILE);
	    gp_expand_tilde(&expanded_history_filename);
#endif
	    read_history(expanded_history_filename);

	    /*
	     * It is safe to ignore the return values of 'atexit()' and
	     * 'on_exit()'. In the worst case, there is no history of your
	     * currrent session and you have to type all again in your next
	     * session.
	     */
	    gp_atexit(wrapper_for_write_history);
#endif /* GNUPLOT_HISTORY */

#if defined(READLINE) && defined(WGP_CONSOLE)
	    fprintf(stderr, "Encoding set to '%s'.\n", encoding_names[encoding]);
#endif
	}			/* if (interactive && term != 0) */
    } else {
	/* come back here from int_error() */
	if (!successful_initialization) {
	    /* Only print the warning once */
	    successful_initialization = TRUE;
	    fprintf(stderr,"WARNING: Error during initialization\n\n");
	}
	if (interactive == FALSE)
	    exit_status = EXIT_FAILURE;
#ifdef HAVE_READLINE_RESET
	else {
	    /* reset properly readline after a SIGINT+longjmp */
	    rl_reset_after_signal ();
	}
#endif

	load_file_error();	/* if we were in load_file(), cleanup */
	SET_CURSOR_ARROW;

#ifdef VMS
	/* after catching interrupt */
	/* VAX stuffs up stdout on SIGINT while writing to stdout,
	   so reopen stdout. */
	if (gpoutfile == stdout) {
	    if ((stdout = freopen("SYS$OUTPUT", "w", stdout)) == NULL) {
		/* couldn't reopen it so try opening it instead */
		if ((stdout = fopen("SYS$OUTPUT", "w")) == NULL) {
		    /* don't use int_error here - causes infinite loop! */
		    fputs("Error opening SYS$OUTPUT as stdout\n", stderr);
		}
	    }
	    gpoutfile = stdout;
	}
#endif /* VMS */

	/* Why a goto?  Because we exited the loop below via int_error */
	/* using LONGJMP.  The compiler was not expecting this, and    */
	/* "optimized" the handling of argc and argv such that simply  */
	/* entering the loop again from the top finds them messed up.  */
	/* If we reenter the loop via a goto then there is some hope   */
	/* that code reordering does not hurt us.                      */
	if (reading_from_dash && interactive)
	    goto RECOVER_FROM_ERROR_IN_DASH;
	reading_from_dash = FALSE;

	if (!interactive && !noinputfiles) {
	    term_reset();
	    gp_exit(EXIT_FAILURE);	/* exit on non-interactive error */
	}
    }

    /* load filenames given as arguments */
    while (--argc > 0) {
	    ++argv;
	    c_token = 0;
	    if (!strncmp(*argv, "-persist", 2) || !strcmp(*argv, "--persist")
#ifdef _WIN32
		|| !stricmp(*argv, "-noend") || !stricmp(*argv, "/noend")
#endif
	    ) {
		FPRINTF((stderr,"'persist' command line option recognized\n"));
	    } else if (strcmp(*argv, "-") == 0) {
#if defined(_WIN32) && !defined(WGP_CONSOLE)
		TextShow(&textwin);
		interactive = TRUE;
#else
		interactive = isatty(fileno(stdin));
#endif

RECOVER_FROM_ERROR_IN_DASH:
		reading_from_dash = TRUE;
		while (!com_line());
		reading_from_dash = FALSE;
		interactive = FALSE;
		noinputfiles = FALSE;

	    } else if (strcmp(*argv, "-e") == 0) {
		int save_state = interactive;
		--argc; ++argv;
		if (argc <= 0) {
		    fprintf(stderr, "syntax:  gnuplot -e \"commands\"\n");
		    return 0;
		}
		interactive = FALSE;
		noinputfiles = FALSE;
		do_string(*argv);
		interactive = save_state;

	    } else if (!strncmp(*argv, "-slow", 2) || !strcmp(*argv, "--slow")) {
		slow_font_startup = TRUE;

	    } else if (!strncmp(*argv, "-d", 2) || !strcmp(*argv, "--default-settings")) {
		/* Ignore this; it already had its effect */
		FPRINTF((stderr, "ignoring -d\n"));

	    } else if (strcmp(*argv, "-c") == 0) {
		/* Pass command line arguments to the gnuplot script in the next
		 * argument. This consumes the remainder of the command line
		 */
		interactive = FALSE;
		noinputfiles = FALSE;
		--argc; ++argv;
		if (argc <= 0) {
		    fprintf(stderr, "syntax:  gnuplot -c scriptname args\n");
		    gp_exit(EXIT_FAILURE);
		}
		call_argc = GPMIN(9, argc - 1);
		for (i=0; i<=call_argc; i++) {
		    /* Need to stash argv[i] somewhere visible to load_file() */
		    call_args[i] = gp_strdup(argv[i+1]);
		}

		load_file(loadpath_fopen(*argv, "r"), gp_strdup(*argv), 5);
		gp_exit(EXIT_SUCCESS);

	    } else if (*argv[0] == '-') {
		fprintf(stderr, "unrecognized option %s\n", *argv);
	    } else {
		interactive = FALSE;
		noinputfiles = FALSE;
		load_file(loadpath_fopen(*argv, "r"), gp_strdup(*argv), 4);
	    }
    }

    /* take commands from stdin */
    if (noinputfiles) {
	while (!com_line())
	    ctrlc_flag = FALSE; /* reset asynchronous Ctrl-C flag */
    }

#ifdef _WIN32
    /* On Windows, handle 'persist' by keeping the main input loop running (windows/wxt), */
    /* but only if there are any windows open. Note that qt handles this properly. */
    if (persist_cl) {
	if (WinAnyWindowOpen()) {
#ifdef WGP_CONSOLE
	    if (!interactive) {
		/* no further input from pipe */
		while (WinAnyWindowOpen())
		win_sleep(100);
	    } else
#endif
	    {
		interactive = TRUE;
		while (!com_line())
		    ctrlc_flag = FALSE; /* reset asynchronous Ctrl-C flag */
		interactive = FALSE;
	    }
	}
    }
#endif

#if (defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDITLINE)) && defined(GNUPLOT_HISTORY)
#if !defined(HAVE_ATEXIT) && !defined(HAVE_ON_EXIT)
    /* You should be here if you neither have 'atexit()' nor 'on_exit()' */
    wrapper_for_write_history();
#endif /* !HAVE_ATEXIT && !HAVE_ON_EXIT */
#endif /* (HAVE_LIBREADLINE || HAVE_LIBEDITLINE) && GNUPLOT_HISTORY */

#ifdef OS2
    RexxDeregisterSubcom("GNUPLOT", NULL);
#endif

    /* HBB 20040223: Not all compilers like exit() to end main() */
    /* exit(exit_status); */
#if ! defined(_WIN32)
    /* Windows does the cleanup later */
    gp_exit_cleanup();
#endif
    return exit_status;
}