DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T s

⟦e5ca77ecb⟧ TextFile

    Length: 45083 (0xb01b)
    Types: TextFile
    Names: »setshow.c«

Derivation

└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦63303ae94⟧ »unix3.14/TeX3.14.tar.Z« 
        └─⟦c58930e5c⟧ 
            └─⟦this⟧ »TeX3.14/TeXcontrib/gnuplot/setshow.c« 

TextFile

/* GNUPLOT - setshow.c */
/*
 * Copyright (C) 1986, 1987, 1990   Thomas Williams, Colin Kelley
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted, 
 * provided that the above copyright notice appear in all copies and 
 * that both that copyright notice and this permission notice appear 
 * in supporting documentation.
 *
 * Permission to modify the software is granted, but not the right to
 * distribute the modified code.  Modifications are to be distributed 
 * as patches to released version.
 *  
 * This software  is provided "as is" without express or implied warranty.
 * 
 *
 * AUTHORS
 * 
 *   Original Software:
 *     Thomas Williams,  Colin Kelley.
 * 
 *   Gnuplot 2.0 additions:
 *       Russell Lang, Dave Kotz, John Campbell.
 * 
 * send your comments or suggestions to (pixar!info-gnuplot@sun.com).
 * 
 */

#include <stdio.h>
#include <math.h>
#include "plot.h"
#include "setshow.h"

#define DEF_FORMAT   "%g"	/* default format for tic mark labels */
#define SIGNIF (0.01)		/* less than one hundredth of a tic mark */

/*
 * global variables to hold status of 'set' options
 *
 */
BOOLEAN			autoscale_t	= TRUE;
BOOLEAN			autoscale_x	= TRUE;
BOOLEAN			autoscale_y	= TRUE;
BOOLEAN			autoscale_lt	= TRUE;
BOOLEAN			autoscale_lx	= TRUE;
BOOLEAN			autoscale_ly	= TRUE;
BOOLEAN 	  	 	clip_points    = FALSE;
BOOLEAN 	  	 	clip_lines1    = TRUE;
BOOLEAN 	  	 	clip_lines2    = FALSE;
char			dummy_var[MAX_ID_LEN+1] = "x";
char			xformat[MAX_ID_LEN+1] = DEF_FORMAT;
char			yformat[MAX_ID_LEN+1] = DEF_FORMAT;
enum PLOT_STYLE data_style	= POINTS,
				func_style	= LINES;
BOOLEAN			grid		= FALSE;
int				key			= -1;	/* default position */
double			key_x, key_y;		/* user specified position for key */
BOOLEAN			log_x		= FALSE,
				log_y		= FALSE;
FILE*			outfile;
char			outstr[MAX_ID_LEN+1] = "STDOUT";
BOOLEAN			polar		= FALSE;
BOOLEAN			parametric	= FALSE;
int				samples		= SAMPLES;
float			xsize		= 1.0;  /* scale factor for size */
float			ysize		= 1.0;  /* scale factor for size */
int				term		= 0;				/* unknown term is 0 */
char			title[MAX_LINE_LEN+1] = "";
char			xlabel[MAX_LINE_LEN+1] = "";
char			ylabel[MAX_LINE_LEN+1] = "";
double			tmin		= -5.0,
				tmax		=  5.0,
				xmin		= -10.0,
				xmax		= 10.0,
				ymin		= -10.0,
				ymax		= 10.0;
double			loff		= 0.0,
				roff		= 0.0,
				toff		= 0.0,
				boff		= 0.0;
double			zero = ZERO;			/* zero threshold, not 0! */

BOOLEAN xzeroaxis = TRUE;
BOOLEAN yzeroaxis = TRUE;

BOOLEAN xtics = TRUE;
BOOLEAN ytics = TRUE;

struct ticdef xticdef = {TIC_COMPUTED};
struct ticdef yticdef = {TIC_COMPUTED};

BOOLEAN			tic_in		= TRUE;

struct text_label *first_label = NULL;
struct arrow_def *first_arrow = NULL;

/*** other things we need *****/
extern char *strcpy(),*strcat();
extern int strlen();
extern FILE *popen();

/* input data, parsing variables */
extern struct lexical_unit token[];
extern char input_line[];
extern int num_tokens, c_token;

extern char replot_line[];
extern struct udvt_entry *first_udv;

extern double magnitude(),real();
extern struct value *const_express();

/******** Local functions ********/
static void set_label();
static void set_nolabel();
static void set_arrow();
static void set_noarrow();
static void load_tics();
static void load_tic_user();
static void free_marklist();
static void load_tic_series();
static void load_offsets();

static void show_style(), show_range(), show_zero();
static void show_offsets(), show_output(), show_samples(), show_size();
static void show_title(), show_xlabel(), show_ylabel();
static void show_xzeroaxis(), show_yzeroaxis();
static void show_label(), show_arrow(), show_grid(), show_key();
static void show_polar(), show_parametric(), show_tics(), show_ticdef();
static void show_term(), show_plot(), show_autoscale(), show_clip();
static void show_format(), show_logscale(), show_variables();

static void delete_label();
static int assign_label_tag();
static void delete_arrow();
static int assign_arrow_tag();

