draw.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:33k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* $Header: /usr/src/mash/repository/vint/xgraph/draw.c,v 1.1.1.1 1999/12/03 23:15:53 heideman Exp $ */
  2. /*
  3.  * draw.c: xgraph drawing code
  4.  *
  5.  * Routines:
  6.  * void DrawWindow();
  7.  *
  8.  * $Log: draw.c,v $
  9.  * Revision 1.1.1.1  1999/12/03 23:15:53  heideman
  10.  * xgraph-12.0
  11.  *
  12.  */
  13. #ifndef lint
  14. static char rcsid[] = "$Id: draw.c,v 1.1.1.1 1999/12/03 23:15:53 heideman Exp $";
  15. #endif
  16. #include "copyright.h"
  17. #include <stdio.h>
  18. #include <math.h>
  19. #include <pwd.h>
  20. #include <ctype.h>
  21. #include "xgraph.h"
  22. #include "xtb.h"
  23. #include "hard_devices.h"
  24. #include "params.h"
  25. static void DrawTitle();
  26. static void DrawGridAndAxis();
  27. static void WriteValue();
  28. static void DrawData();
  29. static void DrawLegend();
  30. static int TransformCompute();
  31. static double initGrid();
  32. static double stepGrid();
  33. static double RoundUp();
  34. static void set_mark_flags();
  35. void
  36. DrawWindow(win_info)
  37. LocalWin *win_info; /* Window information */
  38. /*
  39.  * Draws the data in the window.  Does not clear the window.
  40.  * The data is scaled so that all of the data will fit.
  41.  * Grid lines are drawn at the nearest power of 10 in engineering
  42.  * notation.  Draws axis numbers along bottom and left hand edges.
  43.  * Centers title at top of window.
  44.  */
  45. {
  46.     /* Figure out the transformation constants */
  47.     if (TransformCompute(win_info)) {
  48. /* Draw the title */
  49. DrawTitle(win_info);
  50. /* Draw the legend */
  51. if (!PM_BOOL("NoLegend"))
  52.     DrawLegend(win_info);
  53. /* Draw the axis unit labels,  grid lines,  and grid labels */
  54. DrawGridAndAxis(win_info);
  55. /* Draw the data sets themselves */
  56. DrawData(win_info);
  57.     }
  58. }
  59. static void
  60. DrawTitle(wi)
  61. LocalWin *wi; /* Window information    */
  62. /*
  63.  * This routine draws the title of the graph centered in
  64.  * the window.  It is spaced down from the top by an amount
  65.  * specified by the constant PADDING.  The font must be
  66.  * fixed width.  The routine returns the height of the
  67.  * title in pixels.
  68.  */
  69. {
  70.     if (wi->DOrder == 0) 
  71.       wi->dev_info.xg_text(wi->dev_info.user_state,
  72.  (int)(wi->dev_info.area_w*0.95) ,
  73.  wi->dev_info.axis_pad,
  74.  PM_STR("TitleText"), T_UPPERRIGHT, T_TITLE);
  75.     else if (wi->DOrder == 1)
  76.       wi->dev_info.xg_text(wi->dev_info.user_state,
  77.  (int)(wi->dev_info.area_w*0.95) ,
  78.  wi->dev_info.axis_pad,
  79.  "First Derivative", T_UPPERRIGHT, T_TITLE);
  80.     else if (wi->DOrder == 2)
  81.       wi->dev_info.xg_text(wi->dev_info.user_state,
  82.  (int)(wi->dev_info.area_w*0.95) ,
  83.  wi->dev_info.axis_pad,
  84.  "Second Derivative", T_UPPERRIGHT, T_TITLE);
  85. }
  86. static int
  87. TransformCompute(wi)
  88. LocalWin *wi; /* Window information          */
  89. /*
  90.  * This routine figures out how to draw the axis labels and grid lines.
  91.  * Both linear and logarithmic axes are supported.  Axis labels are
  92.  * drawn in engineering notation.  The power of the axes are labeled
  93.  * in the normal axis labeling spots.  The routine also figures
  94.  * out the necessary transformation information for the display
  95.  * of the points (it touches XOrgX, XOrgY, UsrOrgX, UsrOrgY, and
  96.  * UnitsPerPixel).
  97.  */
  98. {
  99.     double  bbCenX,
  100.             bbCenY,
  101.             bbHalfWidth,
  102.             bbHalfHeight;
  103.     int     idx,
  104.             maxName,
  105.             leftWidth;
  106.     char    err[MAXBUFSIZE];
  107.     char   *XUnitText = PM_STR("XUnitText");
  108.     /*
  109.      * First,  we figure out the origin in the X window.  Above the space we
  110.      * have the title and the Y axis unit label. To the left of the space we
  111.      * have the Y axis grid labels.
  112.      */
  113.     wi->XOrgX = wi->dev_info.bdr_pad + (7 * wi->dev_info.axis_width)
  114. + wi->dev_info.bdr_pad;
  115.     wi->XOrgY = wi->dev_info.bdr_pad + wi->dev_info.title_height
  116. + wi->dev_info.bdr_pad + wi->dev_info.axis_height
  117. + wi->dev_info.axis_height / 2 + wi->dev_info.bdr_pad;
  118.     /*
  119.      * Now we find the lower right corner.  Below the space we have the X axis
  120.      * grid labels.  To the right of the space we have the X axis unit label
  121.      * and the legend.  We assume the worst case size for the unit label.
  122.      */
  123.     maxName = 0;
  124.     for (idx = 0; idx < MAXSETS; idx++) {
  125. if (PlotData[idx].list) {
  126.     int     tempSize;
  127.     tempSize = strlen(PlotData[idx].setName);
  128.     if (tempSize > maxName)
  129. maxName = tempSize;
  130. }
  131.     }
  132.     if (PM_BOOL("NoLegend"))
  133. maxName = 0;
  134.     /* Worst case size of the X axis label: */
  135.     leftWidth = (strlen(XUnitText)) * wi->dev_info.axis_width;
  136.     if ((maxName * wi->dev_info.axis_width) + wi->dev_info.bdr_pad > leftWidth)
  137. leftWidth = maxName * wi->dev_info.axis_width + wi->dev_info.bdr_pad;
  138.     wi->XOppX = wi->dev_info.area_w - wi->dev_info.bdr_pad - leftWidth;
  139.     wi->XOppY = wi->dev_info.area_h - wi->dev_info.bdr_pad
  140. - wi->dev_info.axis_height - wi->dev_info.bdr_pad;
  141.     if ((wi->XOrgX >= wi->XOppX) || (wi->XOrgY >= wi->XOppY)) {
  142. do_error(strcpy(err, "Drawing area is too smalln"));
  143. return 0;
  144.     }
  145.     /*
  146.      * We now have a bounding box for the drawing region. Figure out the units
  147.      * per pixel using the data set bounding box.
  148.      */
  149.     wi->XUnitsPerPixel = (wi->hiX - wi->loX) / 
  150.  ((double) (wi->XOppX - wi->XOrgX));
  151.     wi->YUnitsPerPixel = (wi->hiY - wi->loY) / 
  152.  ((double) (wi->XOppY - wi->XOrgY));
  153.     /*
  154.      * Find origin in user coordinate space.  We keep the center of the
  155.      * original bounding box in the same place.
  156.      */
  157.     bbCenX = (wi->loX + wi->hiX) / 2.0;
  158.     bbCenY = (wi->loY + wi->hiY) / 2.0;
  159.     bbHalfWidth = ((double) (wi->XOppX - wi->XOrgX)) / 2.0 * wi->XUnitsPerPixel;
  160.     bbHalfHeight = ((double) (wi->XOppY - wi->XOrgY)) / 2.0 * wi->YUnitsPerPixel;
  161.     wi->UsrOrgX = bbCenX - bbHalfWidth;
  162.     wi->UsrOrgY = bbCenY - bbHalfHeight;
  163.     wi->UsrOppX = bbCenX + bbHalfWidth;
  164.     wi->UsrOppY = bbCenY + bbHalfHeight;
  165.     /*
  166.      * Everything is defined so we can now use the SCREENX and SCREENY
  167.      * transformations.
  168.      */
  169.     return 1;
  170. }
  171. static void
  172. DrawGridAndAxis(wi)
  173. LocalWin *wi; /* Window information         */
  174. /*
  175.  * This routine draws grid line labels in engineering notation,
  176.  * the grid lines themselves,  and unit labels on the axes.
  177.  */
  178. {
  179.     int     expX,
  180.             expY; /* Engineering powers */
  181.     int     startX;
  182.     int     Yspot,
  183.             Xspot;
  184.     char    power[10],
  185.             value[10],
  186.             final[MAXBUFSIZE + 10];
  187.     double  Xincr,
  188.             Yincr,
  189.             Xstart,
  190.             Ystart,
  191.             Yindex,
  192.             Xindex,
  193.             larger;
  194.     XSegment segs[2];
  195.     double  initGrid(),
  196.             stepGrid();
  197.     int     tickFlag = PM_BOOL("Ticks");
  198.     int     axisFlag = PM_BOOL("TickAxis");
  199.     int     logXFlag = PM_BOOL("LogX");
  200.     int     logYFlag = PM_BOOL("LogY");
  201.     char   *XUnitText = PM_STR("XUnitText");
  202.     char   *YUnitText = PM_STR("YUnitText");
  203.     /*
  204.      * Grid display powers are computed by taking the log of the largest
  205.      * numbers and rounding down to the nearest multiple of 3.
  206.      */
  207.     if (logXFlag) {
  208. expX = 0;
  209.     }
  210.     else {
  211. if (fabs(wi->UsrOrgX) > fabs(wi->UsrOppX)) {
  212.     larger = fabs(wi->UsrOrgX);
  213. }
  214. else {
  215.     larger = fabs(wi->UsrOppX);
  216. }
  217. expX = ((int) floor(nlog10(larger) / 3.0)) * 3;
  218.     }
  219.     if (logYFlag) {
  220. expY = 0;
  221.     }
  222.     else {
  223. if (fabs(wi->UsrOrgY) > fabs(wi->UsrOppY)) {
  224.     larger = fabs(wi->UsrOrgY);
  225. }
  226. else {
  227.     larger = fabs(wi->UsrOppY);
  228. }
  229. expY = ((int) floor(nlog10(larger) / 3.0)) * 3;
  230.     }
  231.     /*
  232.      * With the powers computed,  we can draw the axis labels.
  233.      */
  234.     if (expY != 0) {
  235. (void) strcpy(final, YUnitText);
  236. (void) strcat(final, " x 10");
  237. Xspot = wi->dev_info.bdr_pad +
  238.     ((strlen(YUnitText) + 5) * wi->dev_info.axis_width);
  239. Yspot = wi->dev_info.bdr_pad * 2 + wi->dev_info.title_height +
  240.     wi->dev_info.axis_height / 2;
  241. wi->dev_info.xg_text(wi->dev_info.user_state,
  242.      Xspot, Yspot, final, T_RIGHT, T_AXIS);
  243. (void) sprintf(power, "%d", expY);
  244. wi->dev_info.xg_text(wi->dev_info.user_state,
  245.      Xspot, Yspot, power, T_LOWERLEFT, T_AXIS);
  246.     }
  247.     else {
  248. Yspot = wi->dev_info.bdr_pad * 2 + wi->dev_info.title_height;
  249. wi->dev_info.xg_text(wi->dev_info.user_state,
  250.      wi->dev_info.bdr_pad, Yspot, YUnitText,
  251.      T_UPPERLEFT, T_AXIS);
  252.     }
  253.     startX = wi->dev_info.area_w - wi->dev_info.bdr_pad;
  254.     if (expX != 0) {
  255. (void) sprintf(power, "%d", expX);
  256. startX -= (strlen(power) * wi->dev_info.axis_width);
  257. wi->dev_info.xg_text(wi->dev_info.user_state,
  258.      startX, wi->XOppY, power, T_LOWERLEFT, T_AXIS);
  259. (void) strcpy(final, XUnitText);
  260. (void) strcat(final, " x 10");
  261. wi->dev_info.xg_text(wi->dev_info.user_state,
  262.      startX, wi->XOppY, final, T_RIGHT, T_AXIS);
  263.     }
  264.     else {
  265. wi->dev_info.xg_text(wi->dev_info.user_state,
  266.      startX, wi->XOppY, XUnitText, T_RIGHT, T_AXIS);
  267.     }
  268.     /*
  269.      * First,  the grid line labels
  270.      */
  271.     Yincr = (wi->dev_info.axis_pad + wi->dev_info.axis_height) *
  272.     wi->YUnitsPerPixel;
  273.     Ystart = initGrid(wi->UsrOrgY, Yincr, logYFlag);
  274.     for (Yindex = Ystart; Yindex < wi->UsrOppY; Yindex = stepGrid()) {
  275. Yspot = SCREENY(wi, Yindex);
  276. /* Write the axis label */
  277. WriteValue(value, PM_STR("Format X"), Yindex, expY, logYFlag);
  278. wi->dev_info.xg_text(wi->dev_info.user_state,
  279.      wi->dev_info.bdr_pad +
  280.      (7 * wi->dev_info.axis_width),
  281.      Yspot, value, T_RIGHT, T_AXIS);
  282.     }
  283.     Xincr = (wi->dev_info.axis_pad + (wi->dev_info.axis_width * 7)) * 
  284.     wi->XUnitsPerPixel;
  285.     Xstart = initGrid(wi->UsrOrgX, Xincr, logXFlag);
  286.     for (Xindex = Xstart; Xindex < wi->UsrOppX; Xindex = stepGrid()) {
  287. Xspot = SCREENX(wi, Xindex);
  288. /* Write the axis label */
  289. WriteValue(value, PM_STR("Format Y"), Xindex, expX, logXFlag);
  290. wi->dev_info.xg_text(wi->dev_info.user_state,
  291.      Xspot,
  292.      wi->dev_info.area_h - wi->dev_info.bdr_pad,
  293.      value, T_BOTTOM, T_AXIS);
  294.     }
  295.     /*
  296.      * Now,  the grid lines or tick marks
  297.      */
  298.     Yincr = (wi->dev_info.axis_pad + wi->dev_info.axis_height) * 
  299.     wi->YUnitsPerPixel;
  300.     Ystart = initGrid(wi->UsrOrgY, Yincr, logYFlag);
  301.     for (Yindex = Ystart; Yindex < wi->UsrOppY; Yindex = stepGrid()) {
  302. Yspot = SCREENY(wi, Yindex);
  303. /* Draw the grid line or tick mark */
  304. if (tickFlag && !(axisFlag && Yindex == Ystart)) {
  305.     segs[0].x1 = wi->XOrgX;
  306.     segs[0].x2 = wi->XOrgX + wi->dev_info.tick_len;
  307.     segs[1].x1 = wi->XOppX - wi->dev_info.tick_len;
  308.     segs[1].x2 = wi->XOppX;
  309.     segs[0].y1 = segs[0].y2 = segs[1].y1 = segs[1].y2 = Yspot;
  310. }
  311. else {
  312.     segs[0].x1 = wi->XOrgX;
  313.     segs[0].x2 = wi->XOppX;
  314.     segs[0].y1 = segs[0].y2 = Yspot;
  315. }
  316. if ((ABS(Yindex) < ZERO_THRES) && !logYFlag) {
  317.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  318. 1, segs, PM_INT("ZeroWidth"),
  319. L_ZERO, 0, 0);
  320.     if (tickFlag) {
  321. wi->dev_info.xg_seg(wi->dev_info.user_state,
  322.     1, &(segs[1]), PM_INT("ZeroWidth"),
  323.     L_ZERO, 0, 0);
  324.     }
  325. }
  326. else {
  327.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  328. 1, segs, PM_INT("GridSize"),
  329. L_AXIS, 0, 0);
  330.     if (tickFlag) {
  331. wi->dev_info.xg_seg(wi->dev_info.user_state,
  332.     1, &(segs[1]), PM_INT("GridSize"),
  333.     L_AXIS, 0, 0);
  334.     }
  335. }
  336.     }
  337.     Xincr = (wi->dev_info.axis_pad + (wi->dev_info.axis_width * 7)) *
  338. wi->XUnitsPerPixel;
  339.     Xstart = initGrid(wi->UsrOrgX, Xincr, logXFlag);
  340.     for (Xindex = Xstart; Xindex < wi->UsrOppX; Xindex = stepGrid()) {
  341. Xspot = SCREENX(wi, Xindex);
  342. /* Draw the grid line or tick marks */
  343. if (tickFlag && !(axisFlag && Xindex == Xstart)) {
  344.     segs[0].x1 = segs[0].x2 = segs[1].x1 = segs[1].x2 = Xspot;
  345.     segs[0].y1 = wi->XOrgY;
  346.     segs[0].y2 = wi->XOrgY + wi->dev_info.tick_len;
  347.     segs[1].y1 = wi->XOppY - wi->dev_info.tick_len;
  348.     segs[1].y2 = wi->XOppY;
  349. }
  350. else {
  351.     segs[0].x1 = segs[0].x2 = Xspot;
  352.     segs[0].y1 = wi->XOrgY;
  353.     segs[0].y2 = wi->XOppY;
  354. }
  355. if ((ABS(Xindex) < ZERO_THRES) && !logXFlag) {
  356.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  357. 1, segs, PM_INT("ZeroWidth"), L_ZERO, 0, 0);
  358.     if (tickFlag) {
  359. wi->dev_info.xg_seg(wi->dev_info.user_state,
  360.     1, &(segs[1]), PM_INT("ZeroWidth"),
  361.     L_ZERO, 0, 0);
  362.     }
  363. }
  364. else {
  365.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  366. 1, segs, PM_INT("GridSize"), L_AXIS, 0, 0);
  367.     if (tickFlag) {
  368. wi->dev_info.xg_seg(wi->dev_info.user_state,
  369.      1, &(segs[1]), PM_INT("GridSize"), L_AXIS, 0, 0);
  370.     }
  371. }
  372.     }
  373.     /* Check to see if he wants a bounding box */
  374.     if (PM_BOOL("BoundBox")) {
  375. XSegment bb[4];
  376. /* Draw bounding box */
  377. bb[0].x1 = bb[0].x2 = bb[1].x1 = bb[3].x2 = wi->XOrgX;
  378. bb[0].y1 = bb[2].y2 = bb[3].y1 = bb[3].y2 = wi->XOrgY;
  379. bb[1].x2 = bb[2].x1 = bb[2].x2 = bb[3].x1 = wi->XOppX;
  380. bb[0].y2 = bb[1].y1 = bb[1].y2 = bb[2].y1 = wi->XOppY;
  381. wi->dev_info.xg_seg(wi->dev_info.user_state,
  382.     4, bb, PM_INT("GridSize"), L_AXIS, 0, 0);
  383.     }
  384. }
  385. static double gridBase,
  386.         gridStep,
  387.         gridJuke[101];
  388. static int gridNJuke,
  389.         gridCurJuke;
  390. #define ADD_GRID(val) (gridJuke[gridNJuke++] = log10(val))
  391. static double
  392. initGrid(low, step, logFlag)
  393. double  low; /* desired low value          */
  394. double  step; /* desired step (user coords) */
  395. int     logFlag; /* is axis logarithmic?       */
  396. {
  397.     double  ratio,
  398.             x;
  399.     double  RoundUp(),
  400.             stepGrid();
  401.     gridNJuke = gridCurJuke = 0;
  402.     gridJuke[gridNJuke++] = 0.0;
  403.     if (logFlag) {
  404. ratio = pow(10.0, step);
  405. gridBase = floor(low);
  406. gridStep = ceil(step);
  407. if (ratio <= 3.0) {
  408.     if (ratio > 2.0) {
  409. ADD_GRID(3.0);
  410.     }
  411.     else if (ratio > 1.333) {
  412. ADD_GRID(2.0);
  413. ADD_GRID(5.0);
  414.     }
  415.     else if (ratio > 1.25) {
  416. ADD_GRID(1.5);
  417. ADD_GRID(2.0);
  418. ADD_GRID(3.0);
  419. ADD_GRID(5.0);
  420. ADD_GRID(7.0);
  421.     }
  422.     else {
  423. for (x = 1.0; x < 10.0 && (x + .5) / (x + .4) >= ratio; x += .5) {
  424.     ADD_GRID(x + .1);
  425.     ADD_GRID(x + .2);
  426.     ADD_GRID(x + .3);
  427.     ADD_GRID(x + .4);
  428.     ADD_GRID(x + .5);
  429. }
  430. if (floor(x) != x)
  431.     ADD_GRID(x += .5);
  432. for (; x < 10.0 && (x + 1.0) / (x + .5) >= ratio; x += 1.0) {
  433.     ADD_GRID(x + .5);
  434.     ADD_GRID(x + 1.0);
  435. }
  436. for (; x < 10.0 && (x + 1.0) / x >= ratio; x += 1.0) {
  437.     ADD_GRID(x + 1.0);
  438. }
  439. if (x == 7.0) {
  440.     gridNJuke--;
  441.     x = 6.0;
  442. }
  443. if (x < 7.0) {
  444.     ADD_GRID(x + 2.0);
  445. }
  446. if (x == 10.0)
  447.     gridNJuke--;
  448.     }
  449.     x = low - gridBase;
  450.     for (gridCurJuke = -1; x >= gridJuke[gridCurJuke + 1]; gridCurJuke++) {
  451.     }
  452. }
  453.     }
  454.     else {
  455. gridStep = RoundUp(step);
  456. gridBase = floor(low / gridStep) * gridStep;
  457.     }
  458.     return (stepGrid());
  459. }
  460. static double
  461. stepGrid()
  462. {
  463.     if (++gridCurJuke >= gridNJuke) {
  464. gridCurJuke = 0;
  465. gridBase += gridStep;
  466.     }
  467.     return (gridBase + gridJuke[gridCurJuke]);
  468. }
  469. static double
  470. RoundUp(val)
  471. double  val; /* Value */
  472. /*
  473.  * This routine rounds up the given positive number such that
  474.  * it is some power of ten times either 1, 2, or 5.  It is
  475.  * used to find increments for grid lines.
  476.  */
  477. {
  478.     int     exponent,
  479.             idx;
  480.     exponent = (int) floor(nlog10(val));
  481.     if (exponent < 0) {
  482. for (idx = exponent; idx < 0; idx++) {
  483.     val *= 10.0;
  484. }
  485.     }
  486.     else {
  487. for (idx = 0; idx < exponent; idx++) {
  488.     val /= 10.0;
  489. }
  490.     }
  491.     if (val > 5.0)
  492. val = 10.0;
  493.     else if (val > 2.0)
  494. val = 5.0;
  495.     else if (val > 1.0)
  496. val = 2.0;
  497.     else
  498. val = 1.0;
  499.     if (exponent < 0) {
  500. for (idx = exponent; idx < 0; idx++) {
  501.     val /= 10.0;
  502. }
  503.     }
  504.     else {
  505. for (idx = 0; idx < exponent; idx++) {
  506.     val *= 10.0;
  507. }
  508.     }
  509.     return val;
  510. }
  511. static void
  512. WriteValue(str, fmt, val, expv, logFlag)
  513. char   *str; /* String to write into */
  514. char   *fmt; /* Format to print str  */
  515. double  val; /* Value to print       */
  516. int     expv; /* Exponent             */
  517. int     logFlag; /* Is this a log axis?  */
  518. /*
  519.  * Writes the value provided into the string in a fixed format
  520.  * consisting of seven characters.  The format is:
  521.  *   -ddd.dd
  522.  */
  523. {
  524.     int     idx;
  525.     if (logFlag) {
  526. if (val == floor(val)) {
  527.     if (strcmp(fmt, "%.2f") == 0)
  528. fmt = "%.0e";
  529.     val = pow(10.0, val);
  530. }
  531. else {
  532.     if (strcmp(fmt, "%.2f") == 0)
  533. fmt = "%.2g";
  534.     val = pow(10.0, val - floor(val));
  535. }
  536.     }
  537.     else {
  538. if (expv < 0) {
  539.     for (idx = expv; idx < 0; idx++) {
  540. val *= 10.0;
  541.     }
  542. }
  543. else {
  544.     for (idx = 0; idx < expv; idx++) {
  545. val /= 10.0;
  546.     }
  547. }
  548.     }
  549.     if (strchr(fmt, 'd') || strchr(fmt, 'x'))
  550. (void) sprintf(str, fmt, (int) val);
  551.     else
  552. (void) sprintf(str, fmt, val);
  553. }
  554. #define LEFT_CODE 0x01
  555. #define RIGHT_CODE 0x02
  556. #define BOTTOM_CODE 0x04
  557. #define TOP_CODE 0x08
  558. /* Clipping algorithm from Neumann and Sproull by Cohen and Sutherland */
  559. #define C_CODE(xval, yval, rtn) 
  560. rtn = 0; 
  561. if ((xval) < wi->UsrOrgX) rtn = LEFT_CODE; 
  562. else if ((xval) > wi->UsrOppX) rtn = RIGHT_CODE; 
  563. if ((yval) < wi->UsrOrgY) rtn |= BOTTOM_CODE; 
  564. else if ((yval) > wi->UsrOppY) rtn |= TOP_CODE
  565. void
  566. EraseData(wi)
  567. LocalWin *wi;
  568. /*
  569.  * This routine draws the data sets themselves using the macros
  570.  * for translating coordinates.
  571.  */
  572. {
  573.     double  sx1,
  574.             sy1,
  575.             sx2,
  576.             sy2,
  577.             tx = 0,
  578.             ty = 0;
  579.     int     idx,
  580.             subindex;
  581.     int     code1,
  582.             code2,
  583.             cd,
  584.             mark_inside;
  585.     int     X_idx, StoreIDX; /* PW */
  586.     XSegment *ptr;
  587.     PointList *thisList,
  588.               *lastList;
  589.     int     markFlag,
  590.             pixelMarks,
  591.             bigPixel,
  592.             colorMark;
  593.     int     noLines = PM_BOOL("NoLines");
  594.     int     lineWidth = PM_INT("LineWidth");
  595.     /* PW Suggests we Flush and set first */
  596.     set_mark_flags(&markFlag, &pixelMarks, &bigPixel, &colorMark);
  597.     for (idx = 0; idx < MAXSETS; idx++) {
  598.         if (wi->DOrder == 0)
  599.   thisList = PlotData[idx].list;
  600.         else if (wi->DOrder == 1)
  601.     thisList = DataD1[idx].list;
  602.         else if (wi->DOrder == 2)
  603.     thisList = DataD2[idx].list;
  604.         else {
  605.           printf ("Internal Error differentiating - order > 2!n");
  606.           exit (1);
  607.         }
  608. while (thisList) {
  609.     X_idx = 0;
  610.     for (subindex = 0; subindex < thisList->numPoints - 1; subindex++) {
  611. /* Put segment in (sx1,sy1) (sx2,sy2) */
  612. sx1 = thisList->xvec[subindex];
  613. sy1 = thisList->yvec[subindex];
  614. sx2 = thisList->xvec[subindex + 1];
  615. sy2 = thisList->yvec[subindex + 1];
  616. /* Now clip to current window boundary */
  617. C_CODE(sx1, sy1, code1);
  618. C_CODE(sx2, sy2, code2);
  619. mark_inside = (code1 == 0);
  620. while (code1 || code2) {
  621.     if (code1 & code2)
  622. break;
  623.     cd = (code1 ? code1 : code2);
  624.     if (cd & LEFT_CODE) { /* Crosses left edge */
  625. ty = sy1 + (sy2 - sy1) * (wi->UsrOrgX - sx1) / 
  626.  (sx2 - sx1);
  627. tx = wi->UsrOrgX;
  628.     }
  629.     else if (cd & RIGHT_CODE) { /* Crosses right edge */
  630. ty = sy1 + (sy2 - sy1) * (wi->UsrOppX - sx1) / 
  631.  (sx2 - sx1);
  632. tx = wi->UsrOppX;
  633.     }
  634.     else if (cd & BOTTOM_CODE) {/* Crosses bottom edge */
  635. tx = sx1 + (sx2 - sx1) * (wi->UsrOrgY - sy1) / 
  636.  (sy2 - sy1);
  637. ty = wi->UsrOrgY;
  638.     }
  639.     else if (cd & TOP_CODE) { /* Crosses top edge */
  640. tx = sx1 + (sx2 - sx1) * (wi->UsrOppY - sy1) / 
  641.  (sy2 - sy1);
  642. ty = wi->UsrOppY;
  643.     }
  644.     if (cd == code1) {
  645. sx1 = tx;
  646. sy1 = ty;
  647. C_CODE(sx1, sy1, code1);
  648.     }
  649.     else {
  650. sx2 = tx;
  651. sy2 = ty;
  652. C_CODE(sx2, sy2, code2);
  653.     }
  654. }
  655. if (!code1 && !code2) {
  656.     /* Add segment to list */
  657.     Xsegs[0][X_idx].x1 = Xsegs[1][X_idx].x1;
  658.     Xsegs[0][X_idx].y1 = Xsegs[1][X_idx].y1;
  659.     Xsegs[0][X_idx].x2 = Xsegs[1][X_idx].x2;
  660.     Xsegs[0][X_idx].y2 = Xsegs[1][X_idx].y2;
  661.     Xsegs[1][X_idx].x1 = SCREENX(wi, sx1);
  662.     Xsegs[1][X_idx].y1 = SCREENY(wi, sy1);
  663.     Xsegs[1][X_idx].x2 = SCREENX(wi, sx2);
  664.     Xsegs[1][X_idx].y2 = SCREENY(wi, sy2);
  665.     X_idx++;
  666. }
  667. /* Draw markers if requested and they are in drawing region */
  668. if (markFlag && mark_inside) {
  669.     if (pixelMarks) {
  670. if (bigPixel) {
  671.     wi->dev_info.xg_dot(wi->dev_info.user_state,
  672. Xsegs[1][X_idx - 1].x1,
  673. Xsegs[1][X_idx - 1].y1,
  674. P_DOT, 0, idx % MAXATTR);
  675. }
  676. else {
  677.     wi->dev_info.xg_dot(wi->dev_info.user_state,
  678. Xsegs[1][X_idx - 1].x1,
  679. Xsegs[1][X_idx - 1].y1,
  680. P_PIXEL, 0, PIXVALUE(idx));
  681. }
  682.     }
  683.     else {
  684. /* Distinctive markers */
  685. wi->dev_info.xg_dot(wi->dev_info.user_state,
  686.     Xsegs[1][X_idx - 1].x1,
  687.     Xsegs[1][X_idx - 1].y1,
  688.     P_MARK, MARKSTYLE(idx),
  689.     PIXVALUE(idx));
  690.     }
  691. }
  692. /* Draw bar elements if requested */
  693. if (PM_BOOL("BarGraph")) {
  694.     int     barPixels,
  695.             baseSpot;
  696.     XSegment line;
  697.     barPixels = (int) ((PM_DBL("BarWidth") /
  698. wi->XUnitsPerPixel) + 0.5);
  699.     if (barPixels <= 0)
  700. barPixels = 1;
  701.     baseSpot = SCREENY(wi, PM_DBL("BarBase"));
  702.     line.x1 = line.x2 = Xsegs[1][X_idx - 1].x1 + 
  703. (int) ((PM_DBL("BarOffset") * idx /
  704.     wi->XUnitsPerPixel) + 0.5);
  705.     if (PM_BOOL("StackGraph") && idx != 0)
  706. line.y1 = Xsegs[0][X_idx - 1].y1;
  707.     else
  708. line.y1 = baseSpot;
  709.     line.y2 = Xsegs[1][X_idx - 1].y1;
  710.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  711. 1, &line, barPixels, L_VAR,
  712. LINESTYLE(idx), PIXVALUE(idx));
  713. }
  714.     }
  715.     /* Handle last marker */
  716.     if (markFlag && (thisList->numPoints > 0)) {
  717. C_CODE(thisList->xvec[thisList->numPoints - 1],
  718.        thisList->yvec[thisList->numPoints - 1],
  719.        mark_inside);
  720. if (mark_inside == 0) {
  721.     if (pixelMarks) {
  722. if (bigPixel) {
  723.     wi->dev_info.xg_dot(wi->dev_info.user_state,
  724. Xsegs[1][X_idx - 1].x2,
  725. Xsegs[1][X_idx - 1].y2,
  726. P_DOT, 0, idx % MAXATTR);
  727. }
  728. else {
  729.     wi->dev_info.xg_dot(wi->dev_info.user_state,
  730. Xsegs[1][X_idx - 1].x2,
  731. Xsegs[1][X_idx - 1].y2,
  732. P_PIXEL, 0, PIXVALUE(idx));
  733. }
  734.     }
  735.     else {
  736. /* Distinctive markers */
  737. wi->dev_info.xg_dot(wi->dev_info.user_state,
  738.     Xsegs[1][X_idx - 1].x2,
  739.     Xsegs[1][X_idx - 1].y2,
  740.     P_MARK, MARKSTYLE(idx),
  741.     PIXVALUE(idx));
  742.     }
  743. }
  744.     }
  745.     /* Handle last bar */
  746.     if ((thisList->numPoints > 0) && PM_BOOL("BarGraph")) {
  747. int     barPixels,
  748.         baseSpot;
  749. XSegment line;
  750. barPixels = (int) ((PM_DBL("BarWidth") / 
  751.    wi->XUnitsPerPixel) + 0.5);
  752. if (barPixels <= 0)
  753.     barPixels = 1;
  754. baseSpot = SCREENY(wi, PM_DBL("BarBase"));
  755. line.x1 = line.x2 = Xsegs[1][X_idx - 1].x2 +
  756. (int) ((PM_DBL("BarOffset") * idx /
  757.     wi->XUnitsPerPixel) + 0.5);
  758. if (PM_BOOL("StackGraph") && idx != 0)
  759.     line.y1 = Xsegs[0][X_idx - 1].y2;
  760. else
  761.     line.y1 = baseSpot;
  762. line.y2 = Xsegs[1][X_idx - 1].y2;
  763. wi->dev_info.xg_seg(wi->dev_info.user_state,
  764.     1, &line, barPixels, L_VAR,
  765.     LINESTYLE(idx), PIXVALUE(idx));
  766.     }
  767.     /* Erase segments */
  768.     if ((thisList->numPoints > 0) && (!noLines) && (X_idx > 0)) {
  769. ptr = Xsegs[1];
  770. while (X_idx > wi->dev_info.max_segs) {
  771.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  772. wi->dev_info.max_segs, ptr,
  773. lineWidth, L_VAR,
  774. 16, (int)(1));
  775. /*LINESTYLE(8), (int)(1));*/
  776.     ptr += wi->dev_info.max_segs;
  777.     X_idx -= wi->dev_info.max_segs;
  778. }
  779. wi->dev_info.xg_seg(wi->dev_info.user_state,
  780.     X_idx, ptr,
  781.     lineWidth, L_VAR,
  782.     16,(int)(1));
  783.     }
  784.     /* Next subset */
  785.             thisList = thisList->next;
  786. }
  787.     }
  788.     XFlush (disp);
  789. }
  790. static void
  791. DrawData(wi)
  792. LocalWin *wi;
  793. /*
  794.  * This routine draws the data sets themselves using the macros
  795.  * for translating coordinates.
  796.  */
  797. {
  798.     double  sx1,
  799.             sy1,
  800.             sx2,
  801.             sy2,
  802.             tx = 0,
  803.             ty = 0;
  804.     int     idx,
  805.             subindex;
  806.     int     code1,
  807.             code2,
  808.             cd,
  809.             mark_inside;
  810.     int     X_idx, StoreIDX; /* PW */
  811.     XSegment *ptr;
  812.     PointList *thisList,
  813.               *lastList;
  814.     int     markFlag,
  815.             pixelMarks,
  816.             bigPixel,
  817.             colorMark;
  818.     int     noLines = PM_BOOL("NoLines");
  819.     int     lineWidth = PM_INT("LineWidth");
  820.     /* PW */
  821.     int     theDelay;
  822.     /* PW Suggests we Flush and set first */
  823.     theDelay = PM_INT("DelayValue")*100000;
  824.     XFlush(disp);
  825.     if (PM_BOOL("Animate")) sleep(1);
  826.     set_mark_flags(&markFlag, &pixelMarks, &bigPixel, &colorMark);
  827.     for (idx = 0; idx < MAXSETS; idx++) {
  828.         if (wi->DOrder == 0)
  829.   thisList = PlotData[idx].list;
  830.         else if (wi->DOrder == 1)
  831.     thisList = DataD1[idx].list;
  832.         else if (wi->DOrder == 2)
  833.     thisList = DataD2[idx].list;
  834.         else {
  835.           printf ("Internal Error differentiating - order > 2!n");
  836.           exit (1);
  837.         }
  838. while (thisList) {
  839.     X_idx = 0;
  840.     for (subindex = 0; subindex < thisList->numPoints - 1; subindex++) {
  841. /* Put segment in (sx1,sy1) (sx2,sy2) */
  842. sx1 = thisList->xvec[subindex];
  843. sy1 = thisList->yvec[subindex];
  844. sx2 = thisList->xvec[subindex + 1];
  845. sy2 = thisList->yvec[subindex + 1];
  846. /* Now clip to current window boundary */
  847. C_CODE(sx1, sy1, code1);
  848. C_CODE(sx2, sy2, code2);
  849. mark_inside = (code1 == 0);
  850. while (code1 || code2) {
  851.     if (code1 & code2)
  852. break;
  853.     cd = (code1 ? code1 : code2);
  854.     if (cd & LEFT_CODE) { /* Crosses left edge */
  855. ty = sy1 + (sy2 - sy1) * (wi->UsrOrgX - sx1) / 
  856.  (sx2 - sx1);
  857. tx = wi->UsrOrgX;
  858.     }
  859.     else if (cd & RIGHT_CODE) { /* Crosses right edge */
  860. ty = sy1 + (sy2 - sy1) * (wi->UsrOppX - sx1) / 
  861.  (sx2 - sx1);
  862. tx = wi->UsrOppX;
  863.     }
  864.     else if (cd & BOTTOM_CODE) {/* Crosses bottom edge */
  865. tx = sx1 + (sx2 - sx1) * (wi->UsrOrgY - sy1) / 
  866.  (sy2 - sy1);
  867. ty = wi->UsrOrgY;
  868.     }
  869.     else if (cd & TOP_CODE) { /* Crosses top edge */
  870. tx = sx1 + (sx2 - sx1) * (wi->UsrOppY - sy1) / 
  871.  (sy2 - sy1);
  872. ty = wi->UsrOppY;
  873.     }
  874.     if (cd == code1) {
  875. sx1 = tx;
  876. sy1 = ty;
  877. C_CODE(sx1, sy1, code1);
  878.     }
  879.     else {
  880. sx2 = tx;
  881. sy2 = ty;
  882. C_CODE(sx2, sy2, code2);
  883.     }
  884. }
  885. if (!code1 && !code2) {
  886.     /* Add segment to list */
  887.     Xsegs[0][X_idx].x1 = Xsegs[1][X_idx].x1;
  888.     Xsegs[0][X_idx].y1 = Xsegs[1][X_idx].y1;
  889.     Xsegs[0][X_idx].x2 = Xsegs[1][X_idx].x2;
  890.     Xsegs[0][X_idx].y2 = Xsegs[1][X_idx].y2;
  891.     Xsegs[1][X_idx].x1 = SCREENX(wi, sx1);
  892.     Xsegs[1][X_idx].y1 = SCREENY(wi, sy1);
  893.     Xsegs[1][X_idx].x2 = SCREENX(wi, sx2);
  894.     Xsegs[1][X_idx].y2 = SCREENY(wi, sy2);
  895.     X_idx++;
  896. }
  897. /* Draw markers if requested and they are in drawing region */
  898. if (markFlag && mark_inside) {
  899.     if (pixelMarks) {
  900. if (bigPixel) {
  901.     wi->dev_info.xg_dot(wi->dev_info.user_state,
  902. Xsegs[1][X_idx - 1].x1,
  903. Xsegs[1][X_idx - 1].y1,
  904. P_DOT, 0, idx % MAXATTR);
  905. }
  906. else {
  907.     wi->dev_info.xg_dot(wi->dev_info.user_state,
  908. Xsegs[1][X_idx - 1].x1,
  909. Xsegs[1][X_idx - 1].y1,
  910. P_PIXEL, 0, PIXVALUE(idx));
  911. }
  912.     }
  913.     else {
  914. /* Distinctive markers */
  915. wi->dev_info.xg_dot(wi->dev_info.user_state,
  916.     Xsegs[1][X_idx - 1].x1,
  917.     Xsegs[1][X_idx - 1].y1,
  918.     P_MARK, MARKSTYLE(idx),
  919.     PIXVALUE(idx));
  920.     }
  921. }
  922. /* Draw bar elements if requested */
  923. if (PM_BOOL("BarGraph")) {
  924.     int     barPixels,
  925.             baseSpot;
  926.     XSegment line;
  927.     barPixels = (int) ((PM_DBL("BarWidth") /
  928. wi->XUnitsPerPixel) + 0.5);
  929.     if (barPixels <= 0)
  930. barPixels = 1;
  931.     baseSpot = SCREENY(wi, PM_DBL("BarBase"));
  932.     line.x1 = line.x2 = Xsegs[1][X_idx - 1].x1 + 
  933. (int) ((PM_DBL("BarOffset") * idx /
  934.     wi->XUnitsPerPixel) + 0.5);
  935.     if (PM_BOOL("StackGraph") && idx != 0)
  936. line.y1 = Xsegs[0][X_idx - 1].y1;
  937.     else
  938. line.y1 = baseSpot;
  939.     line.y2 = Xsegs[1][X_idx - 1].y1;
  940.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  941. 1, &line, barPixels, L_VAR,
  942. LINESTYLE(idx), PIXVALUE(idx));
  943. }
  944.     }
  945.     /* Handle last marker */
  946.     if (markFlag && (thisList->numPoints > 0)) {
  947. C_CODE(thisList->xvec[thisList->numPoints - 1],
  948.        thisList->yvec[thisList->numPoints - 1],
  949.        mark_inside);
  950. if (mark_inside == 0) {
  951.     if (pixelMarks) {
  952. if (bigPixel) {
  953.     wi->dev_info.xg_dot(wi->dev_info.user_state,
  954. Xsegs[1][X_idx - 1].x2,
  955. Xsegs[1][X_idx - 1].y2,
  956. P_DOT, 0, idx % MAXATTR);
  957. }
  958. else {
  959.     wi->dev_info.xg_dot(wi->dev_info.user_state,
  960. Xsegs[1][X_idx - 1].x2,
  961. Xsegs[1][X_idx - 1].y2,
  962. P_PIXEL, 0, PIXVALUE(idx));
  963. }
  964.     }
  965.     else {
  966. /* Distinctive markers */
  967. wi->dev_info.xg_dot(wi->dev_info.user_state,
  968.     Xsegs[1][X_idx - 1].x2,
  969.     Xsegs[1][X_idx - 1].y2,
  970.     P_MARK, MARKSTYLE(idx),
  971.     PIXVALUE(idx));
  972.     }
  973. }
  974.     }
  975.     /* Handle last bar */
  976.     if ((thisList->numPoints > 0) && PM_BOOL("BarGraph")) {
  977. int     barPixels,
  978.         baseSpot;
  979. XSegment line;
  980. barPixels = (int) ((PM_DBL("BarWidth") / 
  981.    wi->XUnitsPerPixel) + 0.5);
  982. if (barPixels <= 0)
  983.     barPixels = 1;
  984. baseSpot = SCREENY(wi, PM_DBL("BarBase"));
  985. line.x1 = line.x2 = Xsegs[1][X_idx - 1].x2 +
  986. (int) ((PM_DBL("BarOffset") * idx /
  987.     wi->XUnitsPerPixel) + 0.5);
  988. if (PM_BOOL("StackGraph") && idx != 0)
  989.     line.y1 = Xsegs[0][X_idx - 1].y2;
  990. else
  991.     line.y1 = baseSpot;
  992. line.y2 = Xsegs[1][X_idx - 1].y2;
  993. wi->dev_info.xg_seg(wi->dev_info.user_state,
  994.     1, &line, barPixels, L_VAR,
  995.     LINESTYLE(idx), PIXVALUE(idx));
  996.     }
  997.     /* Draw segments */
  998.             if (!PM_BOOL("Animate")) {
  999.       if (thisList->numPoints > 0 && (!noLines) && (X_idx > 0)) {
  1000. ptr = Xsegs[1];
  1001. while (X_idx > wi->dev_info.max_segs) {
  1002.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  1003. wi->dev_info.max_segs, ptr,
  1004. lineWidth, L_VAR,
  1005. LINESTYLE(idx), PIXVALUE(idx));
  1006.     ptr += wi->dev_info.max_segs;
  1007.     X_idx -= wi->dev_info.max_segs;
  1008. }
  1009. wi->dev_info.xg_seg(wi->dev_info.user_state,
  1010.     X_idx, ptr,
  1011.     lineWidth, L_VAR,
  1012.     LINESTYLE(idx), PIXVALUE(idx));
  1013.       }
  1014.             } else {
  1015.               StoreIDX = X_idx;
  1016.       if (thisList->numPoints > 0 && (!noLines) && (X_idx > 0)) {
  1017. ptr = Xsegs[1];
  1018. while (X_idx > wi->dev_info.max_segs) {
  1019.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  1020. wi->dev_info.max_segs, ptr,
  1021. lineWidth, L_VAR,
  1022. LINESTYLE(1), PIXVALUE(2));
  1023.     ptr += wi->dev_info.max_segs;
  1024.     X_idx -= wi->dev_info.max_segs;
  1025. }
  1026. wi->dev_info.xg_seg(wi->dev_info.user_state,
  1027.     X_idx, ptr,
  1028.     lineWidth, L_VAR,
  1029.     LINESTYLE(1), PIXVALUE(2));
  1030.       }
  1031.               XFlush (disp);
  1032.       for (X_idx=1;X_idx<theDelay;X_idx++);
  1033.               X_idx = StoreIDX;
  1034.       if ((thisList->numPoints > 0) && (!noLines) && (X_idx > 0)) {
  1035. ptr = Xsegs[1];
  1036. while (X_idx > wi->dev_info.max_segs) {
  1037.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  1038. wi->dev_info.max_segs, ptr,
  1039. lineWidth, L_VAR,
  1040. 16, (int)(1));
  1041. /*LINESTYLE(8), (int)(1));*/
  1042.     ptr += wi->dev_info.max_segs;
  1043.     X_idx -= wi->dev_info.max_segs;
  1044. }
  1045. wi->dev_info.xg_seg(wi->dev_info.user_state,
  1046.     X_idx, ptr,
  1047.     lineWidth, L_VAR,
  1048.     16,(int)(1));
  1049.       }
  1050.             }
  1051.     /* Next subset */
  1052.             lastList = thisList;
  1053.             thisList = thisList->next;
  1054. } /* End While */
  1055.       }
  1056.         if (PM_BOOL("Animate")) {
  1057.           X_idx = StoreIDX;
  1058.           thisList = lastList;
  1059.   if (thisList->numPoints > 0 && (!noLines) && (X_idx > 0)) {
  1060.     ptr = Xsegs[1];
  1061.        while (X_idx > wi->dev_info.max_segs) {
  1062.     wi->dev_info.xg_seg(wi->dev_info.user_state,
  1063. wi->dev_info.max_segs, ptr,
  1064. lineWidth, L_VAR,
  1065. LINESTYLE(1), PIXVALUE(2));
  1066.     ptr += wi->dev_info.max_segs;
  1067.     X_idx -= wi->dev_info.max_segs;
  1068. }
  1069. wi->dev_info.xg_seg(wi->dev_info.user_state,
  1070.     X_idx, ptr,
  1071.     lineWidth, L_VAR,
  1072.     LINESTYLE(1), PIXVALUE(2));
  1073.     }
  1074.           }
  1075.     XFlush (disp);
  1076. }
  1077. static void
  1078. DrawLegend(wi)
  1079. LocalWin *wi;
  1080. /*
  1081.  * This draws a legend of the data sets displayed.  Only those that
  1082.  * will fit are drawn.
  1083.  */
  1084. {
  1085.     int     idx,
  1086.             spot,
  1087.             lineLen,
  1088.             oneLen, 
  1089.     incr;
  1090.     XSegment leg_line;
  1091.     int     markFlag,
  1092.             pixelMarks,
  1093.             bigPixel,
  1094.             colorMark;
  1095.     set_mark_flags(&markFlag, &pixelMarks, &bigPixel, &colorMark);
  1096.     spot = wi->XOrgY;
  1097.     lineLen = 0;
  1098.     incr = 2 + wi->dev_info.axis_height + wi->dev_info.bdr_pad;
  1099.     /* First pass draws the text */
  1100.     for (idx = 0; idx < MAXSETS; idx++) {
  1101. if ((PlotData[idx].list) &&
  1102.     (spot + wi->dev_info.axis_height + 2 < wi->XOppY)) {
  1103.     /* Meets the criteria */
  1104.     oneLen = strlen(PlotData[idx].setName);
  1105.     if (oneLen > lineLen)
  1106. lineLen = oneLen;
  1107.     wi->dev_info.xg_text(wi->dev_info.user_state,
  1108.  wi->XOppX + wi->dev_info.bdr_pad,
  1109.  spot + 2,
  1110.  PlotData[idx].setName,
  1111.  T_UPPERLEFT, T_AXIS);
  1112.     spot += incr;
  1113. }
  1114.     }
  1115.     lineLen = lineLen * wi->dev_info.axis_width;
  1116.     leg_line.x1 = wi->XOppX + wi->dev_info.bdr_pad;
  1117.     leg_line.x2 = leg_line.x1 + lineLen;
  1118.     spot = wi->XOrgY;
  1119.     /* second pass draws the lines */
  1120.     for (idx = 0; idx < MAXSETS; idx++) {
  1121. if ((PlotData[idx].list) &&
  1122.     (spot + wi->dev_info.axis_height + 2 < wi->XOppY)) {
  1123.     leg_line.y1 = leg_line.y2 = spot - wi->dev_info.legend_pad;
  1124.     if (PM_BOOL("BarGraph")) 
  1125. wi->dev_info.xg_seg(wi->dev_info.user_state,
  1126.     1, &leg_line,
  1127.     incr / 4,
  1128.     L_VAR, LINESTYLE(idx), PIXVALUE(idx));
  1129.     if (!PM_BOOL("NoLines"))
  1130. wi->dev_info.xg_seg(wi->dev_info.user_state,
  1131.     1, &leg_line, 1, L_VAR,
  1132.     LINESTYLE(idx), PIXVALUE(idx));
  1133.     if (markFlag && !pixelMarks) {
  1134. wi->dev_info.xg_dot(wi->dev_info.user_state,
  1135.     leg_line.x1, leg_line.y1,
  1136.     P_MARK, MARKSTYLE(idx), PIXVALUE(idx));
  1137.     }
  1138.     spot += incr;
  1139. }
  1140.     }
  1141. }
  1142. static void
  1143. set_mark_flags(markFlag, pixelMarks, bigPixel, colorMark)
  1144. int    *markFlag;
  1145. int    *pixelMarks;
  1146. int    *bigPixel;
  1147. int    *colorMark;
  1148. /*
  1149.  * Determines the values of the old boolean flags based on the
  1150.  * new values in the parameters database.
  1151.  */
  1152. {
  1153.     *markFlag = 0;
  1154.     *pixelMarks = 0;
  1155.     *colorMark = 0;
  1156.     *bigPixel = 0;
  1157.     if (PM_BOOL("Markers")) {
  1158. *markFlag = 1;
  1159. *pixelMarks = 0;
  1160. *colorMark = 0;
  1161.     }
  1162.     if (PM_BOOL("PixelMarkers")) {
  1163. *markFlag = 1;
  1164. *pixelMarks = 1;
  1165. *bigPixel = 0;
  1166.     }
  1167.     if (PM_BOOL("LargePixels")) {
  1168. *markFlag = 1;
  1169. *pixelMarks = 1;
  1170. *bigPixel = 1;
  1171.     }
  1172.     if (PM_BOOL("StyleMarkers")) {
  1173. *markFlag = 1;
  1174. *pixelMarks = 0;
  1175. *colorMark = 1;
  1176.     }
  1177. }
  1178.  
  1179. #undef DELAY