home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume15 / gnuplot2 / patch01 / setshow.c < prev    next >
C/C++ Source or Header  |  1990-10-05  |  41KB  |  1,716 lines

  1. /* GNUPLOT - setshow.c */
  2. /*
  3.  * Copyright (C) 1986, 1987, 1990   Thomas Williams, Colin Kelley
  4.  *
  5.  * Permission to use, copy, and distribute this software and its
  6.  * documentation for any purpose with or without fee is hereby granted, 
  7.  * provided that the above copyright notice appear in all copies and 
  8.  * that both that copyright notice and this permission notice appear 
  9.  * in supporting documentation.
  10.  *
  11.  * Permission to modify the software is granted, but not the right to
  12.  * distribute the modified code.  Modifications are to be distributed 
  13.  * as patches to released version.
  14.  *  
  15.  * This software  is provided "as is" without express or implied warranty.
  16.  * 
  17.  *
  18.  * AUTHORS
  19.  * 
  20.  *   Original Software:
  21.  *     Thomas Williams,  Colin Kelley.
  22.  * 
  23.  *   Gnuplot 2.0 additions:
  24.  *       Russell Lang, Dave Kotz, John Campbell.
  25.  * 
  26.  * send your comments or suggestions to (pixar!info-gnuplot@sun.com).
  27.  * 
  28.  */
  29.  
  30. #include <stdio.h>
  31. #include <math.h>
  32. #include "plot.h"
  33. #include "setshow.h"
  34.  
  35. #define DEF_FORMAT   "%g"    /* default format for tic mark labels */
  36. #define SIGNIF (0.01)        /* less than one hundredth of a tic mark */
  37.  
  38. /*
  39.  * global variables to hold status of 'set' options
  40.  *
  41.  */
  42. BOOLEAN            autoscale_x    = TRUE;
  43. BOOLEAN            autoscale_y    = TRUE;
  44. BOOLEAN            autoscale_lx    = TRUE;
  45. BOOLEAN            autoscale_ly    = TRUE;
  46. BOOLEAN                clip_points    = FALSE;
  47. BOOLEAN                clip_lines1    = TRUE;
  48. BOOLEAN                clip_lines2    = FALSE;
  49. char            dummy_var[MAX_ID_LEN+1] = "x";
  50. char            xformat[MAX_ID_LEN+1] = DEF_FORMAT;
  51. char            yformat[MAX_ID_LEN+1] = DEF_FORMAT;
  52. enum PLOT_STYLE data_style    = POINTS,
  53.                 func_style    = LINES;
  54. BOOLEAN            grid        = FALSE;
  55. int                key            = -1;    /* default position */
  56. double            key_x, key_y;        /* user specified position for key */
  57. BOOLEAN            log_x        = FALSE,
  58.                 log_y        = FALSE;
  59. FILE*            outfile;
  60. char            outstr[MAX_ID_LEN+1] = "STDOUT";
  61. BOOLEAN            polar        = FALSE;
  62. int                samples        = SAMPLES;
  63. float            xsize        = 1.0;  /* scale factor for size */
  64. float            ysize        = 1.0;  /* scale factor for size */
  65. int                term        = 0;                /* unknown term is 0 */
  66. char            title[MAX_LINE_LEN+1] = "";
  67. char            xlabel[MAX_LINE_LEN+1] = "";
  68. char            ylabel[MAX_LINE_LEN+1] = "";
  69. double            xmin        = -10.0,
  70.                 xmax        = 10.0,
  71.                 ymin        = -10.0,
  72.                 ymax        = 10.0;
  73. double            loff        = 0.0,
  74.                 roff        = 0.0,
  75.                 toff        = 0.0,
  76.                 boff        = 0.0;
  77. double            zero = ZERO;            /* zero threshold, not 0! */
  78.  
  79. BOOLEAN xtics = TRUE;
  80. BOOLEAN ytics = TRUE;
  81.  
  82. struct ticdef xticdef = {TIC_COMPUTED};
  83. struct ticdef yticdef = {TIC_COMPUTED};
  84.  
  85. BOOLEAN            tic_in        = TRUE;
  86.  
  87. struct text_label *first_label = NULL;
  88. struct arrow_def *first_arrow = NULL;
  89.  
  90. /*** other things we need *****/
  91. extern char *strcpy(),*strcat();
  92. extern int strlen();
  93.  
  94. /* input data, parsing variables */
  95. extern struct lexical_unit token[];
  96. extern char input_line[];
  97. extern int num_tokens, c_token;
  98.  
  99. extern char replot_line[];
  100. extern struct udvt_entry *first_udv;
  101.  
  102. extern double magnitude(),real();
  103. extern struct value *const_express();
  104.  
  105. /******** Local functions ********/
  106. static void set_label();
  107. static void set_nolabel();
  108. static void set_arrow();
  109. static void set_noarrow();
  110. static void load_tics();
  111. static void load_tic_user();
  112. static void free_marklist();
  113. static void load_tic_series();
  114. static void load_offsets();
  115.  
  116. static void show_style(), show_range(), show_zero();
  117. static void show_offsets(), show_output(), show_samples(), show_size();
  118. static void show_title(), show_xlabel(), show_ylabel();
  119. static void show_label(), show_arrow(), show_grid(), show_key();
  120. static void show_polar(), show_tics(), show_ticdef();
  121. static void show_term(), show_plot(), show_autoscale(), show_clip();
  122. static void show_format(), show_logscale(), show_variables();
  123.  
  124. static void delete_label();
  125. static int assign_label_tag();
  126. static void delete_arrow();
  127. static int assign_arrow_tag();
  128.  
  129. /******** The 'set' command ********/
  130. void
  131. set_command()
  132. {
  133.      static char testfile[MAX_LINE_LEN+1];
  134.  
  135.     c_token++;
  136.  
  137.     if (almost_equals(c_token,"ar$row")) {
  138.         c_token++;
  139.         set_arrow();
  140.     }
  141.     else if (almost_equals(c_token,"noar$row")) {
  142.         c_token++;
  143.         set_noarrow();
  144.     }
  145.      else if (almost_equals(c_token,"au$toscale")) {
  146.         c_token++;
  147.         if (END_OF_COMMAND) {
  148.            autoscale_x = autoscale_y = TRUE;
  149.         } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
  150.            autoscale_x = autoscale_y = TRUE;
  151.            c_token++;
  152.         } else if (equals(c_token, "x")) {
  153.            autoscale_x = TRUE;
  154.            c_token++;
  155.         } else if (equals(c_token, "y")) {
  156.            autoscale_y = TRUE;
  157.            c_token++;
  158.         }
  159.     } 
  160.     else if (almost_equals(c_token,"noau$toscale")) {
  161.         c_token++;
  162.         if (END_OF_COMMAND) {
  163.            autoscale_x = autoscale_y = FALSE;
  164.         } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
  165.            autoscale_x = autoscale_y = FALSE;
  166.            c_token++;
  167.         } else if (equals(c_token, "x")) {
  168.            autoscale_x = FALSE;
  169.            c_token++;
  170.         } else if (equals(c_token, "y")) {
  171.            autoscale_y = FALSE;
  172.            c_token++;
  173.         }
  174.     } 
  175.     else if (almost_equals(c_token,"c$lip")) {
  176.         c_token++;
  177.         if (END_OF_COMMAND)
  178.          /* assuming same as points */
  179.          clip_points = TRUE;
  180.         else if (almost_equals(c_token, "p$oints"))
  181.          clip_points = TRUE;
  182.         else if (almost_equals(c_token, "o$ne"))
  183.          clip_lines1 = TRUE;
  184.         else if (almost_equals(c_token, "t$wo"))
  185.          clip_lines2 = TRUE;
  186.         else
  187.          int_error("expecting 'points', 'one', or 'two'", c_token);
  188.         c_token++;
  189.     }
  190.     else if (almost_equals(c_token,"noc$lip")) {
  191.         c_token++;
  192.         if (END_OF_COMMAND) {
  193.            /* same as all three */
  194.            clip_points = FALSE;
  195.            clip_lines1 = FALSE;
  196.            clip_lines2 = FALSE;
  197.         } else if (almost_equals(c_token, "p$oints"))
  198.          clip_points = FALSE;
  199.         else if (almost_equals(c_token, "o$ne"))
  200.          clip_lines1 = FALSE;
  201.         else if (almost_equals(c_token, "t$wo"))
  202.          clip_lines2 = FALSE;
  203.         else
  204.          int_error("expecting 'points', 'one', or 'two'", c_token);
  205.         c_token++;
  206.     }
  207.     else if (almost_equals(c_token,"d$ata")) {
  208.         c_token++;
  209.         if (!almost_equals(c_token,"s$tyle"))
  210.             int_error("expecting keyword 'style'",c_token);
  211.         data_style = get_style();
  212.     }
  213.     else if (almost_equals(c_token,"d$ummy")) {
  214.         c_token++;
  215.         copy_str(dummy_var,c_token++);
  216.     }
  217.     else if (almost_equals(c_token,"fo$rmat")) {
  218.         BOOLEAN setx, sety;
  219.         c_token++;
  220.         if (equals(c_token,"x")) {
  221.             setx = TRUE; sety = FALSE;
  222.             c_token++;
  223.         }
  224.         else if (equals(c_token,"y")) {
  225.             setx = FALSE; sety = TRUE;
  226.             c_token++;
  227.         }
  228.         else if (equals(c_token,"xy") || equals(c_token,"yx")) {
  229.             setx = sety = TRUE;
  230.             c_token++;
  231.         }
  232.         else if (isstring(c_token) || END_OF_COMMAND) {
  233.             /* Assume he wants both */
  234.             setx = sety = TRUE;
  235.         }
  236.         if (END_OF_COMMAND) {
  237.             if (setx)
  238.                 (void) strcpy(xformat,DEF_FORMAT);
  239.             if (sety)
  240.                 (void) strcpy(yformat,DEF_FORMAT);
  241.         }
  242.         else {
  243.             if (!isstring(c_token))
  244.               int_error("expecting format string",c_token);
  245.             else {
  246.                 if (setx)
  247.                  quote_str(xformat,c_token);
  248.                 if (sety)
  249.                  quote_str(yformat,c_token);
  250.                 c_token++;
  251.             }
  252.         }
  253.     }
  254.     else if (almost_equals(c_token,"fu$nction")) {
  255.         c_token++;
  256.         if (!almost_equals(c_token,"s$tyle"))
  257.             int_error("expecting keyword 'style'",c_token);
  258.         func_style = get_style();
  259.     }
  260.     else if (almost_equals(c_token,"la$bel")) {
  261.         c_token++;
  262.         set_label();
  263.     }
  264.     else if (almost_equals(c_token,"nola$bel")) {
  265.         c_token++;
  266.         set_nolabel();
  267.     }
  268.     else if (almost_equals(c_token,"lo$gscale")) {
  269.         c_token++;
  270.         if (END_OF_COMMAND) {
  271.            log_x = log_y = TRUE;
  272.         } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
  273.            log_x = log_y = TRUE;
  274.            c_token++;
  275.         } else if (equals(c_token, "x")) {
  276.            log_x = TRUE;
  277.            c_token++;
  278.         } else if (equals(c_token, "y")) {
  279.            log_y = TRUE;
  280.            c_token++;
  281.         }
  282.     }
  283.     else if (almost_equals(c_token,"nolo$gscale")) {
  284.         c_token++;
  285.         if (END_OF_COMMAND) {
  286.            log_x = log_y = FALSE;
  287.         } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
  288.            log_x = log_y = FALSE;
  289.            c_token++;
  290.         } else if (equals(c_token, "x")) {
  291.            log_x = FALSE;
  292.            c_token++;
  293.         } else if (equals(c_token, "y")) {
  294.            log_y = FALSE;
  295.            c_token++;
  296.         }
  297.     } 
  298.     else if (almost_equals(c_token,"of$fsets")) {
  299.         c_token++;
  300.         if (END_OF_COMMAND) {
  301.             loff = roff = toff = boff = 0.0;  /* Reset offsets */
  302.         }
  303.         else {
  304.             load_offsets (&loff,&roff,&toff,&boff);
  305.         }
  306.     }
  307.     else if (almost_equals(c_token,"o$utput")) {
  308.         register FILE *f;
  309.  
  310.         c_token++;
  311.         if (term && term_init)
  312.             (*term_tbl[term].reset)();
  313.         if (END_OF_COMMAND) {    /* no file specified */
  314.              UP_redirect (4);
  315.             if (outfile != stdout) /* Never close stdout */
  316.                 (void) fclose(outfile);
  317.             outfile = stdout; /* Don't dup... */
  318.             term_init = FALSE;
  319.             (void) strcpy(outstr,"STDOUT");
  320.         } else if (!isstring(c_token))
  321.             int_error("expecting filename",c_token);
  322.         else {
  323.             quote_str(testfile,c_token);
  324.             if ((f = fopen(testfile,"w")) == (FILE *)NULL) {
  325.               os_error("cannot open file; output not changed",c_token);
  326.             }
  327.             if (outfile != stdout) /* Never close stdout */
  328.                 (void) fclose(outfile);
  329.             outfile = f;
  330.             term_init = FALSE;
  331.             outstr[0] = '\'';
  332.             (void) strcat(strcpy(outstr+1,testfile),"'");
  333.              UP_redirect (1);
  334.         }
  335.         c_token++;
  336.     }
  337.     else if (almost_equals(c_token,"tit$le")) {
  338.         c_token++;
  339.         if (END_OF_COMMAND) {    /* no label specified */
  340.             title[0] = '\0';
  341.         } else {
  342.         quotel_str(title,c_token);
  343.         c_token++;
  344.         }
  345.     } 
  346.     else if (almost_equals(c_token,"xl$abel")) {
  347.         c_token++;
  348.         if (END_OF_COMMAND) {    /* no label specified */
  349.             xlabel[0] = '\0';
  350.         } else {
  351.         quotel_str(xlabel,c_token);
  352.         c_token++;
  353.         }
  354.     } 
  355.     else if (almost_equals(c_token,"yl$abel")) {
  356.         c_token++;
  357.         if (END_OF_COMMAND) {    /* no label specified */
  358.             ylabel[0] = '\0';
  359.         } else {
  360.         quotel_str(ylabel,c_token);
  361.         c_token++;
  362.         }
  363.     } 
  364.     else if (almost_equals(c_token,"pol$ar")) {
  365.         if (!polar) {
  366.            polar = TRUE;
  367.            xmin = 0.0;
  368.            xmax = 2*Pi;
  369.         }
  370.         c_token++;
  371.     }
  372.     else if (almost_equals(c_token,"nopo$lar")) {
  373.         if (polar) {
  374.            polar = FALSE;
  375.            xmin = -10.0;
  376.            xmax = 10.0;
  377.         }
  378.         c_token++;
  379.     }
  380.     else if (almost_equals(c_token,"g$rid")) {
  381.         grid = TRUE;
  382.         c_token++;
  383.     }
  384.     else if (almost_equals(c_token,"nog$rid")) {
  385.         grid = FALSE;
  386.         c_token++;
  387.     }
  388.     else if (almost_equals(c_token,"k$ey")) {
  389.         struct value a;
  390.         c_token++;
  391.         if (END_OF_COMMAND) {
  392.             key = -1;
  393.         } 
  394.         else {
  395.             key_x = real(const_express(&a));
  396.             if (!equals(c_token,","))
  397.                 int_error("',' expected",c_token);
  398.             c_token++;
  399.             key_y = real(const_express(&a));
  400.             key = 1;
  401.         } 
  402.     }
  403.     else if (almost_equals(c_token,"nok$ey")) {
  404.         key = 0;
  405.         c_token++;
  406.     }
  407.     else if (almost_equals(c_token,"tic$s")) {
  408.         tic_in = TRUE;
  409.         c_token++;
  410.         if (almost_equals(c_token,"i$n")) {
  411.             tic_in = TRUE;
  412.             c_token++;
  413.         }
  414.         else if (almost_equals(c_token,"o$ut")) {
  415.             tic_in = FALSE;
  416.             c_token++;
  417.         }
  418.     }
  419.      else if (almost_equals(c_token,"xt$ics")) {
  420.         xtics = TRUE;
  421.         c_token++;
  422.         if (END_OF_COMMAND) { /* reset to default */
  423.            if (xticdef.type == TIC_USER) {
  424.               free_marklist(xticdef.def.user);
  425.               xticdef.def.user = NULL;
  426.            }
  427.            xticdef.type = TIC_COMPUTED;
  428.         }
  429.         else
  430.          load_tics(&xticdef);
  431.     } 
  432.      else if (almost_equals(c_token,"noxt$ics")) {
  433.         xtics = FALSE;
  434.         c_token++;
  435.     } 
  436.      else if (almost_equals(c_token,"yt$ics")) {
  437.         ytics = TRUE;
  438.         c_token++;
  439.         if (END_OF_COMMAND) { /* reset to default */
  440.            if (yticdef.type == TIC_USER) {
  441.               free_marklist(yticdef.def.user);
  442.               yticdef.def.user = NULL;
  443.            }
  444.            yticdef.type = TIC_COMPUTED;
  445.         }
  446.         else
  447.          load_tics(&yticdef);
  448.     } 
  449.      else if (almost_equals(c_token,"noyt$ics")) {
  450.         ytics = FALSE;
  451.         c_token++;
  452.     } 
  453.     else if (almost_equals(c_token,"sa$mples")) {
  454.         register int tsamp;
  455.         struct value a;
  456.  
  457.         c_token++;
  458.         tsamp = (int)magnitude(const_express(&a));
  459.         if (tsamp < 1)
  460.             int_error("sampling rate must be > 0; sampling unchanged",
  461.                 c_token);
  462.         else {
  463.              extern struct curve_points *first_plot;
  464.             register struct curve_points *f_p = first_plot;
  465.  
  466.             first_plot = NULL;
  467.             cp_free(f_p);
  468.             samples = tsamp;
  469.         }
  470.     }
  471.     else if (almost_equals(c_token,"si$ze")) {
  472.         struct value s;
  473.         c_token++;
  474.         if (END_OF_COMMAND) {
  475.             xsize = 1.0;
  476.             ysize = 1.0;
  477.         } 
  478.         else {
  479.                 xsize=real(const_express(&s));
  480.                 if (!equals(c_token,","))
  481.                     int_error("',' expected",c_token);
  482.                 c_token++;
  483.                 ysize=real(const_express(&s));
  484.         } 
  485.     } 
  486.     else if (almost_equals(c_token,"t$erminal")) {
  487.         c_token++;
  488.         if (END_OF_COMMAND) {
  489.             list_terms();
  490.             screen_ok = FALSE;
  491.         }
  492.         else {
  493.             if (term && term_init) {
  494.                 (*term_tbl[term].reset)();
  495.                 (void) fflush(outfile);
  496.             }
  497.             term = set_term(c_token);
  498.             c_token++;
  499.         }
  500.     }
  501.     else if (almost_equals(c_token,"xr$ange")) {
  502.          BOOLEAN changed;
  503.         c_token++;
  504.         if (!equals(c_token,"["))
  505.             int_error("expecting '['",c_token);
  506.         c_token++;
  507.         changed = load_range(&xmin,&xmax);
  508.         if (!equals(c_token,"]"))
  509.           int_error("expecting ']'",c_token);
  510.         c_token++;
  511.         if (changed)
  512.           autoscale_x = FALSE;
  513.     }
  514.     else if (almost_equals(c_token,"yr$ange")) {
  515.          BOOLEAN changed;
  516.         c_token++;
  517.         if (!equals(c_token,"["))
  518.             int_error("expecting '['",c_token);
  519.         c_token++;
  520.         changed = load_range(&ymin,&ymax);
  521.         if (!equals(c_token,"]"))
  522.           int_error("expecting ']'",c_token);
  523.         c_token++;
  524.         if (changed)
  525.           autoscale_y = FALSE;
  526.     }
  527.     else if (almost_equals(c_token,"z$ero")) {
  528.         struct value a;
  529.         c_token++;
  530.         zero = magnitude(const_express(&a));
  531.     }
  532.     else
  533.         int_error(
  534.     "valid set options:  '{no}arrow', {no}autoscale', '{no}clip', data', \n\
  535.     'dummy', 'format', 'function', '{no}grid', '{no}key', '{no}label', \n\
  536.     '{no}logscale','offsets', 'output', '{no}polar', 'samples', \n\
  537.     'size', 'terminal', 'tics', 'title', 'xlabel', 'xrange', 'xtics', \n\
  538.     'ylabel', 'yrange', 'ytics', 'zero',\n",
  539.     c_token);
  540. }
  541.  
  542. /*********** Support functions for set_command ***********/
  543.  
  544. /* process a 'set label' command */
  545. /* set label {tag} {label_text} {at x,y} {pos} */
  546. static void
  547. set_label()
  548. {
  549.     struct value a;
  550.     struct text_label *this_label = NULL;
  551.     struct text_label *new_label = NULL;
  552.     struct text_label *prev_label = NULL;
  553.     double x, y;
  554.     char text[MAX_LINE_LEN+1];
  555.     enum JUSTIFY just;
  556.     int tag;
  557.     BOOLEAN set_text, set_position, set_just;
  558.  
  559.     /* get tag */
  560.     if (!END_OF_COMMAND 
  561.        && !isstring(c_token) 
  562.        && !equals(c_token, "at")
  563.        && !equals(c_token, "left")
  564.        && !equals(c_token, "center")
  565.        && !equals(c_token, "centre")
  566.        && !equals(c_token, "right")) {
  567.        /* must be a tag expression! */
  568.        tag = (int)real(const_express(&a));
  569.        if (tag <= 0)
  570.         int_error("tag must be > zero", c_token);
  571.     } else
  572.      tag = assign_label_tag(); /* default next tag */
  573.      
  574.     /* get text */
  575.     if (!END_OF_COMMAND && isstring(c_token)) {
  576.        /* get text */
  577.        quotel_str(text, c_token);
  578.        c_token++;
  579.        set_text = TRUE;
  580.     } else {
  581.        text[0] = '\0';        /* default no text */
  582.        set_text = FALSE;
  583.     }
  584.      
  585.     /* get justification - what the heck, let him put it here */
  586.     if (!END_OF_COMMAND && !equals(c_token, "at")) {
  587.        if (almost_equals(c_token,"l$eft")) {
  588.           just = LEFT;
  589.        }
  590.        else if (almost_equals(c_token,"c$entre")
  591.               || almost_equals(c_token,"c$enter")) {
  592.           just = CENTRE;
  593.        }
  594.        else if (almost_equals(c_token,"r$ight")) {
  595.           just = RIGHT;
  596.        }
  597.        else
  598.         int_error("bad syntax in set label", c_token);
  599.        c_token++;
  600.        set_just = TRUE;
  601.     } else {
  602.        just = LEFT;            /* default left justified */
  603.        set_just = FALSE;
  604.     } 
  605.  
  606.     /* get position */
  607.     if (!END_OF_COMMAND && equals(c_token, "at")) {
  608.        c_token++;
  609.        if (END_OF_COMMAND)
  610.         int_error("coordinates expected", c_token);
  611.        /* get coordinates */
  612.        x = real(const_express(&a));
  613.        if (!equals(c_token,","))
  614.         int_error("',' expected",c_token);
  615.        c_token++;
  616.        y = real(const_express(&a));
  617.        set_position = TRUE;
  618.     } else {
  619.        x = y = 0;            /* default at origin */
  620.        set_position = FALSE;
  621.     }
  622.  
  623.     /* get justification */
  624.     if (!END_OF_COMMAND) {
  625.        if (set_just)
  626.         int_error("only one justification is allowed", c_token);
  627.        if (almost_equals(c_token,"l$eft")) {
  628.           just = LEFT;
  629.        }
  630.        else if (almost_equals(c_token,"c$entre")
  631.               || almost_equals(c_token,"c$enter")) {
  632.           just = CENTRE;
  633.        }
  634.        else if (almost_equals(c_token,"r$ight")) {
  635.           just = RIGHT;
  636.        }
  637.        else
  638.         int_error("bad syntax in set label", c_token);
  639.        c_token++;
  640.        set_just = TRUE;
  641.     } 
  642.  
  643.     if (!END_OF_COMMAND)
  644.      int_error("extraneous or out-of-order arguments in set label", c_token);
  645.  
  646.     /* OK! add label */
  647.     if (first_label != NULL) { /* skip to last label */
  648.        for (this_label = first_label; this_label != NULL ; 
  649.            prev_label = this_label, this_label = this_label->next)
  650.         /* is this the label we want? */
  651.         if (tag <= this_label->tag)
  652.           break;
  653.     }
  654.     if (this_label != NULL && tag == this_label->tag) {
  655.        /* changing the label */
  656.        if (set_position) {
  657.           this_label->x = x;
  658.           this_label->y = y;
  659.        }
  660.        if (set_text)
  661.         (void) strcpy(this_label->text, text);
  662.        if (set_just)
  663.         this_label->pos = just;
  664.     } else {
  665.        /* adding the label */
  666.        new_label = (struct text_label *) 
  667.         alloc ( (unsigned int) sizeof(struct text_label), "label");
  668.        if (prev_label != NULL)
  669.         prev_label->next = new_label; /* add it to end of list */
  670.        else 
  671.         first_label = new_label; /* make it start of list */
  672.        new_label->tag = tag;
  673.        new_label->next = this_label;
  674.        new_label->x = x;
  675.        new_label->y = y;
  676.        (void) strcpy(new_label->text, text);
  677.        new_label->pos = just;
  678.     }
  679. }
  680.  
  681. /* process 'set nolabel' command */
  682. /* set nolabel {tag} */
  683. static void
  684. set_nolabel()
  685. {
  686.     struct value a;
  687.     struct text_label *this_label;
  688.     struct text_label *prev_label; 
  689.     int tag;
  690.  
  691.     if (END_OF_COMMAND) {
  692.        /* delete all labels */
  693.        while (first_label != NULL)
  694.         delete_label((struct text_label *)NULL,first_label);
  695.     }
  696.     else {
  697.        /* get tag */
  698.        tag = (int)real(const_express(&a));
  699.        if (!END_OF_COMMAND)
  700.         int_error("extraneous arguments to set nolabel", c_token);
  701.        for (this_label = first_label, prev_label = NULL;
  702.            this_label != NULL;
  703.            prev_label = this_label, this_label = this_label->next) {
  704.           if (this_label->tag == tag) {
  705.              delete_label(prev_label,this_label);
  706.              return;        /* exit, our job is done */
  707.           }
  708.        }
  709.        int_error("label not found", c_token);
  710.     }
  711. }
  712.  
  713. /* assign a new label tag */
  714. /* labels are kept sorted by tag number, so this is easy */
  715. static int                /* the lowest unassigned tag number */
  716. assign_label_tag()
  717. {
  718.     struct text_label *this_label;
  719.     int last = 0;            /* previous tag value */
  720.  
  721.     for (this_label = first_label; this_label != NULL;
  722.         this_label = this_label->next)
  723.      if (this_label->tag == last+1)
  724.        last++;
  725.      else
  726.        break;
  727.     
  728.     return (last+1);
  729. }
  730.  
  731. /* delete label from linked list started by first_label.
  732.  * called with pointers to the previous label (prev) and the 
  733.  * label to delete (this).
  734.  * If there is no previous label (the label to delete is
  735.  * first_label) then call with prev = NULL.
  736.  */
  737. static void
  738. delete_label(prev,this)
  739.     struct text_label *prev, *this;
  740. {
  741.     if (this!=NULL)    {        /* there really is something to delete */
  742.        if (prev!=NULL)        /* there is a previous label */
  743.         prev->next = this->next; 
  744.        else                /* this = first_label so change first_label */
  745.         first_label = this->next;
  746.        free((char *)this);
  747.     }
  748. }
  749.  
  750.  
  751. /* process a 'set arrow' command */
  752. /* set arrow {tag} {from x,y} {to x,y} */
  753. static void
  754. set_arrow()
  755. {
  756.     struct value a;
  757.     struct arrow_def *this_arrow = NULL;
  758.     struct arrow_def *new_arrow = NULL;
  759.     struct arrow_def *prev_arrow = NULL;
  760.     double sx, sy;
  761.     double ex, ey;
  762.     int tag;
  763.     BOOLEAN set_start, set_end;
  764.  
  765.     /* get tag */
  766.     if (!END_OF_COMMAND 
  767.        && !equals(c_token, "from")
  768.        && !equals(c_token, "to")) {
  769.        /* must be a tag expression! */
  770.        tag = (int)real(const_express(&a));
  771.        if (tag <= 0)
  772.         int_error("tag must be > zero", c_token);
  773.     } else
  774.      tag = assign_arrow_tag(); /* default next tag */
  775.      
  776.     /* get start position */
  777.     if (!END_OF_COMMAND && equals(c_token, "from")) {
  778.        c_token++;
  779.        if (END_OF_COMMAND)
  780.         int_error("start coordinates expected", c_token);
  781.        /* get coordinates */
  782.        sx = real(const_express(&a));
  783.        if (!equals(c_token,","))
  784.         int_error("',' expected",c_token);
  785.        c_token++;
  786.        sy = real(const_express(&a));
  787.        set_start = TRUE;
  788.     } else {
  789.        sx = sy = 0;            /* default at origin */
  790.        set_start = FALSE;
  791.     }
  792.  
  793.     /* get end position */
  794.     if (!END_OF_COMMAND && equals(c_token, "to")) {
  795.        c_token++;
  796.        if (END_OF_COMMAND)
  797.         int_error("end coordinates expected", c_token);
  798.        /* get coordinates */
  799.        ex = real(const_express(&a));
  800.        if (!equals(c_token,","))
  801.         int_error("',' expected",c_token);
  802.        c_token++;
  803.        ey = real(const_express(&a));
  804.        set_end = TRUE;
  805.     } else {
  806.        ex = ey = 0;            /* default at origin */
  807.        set_end = FALSE;
  808.     }
  809.  
  810.     /* get start position - what the heck, either order is ok */
  811.     if (!END_OF_COMMAND && equals(c_token, "from")) {
  812.        if (set_start)
  813.         int_error("only one 'from' is allowed", c_token);
  814.        c_token++;
  815.        if (END_OF_COMMAND)
  816.         int_error("start coordinates expected", c_token);
  817.        /* get coordinates */
  818.        sx = real(const_express(&a));
  819.        if (!equals(c_token,","))
  820.         int_error("',' expected",c_token);
  821.        c_token++;
  822.        sy = real(const_express(&a));
  823.        set_start = TRUE;
  824.     }
  825.  
  826.     if (!END_OF_COMMAND)
  827.      int_error("extraneous or out-of-order arguments in set arrow", c_token);
  828.  
  829.     /* OK! add arrow */
  830.     if (first_arrow != NULL) { /* skip to last arrow */
  831.        for (this_arrow = first_arrow; this_arrow != NULL ; 
  832.            prev_arrow = this_arrow, this_arrow = this_arrow->next)
  833.         /* is this the arrow we want? */
  834.         if (tag <= this_arrow->tag)
  835.           break;
  836.     }
  837.     if (this_arrow != NULL && tag == this_arrow->tag) {
  838.        /* changing the arrow */
  839.        if (set_start) {
  840.           this_arrow->sx = sx;
  841.           this_arrow->sy = sy;
  842.        }
  843.        if (set_end) {
  844.           this_arrow->ex = ex;
  845.           this_arrow->ey = ey;
  846.        }
  847.     } else {
  848.        /* adding the arrow */
  849.        new_arrow = (struct arrow_def *) 
  850.         alloc ( (unsigned int) sizeof(struct arrow_def), "arrow");
  851.        if (prev_arrow != NULL)
  852.         prev_arrow->next = new_arrow; /* add it to end of list */
  853.        else 
  854.         first_arrow = new_arrow; /* make it start of list */
  855.        new_arrow->tag = tag;
  856.        new_arrow->next = this_arrow;
  857.        new_arrow->sx = sx;
  858.        new_arrow->sy = sy;
  859.        new_arrow->ex = ex;
  860.        new_arrow->ey = ey;
  861.     }
  862. }
  863.  
  864. /* process 'set noarrow' command */
  865. /* set noarrow {tag} */
  866. static void
  867. set_noarrow()
  868. {
  869.     struct value a;
  870.     struct arrow_def *this_arrow;
  871.     struct arrow_def *prev_arrow; 
  872.     int tag;
  873.  
  874.     if (END_OF_COMMAND) {
  875.        /* delete all arrows */
  876.        while (first_arrow != NULL)
  877.         delete_arrow((struct arrow_def *)NULL,first_arrow);
  878.     }
  879.     else {
  880.        /* get tag */
  881.        tag = (int)real(const_express(&a));
  882.        if (!END_OF_COMMAND)
  883.         int_error("extraneous arguments to set noarrow", c_token);
  884.        for (this_arrow = first_arrow, prev_arrow = NULL;
  885.            this_arrow != NULL;
  886.            prev_arrow = this_arrow, this_arrow = this_arrow->next) {
  887.           if (this_arrow->tag == tag) {
  888.              delete_arrow(prev_arrow,this_arrow);
  889.              return;        /* exit, our job is done */
  890.           }
  891.        }
  892.        int_error("arrow not found", c_token);
  893.     }
  894. }
  895.  
  896. /* assign a new arrow tag */
  897. /* arrows are kept sorted by tag number, so this is easy */
  898. static int                /* the lowest unassigned tag number */
  899. assign_arrow_tag()
  900. {
  901.     struct arrow_def *this_arrow;
  902.     int last = 0;            /* previous tag value */
  903.  
  904.     for (this_arrow = first_arrow; this_arrow != NULL;
  905.         this_arrow = this_arrow->next)
  906.      if (this_arrow->tag == last+1)
  907.        last++;
  908.      else
  909.        break;
  910.  
  911.     return (last+1);
  912. }
  913.  
  914. /* delete arrow from linked list started by first_arrow.
  915.  * called with pointers to the previous arrow (prev) and the 
  916.  * arrow to delete (this).
  917.  * If there is no previous arrow (the arrow to delete is
  918.  * first_arrow) then call with prev = NULL.
  919.  */
  920. static void
  921. delete_arrow(prev,this)
  922.     struct arrow_def *prev, *this;
  923. {
  924.     if (this!=NULL)    {        /* there really is something to delete */
  925.        if (prev!=NULL)        /* there is a previous arrow */
  926.         prev->next = this->next; 
  927.        else                /* this = first_arrow so change first_arrow */
  928.         first_arrow = this->next;
  929.        free((char *)this);
  930.     }
  931. }
  932.  
  933.  
  934. enum PLOT_STYLE            /* not static; used by command.c */
  935. get_style()
  936. {
  937. register enum PLOT_STYLE ps;
  938.  
  939.     c_token++;
  940.     if (almost_equals(c_token,"l$ines"))
  941.         ps = LINES;
  942.     else if (almost_equals(c_token,"i$mpulses"))
  943.         ps = IMPULSES;
  944.     else if (almost_equals(c_token,"p$oints"))
  945.         ps = POINTS;
  946.     else if (almost_equals(c_token,"linesp$oints"))
  947.         ps = LINESPOINTS;
  948.     else if (almost_equals(c_token,"d$ots"))
  949.         ps = DOTS;
  950.     else
  951.         int_error("expecting 'lines', 'points', 'linespoints', 'dots', or 'impulses'",c_token);
  952.     c_token++;
  953.     return(ps);
  954. }
  955.  
  956. /* For set [xy]tics... command*/
  957. static void
  958. load_tics(tdef)
  959.     struct ticdef *tdef;    /* change this ticdef */
  960. {
  961.     if (equals(c_token,"(")) { /* set : TIC_USER */
  962.        c_token++;
  963.        load_tic_user(tdef);
  964.     } else {                /* series : TIC_SERIES */
  965.        load_tic_series(tdef);
  966.     }
  967. }
  968.  
  969. /* load TIC_USER definition */
  970. /* (tic[,tic]...)
  971.  * where tic is ["string"] value
  972.  * Left paren is already scanned off before entry.
  973.  */
  974. static void
  975. load_tic_user(tdef)
  976.     struct ticdef *tdef;
  977. {
  978.     struct ticmark *list = NULL; /* start of list */
  979.     struct ticmark *last = NULL; /* end of list */
  980.     struct ticmark *tic = NULL; /* new ticmark */
  981.     char temp_string[MAX_LINE_LEN];
  982.     struct value a;
  983.  
  984.     while (!END_OF_COMMAND) {
  985.        /* parse a new ticmark */
  986.        tic = (struct ticmark *)alloc(sizeof(struct ticmark), (char *)NULL);
  987.        if (tic == (struct ticmark *)NULL) {
  988.           free_marklist(list);
  989.           int_error("out of memory for tic mark", c_token);
  990.        }
  991.  
  992.        /* has a string with it? */
  993.        if (isstring(c_token)) {
  994.           quote_str(temp_string,c_token);
  995.           tic->label = alloc((unsigned int)strlen(temp_string)+1, "tic label");
  996.           (void) strcpy(tic->label, temp_string);
  997.           c_token++;
  998.        } else
  999.         tic->label = NULL;
  1000.  
  1001.        /* in any case get the value */
  1002.        tic->position = real(const_express(&a));
  1003.        tic->next = NULL;
  1004.  
  1005.        /* append to list */
  1006.        if (list == NULL)
  1007.         last = list = tic;    /* new list */
  1008.        else {                /* append to list */
  1009.           last->next = tic;
  1010.           last = tic;
  1011.        }
  1012.  
  1013.        /* expect "," or ")" here */
  1014.        if (!END_OF_COMMAND && equals(c_token, ","))
  1015.         c_token++;        /* loop again */
  1016.        else
  1017.         break;            /* hopefully ")" */
  1018.     }
  1019.     
  1020.     if (END_OF_COMMAND || !equals(c_token, ")")) {
  1021.        free_marklist(list);
  1022.        int_error("expecting right parenthesis )", c_token);
  1023.     }
  1024.     c_token++;
  1025.     
  1026.     /* successful list */
  1027.     if (tdef->type == TIC_USER) {
  1028.        /* remove old list */
  1029.         /* VAX Optimiser was stuffing up following line. Turn Optimiser OFF */
  1030.        free_marklist(tdef->def.user);
  1031.        tdef->def.user = NULL;
  1032.     }
  1033.     tdef->type = TIC_USER;
  1034.     tdef->def.user = list;
  1035. }
  1036.  
  1037. static void
  1038. free_marklist(list)
  1039.     struct ticmark *list;
  1040. {
  1041.     register struct ticmark *freeable;
  1042.  
  1043.     while (list != NULL) {
  1044.        freeable = list;
  1045.        list = list->next;
  1046.        if (freeable->label != NULL)
  1047.         free( (char *)freeable->label );
  1048.        free( (char *)freeable );
  1049.     }
  1050. }
  1051.  
  1052. /* load TIC_SERIES definition */
  1053. /* start,incr[,end] */
  1054. static void
  1055. load_tic_series(tdef)
  1056.     struct ticdef *tdef;
  1057. {
  1058.     double start, incr, end;
  1059.     struct value a;
  1060.     int incr_token;
  1061.  
  1062.     start = real(const_express(&a));
  1063.     if (!equals(c_token, ","))
  1064.      int_error("expecting comma to separate start,incr", c_token);
  1065.     c_token++;
  1066.  
  1067.     incr_token = c_token;
  1068.     incr = real(const_express(&a));
  1069.  
  1070.     if (END_OF_COMMAND)
  1071.      end = VERYLARGE;
  1072.     else {
  1073.        if (!equals(c_token, ","))
  1074.         int_error("expecting comma to separate incr,end", c_token);
  1075.        c_token++;
  1076.  
  1077.        end = real(const_express(&a));
  1078.     }
  1079.     if (!END_OF_COMMAND)
  1080.      int_error("tic series is defined by start,increment[,end]", 
  1081.              c_token);
  1082.     
  1083.     if (start < end && incr <= 0)
  1084.      int_error("increment must be positive", incr_token);
  1085.     if (start > end && incr >= 0)
  1086.      int_error("increment must be negative", incr_token);
  1087.     if (start > end) {
  1088.        /* put in order */
  1089.         double numtics;
  1090.         numtics = floor( (end*(1+SIGNIF) - start)/incr );
  1091.         end = start;
  1092.         start = end + numtics*incr;
  1093.         incr = -incr;
  1094. /*
  1095.        double temp = start;
  1096.        start = end;
  1097.        end = temp;
  1098.        incr = -incr;
  1099.  */
  1100.     }
  1101.  
  1102.     if (tdef->type == TIC_USER) {
  1103.        /* remove old list */
  1104.         /* VAX Optimiser was stuffing up following line. Turn Optimiser OFF */
  1105.        free_marklist(tdef->def.user);
  1106.        tdef->def.user = NULL;
  1107.     }
  1108.     tdef->type = TIC_SERIES;
  1109.     tdef->def.series.start = start;
  1110.     tdef->def.series.incr = incr;
  1111.     tdef->def.series.end = end;
  1112. }
  1113.  
  1114. static void
  1115. load_offsets (a, b, c, d)
  1116. double *a,*b, *c, *d;
  1117. {
  1118. struct value t;
  1119.  
  1120.     *a = real (const_express(&t));  /* loff value */
  1121.     c_token++;
  1122.     if (equals(c_token,","))
  1123.         c_token++;
  1124.     if (END_OF_COMMAND) 
  1125.         return;
  1126.  
  1127.     *b = real (const_express(&t));  /* roff value */
  1128.     c_token++;
  1129.     if (equals(c_token,","))
  1130.         c_token++;
  1131.     if (END_OF_COMMAND) 
  1132.         return;
  1133.  
  1134.     *c = real (const_express(&t));  /* toff value */
  1135.     c_token++;
  1136.     if (equals(c_token,","))
  1137.         c_token++;
  1138.     if (END_OF_COMMAND) 
  1139.         return;
  1140.  
  1141.     *d = real (const_express(&t));  /* boff value */
  1142.     c_token++;
  1143. }
  1144.  
  1145.  
  1146. BOOLEAN                    /* TRUE if a or b were changed */
  1147. load_range(a,b)            /* also used by command.c */
  1148. double *a,*b;
  1149. {
  1150. struct value t;
  1151. BOOLEAN changed = FALSE;
  1152.  
  1153.     if (equals(c_token,"]"))
  1154.         return(FALSE);
  1155.     if (END_OF_COMMAND) {
  1156.         int_error("starting range value or ':' or 'to' expected",c_token);
  1157.     } else if (!equals(c_token,"to") && !equals(c_token,":"))  {
  1158.         *a = real(const_express(&t));
  1159.         changed = TRUE;
  1160.     }    
  1161.     if (!equals(c_token,"to") && !equals(c_token,":"))
  1162.         int_error("':' or keyword 'to' expected",c_token);
  1163.     c_token++;
  1164.     if (!equals(c_token,"]")) {
  1165.         *b = real(const_express(&t));
  1166.         changed = TRUE;
  1167.      }
  1168.      return(changed);
  1169. }
  1170.  
  1171.  
  1172.  
  1173. /******* The 'show' command *******/
  1174. void
  1175. show_command()
  1176. {
  1177.     c_token++;
  1178.  
  1179.     if (almost_equals(c_token,"ac$tion_table") ||
  1180.              equals(c_token,"at") ) {
  1181.         c_token++; 
  1182.         show_at();
  1183.         c_token++;
  1184.     }
  1185.     else if (almost_equals(c_token,"ar$row")) {
  1186.         struct value a;
  1187.         int tag = 0;
  1188.  
  1189.         c_token++;
  1190.         if (!END_OF_COMMAND) {
  1191.            tag = (int)real(const_express(&a));
  1192.            if (tag <= 0)
  1193.             int_error("tag must be > zero", c_token);
  1194.         }
  1195.  
  1196.         (void) putc('\n',stderr);
  1197.         show_arrow(tag);
  1198.     }
  1199.     else if (almost_equals(c_token,"au$toscale")) {
  1200.         (void) putc('\n',stderr);
  1201.         show_autoscale();
  1202.         c_token++;
  1203.     }
  1204.     else if (almost_equals(c_token,"c$lip")) {
  1205.         (void) putc('\n',stderr);
  1206.         show_clip();
  1207.         c_token++;
  1208.     }
  1209.     else if (almost_equals(c_token,"d$ata")) {
  1210.         c_token++;
  1211.         if (!almost_equals(c_token,"s$tyle"))
  1212.             int_error("expecting keyword 'style'",c_token);
  1213.         (void) putc('\n',stderr);
  1214.         show_style("data",data_style);
  1215.         c_token++;
  1216.     }
  1217.     else if (almost_equals(c_token,"d$ummy")) {
  1218.         (void) fprintf(stderr,"\n\tdummy variable is %s\n",dummy_var);
  1219.         c_token++;
  1220.     }
  1221.     else if (almost_equals(c_token,"fo$rmat")) {
  1222.         show_format();
  1223.         c_token++;
  1224.     }
  1225.     else if (almost_equals(c_token,"f$unctions")) {
  1226.         c_token++;
  1227.         if (almost_equals(c_token,"s$tyle"))  {
  1228.             (void) putc('\n',stderr);
  1229.             show_style("functions",func_style);
  1230.             c_token++;
  1231.         }
  1232.         else
  1233.             show_functions();
  1234.     }
  1235.     else if (almost_equals(c_token,"lo$gscale")) {
  1236.         (void) putc('\n',stderr);
  1237.         show_logscale();
  1238.         c_token++;
  1239.     }
  1240.     else if (almost_equals(c_token,"of$fsets")) {
  1241.         (void) putc('\n',stderr);
  1242.         show_offsets();
  1243.         c_token++;
  1244.     }
  1245.     else if (almost_equals(c_token,"o$utput")) {
  1246.         (void) putc('\n',stderr);
  1247.         show_output();
  1248.         c_token++;
  1249.     }
  1250.     else if (almost_equals(c_token,"tit$le")) {
  1251.         (void) putc('\n',stderr);
  1252.         show_title();
  1253.         c_token++;
  1254.     }
  1255.     else if (almost_equals(c_token,"xl$abel")) {
  1256.         (void) putc('\n',stderr);
  1257.         show_xlabel();
  1258.         c_token++;
  1259.     }
  1260.     else if (almost_equals(c_token,"yl$abel")) {
  1261.         (void) putc('\n',stderr);
  1262.         show_ylabel();
  1263.         c_token++;
  1264.     }
  1265.     else if (almost_equals(c_token,"la$bel")) {
  1266.         struct value a;
  1267.         int tag = 0;
  1268.  
  1269.         c_token++;
  1270.         if (!END_OF_COMMAND) {
  1271.            tag = (int)real(const_express(&a));
  1272.            if (tag <= 0)
  1273.             int_error("tag must be > zero", c_token);
  1274.         }
  1275.  
  1276.         (void) putc('\n',stderr);
  1277.         show_label(tag);
  1278.     }
  1279.     else if (almost_equals(c_token,"g$rid")) {
  1280.         (void) putc('\n',stderr);
  1281.         show_grid();
  1282.         c_token++;
  1283.     }
  1284.     else if (almost_equals(c_token,"k$ey")) {
  1285.         (void) putc('\n',stderr);
  1286.         show_key();
  1287.         c_token++;
  1288.     }
  1289.     else if (almost_equals(c_token,"p$lot")) {
  1290.         (void) putc('\n',stderr);
  1291.         show_plot();
  1292.         c_token++;
  1293.     }
  1294.     else if (almost_equals(c_token,"pol$ar")) {
  1295.         (void) putc('\n',stderr);
  1296.         show_polar();
  1297.         c_token++;
  1298.     }
  1299.     else if (almost_equals(c_token,"ti$cs")) {
  1300.         (void) putc('\n',stderr);
  1301.         show_tics(TRUE, TRUE);
  1302.         c_token++;
  1303.     }
  1304.     else if (almost_equals(c_token,"xti$cs")) {
  1305.         show_tics(TRUE, FALSE);
  1306.         c_token++;
  1307.     }
  1308.     else if (almost_equals(c_token,"yti$cs")) {
  1309.         show_tics(FALSE, TRUE);
  1310.         c_token++;
  1311.     }
  1312.     else if (almost_equals(c_token,"sa$mples")) {
  1313.         (void) putc('\n',stderr);
  1314.         show_samples();
  1315.         c_token++;
  1316.     }
  1317.     else if (almost_equals(c_token,"si$ze")) {
  1318.         (void) putc('\n',stderr);
  1319.         show_size();
  1320.         c_token++;
  1321.     }
  1322.     else if (almost_equals(c_token,"t$erminal")) {
  1323.         (void) putc('\n',stderr);
  1324.         show_term();
  1325.         c_token++;
  1326.     }
  1327.     else if (almost_equals(c_token,"v$ariables")) {
  1328.         show_variables();
  1329.         c_token++;
  1330.     }
  1331.     else if (almost_equals(c_token,"ve$rsion")) {
  1332.         show_version();
  1333.         c_token++;
  1334.     }
  1335.     else if (almost_equals(c_token,"xr$ange")) {
  1336.         (void) putc('\n',stderr);
  1337.         show_range('x',xmin,xmax);
  1338.         c_token++;
  1339.     }
  1340.     else if (almost_equals(c_token,"yr$ange")) {
  1341.         (void) putc('\n',stderr);
  1342.         show_range('y',ymin,ymax);
  1343.         c_token++;
  1344.     }
  1345.     else if (almost_equals(c_token,"z$ero")) {
  1346.         (void) putc('\n',stderr);
  1347.         show_zero();
  1348.         c_token++;
  1349.     }
  1350.     else if (almost_equals(c_token,"a$ll")) {
  1351.         c_token++;
  1352.         show_version();
  1353.         show_autoscale();
  1354.         show_clip();
  1355.         (void) fprintf(stderr,"\tdummy variable is %s\n",dummy_var);
  1356.         show_format();
  1357.         show_style("data",data_style);
  1358.         show_style("functions",func_style);
  1359.         show_grid();
  1360.         show_label(0);
  1361.         show_arrow(0);
  1362.         show_key();
  1363.         show_logscale();
  1364.         show_offsets();
  1365.         show_output();
  1366.         show_polar();
  1367.         show_samples();
  1368.         show_size();
  1369.         show_term();
  1370.         show_tics(TRUE,TRUE);
  1371.         show_range('x',xmin,xmax);
  1372.         show_range('y',ymin,ymax);
  1373.         show_title();
  1374.         show_xlabel();
  1375.         show_ylabel();
  1376.         show_zero();
  1377.         show_plot();
  1378.         show_variables();
  1379.         show_functions();
  1380.         c_token++;
  1381.     }
  1382.     else
  1383.         int_error(
  1384.     "valid show options:  'action_table', 'all', 'arrow', 'autoscale',  \n\
  1385.     'clip', 'data', 'dummy', 'format', 'function', 'grid', 'key', 'label', \n\
  1386.     'logscale', 'offsets', 'output', 'plot', 'polar', 'samples', \n\
  1387.     'size', 'terminal', 'tics', 'title', 'variables', 'version', \n\
  1388.     'xlabel', 'xrange', 'xtics', 'ylabel', 'yrange', 'ytics', 'zero'", c_token);
  1389.     screen_ok = FALSE;
  1390.     (void) putc('\n',stderr);
  1391. }
  1392.  
  1393.  
  1394. /*********** support functions for 'show'  **********/
  1395. static void
  1396. show_style(name,style)
  1397. char name[];
  1398. enum PLOT_STYLE style;
  1399. {
  1400.     fprintf(stderr,"\t%s are plotted with ",name);
  1401.     switch (style) {
  1402.         case LINES: fprintf(stderr,"lines\n"); break;
  1403.         case POINTS: fprintf(stderr,"points\n"); break;
  1404.         case IMPULSES: fprintf(stderr,"impulses\n"); break;
  1405.         case LINESPOINTS: fprintf(stderr,"linespoints\n"); break;
  1406.         case DOTS: fprintf(stderr,"dots\n"); break;
  1407.     }
  1408. }
  1409.  
  1410. static void
  1411. show_range(name,min,max)
  1412. char name;
  1413. double min,max;
  1414. {
  1415.     fprintf(stderr,"\t%crange is [%g : %g]\n",name,min,max);
  1416. }
  1417.  
  1418. static void
  1419. show_zero()
  1420. {
  1421.     fprintf(stderr,"\tzero is %g\n",zero);
  1422. }
  1423.  
  1424. static void
  1425. show_offsets()
  1426. {
  1427.     fprintf(stderr,"\toffsets are %g, %g, %g, %g\n",loff,roff,toff,boff);
  1428. }
  1429.  
  1430. static void
  1431. show_output()
  1432. {
  1433.     fprintf(stderr,"\toutput is sent to %s\n",outstr);
  1434. }
  1435.  
  1436. static void
  1437. show_samples()
  1438. {
  1439.     fprintf(stderr,"\tsampling rate is %d\n",samples);
  1440. }
  1441.  
  1442. static void
  1443. show_size()
  1444. {
  1445.     fprintf(stderr,"\tsize is scaled by %g,%g\n",xsize,ysize);
  1446. }
  1447.  
  1448. static void
  1449. show_title()
  1450. {
  1451.     fprintf(stderr,"\ttitle is \"%s\"\n",title);
  1452. }
  1453.  
  1454. static void
  1455. show_xlabel()
  1456. {
  1457.     fprintf(stderr,"\txlabel is \"%s\"\n",xlabel);
  1458. }
  1459.  
  1460. static void
  1461. show_ylabel()
  1462. {
  1463.     fprintf(stderr,"\tylabel is \"%s\"\n",ylabel);
  1464. }
  1465.  
  1466. static void
  1467. show_label(tag)
  1468.     int tag;                /* 0 means show all */
  1469. {
  1470.     struct text_label *this_label;
  1471.     BOOLEAN showed = FALSE;
  1472.  
  1473.     for (this_label = first_label; this_label != NULL;
  1474.         this_label = this_label->next) {
  1475.        if (tag == 0 || tag == this_label->tag) {
  1476.           showed = TRUE;
  1477.           fprintf(stderr,"\tlabel %d \"%s\" at %g,%g ",
  1478.                 this_label->tag, this_label->text, 
  1479.                 this_label->x, this_label->y);
  1480.           switch(this_label->pos) {
  1481.              case LEFT : {
  1482.                 fprintf(stderr,"left");
  1483.                 break;
  1484.              }
  1485.              case CENTRE : {
  1486.                 fprintf(stderr,"centre");
  1487.                 break;
  1488.              }
  1489.              case RIGHT : {
  1490.                 fprintf(stderr,"right");
  1491.                 break;
  1492.              }
  1493.           }
  1494.           fputc('\n',stderr);
  1495.        }
  1496.     }
  1497.     if (tag > 0 && !showed)
  1498.      int_error("label not found", c_token);
  1499. }
  1500.  
  1501. static void
  1502. show_arrow(tag)
  1503.     int tag;                /* 0 means show all */
  1504. {
  1505.     struct arrow_def *this_arrow;
  1506.     BOOLEAN showed = FALSE;
  1507.  
  1508.     for (this_arrow = first_arrow; this_arrow != NULL;
  1509.         this_arrow = this_arrow->next) {
  1510.        if (tag == 0 || tag == this_arrow->tag) {
  1511.           showed = TRUE;
  1512.           fprintf(stderr,"\tarrow %d from %g,%g to %g,%g\n",
  1513.                 this_arrow->tag, 
  1514.                 this_arrow->sx, this_arrow->sy,
  1515.                 this_arrow->ex, this_arrow->ey);
  1516.        }
  1517.     }
  1518.     if (tag > 0 && !showed)
  1519.      int_error("arrow not found", c_token);
  1520. }
  1521.  
  1522. static void
  1523. show_grid()
  1524. {
  1525.     fprintf(stderr,"\tgrid is %s\n",(grid)? "ON" : "OFF");
  1526. }
  1527.  
  1528. static void
  1529. show_key()
  1530. {
  1531.     switch (key) {
  1532.         case -1 : 
  1533.             fprintf(stderr,"\tkey is ON\n");
  1534.             break;
  1535.         case 0 :
  1536.             fprintf(stderr,"\tkey is OFF\n");
  1537.             break;
  1538.         case 1 :
  1539.             fprintf(stderr,"\tkey is at %g,%g\n",key_x,key_y);
  1540.             break;
  1541.     }
  1542. }
  1543.  
  1544. static void
  1545. show_polar()
  1546. {
  1547.     fprintf(stderr,"\tpolar is %s\n",(polar)? "ON" : "OFF");
  1548. }
  1549.  
  1550. static void
  1551. show_tics(showx, showy)
  1552.     BOOLEAN showx, showy;
  1553. {
  1554.     fprintf(stderr,"\ttics are %s\n",(tic_in)? "IN" : "OUT");
  1555.  
  1556.     if (showx)
  1557.      show_ticdef(xtics, 'x', &xticdef);
  1558.     if (showy)
  1559.      show_ticdef(ytics, 'y', &yticdef);
  1560.     screen_ok = FALSE;
  1561. }
  1562.  
  1563. /* called by show_tics */
  1564. static void
  1565. show_ticdef(tics, axis, tdef)
  1566.     BOOLEAN tics;            /* xtics or ytics */
  1567.     char axis;            /* 'x' or 'y' */
  1568.     struct ticdef *tdef;    /* xticdef or yticdef */
  1569. {
  1570.     register struct ticmark *t;
  1571.  
  1572.     fprintf(stderr, "\t%c-axis tic labelling is ", axis);
  1573.     if (!tics) {
  1574.        fprintf(stderr, "OFF\n");
  1575.        return;
  1576.     }
  1577.  
  1578.     switch(tdef->type) {
  1579.        case TIC_COMPUTED: {
  1580.           fprintf(stderr, "computed automatically\n");
  1581.           break;
  1582.        }
  1583.        case TIC_SERIES: {
  1584.           if (tdef->def.series.end == VERYLARGE)
  1585.             fprintf(stderr, "series from %g by %g\n", 
  1586.                   tdef->def.series.start, tdef->def.series.incr);
  1587.           else
  1588.             fprintf(stderr, "series from %g by %g until %g\n", 
  1589.                   tdef->def.series.start, tdef->def.series.incr, 
  1590.                   tdef->def.series.end);
  1591.           break;
  1592.        }
  1593.        case TIC_USER: {
  1594.           fprintf(stderr, "list (");
  1595.           for (t = tdef->def.user; t != NULL; t=t->next) {
  1596.              if (t->label)
  1597.                fprintf(stderr, "\"%s\" ", t->label);
  1598.              if (t->next)
  1599.                fprintf(stderr, "%g, ", t->position);
  1600.              else
  1601.                fprintf(stderr, "%g", t->position);
  1602.           }
  1603.           fprintf(stderr, ")\n");
  1604.           break;
  1605.        }
  1606.        default: {
  1607.           int_error("unknown ticdef type in show_ticdef()", NO_CARET);
  1608.           /* NOTREACHED */
  1609.        }
  1610.     }
  1611. }
  1612.  
  1613. static void
  1614. show_term()
  1615. {
  1616.     fprintf(stderr,"\tterminal type is %s\n",term_tbl[term].name);
  1617. }
  1618.  
  1619. static void
  1620. show_plot()
  1621. {
  1622.     fprintf(stderr,"\tlast plot command was: %s\n",replot_line);
  1623. }
  1624.  
  1625. static void
  1626. show_autoscale()
  1627. {
  1628.     fprintf(stderr,"\tx autoscaling is %s\n",(autoscale_x)? "ON" : "OFF");
  1629.     fprintf(stderr,"\ty autoscaling is %s\n",(autoscale_y)? "ON" : "OFF");
  1630. }
  1631.  
  1632. static void
  1633. show_clip()
  1634. {
  1635.     fprintf(stderr,"\tpoint clip is %s\n",(clip_points)? "ON" : "OFF");
  1636.  
  1637.     if (clip_lines1)
  1638.       fprintf(stderr,
  1639.          "\tdrawing and clipping lines between inrange and outrange points\n");
  1640.     else
  1641.       fprintf(stderr,
  1642.          "\tnot drawing lines between inrange and outrange points\n");
  1643.  
  1644.     if (clip_lines2)
  1645.       fprintf(stderr,
  1646.          "\tdrawing and clipping lines between two outrange points\n");
  1647.     else
  1648.       fprintf(stderr,
  1649.          "\tnot drawing lines between two outrange points\n");
  1650. }
  1651.  
  1652. static void
  1653. show_format()
  1654. {
  1655.     fprintf(stderr, "\tx-axis tic format is \"%s\"\n", xformat);
  1656.     fprintf(stderr, "\ty-axis tic format is \"%s\"\n", yformat);
  1657. }
  1658.  
  1659. static void
  1660. show_logscale()
  1661. {
  1662.     if (log_x && log_y)
  1663.         fprintf(stderr,"\tlogscaling both x and y axes\n");
  1664.     else if (log_x)
  1665.         fprintf(stderr,"\tlogscaling x axis\n");
  1666.     else if (log_y)
  1667.         fprintf(stderr,"\tlogscaling y axis\n");
  1668.     else
  1669.         fprintf(stderr,"\tno logscaling\n");
  1670. }
  1671.  
  1672. static void
  1673. show_variables()
  1674. {
  1675. register struct udvt_entry *udv = first_udv;
  1676. int len;
  1677.  
  1678.     fprintf(stderr,"\n\tVariables:\n");
  1679.     while (udv) {
  1680.          len = instring(udv->udv_name, ' ');
  1681.         fprintf(stderr,"\t%-*s ",len,udv->udv_name);
  1682.         if (udv->udv_undef)
  1683.             fputs("is undefined\n",stderr);
  1684.         else {
  1685.             fputs("= ",stderr);
  1686.             disp_value(stderr,&(udv->udv_value));
  1687.             (void) putc('\n',stderr);
  1688.         }
  1689.         udv = udv->next_udv;
  1690.     }
  1691. }
  1692.  
  1693. void                /* used by plot.c */
  1694. show_version()
  1695. {
  1696. extern char version[];
  1697. extern char patchlevel[];
  1698. extern char date[];
  1699. extern char bug_email[];
  1700. static char *authors[] = {"Thomas Williams","Colin Kelley"}; /* primary */
  1701. int x;
  1702. long time();
  1703.  
  1704.     x = time((long *)NULL) & 1;
  1705.     fprintf(stderr,"\n\t%s\n\t%sversion %s\n",
  1706.         PROGRAM, OS, version); 
  1707.     fprintf(stderr,"\tpatchlevel %s\n",patchlevel);
  1708.      fprintf(stderr, "\tlast modified %s\n", date);
  1709.     fprintf(stderr,"\tCopyright (C) 1986, 1987, 1990  %s, %s\n",
  1710.         authors[x],authors[1-x]);
  1711. #ifdef __TURBOC__
  1712.     fprintf(stderr,"\tCreated using Turbo C, Copyright Borland 1987, 1988\n");
  1713. #endif
  1714.     fprintf(stderr, "\n\tSend bugs and comments to %s\n", bug_email);
  1715. }
  1716.