home *** CD-ROM | disk | FTP | other *** search
/ Graphics 16,000 / graphics-16000.iso / msdos / viewers / showgl19 / hpgl2.c < prev    next >
C/C++ Source or Header  |  1992-08-18  |  23KB  |  841 lines

  1. #pragma linesize(132)    /* listing linewidth = 132 */
  2. /* hpgl2.c */
  3.  
  4. /* Copyright 1991-1992, Robert C. Becker */
  5.  
  6. /* rev. C 8/18/92
  7.  
  8.     Added code for TD (transparent data) to hpgl2.c */
  9.  
  10. /* rev. B 8/13/92
  11.  
  12.     Relocated some code from hpgl1.c to hpgl2.c to make file sizes more
  13. equal and reduce compile time of hpgl1.c . */
  14.  
  15. /* rev. A  8/3/92
  16.  
  17.     Found a bug in labeling routine.  If no label terminator char
  18. was found, the routine would not stop reading at the EOF.  Cause was traced
  19. to comparing an unsigned char with (char) EOF: changed to (unsigned char) EOF.
  20. */
  21.  
  22. /* this file contains the following functions:
  23.  
  24.     begin_plot ()
  25.     calc_csize ()
  26.     char_plot ()
  27.     define_path ()
  28.     draw_arc ()
  29.     draw_wedge ()
  30.     extra_space ()
  31.     get_xy ()
  32.     get_val ()
  33.     label_dir ()
  34.     label_graph ()
  35.     label_origin ()
  36.     label_term ()
  37.     line_pattern ()
  38.     page_adv ()
  39.     recalc_csize ()
  40.     set_csize ()
  41.     set_slant ()
  42.     symbol_mark ()
  43.     xparent_data ()
  44. */
  45.  
  46. #include <stdio.h>
  47. #include <math.h>
  48. #define NO_VIDEO        /* define no video for hpgl.h */
  49. #include "hpgl.h"
  50. #include "graph.h"
  51.  
  52. extern struct csizes cs;
  53. extern struct cplot cp;
  54. extern int chord_type, p_status, symbol_mode;
  55. extern char symbol;
  56.  
  57. extern double p1x, p2x, p1y, p2y;
  58. extern unsigned endlabel;
  59.  
  60. static char copyright[] = "Copyright 1991-1992, Robert C. Becker, Lantern Systems";
  61. static unsigned char label_bfr[LABEL_BFR];
  62. static double es_x, es_y;
  63. static char bfr[256];            /* scratch char buffer for get_val */
  64.  
  65. /*--------------------------------------*/
  66.  
  67. void label_origin (FILE * infile)
  68.     {
  69.     double x;
  70.     int l;
  71.  
  72.     if (!get_val (infile, &x) )
  73.         {
  74.         cp.lorg = LORG_DEFAULT;
  75.         return;
  76.         }
  77.     l = (int) x;
  78.     if (l > 19 || l < 1 || l == 10)    /* no lorg (10) */
  79.         {
  80.         print_string ("LO: value out of range\n");
  81.         return;        /* no changes */
  82.         }
  83.     cp.lorg = l;    /* new label origin */
  84.     return;
  85.     }
  86.  
  87. /*--------------------------------------*/
  88.  
  89. void line_pattern (FILE * infile)
  90.     {
  91.     double x, y;
  92.     int l;
  93.  
  94.     DB (printf ("line_pattern\n");)
  95.     if ( !get_val (infile, &x) )
  96.         {    /* default line type */
  97.         DB (printf ("line_pattern: default pattern\n");)
  98.         line_type (1, 0);
  99.         return;
  100.         }
  101.     else
  102.         {
  103.         DB (printf ("line_pattern: line type = %lf\n", x);)
  104.         if (x < 0)        /* line type w/pattern # */
  105.             {
  106.             print_noinstr ("Adaptive line type");
  107.             return;
  108.             }
  109.         l = (int) (MAX (0.0, MIN (6.0, x)) ) + 2;
  110.             /* translate HPGL patterns to library patterns */
  111.         if (!get_val (infile, &y))
  112.             {
  113.             DB (printf ("line_pattern: line pattern = %d\n", l);)
  114.             line_type (l, 0);
  115.             return;
  116.             }
  117.         else    /* line type w/pattern # and repeat length */
  118.             {
  119.             DB (printf ("line_pattern: line pattern = %d, length = %lf\n", l, MIN (y, 127.9999));)
  120.             line_type (l, MAX (0.0, MIN ( y, 127.9999)));
  121.             return;
  122.             }
  123.         }
  124.     return;
  125.     }
  126.  
  127. /*--------------------------------------*/
  128.  
  129. void set_csize (FILE * infile, int type)
  130.     {    /* type: 0 -> absolute, 1 -> relative */
  131.         /* set height (y) and width (x) of char (in cm) */
  132.     double x, y;
  133.  
  134.     if (type == RELATIVE)
  135.         {        /* relative size */
  136.         cs.rcsize_x = x = 0.75;    /* width: 0.75% (p2x - p1x) */
  137.         cs.rcsize_y = y = 1.50;    /* height: 1.5% (p2y - p1y) */
  138.         }
  139.     else
  140.         {        /* absolute size */
  141.         cs.acsize_x = x = 0.19;    /* default width (cm) */
  142.         cs.acsize_y = y = 0.27;
  143.         }
  144.     if (get_val (infile, &x) )    /* got width value: need height */
  145.         {
  146.         if ( !get_val (infile, &y))    /* missing height */
  147.             {
  148.             if (type == RELATIVE)
  149.                 print_string ("SR: missing height parameter\n");
  150.             else
  151.                 print_string ("SI: missing height parameter\n");
  152.             return;
  153.             }
  154.         }
  155.  
  156.     x = MAX (-128.00, (MIN (127.9999, x)));
  157.     y = MAX (-128.00, (MIN (127.9999, y)));
  158.  
  159.     calc_csize (x, y, type);    /* set char size */
  160.  
  161.     return;
  162.     }
  163.  
  164. /*--------------------------------------*/
  165.  
  166. void recalc_csize (void)
  167.     {
  168.  
  169.     DB (printf ("recalc_csize: cs.cscale_mode = %d\n", cs.cscale_mode);)
  170.     if (cs.cscale_mode) 
  171.         {
  172.         DB (printf ("recalc_csize: cs.rcsize_x = %lf, cs.rcsize_y = %lf\n", cs.rcsize_x, cs.rcsize_y);)
  173.         calc_csize (cs.rcsize_x, cs.rcsize_y, cs.cscale_mode);
  174.         }    /* rescale char size for relative scaling */
  175.     else
  176.         {
  177.         DB (printf ("recalc_csize: cs.acsize_x = %lf, cs.acsize_y = %lf\n", cs.acsize_x, cs.acsize_y);)
  178.         calc_csize (cs.acsize_x, cs.acsize_y, cs.cscale_mode);
  179.         }    /* rescale char size for absolute scaling */
  180.  
  181.     return;
  182.     }
  183.  
  184. /*--------------------------------------*/
  185.  
  186. void calc_csize (double x, double y, int type)
  187.     {
  188.     double ar;
  189.  
  190.     cs.cscale_mode = 0;    /* default to abs. char size scaling */
  191.     if (type == RELATIVE)    /* relative char size: convert to cm */
  192.         {
  193.         cs.cscale_mode = 1;    /* turn on relative char size scaling */
  194.         cs.rcsize_x = x;
  195.         cs.rcsize_y = y;    /* save relative csizes for changes in IP */
  196.         x = x * fabs (p2x - p1x) * 0.00254 / 100.0;
  197.         y = y * fabs (p2y - p1y) * 0.00254 / 100.0;
  198.         }    /* P1, P2 are in mils.  0.00254 cm/mil */
  199.  
  200.     cs.acsize_x = x;
  201.     cs.acsize_y = y;    /* save absolute char sizes */
  202.  
  203.     x = cs.csize_x = cs.csize_basis * (10.0) * ((p1x > p2x) ? -x : x);    /* convert from cm to mm's for csize () */
  204.     y = cs.csize_y = cs.csize_basis * (10.0) * ((p1y > p2y) ? -y : y);    /* correct for reflection/inversion of P2 - P1 */
  205.         /* cs.csize_x, cs.csize_y save char size for SL function */
  206.         /* cs.csize_basis changes char size to maintain proportion to paper size */
  207.  
  208.     ar = x / fabs (y);            /* aspect ratio */
  209.     /* need fabs() to isolate AR from possibly negative y-size, but retain sign of x */
  210.  
  211.     if (type == ABSOLUTE) cs.csize_y = (y *= 0.725);
  212.         /* factor of 0.725 corrects default graphix lib font size to 
  213.         HPGL plotter font size for absolute font sizes (this is a patch) */
  214.  
  215.     csize (y, ar, cs.slant);    /* height (in cm), aspect ratio, slant (deg)  */
  216.     return;
  217.     }
  218.  
  219. /*--------------------------------------*/
  220.  
  221. void set_slant ( FILE *infile )
  222.     {
  223.     double ar, x;
  224.  
  225.     DB (printf ("SL\n");)
  226.     x = 0.0;
  227.     get_val (infile, &x);    /* if no value present, x is unchanged */
  228.     x = MAX (-128.00, (MIN (127.9999, x)));
  229.     cs.slant = RAD_2_DEG * atan (x);    /* sl is in degrees */
  230.     DB (printf ("SL: angle = %lf\n", cs.slant);)
  231.  
  232.     ar = cs.csize_x / fabs (cs.csize_y);    /* aspect ratio */
  233.     /* need fabs() to isolate AR from possibly negative y-size, but retain sign of x */
  234.  
  235.     csize (cs.csize_y, ar, cs.slant);    /* height (in cm), aspect ratio, slant (deg)  */
  236.     return;
  237.     }
  238.  
  239. /*--------------------------------------*/
  240.  
  241. void extra_space ( double x, double y)
  242.     {
  243.  
  244.     es_x = x;    /* save extra space for char_plot */
  245.     es_y = y;
  246.     char_xspace (100.0 * x, 100.0 * y);    /* char_xspace takes % values */
  247.     return;
  248.     }
  249.  
  250. /*--------------------------------------*/
  251.  
  252. void char_plot (FILE *infile)
  253.     {
  254.     double x, y, x_1, y_1;
  255.     double lsin, lcos, xdir, ydir;
  256.  
  257.     if (get_val (infile, &x))    /* get # spaces */
  258.         {    /* got x-value: try for y-value */
  259.         if (!get_val (infile, &y)) y = 0.0;    /* get # linefeeds (if any) */
  260.         }
  261.     else    /* got no x-value: default to 1 linefeed */
  262.         {
  263.         move (cp.x, cp.y);
  264.         labelf ("\n");
  265.         where (&cp.x, &cp.y);
  266.         return;
  267.         }
  268.  
  269.     /* move x spaces "horizontally" and y lines "vertically" */
  270.     /* directions depend on current label direction & mirroring */
  271.  
  272.     DB (printf ("CP: x = %lf, y = %lf, cp.dv = %d\n", x, y, cp.dv);)
  273.     DB (printf ("CP1: cp.x = %lf, cp.y = %lf\n", cp.x, cp.y);)
  274.  
  275.     move (cp.x, cp.y);
  276.     setgu ();        /* this looks like a kludge, but it gets */
  277.     where (&x_1, &y_1);    /* around problems of not knowing character */
  278.                 /* sizes in both plotter and user units */
  279.  
  280.     lcos = cos ( (cp.ldir + cp.dvdir) / RAD_2_DEG );
  281.     lsin = sin ( (cp.ldir + cp.dvdir) / RAD_2_DEG );    /* label directions */
  282.  
  283.     xdir = (p1x > p2x) ? -1.0 : 1.0;
  284.     ydir = (p1y > p2y) ? -1.0 : 1.0;    /* correct for P1/P2 mirroring */
  285.  
  286.     switch (cp.dv)    /* calculate x, y move from # x, y spaces */
  287.         {
  288.         case 0:    /* horizontal */
  289.             x = x * cs.csize_x * CP_XSCALE * xdir * (1.0 + es_x);
  290.             y = y * cs.csize_y * CP_YSCALE * ydir * (1.0 + es_y);
  291.             break;
  292.         case 1:    /* -90 degrees: 'x' chars of y-size, 'y' chars of x-size */
  293.             x = x * cs.csize_y * CP_YSCALE * ydir * (1.0 + es_y);
  294.             y = y * cs.csize_x * CP_XSCALE * xdir * (1.0 + es_x);
  295.             break;
  296.         case 2:    /* 180 degrees */
  297.             x = x * cs.csize_x * CP_XSCALE * xdir * (1.0 + es_x);
  298.             y = y * cs.csize_y * CP_YSCALE * ydir * (1.0 + es_y);
  299.             break;
  300.         case 3:    /* 90 degrees: 'x' chars of y-size, 'y' chars of x-size */
  301.             x = x * cs.csize_y * CP_YSCALE * ydir * (1.0 + es_y);
  302.             y = y * cs.csize_x * CP_XSCALE * xdir * (1.0 + es_x);
  303.             break;
  304.         default: break;
  305.         }
  306.  
  307.     /* now rotate char offset to label direction */
  308.     x_1 += x * lcos - y * lsin;
  309.     y_1 += y * lcos + x * lsin;
  310.  
  311.     move (x_1, y_1);    /* new position */
  312.     setuu ();
  313.     where (&cp.x, &cp.y);
  314.  
  315.     DB (printf ("CP2: cp.x = %lf, cp.y = %lf\n", cp.x, cp.y);)
  316.  
  317.     return;
  318.     }
  319.  
  320. /*--------------------------------------*/
  321.  
  322. void label_graph (FILE * infile)
  323.     {
  324.     double xpos, ypos, x_offset, y_offset;
  325.     unsigned char c2;
  326.     int i;
  327.  
  328.     DB (printf ("LB\n");)
  329.     setgu ();            /* switch to GDU's */
  330.     where ( &xpos, &ypos );        /* get current position in GDU's */
  331.  
  332.     x_offset = y_offset = 0.0;
  333.     if (cp.lorg < 10)    /* anchor label to edges of label */
  334.         {
  335.         switch (cp.lorg)    /* these offsets derived by experimentation */
  336.             {
  337.             case 1:
  338.                 y_offset = -0.386 * cs.csize_y;
  339.                 x_offset = -0.10 * cs.csize_x;
  340.                 break;
  341.             case 2:
  342.                 x_offset = -0.10 * cs.csize_x;
  343.                 break;
  344.             case 3:
  345.                 y_offset = 0.303 * cs.csize_y;
  346.                 x_offset = -0.10 * cs.csize_x;
  347.                 break;
  348.             case 4:
  349.                 y_offset = -0.386 * cs.csize_y;
  350.                 break;
  351.             case 5: break;    /* centered in (x,y) */
  352.             case 6:
  353.                 y_offset = 0.303 * cs.csize_y;
  354.                 break;
  355.             case 7:
  356.                 x_offset = 0.09 * cs.csize_x;
  357.                 y_offset = -0.386 * cs.csize_y;
  358.                 break;
  359.             case 8:
  360.                 x_offset = 0.09 * cs.csize_x;
  361.                 break;
  362.             case 9:
  363.                 y_offset = 0.303 * cs.csize_y;
  364.                 x_offset = 0.09 * cs.csize_x;
  365.                 break;
  366.             default: break;
  367.             }
  368.         move (xpos + x_offset, ypos + y_offset);    /* correct for normally offset label origins */
  369.         lorg (cp.lorg);
  370.         }
  371.     else    /* normal label origins:  offset from edges of labels */
  372.         {
  373.         lorg (cp.lorg - 10);
  374.         }
  375.     setuu ();    /* back to user units */
  376.     i = 0;
  377.     while ( 1 )
  378.         {
  379.         label_bfr[i] = c2 = getc (infile);
  380.         DB (printf ("LB: c2 = 0x%02X\n", c2);)
  381.         if (i >= LABEL_BFR - 1 || c2 == '\n')
  382.              {
  383.             label_bfr[++i] = '\0';        /* terminate label string */
  384.             DB (printf ("LB: i = %d, labeling plot\n", i);)
  385.             labelf ("%s", label_bfr);    /* label the plot */
  386.             if (c2 == '\n')
  387.                 {
  388.                 setgu ();
  389.                 imove (-x_offset, -y_offset);    /* remove for label origin offset */
  390.                 setuu ();
  391.                 where (&cp.x, &cp.y);        /* get label position: new <cr> position for CP fn. */
  392.                 setgu ();
  393.                 imove (x_offset, y_offset);    /* restore for label origin offset */
  394.                 setuu ();
  395.                 }
  396.             i = 0;
  397.             continue;
  398.             }
  399.         if (c2 == endlabel || c2 == (unsigned char) EOF)
  400.              {
  401.             DB (printf ("LB:endlabel: c2 = 0x%02X\n", c2);)
  402.             label_bfr[i] = '\0';        /* terminate label string */
  403.             labelf ("%s", label_bfr);    /* label the plot */
  404.             setgu ();
  405.             imove (-x_offset, -y_offset);    /* remove for label origin offset */
  406.             setuu ();
  407.             break;
  408.             }
  409.         label_bfr[i++] = c2;
  410.          }
  411.     DB (printf ("end: LB\n");)
  412.     plotted_on (1);        /* we drew something on this plot */
  413.     return;
  414.     }
  415.  
  416. /*--------------------------------------*/
  417.  
  418. void define_path (FILE * infile)
  419.     {
  420.     double path, line;
  421.     int l, p;
  422.  
  423.     if (!get_val (infile, &path))    /* no parameters-> defaults */
  424.         {
  425.         cp.dv = 0;    /* store label direction for CP fn. */
  426.         cp.dvdir = 0.0;    /* clear stacking direction */
  427.         cdir (0);    /* char direction along label direction */
  428.         ldir (cp.ldir);    /* horizontal label directions */
  429.         return;
  430.         }
  431.     if (path < 0.0 || path > 3.0)
  432.         return;        /* illegal values: do nothing */
  433.     p = (int) path;
  434.     if ( get_val (infile, &line))
  435.         {    /* have a linefeed type param */
  436.         print_string ("DV: linefeed parameter not implimented\n");
  437.         if (line != 0.0 || line != 1.0)
  438.             l = 0;    /* force default for illegal value */
  439.         else
  440.             l = (int) line;
  441.         }
  442.  
  443.     switch (p)
  444.         {
  445.         case 0:            /* normal directions */
  446.             cdir (0.0);
  447.             cp.dvdir = 0.0;    /* normal stacking direction */
  448.             cp.dv = 0;    /* store direction code for CP fn. */
  449.             break;
  450.         case 1:            /* down with vertical stacking */
  451.             cdir (90.0);
  452.             cp.dvdir = -90.0;    /* downward label stacking */
  453.             cp.dv = 1;    /* store label direction for CP fn. */
  454.             break;
  455.         case 2:            /* left, with reversed lettering */
  456.             cdir (180.0);
  457.             cp.dvdir = 180.0;    /* left label stacking */
  458.             cp.dv = 2;    /* store label direction for CP fn. */
  459.             break;
  460.         case 3:            /* up with vertical stacking, reversed */
  461.             cdir (-90.0);
  462.             cp.dvdir = 90.0;    /* upward label stacking */
  463.             cp.dv = 3;    /* store label direction for CP fn. */
  464.             break;
  465.         default: break;
  466.         }
  467.     ldir (cp.ldir + cp.dvdir);    /* rotate DV angle by label direction */
  468.     return;
  469.     }
  470.  
  471. /*--------------------------------------*/
  472.  
  473. void symbol_mark (unsigned char symbol)
  474.     {
  475.  
  476.     lorg (5);
  477.     labelf ("%c", symbol);
  478.     if (cp.lorg < 10)
  479.         lorg (cp.lorg);
  480.     else
  481.         lorg (cp.lorg - 10);
  482.     return;
  483.     }
  484.  
  485. /*--------------------------------------*/
  486.  
  487. void label_term (FILE * infile)
  488.     {
  489.     unsigned l;
  490.     double x;
  491.  
  492.     l = (unsigned) getc (infile);
  493.     /* test for illegal values */
  494.     if ( l < 1 || l > 127 || l == 5 || l == 27) return;
  495.     endlabel = l;
  496.     return;
  497.     }
  498.  
  499. /*--------------------------------------*/
  500.  
  501. void label_dir (FILE * infile, int type)
  502.     {    /* set relative character direction */
  503.         /* type 0 -> abs, type 1 -> relative */
  504.     double rise, run;
  505.  
  506.     if ( !get_val (infile, &run))    /* get run value */
  507.          {    /* No value: ldir defaults to 0.0 */
  508.          cp.ldir = 0.0;    /* save for CP fn. */
  509.         ldir (cp.dvdir);    /* label in direction of text stacking */
  510.         return;
  511.         }
  512.     if ( !get_val (infile, &rise))    /* get rise value */
  513.         {
  514.         return;    /* no rise coordinate: error: do nothing */
  515.         }
  516.     if (type == ABSOLUTE)    /* absolute label direction */
  517.         {        /* set absolute angle, & save for CP fn. */
  518.         cp.ldir = RAD_2_DEG * atan2 (rise, run);
  519.         ldir ( cp.ldir + cp.dvdir );
  520.         return;
  521.         }
  522.  
  523.     if (rise < -128.0 || rise > 127.9999 || run < -128.0 || run > 127.9999) return;    /* fault */
  524.  
  525.     /* relative angle determined by delta P1:P2 plot scaling takes care of 
  526.     case where P1 > P2.  Must use fabs () to eliminate 2nd compensation 
  527.     for P1 > P2 in for relative directions */
  528.  
  529.     rise = rise * fabs (p2y - p1y) / 100.0;
  530.     run = run * fabs (p2x - p1x) / 100.0;
  531.  
  532.     /* set relative angle & save for CP fn. */
  533.  
  534.     cp.ldir = RAD_2_DEG * atan2 (rise, run);
  535.     ldir ( cp.ldir + cp.dvdir );
  536.  
  537.     return;
  538.     }
  539.  
  540. /*--------------------------------------*/
  541.  
  542. void begin_plot (FILE * infile)
  543.     {
  544.     double x;
  545.     unsigned l;
  546.     unsigned char c;
  547.  
  548.  
  549.     if ( plotted_on (0) )
  550.         {
  551.         twait (infile, PG_DELAY);    /* if we have a plot already up, delay screen clear */
  552.         gclear ();
  553.         }
  554.     initialize (infile);        /* initialize plotter */
  555.  
  556.     if (!get_val (infile, &x)) return;    /* no arguments */
  557.  
  558.     do        /* process arguments */
  559.         {
  560.         l = (int) x;
  561.         switch (l)
  562.             {
  563.             case 1:    /* newstring (in quotes) */
  564.                 c = getc (infile);    /* find 1st '"' char */
  565.                 while (c  && c != (unsigned char) EOF && c != '"') c = getc (infile);
  566.                 c = getc (infile);    /* dump everything through next '"' char */
  567.                 while (c  && c != (unsigned char) EOF && c != '"') c = getc (infile);
  568.                 break;
  569.             case 2:    /* number of copies: NOP */
  570.                 if (!get_val (infile, &x))    /* mus supply a value, anyway */
  571.                     {
  572.                     print_string ("BP: missing argument to number of copies\n");
  573.                     return;
  574.                     }
  575.                 break;
  576.             case 3:    /* file disposition code: NOP */
  577.                 if (!get_val (infile, &x))    /* must supply a disposition code, anyway */
  578.                     {
  579.                     print_string ("BP: missing file disposition code\n");
  580.                     return;
  581.                     }
  582.                 break;
  583.             case 4:    /* render last plot if unfinished */
  584.                 if (!get_val (infile, &x))
  585.                     {
  586.                     print_string ("BP: incomplete 'unfinished plot' rendering code\n");
  587.                     break;
  588.                     }
  589.             default:
  590.                 print_string ("BP: invalid kind parameter\n");
  591.                 return;    /* stop processing BP at invalid kind */
  592.                 break;
  593.             }
  594.         }
  595.     while (get_val (infile, &x));
  596.  
  597.     return;
  598.     }
  599.  
  600. /*--------------------------------------*/
  601.  
  602. void xparent_data (FILE * infile)
  603.     {
  604.     double x;
  605.  
  606.     x = 0.0;        /* value remains unchanged if nothing to read */
  607.     get_val (infile, &x);    /* read one possible value */
  608.     if (x != 1.0 && x != 0.0)
  609.         {
  610.         print_string ("TD: value out of range\n");
  611.         return;
  612.         }
  613.     if (x == 0.0)
  614.         disp_fns (DFN_OFF);    /* function code display off */
  615.     else
  616.         disp_fns (DFN_ON);    /*function code display on */
  617.  
  618.     return;
  619.     }
  620.  
  621. /*--------------------------------------*/
  622.  
  623. void page_adv (FILE * infile)
  624.     {
  625.     double x;
  626.  
  627.     get_val (infile, &x);    /* get possibly one value */
  628.     setgu ();
  629.     move (0.0, 0.0);    /* move to lower left corner of hard clip */
  630.     setuu ();
  631.     twait (infile, PG_DELAY);    /* delay PG_DELAY seconds */
  632.     gclear ();
  633.     plotted_on (0);        /* new page */
  634.     return;
  635.     }
  636.  
  637. /*--------------------------------------*/
  638.  
  639. void draw_arc (FILE * infile, int type )
  640.     {    /* type: 0 -> absolute, 1 -> relative */
  641.     double radius, x, y, x_1, y_1, x_2, y_2, val4, ang1, ang2, ang3;
  642.     unsigned char c2;
  643.     int segs;
  644.  
  645.     DB (if (type == RELATIVE) printf ("AR\n"); else printf ("AA\n");)
  646.     if (!get_xy (infile, &x, &y))
  647.         {
  648.         if (type == RELATIVE)
  649.             print_string ("AR: missing x- or y-value\n");
  650.         else
  651.             print_string ("AA: missing x- or y-value\n");
  652.         return;    /* illegal instr */
  653.         }
  654.     if (!get_val (infile, &ang1))    /* arc angle */
  655.         {
  656.         if (type == RELATIVE)
  657.             print_string ("AR: missing arc angle\n");
  658.         else
  659.             print_string ("AA: missing arc angle\n");
  660.         return;    /* illegal instr */
  661.         }
  662.     DB (printf ("input value: x = %lf, y = %lf, ang1 = %lf\n", x, y, ang1);)
  663.     where (&x_1, &y_1);    /* get starting point */
  664.     if (type == RELATIVE)
  665.         {        /* relative */
  666.         DB (printf ("current location: (x,y) = (%lf, %lf)\n", x_1, y_1);)
  667.         x_2 = x_1 + x;
  668.         y_2 = y_1 + y;
  669.         x_1 = -x;
  670.         y_1 = -y;
  671.         }
  672.     else
  673.         {        /* absolute */
  674.         x_2 = x;
  675.         y_2 = y;    /* save center position */
  676.         x_1 -= x;
  677.         y_1 -= y;    /* delta-x, -y */
  678.         }
  679.     DB (printf ("arc center: (x,y) = (%lf, %lf), angle = %lf\n", x_2, y_2, ang1);)
  680.     move (x_2, y_2);    /* move to center of arc */
  681.     radius = sqrt (x_1*x_1 + y_1*y_1);
  682.  
  683.     ang2 = val4 = DEF_CHORD;
  684.     if (get_val (infile, &val4))
  685.         {
  686.         val4 = fabs (val4);    /* only positive values allowed */
  687.         if (chord_type == ANG || val4 == 0.0)        /* using angles, not deviations */
  688.             {
  689.             if (val4 == 0.0) val4 = DEF_CHORD;    /* set default chord angle or deviation */
  690.             ang2 = MIN (MAX_CHORD, (MAX (val4, MIN_CHORD)));
  691.             }
  692.         else        /* chord angle determined by deviation of segments from circle radius */
  693.             {    /* at this point, val4 is length in current units, not angle in degrees */
  694.             if (val4 > 2.0 * radius) val4 = 2.0 * radius;    /* limit deviation: resulting chord angle < 180 deg. */
  695.             ang2 = acos ( (radius - val4) / radius) * RAD_2_DEG;
  696.             }
  697.         }
  698.  
  699.     segs = (int) (fabs (ang1) / ang2 + 0.5);    /* # segments in "ang1" deg. */
  700.         /* sign of 'segs' changes direction of arc () */
  701.     DB (printf ("chord = %lf, # segments = %d\n", ang2, segs);)
  702.     ang3 = RAD_2_DEG * atan2 (y_1, x_1);
  703.     if (p_status == PENDOWN)    /* draw the arc only if pen is down */
  704.         {
  705.         DB (printf ("radius = %lf, start angle = %lf, stop angle = %lf\n", radius, ang3, ang1 + ang3);)
  706.         arc ( radius, segs, ang3, ang1 + ang3);
  707.         }
  708.     if (symbol_mode)
  709.         {
  710.         move (x_2, y_2);
  711.         symbol_mark (symbol);
  712.         }
  713.     plotted_on (1);        /* we drew something on this plot */
  714.     return;
  715.     }
  716.  
  717. /*--------------------------------------*/
  718.  
  719. void draw_wedge (FILE * infile)
  720.     {
  721.     double radius, xc, yc, x_1, y_1, val3, ang1, ang2, ang3;
  722.     int segs;
  723.  
  724.     DB (printf ("EW\n");)
  725.     if (!get_val (infile, &radius))
  726.         {
  727.         print_string ("EW: missing radius\n");
  728.         return;    /* illegal instr */
  729.         }
  730.     if (!get_val (infile, &ang1))
  731.         {
  732.         print_string ("EW: missing start_ang\n");
  733.         return;    /* illegal instr */
  734.         }
  735.     if (!get_val (infile, &ang2))    /* arc angle */
  736.         {
  737.         print_string ("EW: missing sweep angle\n");
  738.         return;    /* illegal instr */
  739.         }
  740.     where (&xc, &yc);    /* get starting point */
  741.     DB (printf ("center: (x,y) = (%lf, %lf), start angle = %lf\n", xc, yc, ang1);)
  742.  
  743.     val3 = ang3 = DEF_CHORD;
  744.     if (get_val (infile, &val3))
  745.         {
  746.         val3 = fabs (val3);    /* only positive values allowed */
  747.         if (chord_type == ANG || val3 == 0.0)        /* using angles, not deviations */
  748.             {
  749.             if (val3 == 0.0) val3 = DEF_CHORD;    /* set default chord angle or deviation */
  750.             ang3 = MIN (MAX_CHORD, (MAX (val3, MIN_CHORD)));
  751.             }
  752.         else        /* chord angle determined by deviation of segments from circle radius */
  753.             {    /* at this point, val3 is length in current units, not angle in degrees */
  754.             if (val3 > 2.0 * radius) val3 = 2.0 * radius;    /* limit deviation: resulting chord angle < 180 deg. */
  755.             ang3 = acos ( (radius - val3) / radius) * RAD_2_DEG;
  756.             }
  757.         }
  758.     segs = (int) (fabs (ang2) / ang3 + 0.5);    /* # segments in "ang1" deg. */
  759.         /* sign of 'segs' changes direction of arc () */
  760.  
  761.     DB (printf ("chord = %lf, # segments = %d\n", ang3, segs);)
  762.     DB (printf ("radius = %lf, start angle = %lf, stop angle = %lf\n", radius, ang1, ang1 + ang2);)
  763.     x_1 = xc + radius * cos (ang1 / RAD_2_DEG);
  764.     y_1 = yc + radius * sin (ang1 / RAD_2_DEG);    /* position of start of arc */
  765.  
  766.     draw (x_1, y_1);            /* draw line from center to start of arc */
  767.     move (xc, yc);
  768.     arc ( radius, segs, ang1, ang1 + ang2);    /* draw arc: leaves pen at end of arc */
  769.     draw (xc, yc);                /* draw line from end of arc to center */
  770.  
  771.     if (symbol_mode)
  772.         {
  773.         symbol_mark (symbol);
  774.         }
  775.  
  776.     plotted_on (1);        /* we drew something on this plot */
  777.     return;
  778.     }
  779.  
  780. /*--------------------------------------*/
  781.  
  782. int get_xy (FILE *infile, double *xv, double *yv)
  783.     {
  784.  
  785.     if (get_val (infile, xv))    /* get x values */
  786.          {
  787.         if ( !get_val (infile, yv))    /* get y value */
  788.             {
  789.             print_string ("get_xy():  missing y-value\n");
  790.             return (0);
  791.             }
  792.         return (1);    /* have 2 values */
  793.         }
  794.     return (0);    /* no values */
  795.     }
  796.  
  797. /*--------------------------------------*/
  798.  
  799. int get_val (FILE *infile, double *rval)
  800.     {
  801.     int j;
  802.     char c;
  803.  
  804.     c = getc (infile);
  805.     while ( c  && c != (char) EOF && isspace (c) ) c = getc (infile);
  806.     /* remove leading white-space */
  807.  
  808.     if ( c == TERMCHAR || c == (char) EOF) return (0);    /* terminated: return # params read */
  809.     if ( ! (isdigit (c) || c == ',' || c == '-' || c == '+' || c == '.'))
  810.         {
  811.         ungetc (c, infile);    /* put back what we grabbed */
  812.         return (0);        /* next char not a number */
  813.         }
  814.     if (c == ',') c = getc (infile);
  815.  
  816.     j = 0;
  817.     while ( isdigit ( c ) || c == '-' || c == '+' || c == '.' )
  818.         {
  819.         bfr[j] = c;
  820.         c = getc (infile);
  821.         ++j;
  822.         }
  823.     bfr[j] = '\0';    /* terminate string */
  824.     if (c != ',' && !isspace (c) ) ungetc (c, infile);    /* DO NOT INCLUDE termchar IN THIS TEST!! */
  825.  
  826.     /* including termchar in the test to unget a char will cause a failure if termchar was read 
  827.     by this routine and it is called again immediately thereafter (will return 1 argument of zero value [error]) */
  828.  
  829.     if (j == 0)    /* trap zero length arguments */
  830.         {
  831.         print_string ("? Null argument in get_val ()\n");
  832.         return (0);
  833.         }
  834.  
  835.     DB (printf ("get_val: instring = %s\n", bfr);)
  836.     *rval = atof (bfr);
  837.     return (1);
  838.     }
  839.  
  840. /*--------------------------------------*/
  841.