/******** The 'set' command ********/
void
set_command()
{
     static char testfile[MAX_LINE_LEN+1];
#ifdef unix
     static BOOLEAN pipe_open = FALSE;
#endif

	c_token++;

	if (almost_equals(c_token,"ar$row")) {
		c_token++;
		set_arrow();
	}
	else if (almost_equals(c_token,"noar$row")) {
		c_token++;
		set_noarrow();
	}
     else if (almost_equals(c_token,"au$toscale")) {
	    c_token++;
	    if (END_OF_COMMAND) {
		   autoscale_t = autoscale_x = autoscale_y = TRUE;
	    } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
		   autoscale_x = autoscale_y = TRUE;
		   c_token++;
	    } else if (equals(c_token, "t")) {
		   autoscale_t = TRUE;
		   c_token++;
	    } else if (equals(c_token, "x")) {
		   autoscale_x = TRUE;
		   c_token++;
	    } else if (equals(c_token, "y")) {
		   autoscale_y = TRUE;
		   c_token++;
	    }
	} 
	else if (almost_equals(c_token,"noau$toscale")) {
	    c_token++;
	    if (END_OF_COMMAND) {
		   autoscale_t = autoscale_x = autoscale_y = FALSE;
	    } else if (equals(c_token, "xy") || equals(c_token, "tyx")) {
		   autoscale_x = autoscale_y = FALSE;
		   c_token++;
	    } else if (equals(c_token, "t")) {
		   autoscale_t = FALSE;
		   c_token++;
	    } else if (equals(c_token, "x")) {
		   autoscale_x = FALSE;
		   c_token++;
	    } else if (equals(c_token, "y")) {
		   autoscale_y = FALSE;
		   c_token++;
	    }
	} 
	else if (almost_equals(c_token,"c$lip")) {
	    c_token++;
	    if (END_OF_COMMAND)
		 /* assuming same as points */
		 clip_points = TRUE;
	    else if (almost_equals(c_token, "p$oints"))
		 clip_points = TRUE;
	    else if (almost_equals(c_token, "o$ne"))
		 clip_lines1 = TRUE;
	    else if (almost_equals(c_token, "t$wo"))
		 clip_lines2 = TRUE;
	    else
		 int_error("expecting 'points', 'one', or 'two'", c_token);
	    c_token++;
	}
	else if (almost_equals(c_token,"noc$lip")) {
	    c_token++;
	    if (END_OF_COMMAND) {
		   /* same as all three */
		   clip_points = FALSE;
		   clip_lines1 = FALSE;
		   clip_lines2 = FALSE;
	    } else if (almost_equals(c_token, "p$oints"))
		 clip_points = FALSE;
	    else if (almost_equals(c_token, "o$ne"))
		 clip_lines1 = FALSE;
	    else if (almost_equals(c_token, "t$wo"))
		 clip_lines2 = FALSE;
	    else
		 int_error("expecting 'points', 'one', or 'two'", c_token);
	    c_token++;
	}
	else if (almost_equals(c_token,"d$ata")) {
		c_token++;
		if (!almost_equals(c_token,"s$tyle"))
			int_error("expecting keyword 'style'",c_token);
		data_style = get_style();
	}
	else if (almost_equals(c_token,"d$ummy")) {
		c_token++;
		if (END_OF_COMMAND)
		    int_error("expecting dummy variable name", c_token);
		else
		    copy_str(dummy_var,c_token++);
	}
	else if (almost_equals(c_token,"fo$rmat")) {
		BOOLEAN setx, sety;
		c_token++;
		if (equals(c_token,"x")) {
			setx = TRUE; sety = FALSE;
			c_token++;
		}
		else if (equals(c_token,"y")) {
			setx = FALSE; sety = TRUE;
			c_token++;
		}
		else if (equals(c_token,"xy") || equals(c_token,"yx")) {
			setx = sety = TRUE;
			c_token++;
		}
		else if (isstring(c_token) || END_OF_COMMAND) {
			/* Assume he wants both */
			setx = sety = TRUE;
		}
		if (END_OF_COMMAND) {
			if (setx)
				(void) strcpy(xformat,DEF_FORMAT);
			if (sety)
				(void) strcpy(yformat,DEF_FORMAT);
		}
		else {
			if (!isstring(c_token))
			  int_error("expecting format string",c_token);
			else {
				if (setx)
				 quote_str(xformat,c_token);
				if (sety)
				 quote_str(yformat,c_token);
				c_token++;
			}
		}
	}
	else if (almost_equals(c_token,"fu$nction")) {
		c_token++;
		if (!almost_equals(c_token,"s$tyle"))
			int_error("expecting keyword 'style'",c_token);
		func_style = get_style();
	}
	else if (almost_equals(c_token,"la$bel")) {
		c_token++;
		set_label();
	}
	else if (almost_equals(c_token,"nola$bel")) {
		c_token++;
		set_nolabel();
	}
	else if (almost_equals(c_token,"lo$gscale")) {
		c_token++;
	    if (END_OF_COMMAND) {
		   log_x = log_y = TRUE;
	    } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
		   log_x = log_y = TRUE;
		   c_token++;
	    } else if (equals(c_token, "x")) {
		   log_x = TRUE;
		   c_token++;
	    } else if (equals(c_token, "y")) {
		   log_y = TRUE;
		   c_token++;
	    }
	}
	else if (almost_equals(c_token,"nolo$gscale")) {
		c_token++;
		if (END_OF_COMMAND) {
		   log_x = log_y = FALSE;
		} else if (equals(c_token, "xy") || equals(c_token, "yx")) {
		   log_x = log_y = FALSE;
		   c_token++;
		} else if (equals(c_token, "x")) {
		   log_x = FALSE;
		   c_token++;
		} else if (equals(c_token, "y")) {
		   log_y = FALSE;
		   c_token++;
		}
	} 
	else if (almost_equals(c_token,"of$fsets")) {
		c_token++;
		if (END_OF_COMMAND) {
			loff = roff = toff = boff = 0.0;  /* Reset offsets */
		}
		else {
			load_offsets (&loff,&roff,&toff,&boff);
		}
	}
	else if (almost_equals(c_token,"o$utput")) {
		register FILE *f;

		c_token++;
		if (term && term_init)
			(*term_tbl[term].reset)();
		if (END_OF_COMMAND) {	/* no file specified */
 			UP_redirect (4);
			if (outfile != stdout) { /* Never close stdout */
#ifdef unix
				if ( pipe_open ) {
					(void) pclose(outfile);
					pipe_open = FALSE;
				} else
#endif
					(void) fclose(outfile);
			}
			outfile = stdout; /* Don't dup... */
			term_init = FALSE;
			(void) strcpy(outstr,"STDOUT");
		} else if (!isstring(c_token))
			int_error("expecting filename",c_token);
		else {
			quote_str(testfile,c_token);
#ifdef unix
			if ( *testfile == '|' ) {
			  if ((f = popen(testfile+1,"w")) == (FILE *)NULL)
			    os_error("cannot create pipe; output not changed",c_token);
			  else
			    pipe_open = TRUE;
			} else
#endif
			  if ((f = fopen(testfile,"w")) == (FILE *)NULL)
			    os_error("cannot open file; output not changed",c_token);
			if (outfile != stdout) /* Never close stdout */
				(void) fclose(outfile);
			outfile = f;
			term_init = FALSE;
			outstr[0] = '\'';
			(void) strcat(strcpy(outstr+1,testfile),"'");
 			UP_redirect (1);
		}
		c_token++;
	}
	else if (almost_equals(c_token,"tit$le")) {
		c_token++;
		if (END_OF_COMMAND) {	/* no label specified */
			title[0] = '\0';
		} else {
		quotel_str(title,c_token);
		c_token++;
		}
	} 
	else if (almost_equals(c_token,"xl$abel")) {
		c_token++;
		if (END_OF_COMMAND) {	/* no label specified */
			xlabel[0] = '\0';
		} else {
		quotel_str(xlabel,c_token);
		c_token++;
		}
	} 
	else if (almost_equals(c_token,"yl$abel")) {
		c_token++;
		if (END_OF_COMMAND) {	/* no label specified */
			ylabel[0] = '\0';
		} else {
		quotel_str(ylabel,c_token);
		c_token++;
		}
	} 
	else if (almost_equals(c_token,"xzero$axis")) {
		c_token++;
		xzeroaxis = TRUE;
	} 
	else if (almost_equals(c_token,"yzero$axis")) {
		c_token++;
		yzeroaxis = TRUE;
	} 
	else if (almost_equals(c_token,"zeroa$xis")) {
		c_token++;
		yzeroaxis = TRUE;
		xzeroaxis = TRUE;
	} 
	else if (almost_equals(c_token,"noxzero$axis")) {
		c_token++;
		xzeroaxis = FALSE;
	} 
	else if (almost_equals(c_token,"noyzero$axis")) {
		c_token++;
		yzeroaxis = FALSE;
	} 
	else if (almost_equals(c_token,"nozero$axis")) {
		c_token++;
		xzeroaxis = FALSE;
		yzeroaxis = FALSE;
	} 
	else if (almost_equals(c_token,"par$ametric")) {
	    if (!parametric) {
		   parametric = TRUE;
		   strcpy (dummy_var, "t");
	  	   (void) fprintf(stderr,"\n\tdummy variable is %s\n",dummy_var);
	    }
	    c_token++;
	}
	else if (almost_equals(c_token,"nopar$ametric")) {
	    if (parametric) {
		   parametric = FALSE;
		   strcpy (dummy_var, "x");
	  	   (void) fprintf(stderr,"\n\tdummy variable is %s\n",dummy_var);
	    }
	    c_token++;
	}
	else if (almost_equals(c_token,"pol$ar")) {
	    if (!polar) {
			polar = TRUE;
			if (parametric) {
				tmin = 0.0;
				tmax = 2*Pi;
			} else {
				xmin = 0.0;
				xmax = 2*Pi;
			}
	    }
	    c_token++;
	}
	else if (almost_equals(c_token,"nopo$lar")) {
	    if (polar) {
			polar = FALSE;
			if (parametric) {
				tmin = -5.0;
				tmax = 5.0;
			} else {
				xmin = -10.0;
				xmax = 10.0;
			}
	    }
	    c_token++;
	}
	else if (almost_equals(c_token,"g$rid")) {
		grid = TRUE;
		c_token++;
	}
	else if (almost_equals(c_token,"nog$rid")) {
		grid = FALSE;
		c_token++;
	}
	else if (almost_equals(c_token,"k$ey")) {
		struct value a;
		c_token++;
		if (END_OF_COMMAND) {
			key = -1;
		} 
		else {
			key_x = real(const_express(&a));
			if (!equals(c_token,","))
				int_error("',' expected",c_token);
			c_token++;
			key_y = real(const_express(&a));
			key = 1;
		} 
	}
	else if (almost_equals(c_token,"nok$ey")) {
		key = 0;
		c_token++;
	}
	else if (almost_equals(c_token,"tic$s")) {
		tic_in = TRUE;
		c_token++;
		if (almost_equals(c_token,"i$n")) {
			tic_in = TRUE;
			c_token++;
		}
		else if (almost_equals(c_token,"o$ut")) {
			tic_in = FALSE;
			c_token++;
		}
	}
     else if (almost_equals(c_token,"xt$ics")) {
	    xtics = TRUE;
	    c_token++;
	    if (END_OF_COMMAND) { /* reset to default */
		   if (xticdef.type == TIC_USER) {
			  free_marklist(xticdef.def.user);
			  xticdef.def.user = NULL;
		   }
		   xticdef.type = TIC_COMPUTED;
	    }
	    else
		 load_tics(&xticdef);
	} 
     else if (almost_equals(c_token,"noxt$ics")) {
	    xtics = FALSE;
	    c_token++;
	} 
     else if (almost_equals(c_token,"yt$ics")) {
	    ytics = TRUE;
	    c_token++;
	    if (END_OF_COMMAND) { /* reset to default */
		   if (yticdef.type == TIC_USER) {
			  free_marklist(yticdef.def.user);
			  yticdef.def.user = NULL;
		   }
		   yticdef.type = TIC_COMPUTED;
	    }
	    else
		 load_tics(&yticdef);
	} 
     else if (almost_equals(c_token,"noyt$ics")) {
	    ytics = FALSE;
	    c_token++;
	} 
	else if (almost_equals(c_token,"sa$mples")) {
		register int tsamp;
		struct value a;

		c_token++;
		tsamp = (int)magnitude(const_express(&a));
		if (tsamp < 1)
			int_error("sampling rate must be > 0; sampling unchanged",
				c_token);
		else {
		     extern struct curve_points *first_plot;
			register struct curve_points *f_p = first_plot;

			first_plot = NULL;
			cp_free(f_p);
			samples = tsamp;
		}
	}
	else if (almost_equals(c_token,"si$ze")) {
		struct value s;
		c_token++;
		if (END_OF_COMMAND) {
			xsize = 1.0;
			ysize = 1.0;
		} 
		else {
				xsize=real(const_express(&s));
				if (!equals(c_token,","))
					int_error("',' expected",c_token);
				c_token++;
				ysize=real(const_express(&s));
		} 
	} 
	else if (almost_equals(c_token,"t$erminal")) {
		c_token++;
		if (END_OF_COMMAND) {
			list_terms();
			screen_ok = FALSE;
		}
		else {
			if (term && term_init) {
				(*term_tbl[term].reset)();
				(void) fflush(outfile);
			}
			term = set_term(c_token);
			c_token++;
		}
	}
	else if (almost_equals(c_token,"tr$ange")) {
	     BOOLEAN changed;
		c_token++;
		if (!equals(c_token,"["))
			int_error("expecting '['",c_token);
		c_token++;
		changed = load_range(&tmin,&tmax);
		if (!equals(c_token,"]"))
		  int_error("expecting ']'",c_token);
		c_token++;
		if (changed)
		  autoscale_t = FALSE;
	}
	else if (almost_equals(c_token,"xr$ange")) {
	     BOOLEAN changed;
		c_token++;
		if (!equals(c_token,"["))
			int_error("expecting '['",c_token);
		c_token++;
		changed = load_range(&xmin,&xmax);
		if (!equals(c_token,"]"))
		  int_error("expecting ']'",c_token);
		c_token++;
		if (changed)
		  autoscale_x = FALSE;
	}
	else if (almost_equals(c_token,"yr$ange")) {
	     BOOLEAN changed;
		c_token++;
		if (!equals(c_token,"["))
			int_error("expecting '['",c_token);
		c_token++;
		changed = load_range(&ymin,&ymax);
		if (!equals(c_token,"]"))
		  int_error("expecting ']'",c_token);
		c_token++;
		if (changed)
		  autoscale_y = FALSE;
	}
	else if (almost_equals(c_token,"z$ero")) {
		struct value a;
		c_token++;
		zero = magnitude(const_express(&a));
	}
	else
		int_error(
	"valid set options:  '{no}arrow', {no}autoscale', '{no}clip', data', \n\
	'dummy', 'format', 'function', '{no}grid', '{no}key', '{no}label', \n\
	'{no}logscale','offsets', 'output', '{no}parametric', '{no}polar', \n\
        'samples', 'size', 'terminal', 'tics', 'title', 'xlabel', 'xrange', \n\
        'xtics', '{no}xzeroaxis', 'ylabel', 'yrange', 'ytics', \n\
	'{no}yzeroaxis','zero','zeroaxis'", c_token);
}

