home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 2 / FFMCD02.bin / new / misc / sci / cp / source / drawview.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-21  |  21.9 KB  |  1,037 lines

  1.  
  2. #include "cp.h"
  3.  
  4. #define SIZETIC  5  /* size major tik in pixels */
  5. #define BOXOFF   9  /* add to filename box size */
  6. #define TIKCOLOR 2  /* color for tiks */
  7. #define BORDER   20 /* size between filename boxes */
  8.  
  9. struct RastPort *rp;
  10. struct ViewPort *vp;
  11.  
  12. struct World wd;
  13. struct CurView cv;
  14.  
  15. WORD WIDTH;
  16. WORD HEIGHT;
  17. WORD OFFSET;
  18.  
  19. WORD xoff;
  20. WORD yoff;
  21.  
  22.  
  23. /* Draw everything if full is TRUE autoscale */
  24.  
  25. void DrawView ( BOOL full )
  26. {
  27. WORD w;
  28.  
  29.      if( SetList-> lh_TailPred != (struct Node *)SetList )
  30.        {
  31.  
  32.           vp = &(Scr-> ViewPort);
  33.           rp = PlotWindowWnd-> RPort;
  34.  
  35.           SetAPen(rp,1);
  36.  
  37.           OFFSET = rp-> Font-> tf_YSize + 2 * BORDER + Scr-> BarHeight;
  38.           HEIGHT = PlotWindowWnd-> Height - OFFSET - ( CPANEL ? 4 : 3 ) * GADHEIGHT;
  39.  
  40.           yoff = OFFSET + HEIGHT;
  41.  
  42.           xoff = rp-> Font-> tf_XSize * 6 + BORDER + SIZETIC;
  43.  
  44.           w = DrawFileNameBoxes( yoff - HEIGHT);
  45.  
  46.           WIDTH = PlotWindowWnd-> Width - w - xoff;
  47.  
  48.           if ( WIDTH < BORDER || HEIGHT < BORDER ) Death(20);
  49.  
  50.           DrawColorBox( xoff , yoff, WIDTH, HEIGHT, 14);
  51.  
  52.           if( full ) FindWorld ();
  53.  
  54.           XAxis();
  55.           YAxis();
  56.  
  57.           DrawAllSets ();
  58.  
  59.           if ( sym ) SymAllSets();
  60.           if ( grid ) Grid();
  61.        }
  62.  
  63. }
  64.  
  65. /* Draw all sets in SetList */
  66.  
  67. void DrawAllSets ()
  68. {
  69. WORD p = 4;
  70. struct Set *node;
  71.  
  72.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  73.        {
  74.  
  75.           SetAPen(rp,min(p,lastcolor));
  76.  
  77.           DrawSet ( node-> FirstPoint );
  78.  
  79.           p++;
  80.  
  81.           if ( p > lastcolor - 2 ) p = 4;
  82.        }
  83. }
  84.  
  85. /* Draw symbols on all sets */
  86.  
  87. void SymAllSets ()
  88. {
  89. struct Set *node;
  90.  
  91.      SetAPen( rp, min(15,lastcolor));
  92.      SetDrMd( rp, JAM2);
  93.  
  94.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  95.        {
  96.           SymSet ( node-> FirstPoint );
  97.        }
  98. }
  99.  
  100. /* Adjust view so all data sets show */
  101.  
  102. void FindWorld ()
  103. {
  104. struct Set *node;
  105.  
  106.      node = (struct Set *)SetList-> lh_Head;
  107.  
  108.      wd.xmax = node-> xmax;
  109.      wd.xmin = node-> xmin;
  110.      wd.ymax = node-> ymax;
  111.      wd.ymin = node-> ymin;
  112.  
  113.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  114.        {
  115.  
  116.           wd.xmax = max( wd.xmax, node-> xmax);
  117.           wd.xmin = min( wd.xmin, node-> xmin);
  118.           wd.ymax = max( wd.ymax, node-> ymax);
  119.           wd.ymin = min( wd.ymin, node-> ymin);
  120.  
  121.        }
  122.  
  123.      cv.xmax = wd.xmax;
  124.      cv.xmin = wd.xmin;
  125.      cv.ymax = wd.ymax;
  126.      cv.ymin = wd.ymin;
  127.  
  128.      wd.xdelta = wd.xmax - wd.xmin;
  129.      wd.ydelta = wd.ymax - wd.ymin;
  130.  
  131.      cv.xdelta = wd.xdelta;
  132.      cv.ydelta= wd.ydelta;
  133. }
  134.  
  135. /* Draw one set */
  136.  
  137. void DrawSet ( struct Point *ThisPoint )
  138. {
  139. LONG qx, qy;
  140. LONG le, te, re, be;
  141.  
  142. struct Rectangle rect;
  143. struct Region *new_region;
  144. struct Region *old_region;
  145.  
  146.      rect.MinX = xoff;
  147.      rect.MaxX = xoff + WIDTH;
  148.      rect.MinY = yoff - HEIGHT;
  149.      rect.MaxY = yoff;
  150.  
  151.      le = PlotWindowWnd-> LeftEdge;
  152.      te = PlotWindowWnd-> TopEdge;
  153.      re = PlotWindowWnd-> LeftEdge + PlotWindowWnd-> Width;
  154.      be = PlotWindowWnd-> TopEdge + PlotWindowWnd-> Height;
  155.  
  156.      if ( ! (new_region = NewRegion())) return;
  157.  
  158.      if ( ! (OrRectRegion( new_region, &rect))) return;
  159.  
  160.      if (( old_region = InstallClipRegion( PlotWindowWnd-> WLayer, new_region ))) return;
  161.  
  162.      qx = ScaleX( ThisPoint-> xval);
  163.      qy = ScaleY( ThisPoint-> yval);
  164.  
  165.      if ( qx < le ) qx = le;
  166.      if ( qx > re ) qx = re;
  167.      if ( qy < te ) qy = te;
  168.      if ( qy > be ) qy = be;
  169.  
  170.      Move ( rp, qx, qy );
  171.  
  172.      do
  173.        {
  174.           ThisPoint = ThisPoint-> NextPoint;
  175.  
  176.           qx = ScaleX( ThisPoint-> xval);
  177.  
  178.           /* need to change if not time sampled data */
  179.           if ( qx < le ) continue;
  180.           if ( qx > re ) break;
  181.  
  182.           qy = ScaleY( ThisPoint-> yval);
  183.  
  184.           if ( qy < te ) qy = te;
  185.           if ( qy > be ) qy = be;
  186.  
  187.           Draw ( rp, qx, qy);
  188.  
  189.        } while ( ThisPoint-> NextPoint );
  190.  
  191.      new_region = InstallClipRegion(PlotWindowWnd->WLayer, old_region);
  192.  
  193.      DisposeRegion(new_region);
  194. }
  195.  
  196. /* draw symbols on one set */
  197.  
  198. void SymSet ( struct Point *ThisPoint )
  199. {
  200. LONG qx, qy;
  201. WORD dx, dy;
  202. BOOL clip;
  203.  
  204.      dx = xoff + WIDTH;
  205.      dy = yoff - HEIGHT;
  206.  
  207.      do {
  208.  
  209.           clip = FALSE;
  210.  
  211.           qx = ScaleX( ThisPoint-> xval);
  212.           qy = ScaleY( ThisPoint-> yval);
  213.  
  214.           if ( qx < xoff )
  215.             {
  216.                qx = xoff;
  217.                clip = TRUE;
  218.             }
  219.           else if ( qx > dx )
  220.             {
  221.                qx = dx;
  222.                clip = TRUE;
  223.             }
  224.           if ( qy > yoff )
  225.             {
  226.                qy = yoff;
  227.                clip = TRUE;
  228.             }
  229.           else if ( qy < dy )
  230.             {
  231.                qy = dy;
  232.                clip = TRUE;
  233.             }
  234.  
  235.           if ( !clip )
  236.             {
  237.                Move ( rp, qx - 1, qy + 1);
  238.                Draw ( rp, qx + 1, qy - 1);
  239.                Move ( rp, qx + 1, qy + 1);
  240.                Draw ( rp, qx - 1, qy - 1);
  241.             }
  242.  
  243.           ThisPoint = ThisPoint-> NextPoint;
  244.  
  245.      } while ( ThisPoint-> NextPoint );
  246. }
  247.  
  248. /* Draw recessed bevel box filled with color */
  249.  
  250. void DrawColorBox ( WORD xs ,WORD ys , WORD xw ,WORD yh, WORD color)
  251. {
  252.  
  253.      SetAPen( rp, (MONO ? 0 : color));
  254.  
  255.      RectFill( rp, xs, ys - yh - 1, xs + xw, ys + 1 );
  256.  
  257.      DrawBevelBox( rp, xs - 2, ys - yh - 1 , xw + 5, yh + 4, GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE);
  258. }
  259.  
  260.  
  261. /* Draw Color boxes with filenames in them */
  262.  
  263. WORD DrawFileNameBoxes( WORD ys)
  264. {
  265. struct Set *node;
  266. struct TextExtent txex;
  267. WORD p = 4, h = 0, w = 0, xs, ns = 0;
  268.  
  269.  
  270.     if (NOFNAME) return((WORD)xoff);
  271.  
  272.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  273.        {
  274.           TextExtent( rp, node-> fn, strlen( node-> fn ), &txex);
  275.  
  276.           w = max( w, txex.te_Width);
  277.           h = max( h, txex.te_Height);
  278.  
  279.           ns++;
  280.        }
  281.  
  282.      w += BOXOFF;
  283.      h += BOXOFF;
  284.  
  285.      SetBPen( rp, 1);
  286.  
  287.      if ( ns > 1 )
  288.           xs = PlotWindowWnd-> Width - w - BORDER;
  289.      else
  290.        {
  291.           xs = ( PlotWindowWnd-> Width / 2 - w / 2);
  292.           ys = BORDER;
  293.        }
  294.  
  295.      for ( node = (struct Set *)SetList-> lh_Head; node-> snode.ln_Succ; node = (struct Set *)node-> snode.ln_Succ )
  296.        {
  297.           SetAPen( rp, p);
  298.  
  299.           ys += h;
  300.  
  301.           TextExtent( rp, node-> fn, strlen( node-> fn ), &txex);
  302.  
  303.           DrawColorBox( xs , ys, w, h, p );
  304.  
  305.           SetDrMd( rp, (JAM2 | INVERSVID));
  306.  
  307.           Move ( rp, xs + w/2 - txex.te_Width/2 , ys - BOXOFF / 2 );
  308.           Text( rp, node-> fn, strlen( node-> fn));
  309.  
  310.           ys += BORDER;
  311.  
  312.           SetDrMd( rp, JAM2);
  313.  
  314.           p++;
  315.           if ( p > lastcolor - 2 ) p = 4;
  316.        }
  317.  
  318.      return (WORD)( ns > 1 ? w + 2 * BORDER : xoff );
  319. }
  320.  
  321. /* Adjust xmin and xmax to even nubers and draw tiks with text */
  322.  
  323. void XAxis()
  324. {
  325.      LOGX ? logXAxis() : linXAxis();
  326. }
  327.  
  328. /* Adjust ymin and ymax to even nubers and draw tiks with text */
  329.  
  330. void YAxis()
  331. {
  332.      LOGY ? logYAxis() : linYAxis();
  333. }
  334.  
  335. void logXAxis()
  336. {
  337. LONG j, k, l;
  338. double q, r;
  339.  
  340.      /* Cant do negative log scale set lin */
  341.  
  342.      if( cv.xmin <= 0.0 )
  343.        {
  344.           LOGX = FALSE;
  345.           linXAxis();
  346.           return;
  347.        }
  348.  
  349.      j = (LONG) log10( cv.xmin );
  350.      if( log10( cv.xmin ) <= 0.0 ) j-- ;
  351.      cv.xmin = pow( 10.0, (double)j );
  352.  
  353.      k = (LONG) log10( cv.xmax );
  354.      if( log10( cv.xmax ) > 0.0 ) k++ ;
  355.      cv.xmax = pow( 10.0, (double)k );
  356.  
  357.      cv.xdec = k - j;
  358.  
  359.      cv.xmode = -1;
  360.  
  361.      cv.xdelta = cv.xmax - cv.xmin;
  362.  
  363.      cv.xfact = 1;
  364.  
  365.      for( q = cv.xmin ; q < cv.xmax; j++)
  366.        {
  367.           ticX( q, TRUE);
  368.           for( l = 2; l < 10; l++)
  369.             {
  370.                r = q * l;
  371.                if( r > cv.xmax ) break;
  372.                ticX( r, FALSE);
  373.             }
  374.           q = pow( 10.0, (double)j );
  375.        }
  376.  
  377.      ticX( cv.xmax, TRUE);
  378. }
  379.  
  380. void logYAxis()
  381. {
  382. LONG j, k, l;
  383. double q, r;
  384.  
  385.      /* Cant do negative log scale set lin */
  386.  
  387.      if( cv.ymin <= 0.0 )
  388.        {
  389.           LOGY = FALSE;
  390.           linYAxis();
  391.           return;
  392.        }
  393.  
  394.      j = (LONG) log10( cv.ymin );
  395.      if( log10( cv.ymin ) <= 0.0 ) j-- ;
  396.      cv.ymin = pow( 10.0, (double)j );
  397.  
  398.      k = (LONG) log10( cv.ymax );
  399.      if( log10( cv.ymax ) > 0.0 ) k++ ;
  400.      cv.ymax = pow( 10.0, (double)k );
  401.  
  402.      cv.ydec = k - j;
  403.  
  404.      cv.ymode = -1;
  405.  
  406.      cv.ydelta = cv.ymax - cv.ymin;
  407.  
  408.      cv.yfact = 1;
  409.  
  410.      for( q = cv.ymin ; q < cv.ymax; j++)
  411.        {
  412.           ticY( q, TRUE);
  413.           for( l = 2; l < 10; l++)
  414.             {
  415.                r = q * l;
  416.                if( r > cv.ymax ) break;
  417.                ticY( r, FALSE);
  418.             }
  419.           q = pow( 10.0, (double)j );
  420.        }
  421.  
  422.      ticY( cv.ymax, TRUE);
  423. }
  424.  
  425. void linXAxis()
  426. {
  427. double a, p;
  428. LONG b;
  429. WORD k;
  430. UBYTE s[32];
  431. struct TextExtent txex;
  432.  
  433.      /* if x all the same value kluge */
  434.  
  435.      if ( cv.xmax == cv.xmin )
  436.        {
  437.           if ( cv.xmax == 0.0 ) cv.xmax = 1.0;
  438.           cv.xmax *= 1.01;
  439.           cv.xmin *= 0.99;
  440.        }
  441.  
  442.      /* end kluge */
  443.  
  444.      /* Calculate X View */
  445.  
  446.      cv.xtik = cv.xsubt = cv.xmode = cv.xprec = 0.0;
  447.  
  448.      tik( cv.xmin, cv.xmax, &cv.xtik, &cv.xsubt, &cv.xmode, &cv.xprec);
  449.  
  450.      a = cv.xmin / cv.xtik;
  451.      Round ( &a );
  452.      b = (LONG)a;
  453.      if ( a < 0 && b != a ) b--;
  454.      cv.xmin = cv.xtik * b;
  455.  
  456.      a = cv.xmax / cv.xtik;
  457.      Round ( &a );
  458.      b = (LONG)a;
  459.      if ( a > 0 && b != a ) b++;
  460.      cv.xmax = cv.xtik * b;
  461.  
  462.      cv.xdelta = cv.xmax - cv.xmin;
  463.  
  464.      SetDrMd( rp, JAM1);
  465.  
  466.      if ( cv.xmode )
  467.        {
  468.           CalcMode ( cv.xdelta , &cv.xfact );
  469.  
  470.           sprintf( s, "x %.0le", cv.xfact);
  471.           E2xTen( s );
  472.  
  473.           TextExtent( rp, s, strlen( s ), &txex);
  474.  
  475.           SetAPen( rp, (MONO ? 1 : TIKCOLOR));
  476.  
  477.           Move ( rp, xoff + WIDTH/2 - txex.te_Width/2, yoff + 2 * GADHEIGHT);
  478.           Text( rp, s, strlen( s ));
  479.        }
  480.  
  481.      /* Draw Tick Marks */
  482.  
  483.      a = p = cv.xmin;
  484.      do
  485.        {
  486.           ticX( a, TRUE );
  487.           a += cv.xtik;
  488.           for ( k = 1; k <= cv.xsubt && p <= cv.xmax; k++)
  489.             {
  490.                ticX( p, FALSE);
  491.                p = a - k * cv.xtik / cv.xsubt;
  492.             }
  493.        } while ( p < cv.xmax );
  494.  
  495.      ticX( cv.xmax, TRUE);
  496. }
  497.  
  498. void linYAxis()
  499. {
  500. double a, p;
  501. LONG b;
  502. WORD k;
  503. UBYTE s[32];
  504. struct TextExtent txex;
  505.  
  506.      /* if y all the same value kluge */
  507.  
  508.      if ( cv.ymax == cv.ymin )
  509.        {
  510.           if ( cv.ymax == 0.0 ) cv.ymax = 1.0;
  511.           cv.ymax *= 1.01;
  512.           cv.ymin *= 0.99;
  513.        }
  514.  
  515.      /* end kluge */
  516.  
  517.      /* Calculate Y View */
  518.  
  519.      cv.ytik = cv.ysubt = cv.ymode = cv.yprec = 0.0;
  520.  
  521.      tik( cv.ymin, cv.ymax, &cv.ytik, &cv.ysubt, &cv.ymode, &cv.yprec);
  522.  
  523.      a = cv.ymin / cv.ytik;
  524.      Round ( &a );
  525.      b = (LONG)a;
  526.      if ( a < 0 && b != a ) b--;
  527.      cv.ymin = cv.ytik * b;
  528.  
  529.      a = cv.ymax / cv.ytik;
  530.      Round ( &a );
  531.      b = (LONG)a;
  532.      if ( a > 0 && b != a ) b++;
  533.      cv.ymax = cv.ytik * b;
  534.  
  535.      cv.ydelta = cv.ymax - cv.ymin;
  536.  
  537.  
  538.      SetDrMd( rp, JAM1);
  539.  
  540.  
  541.      if ( cv.ymode )
  542.        {
  543.           CalcMode ( cv.ydelta , &cv.yfact );
  544.  
  545.           sprintf( s, "%.0le", cv.yfact);
  546.           E2xTen( s );
  547.  
  548.           TextExtent( rp, s, strlen( s ), &txex);
  549.  
  550.           SetAPen( rp, (MONO ? 1 : TIKCOLOR));
  551.  
  552.           Move ( rp, xoff - BORDER - txex.te_Width, PlotWindowWnd-> TopEdge + txex.te_Height);
  553.           Text( rp, s, strlen( s ));
  554.        }
  555.  
  556.  
  557.  
  558.      /* Draw Tick Marks */
  559.  
  560.      a = p = cv.ymin;
  561.      do
  562.        {
  563.           ticY( a , TRUE);
  564.           a += cv.ytik;
  565.           for ( k = 1; k <= cv.ysubt && p <= cv.ymax; k++)
  566.             {
  567.                ticY( p, FALSE);
  568.                p = a - k * cv.ytik / cv.ysubt;
  569.             }
  570.        } while ( p < cv.ymax );
  571.  
  572.      ticY( cv.ymax, TRUE);
  573. }
  574.  
  575. void Grid()
  576. {
  577.      LOGX ? logXGrid() : linXGrid() ;
  578.      LOGY ? logYGrid() : linYGrid() ;
  579. }
  580.  
  581. void logXGrid()
  582. {
  583. float q;
  584. double j, k;
  585. LONG x;
  586.  
  587.      SetDrMd( rp, COMPLEMENT);
  588.      SetDrPt( rp, 0x3333);
  589.  
  590.      j = log10( cv.xmin ) + 1;
  591.      k = log10( cv.xmax );
  592.  
  593.      for( j; j < k; j += 1.0)
  594.        {
  595.           q = pow( 10.0, (double)j );
  596.           x = ScaleX( q );
  597.           if ( x < xoff + WIDTH - 1 )
  598.             {
  599.                Move( rp, x, yoff );
  600.                Draw( rp, x, yoff - HEIGHT );
  601.             }
  602.        }
  603.  
  604.      SetDrPt( rp, 0xFFFF);
  605. }
  606.  
  607.  
  608. void logYGrid()
  609. {
  610. float q;
  611. double j, k;
  612. LONG y;
  613.  
  614.      SetDrMd( rp, COMPLEMENT);
  615.      SetDrPt( rp, 0x3333);
  616.  
  617.      j = log10( cv.ymin ) + 1.0;
  618.      k = log10( cv.ymax );
  619.  
  620.      for( j; j < k; j += 1.0)
  621.        {
  622.           q = pow( 10.0, (double)j );
  623.           y = ScaleY( q );
  624.           if ( y > yoff - HEIGHT + 1 )
  625.             {
  626.                Move( rp, xoff, y );
  627.                Draw( rp, xoff + WIDTH, y );
  628.             }
  629.        }
  630.  
  631.      SetDrPt( rp, 0xFFFF);
  632. }
  633.  
  634. void linXGrid()
  635. {
  636. double a;
  637. WORD x;
  638.  
  639.      SetDrMd( rp, COMPLEMENT);
  640.      SetDrPt( rp, 0x3333);
  641.  
  642.      a = cv.xmin;
  643.  
  644.      while ( a  < cv.xmax - cv.xtik )
  645.        {
  646.           a += cv.xtik;
  647.           x = ScaleX( (float)a );
  648.           if ( x < xoff + WIDTH - 1 )
  649.             {
  650.                Move( rp, x, yoff);
  651.                Draw( rp, x, yoff - HEIGHT);
  652.             }
  653.        }
  654.  
  655.      SetDrPt( rp, 0xFFFF);
  656. }
  657.  
  658. void linYGrid()
  659. {
  660. double a;
  661. WORD y;
  662.  
  663.      SetDrMd( rp, COMPLEMENT);
  664.      SetDrPt( rp, 0x3333);
  665.  
  666.      a = cv.ymin;
  667.  
  668.      while ( a < cv.ymax - cv.ytik )
  669.        {
  670.           a += cv.ytik;
  671.           y = ScaleY( (float)a );
  672.           if ( y > yoff - HEIGHT + 1 )
  673.             {
  674.                Move( rp, xoff, y );
  675.                Draw( rp, xoff + WIDTH, y );
  676.             }
  677.        }
  678.  
  679.      SetDrPt( rp, 0xFFFF);
  680. }
  681.  
  682. /* Color entire window with pen zero then refresh gadgets if control panel on*/
  683.  
  684. void Erase()
  685. {
  686.      SetAPen( rp, 0);
  687.      SetDrMd( rp, JAM1);
  688.      RectFill( rp, 0, 0, PlotWindowWnd-> Width, PlotWindowWnd-> Height );
  689.      if ( CPANEL ) RefreshGadgets( PlotWindowGadgets[0], PlotWindowWnd, NULL);
  690. }
  691.  
  692. /* Draw an XAxis tik and put text if major */
  693.  
  694. void ticX ( double val, BOOL major)
  695. {
  696. LONG x, y;
  697. UBYTE tx[32];
  698. UBYTE *txp;
  699. UBYTE fm[32];
  700. double rs;
  701. struct TextExtent txex;
  702.  
  703.      x = ScaleX((float) val);
  704.      y = yoff + 3;
  705.      Move ( rp, x, y);
  706.      txp = tx;
  707.  
  708.      if ( major )
  709.           y += SIZETIC;
  710.      else
  711.           y += SIZETIC/2;
  712.  
  713.      SetDrMd( rp, JAM2);
  714.      SetBPen(rp,0);
  715.      SetAPen( rp, ( MONO ? 1 : TIKCOLOR));
  716.  
  717.      Draw( rp, x, y);
  718.  
  719.      if ( major )
  720.        {
  721.           if ( cv.xmode == 1 )
  722.             {
  723.                rs = val / cv.xfact;
  724.                Round( &rs );
  725.                sprintf( tx, "%lg", rs);
  726.             }
  727.           else if ( cv.xmode == 0 )
  728.             {
  729.                sprintf( fm, "%%.%hdlf", cv.xprec);
  730.                sprintf( tx, fm, val);
  731.             }
  732.           else if ( cv.xmode == -1 )
  733.             {
  734.                sprintf( tx, "%le", val);
  735.                E2xTen( tx );
  736.                txp++;
  737.             }
  738.  
  739.           TextExtent( rp, txp, strlen( txp ), &txex);
  740.           Move ( rp, x - txex.te_Width/2, y + txex.te_Height + SIZETIC / 2 );
  741.           Text( rp, txp, strlen( txp ));
  742.        }
  743.  
  744. }
  745.  
  746. /* Draw a YAxis tik and put text if major */
  747.  
  748. void ticY ( double val, BOOL major)
  749. {
  750. LONG x, y;
  751. UBYTE tx[32];
  752. UBYTE *txp;
  753. UBYTE fm[32];
  754. double rs;
  755. struct TextExtent txex;
  756.  
  757.      y = ScaleY((float) val);
  758.      x = xoff - 3;
  759.      Move ( rp, x, y);
  760.      txp = tx;
  761.  
  762.      if ( major )
  763.           x -= SIZETIC;
  764.      else
  765.           x -= SIZETIC/2;
  766.  
  767.      SetDrMd( rp, JAM2);
  768.      SetBPen( rp, 0);
  769.      SetAPen( rp, (MONO ? 1 : TIKCOLOR));
  770.  
  771.      Draw( rp, x, y);
  772.  
  773.      if ( major )
  774.        {
  775.           if ( cv.ymode == 1 )
  776.             {
  777.                rs = val / cv.yfact;
  778.                Round( &rs );
  779.                sprintf( tx, "%lg", rs);
  780.             }
  781.           else if ( cv.ymode == 0 )
  782.             {
  783.                sprintf( fm, "%%.%hdlf", cv.yprec);
  784.                sprintf( tx, fm, val);
  785.             }
  786.           else if ( cv.ymode == -1 )
  787.             {
  788.                sprintf( tx, "%le", val);
  789.                E2xTen( tx );
  790.                txp++;
  791.             }
  792.  
  793.  
  794.           TextExtent(rp, txp, strlen( txp ), &txex);
  795.           Move( rp, x - txex.te_Width - SIZETIC / 2, y + txex.te_Height/2 - 1);
  796.           Text( rp, txp, strlen( txp ));
  797.        }
  798. }
  799.  
  800. /* Routine does everything when Zoom gadget selected */
  801.  
  802. void Zoom()
  803. {
  804. BOOL   running = TRUE;
  805. BOOL   select = FALSE;
  806. LONG   j = 0, k = 0;
  807. WORD   selco[2];
  808. static WORD Cross [2];
  809. struct IntuiMessage *m;
  810. double a,b,c,d;
  811.  
  812.      ReportMouse( TRUE, PlotWindowWnd);
  813.      SetMouseQueue( PlotWindowWnd, 1 );
  814.      do {
  815.  
  816.        Wait ( 1L << PlotWindowWnd-> UserPort-> mp_SigBit );
  817.  
  818.        while( m = GT_GetIMsg( PlotWindowWnd->UserPort )) {
  819.  
  820.           CopyMem(( char * )m, ( char * )&PlotWindowMsg, (long)sizeof( struct IntuiMessage ));
  821.  
  822.           GT_ReplyIMsg( m );
  823.  
  824.           switch ( PlotWindowMsg.Class ) {
  825.  
  826.                case IDCMP_MOUSEMOVE:
  827.  
  828.                     if ( PlotWindowMsg.MouseX > xoff && PlotWindowMsg.MouseX < xoff + WIDTH
  829.                          && PlotWindowMsg.MouseY < yoff && PlotWindowMsg.MouseY > yoff - HEIGHT)
  830.                       {
  831.                          SetDrMd( rp, COMPLEMENT);
  832.  
  833.                          if ( k )
  834.                            {
  835.                               Move( rp, xoff, Cross[1]);
  836.                               Draw( rp, xoff + WIDTH, Cross[1]);
  837.  
  838.                               Move( rp, Cross[0], yoff);
  839.                               Draw( rp, Cross[0], yoff - HEIGHT);
  840.                            }
  841.  
  842.  
  843.                          Move( rp, xoff, PlotWindowMsg.MouseY);
  844.                          Draw( rp, xoff + WIDTH, PlotWindowMsg.MouseY);
  845.  
  846.                          Move( rp, PlotWindowMsg.MouseX, yoff);
  847.                          Draw( rp, PlotWindowMsg.MouseX, yoff - HEIGHT);
  848.  
  849.                          if ( select )
  850.                            {
  851.                               if ( j )
  852.                                 {
  853.                                    Move( rp, selco[0], selco[1]);
  854.                                    Draw( rp, selco[0], Cross[1]);
  855.                                    Move( rp, selco[0], selco[1]);
  856.                                    Draw( rp, Cross[0], selco[1]);
  857.                                 }
  858.  
  859.                               Move( rp, selco[0], selco[1]);
  860.                               Draw( rp, selco[0], PlotWindowMsg.MouseY);
  861.                               Move( rp, selco[0], selco[1]);
  862.                               Draw( rp, PlotWindowMsg.MouseX, selco[1]);
  863.  
  864.                               j++;
  865.                            }
  866.  
  867.                          Cross[0] = PlotWindowMsg.MouseX;
  868.                          Cross[1] = PlotWindowMsg.MouseY;
  869.  
  870.                          k++;
  871.                       }
  872.  
  873.                     break;
  874.  
  875.                case IDCMP_MOUSEBUTTONS:
  876.                     if (PlotWindowMsg.Code == SELECTUP) running = FALSE;
  877.                     else if (PlotWindowMsg.Code == SELECTDOWN)
  878.                       {
  879.                          select = TRUE;
  880.                          selco[0] = PlotWindowMsg.MouseX;
  881.                          selco[1] = PlotWindowMsg.MouseY;
  882.                       }
  883.                     break;
  884.  
  885.                case IDCMP_VANILLAKEY:
  886.  
  887.                               if ( k )
  888.                                 {
  889.                                    Move( rp, xoff, Cross[1]);
  890.                                    Draw( rp, xoff + WIDTH, Cross[1]);
  891.  
  892.                                    Move( rp, Cross[0], yoff);
  893.                                    Draw( rp, Cross[0], yoff - HEIGHT);
  894.                                    goto end;
  895.                                 }
  896.  
  897.                default:
  898.                     break;
  899.           }
  900.        }
  901.      } while ( running);
  902.  
  903.      if ( selco[0] == PlotWindowMsg.MouseX || selco[1] == PlotWindowMsg.MouseY )
  904.        {
  905.           Erase ();
  906.           DrawView( FALSE );
  907.           return;
  908.        }
  909.      if ( select )
  910.        {
  911.           a = ZoomX( selco[0] );
  912.           b = ZoomX( PlotWindowMsg.MouseX );
  913.           c = ZoomY( selco[1] );
  914.           d = ZoomY( PlotWindowMsg.MouseY );
  915.  
  916.           cv.xmin = min( a, b);
  917.           cv.xmax = max( a, b);
  918.  
  919.           cv.ymin = min( c, d);
  920.           cv.ymax = max( c, d);
  921.  
  922.           cv.xdelta = cv.xmax - cv.xmin;
  923.           cv.ydelta = cv.ymax - cv.ymin;
  924.  
  925.           Erase();
  926.  
  927.           DrawView( FALSE );
  928.        }
  929. end:
  930.      ReportMouse( FALSE, PlotWindowWnd);
  931.  
  932. }
  933.  
  934. /* When mode is exponential keep in engineering units */
  935.  
  936. void CalcMode ( double delta , double *fact )
  937. {
  938. UBYTE s[32];
  939. WORD e;
  940. WORD j = 0, k = 0;
  941.  
  942.      sprintf( s ,"%.0le", delta);
  943.  
  944.      while ( s[k] != 'e' ) ++k;
  945.  
  946.      sscanf( &s[++k], "%hd", &e);
  947.  
  948.      if ( e < 1 )  while( j > e ) j -= 3;
  949.      else  while( j+1 < e ) j += 3;
  950.  
  951.      *fact = pow( 10.0, (double)j );
  952. }
  953.  
  954. /* Change exponetial to X10 */
  955.  
  956. void E2xTen( UBYTE *s)
  957. {
  958. WORD e;
  959. WORD k = 0;
  960.  
  961.      while ( s[k] != 'e' && s[k] != 'E') ++k;
  962.  
  963.      sscanf( &s[++k], "%hd", &e);
  964.  
  965.      sprintf( s,"X 10%+hd",e);
  966. }
  967.  
  968. /* Write X and Y to screen when mouse select
  969.    Erase text if mouse has moved more than 3
  970.    pixels since seldown */
  971.  
  972. void Identify(WORD x, WORD y, BOOL SelDOWN)
  973. {
  974. static WORD ox;
  975. static WORD oy;
  976. struct TextExtent txex;
  977. static double zx;
  978. static double zy;
  979. UBYTE txt[16];
  980.  
  981.      SetDrMd( rp, COMPLEMENT);
  982.  
  983.      if( SelDOWN )
  984.        {
  985.           SetDrMd( rp, JAM1);
  986.           SetAPen(rp,15);
  987.           WritePixel( rp, x, y);
  988.           SetAPen(rp,9);
  989.           WritePixel( rp, x+1, y);
  990.           WritePixel( rp, x-1, y);
  991.           WritePixel( rp, x, y-1);
  992.           WritePixel( rp, x, y+1);
  993.  
  994.           SetAPen(rp,13);
  995.           WritePixel( rp, x+2, y+2);
  996.           WritePixel( rp, x+2, y-2);
  997.           WritePixel( rp, x-2, y-2);
  998.           WritePixel( rp, x-2, y+2);
  999.  
  1000.           zx = ZoomX( x );
  1001.           zy = ZoomY( y );
  1002.  
  1003.           SetDrMd( rp, COMPLEMENT);
  1004.        }
  1005.  
  1006.      else if ( (x >= ox - 3 && x <= ox + 3 )  && ( y >= oy - 3 && y <= oy + 3 ))
  1007.        {
  1008.           SetDrMd( rp, JAM1);
  1009.           x = ox;
  1010.           y = oy;
  1011.        }
  1012.      else
  1013.        {
  1014.           x = ox;
  1015.           y = oy;
  1016.        }
  1017.  
  1018.  
  1019.      if (depth > 2)
  1020.           SetAPen(rp,15);
  1021.      else
  1022.           SetAPen(rp,1);
  1023.  
  1024.      sprintf( txt ,"%.2lE", zx);
  1025.  
  1026.      TextExtent( rp, txt, strlen( txt ), &txex);
  1027.      Move ( rp, x+6, y + txex.te_Height);
  1028.      Text (rp,txt, strlen(txt));
  1029.  
  1030.      sprintf( txt ,"%.2lE", zy);
  1031.  
  1032.      TextExtent( rp, txt, strlen( txt ), &txex);
  1033.      Move ( rp, x+6, y-2 );
  1034.      Text (rp,txt, strlen(txt));
  1035.  
  1036.      ox = x;
  1037.      oy = y;
  1038. }