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