/*********** Support functions for set_command ***********/

/* process a 'set label' command */
/* set label {tag} {label_text} {at x,y} {pos} */
static void
set_label()
{
    struct value a;
    struct text_label *this_label = NULL;
    struct text_label *new_label = NULL;
    struct text_label *prev_label = NULL;
    double x, y;
    char text[MAX_LINE_LEN+1];
    enum JUSTIFY just;
    int tag;
    BOOLEAN set_text, set_position, set_just;

    /* get tag */
    if (!END_OF_COMMAND 
	   && !isstring(c_token) 
	   && !equals(c_token, "at")
	   && !equals(c_token, "left")
	   && !equals(c_token, "center")
	   && !equals(c_token, "centre")
	   && !equals(c_token, "right")) {
	   /* must be a tag expression! */
	   tag = (int)real(const_express(&a));
	   if (tag <= 0)
		int_error("tag must be > zero", c_token);
    } else
	 tag = assign_label_tag(); /* default next tag */
	 
    /* get text */
    if (!END_OF_COMMAND && isstring(c_token)) {
	   /* get text */
	   quotel_str(text, c_token);
	   c_token++;
	   set_text = TRUE;
    } else {
	   text[0] = '\0';		/* default no text */
	   set_text = FALSE;
    }
	 
    /* get justification - what the heck, let him put it here */
    if (!END_OF_COMMAND && !equals(c_token, "at")) {
	   if (almost_equals(c_token,"l$eft")) {
		  just = LEFT;
	   }
	   else if (almost_equals(c_token,"c$entre")
			  || almost_equals(c_token,"c$enter")) {
		  just = CENTRE;
	   }
	   else if (almost_equals(c_token,"r$ight")) {
		  just = RIGHT;
	   }
	   else
		int_error("bad syntax in set label", c_token);
	   c_token++;
	   set_just = TRUE;
    } else {
	   just = LEFT;			/* default left justified */
	   set_just = FALSE;
    } 

    /* get position */
    if (!END_OF_COMMAND && equals(c_token, "at")) {
	   c_token++;
	   if (END_OF_COMMAND)
		int_error("coordinates expected", c_token);
	   /* get coordinates */
	   x = real(const_express(&a));
	   if (!equals(c_token,","))
		int_error("',' expected",c_token);
	   c_token++;
	   y = real(const_express(&a));
	   set_position = TRUE;
    } else {
	   x = y = 0;			/* default at origin */
	   set_position = FALSE;
    }

    /* get justification */
    if (!END_OF_COMMAND) {
	   if (set_just)
		int_error("only one justification is allowed", c_token);
	   if (almost_equals(c_token,"l$eft")) {
		  just = LEFT;
	   }
	   else if (almost_equals(c_token,"c$entre")
			  || almost_equals(c_token,"c$enter")) {
		  just = CENTRE;
	   }
	   else if (almost_equals(c_token,"r$ight")) {
		  just = RIGHT;
	   }
	   else
		int_error("bad syntax in set label", c_token);
	   c_token++;
	   set_just = TRUE;
    } 

    if (!END_OF_COMMAND)
	 int_error("extraneous or out-of-order arguments in set label", c_token);

    /* OK! add label */
    if (first_label != NULL) { /* skip to last label */
	   for (this_label = first_label; this_label != NULL ; 
		   prev_label = this_label, this_label = this_label->next)
		/* is this the label we want? */
		if (tag <= this_label->tag)
		  break;
    }
    if (this_label != NULL && tag == this_label->tag) {
	   /* changing the label */
	   if (set_position) {
		  this_label->x = x;
		  this_label->y = y;
	   }
	   if (set_text)
		(void) strcpy(this_label->text, text);
	   if (set_just)
		this_label->pos = just;
    } else {
	   /* adding the label */
	   new_label = (struct text_label *) 
		alloc ( (unsigned int) sizeof(struct text_label), "label");
	   if (prev_label != NULL)
		prev_label->next = new_label; /* add it to end of list */
	   else 
		first_label = new_label; /* make it start of list */
	   new_label->tag = tag;
	   new_label->next = this_label;
	   new_label->x = x;
	   new_label->y = y;
	   (void) strcpy(new_label->text, text);
	   new_label->pos = just;
    }
}

