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