/* process 'set nolabel' command */
/* set nolabel {tag} */
static void
set_nolabel()
{
    struct value a;
    struct text_label *this_label;
    struct text_label *prev_label; 
    int tag;

    if (END_OF_COMMAND) {
	   /* delete all labels */
	   while (first_label != NULL)
		delete_label((struct text_label *)NULL,first_label);
    }
    else {
	   /* get tag */
	   tag = (int)real(const_express(&a));
	   if (!END_OF_COMMAND)
		int_error("extraneous arguments to set nolabel", c_token);
	   for (this_label = first_label, prev_label = NULL;
		   this_label != NULL;
		   prev_label = this_label, this_label = this_label->next) {
		  if (this_label->tag == tag) {
			 delete_label(prev_label,this_label);
			 return;		/* exit, our job is done */
		  }
	   }
	   int_error("label not found", c_token);
    }
}

/* assign a new label tag */
/* labels are kept sorted by tag number, so this is easy */
static int				/* the lowest unassigned tag number */
assign_label_tag()
{
    struct text_label *this_label;
    int last = 0;			/* previous tag value */

    for (this_label = first_label; this_label != NULL;
	    this_label = this_label->next)
	 if (this_label->tag == last+1)
	   last++;
	 else
	   break;
    
    return (last+1);
}

/* delete label from linked list started by first_label.
 * called with pointers to the previous label (prev) and the 
 * label to delete (this).
 * If there is no previous label (the label to delete is
 * first_label) then call with prev = NULL.
 */
static void
delete_label(prev,this)
	struct text_label *prev, *this;
{
    if (this!=NULL)	{		/* there really is something to delete */
	   if (prev!=NULL)		/* there is a previous label */
		prev->next = this->next; 
	   else				/* this = first_label so change first_label */
		first_label = this->next;
	   free((char *)this);
    }
}


/* process a 'set arrow' command */
/* set arrow {tag} {from x,y} {to x,y} */
static void
set_arrow()
{
    struct value a;
    struct arrow_def *this_arrow = NULL;
    struct arrow_def *new_arrow = NULL;
    struct arrow_def *prev_arrow = NULL;
    double sx, sy;
    double ex, ey;
    int tag;
    BOOLEAN set_start, set_end;

    /* get tag */
    if (!END_OF_COMMAND 
	   && !equals(c_token, "from")
	   && !equals(c_token, "to")) {
	   /* must be a tag expression! */
	   tag = (int)real(const_express(&a));
	   if (tag <= 0)
		int_error("tag must be > zero", c_token);
    } else
	 tag = assign_arrow_tag(); /* default next tag */
	 
    /* get start position */
    if (!END_OF_COMMAND && equals(c_token, "from")) {
	   c_token++;
	   if (END_OF_COMMAND)
		int_error("start coordinates expected", c_token);
	   /* get coordinates */
	   sx = real(const_express(&a));
	   if (!equals(c_token,","))
		int_error("',' expected",c_token);
	   c_token++;
	   sy = real(const_express(&a));
	   set_start = TRUE;
    } else {
	   sx = sy = 0;			/* default at origin */
	   set_start = FALSE;
    }

    /* get end position */
    if (!END_OF_COMMAND && equals(c_token, "to")) {
	   c_token++;
	   if (END_OF_COMMAND)
		int_error("end coordinates expected", c_token);
	   /* get coordinates */
	   ex = real(const_express(&a));
	   if (!equals(c_token,","))
		int_error("',' expected",c_token);
	   c_token++;
	   ey = real(const_express(&a));
	   set_end = TRUE;
    } else {
	   ex = ey = 0;			/* default at origin */
	   set_end = FALSE;
    }

    /* get start position - what the heck, either order is ok */
    if (!END_OF_COMMAND && equals(c_token, "from")) {
	   if (set_start)
		int_error("only one 'from' is allowed", c_token);
	   c_token++;
	   if (END_OF_COMMAND)
		int_error("start coordinates expected", c_token);
	   /* get coordinates */
	   sx = real(const_express(&a));
	   if (!equals(c_token,","))
		int_error("',' expected",c_token);
	   c_token++;
	   sy = real(const_express(&a));
	   set_start = TRUE;
    }

    if (!END_OF_COMMAND)
	 int_error("extraneous or out-of-order arguments in set arrow", c_token);

    /* OK! add arrow */
    if (first_arrow != NULL) { /* skip to last arrow */
	   for (this_arrow = first_arrow; this_arrow != NULL ; 
		   prev_arrow = this_arrow, this_arrow = this_arrow->next)
		/* is this the arrow we want? */
		if (tag <= this_arrow->tag)
		  break;
    }
    if (this_arrow != NULL && tag == this_arrow->tag) {
	   /* changing the arrow */
	   if (set_start) {
		  this_arrow->sx = sx;
		  this_arrow->sy = sy;
	   }
	   if (set_end) {
		  this_arrow->ex = ex;
		  this_arrow->ey = ey;
	   }
    } else {
	   /* adding the arrow */
	   new_arrow = (struct arrow_def *) 
		alloc ( (unsigned int) sizeof(struct arrow_def), "arrow");
	   if (prev_arrow != NULL)
		prev_arrow->next = new_arrow; /* add it to end of list */
	   else 
		first_arrow = new_arrow; /* make it start of list */
	   new_arrow->tag = tag;
	   new_arrow->next = this_arrow;
	   new_arrow->sx = sx;
	   new_arrow->sy = sy;
	   new_arrow->ex = ex;
	   new_arrow->ey = ey;
    }
}

/* process 'set noarrow' command */
/* set noarrow {tag} */
static void
set_noarrow()
{
    struct value a;
    struct arrow_def *this_arrow;
    struct arrow_def *prev_arrow; 
    int tag;

    if (END_OF_COMMAND) {
	   /* delete all arrows */
	   while (first_arrow != NULL)
		delete_arrow((struct arrow_def *)NULL,first_arrow);
    }
    else {
	   /* get tag */
	   tag = (int)real(const_express(&a));
	   if (!END_OF_COMMAND)
		int_error("extraneous arguments to set noarrow", c_token);
	   for (this_arrow = first_arrow, prev_arrow = NULL;
		   this_arrow != NULL;
		   prev_arrow = this_arrow, this_arrow = this_arrow->next) {
		  if (this_arrow->tag == tag) {
			 delete_arrow(prev_arrow,this_arrow);
			 return;		/* exit, our job is done */
		  }
	   }
	   int_error("arrow not found", c_token);
    }
}

/* assign a new arrow tag */
/* arrows are kept sorted by tag number, so this is easy */
static int				/* the lowest unassigned tag number */
assign_arrow_tag()
{
    struct arrow_def *this_arrow;
    int last = 0;			/* previous tag value */

    for (this_arrow = first_arrow; this_arrow != NULL;
	    this_arrow = this_arrow->next)
	 if (this_arrow->tag == last+1)
	   last++;
	 else
	   break;

    return (last+1);
}

/* delete arrow from linked list started by first_arrow.
 * called with pointers to the previous arrow (prev) and the 
 * arrow to delete (this).
 * If there is no previous arrow (the arrow to delete is
 * first_arrow) then call with prev = NULL.
 */
static void
delete_arrow(prev,this)
	struct arrow_def *prev, *this;
{
    if (this!=NULL)	{		/* there really is something to delete */
	   if (prev!=NULL)		/* there is a previous arrow */
		prev->next = this->next; 
	   else				/* this = first_arrow so change first_arrow */
		first_arrow = this->next;
	   free((char *)this);
    }
}


enum PLOT_STYLE			/* not static; used by command.c */
get_style()
{
register enum PLOT_STYLE ps;

	c_token++;
	if (almost_equals(c_token,"l$ines"))
		ps = LINES;
	else if (almost_equals(c_token,"i$mpulses"))
		ps = IMPULSES;
	else if (almost_equals(c_token,"p$oints"))
		ps = POINTS;
	else if (almost_equals(c_token,"linesp$oints"))
		ps = LINESPOINTS;
	else if (almost_equals(c_token,"d$ots"))
		ps = DOTS;
	else
		int_error("expecting 'lines', 'points', 'linespoints', 'dots', or 'impulses'",c_token);
	c_token++;
	return(ps);
}

/* For set [xy]tics... command*/
static void
load_tics(tdef)
	struct ticdef *tdef;	/* change this ticdef */
{
    if (equals(c_token,"(")) { /* set : TIC_USER */
	   c_token++;
	   load_tic_user(tdef);
    } else {				/* series : TIC_SERIES */
	   load_tic_series(tdef);
    }
}

/* load TIC_USER definition */
/* (tic[,tic]...)
 * where tic is ["string"] value
 * Left paren is already scanned off before entry.
 */
static void
load_tic_user(tdef)
	struct ticdef *tdef;
{
    struct ticmark *list = NULL; /* start of list */
    struct ticmark *last = NULL; /* end of list */
    struct ticmark *tic = NULL; /* new ticmark */
    char temp_string[MAX_LINE_LEN];
    struct value a;

    while (!END_OF_COMMAND) {
	   /* parse a new ticmark */
	   tic = (struct ticmark *)alloc(sizeof(struct ticmark), (char *)NULL);
	   if (tic == (struct ticmark *)NULL) {
		  free_marklist(list);
		  int_error("out of memory for tic mark", c_token);
	   }

	   /* has a string with it? */
	   if (isstring(c_token)) {
		  quote_str(temp_string,c_token);
		  tic->label = alloc((unsigned int)strlen(temp_string)+1, "tic label");
		  (void) strcpy(tic->label, temp_string);
		  c_token++;
	   } else
		tic->label = NULL;

	   /* in any case get the value */
	   tic->position = real(const_express(&a));
	   tic->next = NULL;

	   /* append to list */
	   if (list == NULL)
		last = list = tic;	/* new list */
	   else {				/* append to list */
		  last->next = tic;
		  last = tic;
	   }

	   /* expect "," or ")" here */
	   if (!END_OF_COMMAND && equals(c_token, ","))
		c_token++;		/* loop again */
	   else
		break;			/* hopefully ")" */
    }
    
    if (END_OF_COMMAND || !equals(c_token, ")")) {
	   free_marklist(list);
	   int_error("expecting right parenthesis )", c_token);
    }
    c_token++;
    
    /* successful list */
    if (tdef->type == TIC_USER) {
	   /* remove old list */
		/* VAX Optimiser was stuffing up following line. Turn Optimiser OFF */
	   free_marklist(tdef->def.user);
	   tdef->def.user = NULL;
    }
    tdef->type = TIC_USER;
    tdef->def.user = list;
}

static void
free_marklist(list)
	struct ticmark *list;
{
    register struct ticmark *freeable;

    while (list != NULL) {
	   freeable = list;
	   list = list->next;
	   if (freeable->label != NULL)
		free( (char *)freeable->label );
	   free( (char *)freeable );
    }
}

/* load TIC_SERIES definition */
/* start,incr[,end] */
static void
load_tic_series(tdef)
	struct ticdef *tdef;
{
    double start, incr, end;
    struct value a;
    int incr_token;

    start = real(const_express(&a));
    if (!equals(c_token, ","))
	 int_error("expecting comma to separate start,incr", c_token);
    c_token++;

    incr_token = c_token;
    incr = real(const_express(&a));

    if (END_OF_COMMAND)
	 end = VERYLARGE;
    else {
	   if (!equals(c_token, ","))
		int_error("expecting comma to separate incr,end", c_token);
	   c_token++;

	   end = real(const_express(&a));
    }
    if (!END_OF_COMMAND)
	 int_error("tic series is defined by start,increment[,end]", 
			 c_token);
    
    if (start < end && incr <= 0)
	 int_error("increment must be positive", incr_token);
    if (start > end && incr >= 0)
	 int_error("increment must be negative", incr_token);
    if (start > end) {
	   /* put in order */
		double numtics;
		numtics = floor( (end*(1+SIGNIF) - start)/incr );
		end = start;
		start = end + numtics*incr;
		incr = -incr;
/*
	   double temp = start;
	   start = end;
	   end = temp;
	   incr = -incr;
 */
    }

    if (tdef->type == TIC_USER) {
	   /* remove old list */
		/* VAX Optimiser was stuffing up following line. Turn Optimiser OFF */
	   free_marklist(tdef->def.user);
	   tdef->def.user = NULL;
    }
    tdef->type = TIC_SERIES;
    tdef->def.series.start = start;
    tdef->def.series.incr = incr;
    tdef->def.series.end = end;
}

static void
load_offsets (a, b, c, d)
double *a,*b, *c, *d;
{
struct value t;

	*a = real (const_express(&t));  /* loff value */
	c_token++;
	if (equals(c_token,","))
		c_token++;
	if (END_OF_COMMAND) 
	    return;

	*b = real (const_express(&t));  /* roff value */
	c_token++;
	if (equals(c_token,","))
		c_token++;
	if (END_OF_COMMAND) 
	    return;

	*c = real (const_express(&t));  /* toff value */
	c_token++;
	if (equals(c_token,","))
		c_token++;
	if (END_OF_COMMAND) 
	    return;

	*d = real (const_express(&t));  /* boff value */
	c_token++;
}


BOOLEAN					/* TRUE if a or b were changed */
load_range(a,b)			/* also used by command.c */
double *a,*b;
{
struct value t;
BOOLEAN changed = FALSE;

	if (equals(c_token,"]"))
		return(FALSE);
	if (END_OF_COMMAND) {
	    int_error("starting range value or ':' or 'to' expected",c_token);
	} else if (!equals(c_token,"to") && !equals(c_token,":"))  {
		*a = real(const_express(&t));
		changed = TRUE;
	}	
	if (!equals(c_token,"to") && !equals(c_token,":"))
		int_error("':' or keyword 'to' expected",c_token);
	c_token++;
	if (!equals(c_token,"]")) {
		*b = real(const_express(&t));
		changed = TRUE;
	 }
     return(changed);
}



/******* The 'show' command *******/
void
show_command()
{
    c_token++;

	if (almost_equals(c_token,"ac$tion_table") ||
			 equals(c_token,"at") ) {
		c_token++; 
		show_at();
		c_token++;
	}
	else if (almost_equals(c_token,"ar$row")) {
	    struct value a;
	    int tag = 0;

	    c_token++;
	    if (!END_OF_COMMAND) {
		   tag = (int)real(const_express(&a));
		   if (tag <= 0)
			int_error("tag must be > zero", c_token);
	    }

	    (void) putc('\n',stderr);
	    show_arrow(tag);
	}
	else if (almost_equals(c_token,"au$toscale")) {
		(void) putc('\n',stderr);
		show_autoscale();
		c_token++;
	}
	else if (almost_equals(c_token,"c$lip")) {
		(void) putc('\n',stderr);
		show_clip();
		c_token++;
	}
	else if (almost_equals(c_token,"d$ata")) {
		c_token++;
		if (!almost_equals(c_token,"s$tyle"))
			int_error("expecting keyword 'style'",c_token);
		(void) putc('\n',stderr);
		show_style("data",data_style);
		c_token++;
	}
	else if (almost_equals(c_token,"d$ummy")) {
		(void) fprintf(stderr,"\n\tdummy variable is %s\n",dummy_var);
		c_token++;
	}
	else if (almost_equals(c_token,"fo$rmat")) {
		show_format();
		c_token++;
	}
	else if (almost_equals(c_token,"f$unctions")) {
		c_token++;
		if (almost_equals(c_token,"s$tyle"))  {
			(void) putc('\n',stderr);
			show_style("functions",func_style);
			c_token++;
		}
		else
			show_functions();
	}
	else if (almost_equals(c_token,"lo$gscale")) {
		(void) putc('\n',stderr);
		show_logscale();
		c_token++;
	}
	else if (almost_equals(c_token,"of$fsets")) {
		(void) putc('\n',stderr);
		show_offsets();
		c_token++;
	}
	else if (almost_equals(c_token,"o$utput")) {
		(void) putc('\n',stderr);
		show_output();
		c_token++;
	}
	else if (almost_equals(c_token,"tit$le")) {
		(void) putc('\n',stderr);
		show_title();
		c_token++;
	}
	else if (almost_equals(c_token,"xl$abel")) {
		(void) putc('\n',stderr);
		show_xlabel();
		c_token++;
	}
	else if (almost_equals(c_token,"yl$abel")) {
		(void) putc('\n',stderr);
		show_ylabel();
		c_token++;
	}
	else if (almost_equals(c_token,"xzero$axis")) {
		(void) putc('\n',stderr);
		show_xzeroaxis();
		c_token++;
	}
	else if (almost_equals(c_token,"yzero$axis")) {
		(void) putc('\n',stderr);
		show_yzeroaxis();
		c_token++;
	}
	else if (almost_equals(c_token,"zeroa$xis")) {
		(void) putc('\n',stderr);
		show_xzeroaxis();
		show_yzeroaxis();
		c_token++;
	}
	else if (almost_equals(c_token,"la$bel")) {
	    struct value a;
	    int tag = 0;

	    c_token++;
	    if (!END_OF_COMMAND) {
		   tag = (int)real(const_express(&a));
		   if (tag <= 0)
			int_error("tag must be > zero", c_token);
	    }

	    (void) putc('\n',stderr);
	    show_label(tag);
	}
	else if (almost_equals(c_token,"g$rid")) {
		(void) putc('\n',stderr);
		show_grid();
		c_token++;
	}
	else if (almost_equals(c_token,"k$ey")) {
		(void) putc('\n',stderr);
		show_key();
		c_token++;
	}
	else if (almost_equals(c_token,"p$lot")) {
		(void) putc('\n',stderr);
		show_plot();
		c_token++;
	}
	else if (almost_equals(c_token,"par$ametric")) {
		(void) putc('\n',stderr);
		show_parametric();
		c_token++;
	}
	else if (almost_equals(c_token,"pol$ar")) {
		(void) putc('\n',stderr);
		show_polar();
		c_token++;
	}
	else if (almost_equals(c_token,"ti$cs")) {
		(void) putc('\n',stderr);
		show_tics(TRUE, TRUE);
		c_token++;
	}
	else if (almost_equals(c_token,"xti$cs")) {
	    show_tics(TRUE, FALSE);
	    c_token++;
	}
	else if (almost_equals(c_token,"yti$cs")) {
	    show_tics(FALSE, TRUE);
	    c_token++;
	}
	else if (almost_equals(c_token,"sa$mples")) {
		(void) putc('\n',stderr);
		show_samples();
		c_token++;
	}
	else if (almost_equals(c_token,"si$ze")) {
		(void) putc('\n',stderr);
		show_size();
		c_token++;
	}
	else if (almost_equals(c_token,"t$erminal")) {
		(void) putc('\n',stderr);
		show_term();
		c_token++;
	}
	else if (almost_equals(c_token,"tr$ange")) {
		(void) putc('\n',stderr);
		show_range('t',tmin,tmax);
		c_token++;
	}
	else if (almost_equals(c_token,"v$ariables")) {
		show_variables();
		c_token++;
	}
	else if (almost_equals(c_token,"ve$rsion")) {
		show_version();
		c_token++;
	}
	else if (almost_equals(c_token,"xr$ange")) {
		(void) putc('\n',stderr);
		show_range('x',xmin,xmax);
		c_token++;
	}
	else if (almost_equals(c_token,"yr$ange")) {
		(void) putc('\n',stderr);
		show_range('y',ymin,ymax);
		c_token++;
	}
	else if (almost_equals(c_token,"z$ero")) {
		(void) putc('\n',stderr);
		show_zero();
		c_token++;
	}
	else if (almost_equals(c_token,"a$ll")) {
		c_token++;
		show_version();
		show_autoscale();
		show_clip();
		(void) fprintf(stderr,"\tdummy variable is %s\n",dummy_var);
		show_format();
		show_style("data",data_style);
		show_style("functions",func_style);
		show_grid();
		show_label(0);
		show_arrow(0);
		show_key();
		show_logscale();
		show_offsets();
		show_output();
		show_parametric();
		show_polar();
		show_samples();
		show_size();
		show_term();
		show_tics(TRUE,TRUE);
		if (parametric)
			show_range('t',tmin,tmax);
		show_range('x',xmin,xmax);
		show_range('y',ymin,ymax);
		show_title();
		show_xlabel();
		show_ylabel();
		show_zero();
		show_plot();
		show_variables();
		show_functions();
		c_token++;
	}
	else
		int_error(
	"valid show options:  'action_table', 'all', 'arrow', 'autoscale',  \n\
	'clip', 'data', 'dummy', 'format', 'function', 'grid', 'key', 'label', \n\
	'logscale', 'offsets', 'output', 'plot', 'parametric','polar', \n\
	'samples', 'size', 'terminal', 'tics', 'title', 'trange', 'variables', \n\
	'version', 'xlabel', 'xrange', 'xtics', 'xzeroaxis', 'ylabel', \n\
	'yrange', 'ytics', 'yzeroaxis', 'zero','zeroaxis'", c_token);
	screen_ok = FALSE;
	(void) putc('\n',stderr);
}


/*********** support functions for 'show'  **********/
static void
show_style(name,style)
char name[];
enum PLOT_STYLE style;
{
	fprintf(stderr,"\t%s are plotted with ",name);
	switch (style) {
		case LINES: fprintf(stderr,"lines\n"); break;
		case POINTS: fprintf(stderr,"points\n"); break;
		case IMPULSES: fprintf(stderr,"impulses\n"); break;
		case LINESPOINTS: fprintf(stderr,"linespoints\n"); break;
		case DOTS: fprintf(stderr,"dots\n"); break;
	}
}

static void
show_range(name,min,max)
char name;
double min,max;
{
	fprintf(stderr,"\t%crange is [%g : %g]\n",name,min,max);
}

static void
show_zero()
{
	fprintf(stderr,"\tzero is %g\n",zero);
}

static void
show_offsets()
{
	fprintf(stderr,"\toffsets are %g, %g, %g, %g\n",loff,roff,toff,boff);
}

static void
show_output()
{
	fprintf(stderr,"\toutput is sent to %s\n",outstr);
}

static void
show_samples()
{
	fprintf(stderr,"\tsampling rate is %d\n",samples);
}

static void
show_size()
{
	fprintf(stderr,"\tsize is scaled by %g,%g\n",xsize,ysize);
}

static void
show_title()
{
	fprintf(stderr,"\ttitle is \"%s\"\n",title);
}

static void
show_xlabel()
{
	fprintf(stderr,"\txlabel is \"%s\"\n",xlabel);
}

static void
show_ylabel()
{
	fprintf(stderr,"\tylabel is \"%s\"\n",ylabel);
}

static void
show_xzeroaxis()
{
	fprintf(stderr,"\txzeroaxis is %s\n",(xzeroaxis)? "ON" : "OFF");
}

static void
show_yzeroaxis()
{
	fprintf(stderr,"\tyzeroaxis is %s\n",(yzeroaxis)? "ON" : "OFF");
}

static void
show_label(tag)
    int tag;				/* 0 means show all */
{
    struct text_label *this_label;
    BOOLEAN showed = FALSE;

    for (this_label = first_label; this_label != NULL;
	    this_label = this_label->next) {
	   if (tag == 0 || tag == this_label->tag) {
		  showed = TRUE;
		  fprintf(stderr,"\tlabel %d \"%s\" at %g,%g ",
				this_label->tag, this_label->text, 
				this_label->x, this_label->y);
		  switch(this_label->pos) {
			 case LEFT : {
				fprintf(stderr,"left");
				break;
			 }
			 case CENTRE : {
				fprintf(stderr,"centre");
				break;
			 }
			 case RIGHT : {
				fprintf(stderr,"right");
				break;
			 }
		  }
		  fputc('\n',stderr);
	   }
    }
    if (tag > 0 && !showed)
	 int_error("label not found", c_token);
}

static void
show_arrow(tag)
    int tag;				/* 0 means show all */
{
    struct arrow_def *this_arrow;
    BOOLEAN showed = FALSE;

    for (this_arrow = first_arrow; this_arrow != NULL;
	    this_arrow = this_arrow->next) {
	   if (tag == 0 || tag == this_arrow->tag) {
		  showed = TRUE;
		  fprintf(stderr,"\tarrow %d from %g,%g to %g,%g\n",
				this_arrow->tag, 
				this_arrow->sx, this_arrow->sy,
				this_arrow->ex, this_arrow->ey);
	   }
    }
    if (tag > 0 && !showed)
	 int_error("arrow not found", c_token);
}

static void
show_grid()
{
	fprintf(stderr,"\tgrid is %s\n",(grid)? "ON" : "OFF");
}

static void
show_key()
{
	switch (key) {
		case -1 : 
			fprintf(stderr,"\tkey is ON\n");
			break;
		case 0 :
			fprintf(stderr,"\tkey is OFF\n");
			break;
		case 1 :
			fprintf(stderr,"\tkey is at %g,%g\n",key_x,key_y);
			break;
	}
}

static void
show_parametric()
{
	fprintf(stderr,"\tparametric is %s\n",(parametric)? "ON" : "OFF");
}

static void
show_polar()
{
	fprintf(stderr,"\tpolar is %s\n",(polar)? "ON" : "OFF");
}

static void
show_tics(showx, showy)
	BOOLEAN showx, showy;
{
    fprintf(stderr,"\ttics are %s\n",(tic_in)? "IN" : "OUT");

    if (showx)
	 show_ticdef(xtics, 'x', &xticdef);
    if (showy)
	 show_ticdef(ytics, 'y', &yticdef);
    screen_ok = FALSE;
}

/* called by show_tics */
static void
show_ticdef(tics, axis, tdef)
	BOOLEAN tics;			/* xtics or ytics */
	char axis;			/* 'x' or 'y' */
	struct ticdef *tdef;	/* xticdef or yticdef */
{
    register struct ticmark *t;

    fprintf(stderr, "\t%c-axis tic labelling is ", axis);
    if (!tics) {
	   fprintf(stderr, "OFF\n");
	   return;
    }

    switch(tdef->type) {
	   case TIC_COMPUTED: {
		  fprintf(stderr, "computed automatically\n");
		  break;
	   }
	   case TIC_SERIES: {
		  if (tdef->def.series.end == VERYLARGE)
		    fprintf(stderr, "series from %g by %g\n", 
				  tdef->def.series.start, tdef->def.series.incr);
		  else
		    fprintf(stderr, "series from %g by %g until %g\n", 
				  tdef->def.series.start, tdef->def.series.incr, 
				  tdef->def.series.end);
		  break;
	   }
	   case TIC_USER: {
		  fprintf(stderr, "list (");
		  for (t = tdef->def.user; t != NULL; t=t->next) {
			 if (t->label)
			   fprintf(stderr, "\"%s\" ", t->label);
			 if (t->next)
			   fprintf(stderr, "%g, ", t->position);
			 else
			   fprintf(stderr, "%g", t->position);
		  }
		  fprintf(stderr, ")\n");
		  break;
	   }
	   default: {
		  int_error("unknown ticdef type in show_ticdef()", NO_CARET);
		  /* NOTREACHED */
	   }
    }
}

static void
show_term()
{
	fprintf(stderr,"\tterminal type is %s\n",term_tbl[term].name);
}

static void
show_plot()
{
	fprintf(stderr,"\tlast plot command was: %s\n",replot_line);
}

static void
show_autoscale()
{
	if (parametric)
		fprintf(stderr,"\tt autoscaling is %s\n",(autoscale_t)? "ON" : "OFF");
	fprintf(stderr,"\tx autoscaling is %s\n",(autoscale_x)? "ON" : "OFF");
	fprintf(stderr,"\ty autoscaling is %s\n",(autoscale_y)? "ON" : "OFF");
}

static void
show_clip()
{
	fprintf(stderr,"\tpoint clip is %s\n",(clip_points)? "ON" : "OFF");

	if (clip_lines1)
	  fprintf(stderr,
         "\tdrawing and clipping lines between inrange and outrange points\n");
	else
	  fprintf(stderr,
         "\tnot drawing lines between inrange and outrange points\n");

	if (clip_lines2)
	  fprintf(stderr,
         "\tdrawing and clipping lines between two outrange points\n");
	else
	  fprintf(stderr,
         "\tnot drawing lines between two outrange points\n");
}

static void
show_format()
{
	fprintf(stderr, "\tx-axis tic format is \"%s\"\n", xformat);
	fprintf(stderr, "\ty-axis tic format is \"%s\"\n", yformat);
}

static void
show_logscale()
{
	if (log_x && log_y)
		fprintf(stderr,"\tlogscaling both x and y axes\n");
	else if (log_x)
		fprintf(stderr,"\tlogscaling x axis\n");
	else if (log_y)
		fprintf(stderr,"\tlogscaling y axis\n");
	else
		fprintf(stderr,"\tno logscaling\n");
}

static void
show_variables()
{
register struct udvt_entry *udv = first_udv;
int len;

	fprintf(stderr,"\n\tVariables:\n");
	while (udv) {
	     len = instring(udv->udv_name, ' ');
		fprintf(stderr,"\t%-*s ",len,udv->udv_name);
		if (udv->udv_undef)
			fputs("is undefined\n",stderr);
		else {
			fputs("= ",stderr);
			disp_value(stderr,&(udv->udv_value));
			(void) putc('\n',stderr);
		}
		udv = udv->next_udv;
	}
}

void				/* used by plot.c */
show_version()
{
extern char version[];
extern char patchlevel[];
extern char date[];
extern char bug_email[];
static char *authors[] = {"Thomas Williams","Colin Kelley"}; /* primary */
int x;
long time();

	x = time((long *)NULL) & 1;
	fprintf(stderr,"\n\t%s\n\t%sversion %s\n",
		PROGRAM, OS, version); 
	fprintf(stderr,"\tpatchlevel %s\n",patchlevel);
     fprintf(stderr, "\tlast modified %s\n", date);
	fprintf(stderr,"\tCopyright (C) 1986, 1987, 1990  %s, %s\n",
		authors[x],authors[1-x]);
#ifdef __TURBOC__
	fprintf(stderr,"\tCreated using Turbo C, Copyright Borland 1987, 1988\n");
#endif
    fprintf(stderr, "\n\tSend bugs and comments to %s\n", bug_email);
}