/*------------------------------------------------------------\
|                                                             |
| Tool    :                   GRAAL                           |
|                                                             |
| File    :                   View.c                          |
|                                                             |
| Authors :      Venot Frederic and Jacomme Ludovic           |
|                                                             |
| Date    :                  26/02/93                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                         Include Files                       |
|                                                             |
\------------------------------------------------------------*/

# include <stdio.h>
# include <Xm/Xm.h>

# include MUT_H
# include MPH_H
# include RDS_H
# include RPR_H
# include RFM_H
# include GRM_H
# include GSB_H
# include GTB_H
# include GMX_H
# include GMV_H

# include "GMV_view.h"

/*------------------------------------------------------------\
|                                                             |
|                           Constants                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                            Types                            |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                          Variables                          |
|                                                             |
\------------------------------------------------------------*/

 graalzoom *GraalHeadZoom    = (graalzoom *)NULL;

 int        GraalPercentZoom = GRAAL_PERCENT_ZOOM;
 int        GraalPercentMove = GRAAL_PERCENT_MOVE;

/*------------------------------------------------------------\
|                                                             |
|                            Menu                             |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                          Functions                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                       GraalAllocZoom                        |
|                                                             |
\------------------------------------------------------------*/

 graalzoom *GraalAllocZoom ()

 {
   return ( (graalzoom *) rdsalloc ( sizeof ( graalzoom ), 1));
 }

/*------------------------------------------------------------\
|                                                             |
|                       GraalFreeZoom                         |
|                                                             |
\------------------------------------------------------------*/

 void GraalFreeZoom ( FreeZoom )

    graalzoom *FreeZoom;

 {
   rdsfree ( (char *)FreeZoom, sizeof(FreeZoom) );
 }

/*------------------------------------------------------------\
|                                                             |
|                       GraalAddZoom                          |
|                                                             |
\------------------------------------------------------------*/
 
 void GraalAddZoom ()
 
 {
   graalzoom *GraalZoom;
 
   GraalZoom       = GraalAllocZoom ();
   GraalZoom->X    = GraalLambdaGridX;
   GraalZoom->Y    = GraalLambdaGridY;
   GraalZoom->DX   = GraalLambdaGridDx;
   GraalZoom->DY   = GraalLambdaGridDy;
   GraalZoom->NEXT = GraalHeadZoom;
   GraalHeadZoom   = GraalZoom;
 }

/*------------------------------------------------------------\
|                                                             |
|                         GraalDelZoom                        |
|                                                             |
\------------------------------------------------------------*/

 char GraalDelZoom()

 {
   graalzoom *GraalZoom;

   if ( GraalHeadZoom != (graalzoom *) NULL )
   {
     GraalZoom     = GraalHeadZoom;
     GraalHeadZoom = GraalHeadZoom->NEXT;
     GraalFreeZoom( GraalZoom );

     return( GRAAL_TRUE ); 
   }

   return( GRAAL_FALSE );
 }

/*------------------------------------------------------------\
|                                                             |
|                     GraalInitializeZoom                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalInitializeZoom()

  {
    while( GraalDelZoom() != GRAAL_FALSE );

    if ( GraalComputeBound() == GRAAL_FALSE )
    {
      GraalInitializeLambdaGrid();
    }
    else
    {
      GraalLambdaGridX  = ( GraalBoundXmin / RDS_LAMBDA ) - 1;
      GraalLambdaGridY  = ( GraalBoundYmin / RDS_LAMBDA ) - 1;
      GraalLambdaGridDx = GraalBoundXmax / RDS_LAMBDA;
      GraalLambdaGridDy = GraalBoundYmax / RDS_LAMBDA;
      GraalLambdaGridDx = GraalLambdaGridDx - GraalLambdaGridX + 1;
      GraalLambdaGridDy = GraalLambdaGridDy - GraalLambdaGridY + 1;

      GraalComputeLambdaGrid();
    }

    GraalComputeAndDisplayMap();
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalZoomUndo                        |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomUndo()

  {
    if ( GraalHeadZoom == (graalzoom *)NULL )
    {
      GraalErrorMessage( GraalMainWindow, "No previous zoom !" ); 
    }
    else
    {
      GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

      GraalLambdaGridX  = GraalHeadZoom->X;
      GraalLambdaGridY  = GraalHeadZoom->Y;
      GraalLambdaGridDx = GraalHeadZoom->DX;
      GraalLambdaGridDy = GraalHeadZoom->DY;

      GraalComputeLambdaGrid();
      GraalComputeAndDisplayMap();

      GraalDisplayFigure( 0, 0,
                          GraalGraphicDx, GraalGraphicDy );

      GraalRefreshGraphicWindow( 0, 0,
                                 GraalGraphicDx, GraalGraphicDy);

      GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );

      GraalDelZoom();
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalZoomRight                       |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomRight()

  {
    long      Delta;
    long      Offset;
    long      GraalOldPixelGridX;

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

    Delta = ( GraalPercentMove * GraalLambdaGridDx ) / 100;

    if ( Delta == 0 ) Delta = 1;

    if ( ( GraalLambdaGridX + GraalLambdaGridDx + Delta ) < 
         ( GraalWindowXmax / RDS_LAMBDA                 ) )
    {
      GraalLambdaGridX = GraalLambdaGridX + Delta;
    }

    GraalOldPixelGridX = GraalPixelGridX;
    GraalPixelGridX    = (float)(GraalLambdaGridX) * GraalLambdaGridStep;
    Offset             = GraalPixelGridX - GraalOldPixelGridX;

    XCopyArea( XtDisplay ( GraalGraphicWindow ),
               GraalGraphicPixmap,
               GraalGraphicPixmap,
               GraalBackgroundGC,
               Offset, 0,
               GraalGraphicDx - Offset,
               GraalGraphicDy,
               0, 0
             ); 

    GraalComputeAndDisplayMap();
    GraalDisplayFigure( GraalGraphicDx - Offset, 0, 
                        GraalGraphicDx, GraalGraphicDy ); 
    GraalRefreshGraphicWindow( 0, 0,
                               GraalGraphicDx, GraalGraphicDy); 

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalZoomLeft                        |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomLeft()

  {
    long      Delta;
    long      Offset;
    long      GraalOldPixelGridX;

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

    Delta = ( GraalPercentMove * GraalLambdaGridDx ) / 100;

    if ( Delta == 0 ) Delta = 1;

    if ( ( GraalLambdaGridX - Delta ) > ( GraalWindowXmin / RDS_LAMBDA ) )
    {
      GraalLambdaGridX = GraalLambdaGridX - Delta;
    }

    GraalOldPixelGridX = GraalPixelGridX;
    GraalPixelGridX    = (float)(GraalLambdaGridX) * GraalLambdaGridStep;
    Offset             = GraalOldPixelGridX - GraalPixelGridX;

    XCopyArea( XtDisplay ( GraalGraphicWindow ),
               GraalGraphicPixmap,
               GraalGraphicPixmap,
               GraalBackgroundGC,
               0, 0,
               GraalGraphicDx - Offset,
               GraalGraphicDy,
               Offset, 0
             ); 

    GraalComputeAndDisplayMap();
    GraalDisplayFigure( 0, 0, Offset, GraalGraphicDy );
    GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy);

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
  }

/*------------------------------------------------------------\
|                                                             |
|                         GraalZoomDown                       |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomDown()

  {
    long      Delta;
    long      Offset;
    long      GraalOldPixelGridY;

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

    Delta = ( GraalPercentMove * GraalLambdaGridDy ) / 100;

    if ( Delta == 0 ) Delta = 1;

    if ( ( GraalLambdaGridY - Delta ) > ( GraalWindowYmin / RDS_LAMBDA ) )
    {
      GraalLambdaGridY = GraalLambdaGridY - Delta;
    }

    GraalOldPixelGridY = GraalPixelGridY;
    GraalPixelGridY    = (float)(GraalLambdaGridY) * GraalLambdaGridStep;
    Offset             = GraalOldPixelGridY - GraalPixelGridY;

    XCopyArea( XtDisplay ( GraalGraphicWindow ),
               GraalGraphicPixmap,
               GraalGraphicPixmap,
               GraalBackgroundGC,
               0, Offset,
               GraalGraphicDx,
               GraalGraphicDy - Offset,
               0, 0
             ); 

    GraalComputeAndDisplayMap();
    GraalDisplayFigure( 0, 0, GraalGraphicDx, Offset ); 
    GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy);

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
  }

/*------------------------------------------------------------\
|                                                             |
|                         GraalZoomUp                         |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomUp()

  {
    long      Delta;
    long      Offset;
    long      GraalOldPixelGridY;

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

    Delta = ( GraalPercentMove * GraalLambdaGridDy ) / 100;

    if ( Delta == 0 ) Delta = 1;

    if ( ( GraalLambdaGridY + GraalLambdaGridDy + Delta ) < 
         ( GraalWindowYmax / RDS_LAMBDA                ) )
    {
      GraalLambdaGridY = GraalLambdaGridY + Delta;
    }

    GraalOldPixelGridY = GraalPixelGridY;
    GraalPixelGridY    = (float)(GraalLambdaGridY) * GraalLambdaGridStep;
    Offset             = GraalPixelGridY - GraalOldPixelGridY;

    XCopyArea( XtDisplay ( GraalGraphicWindow ),
               GraalGraphicPixmap,
               GraalGraphicPixmap,
               GraalBackgroundGC,
               0, 0,
               GraalGraphicDx,
               GraalGraphicDy - Offset,
               0, Offset
             ); 

    GraalComputeAndDisplayMap();
    GraalDisplayFigure( 0, GraalGraphicDy - Offset,
                        GraalGraphicDx, GraalGraphicDy ); 
    GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy);

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalZoomMore                        |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomMore()

  {
    long DeltaX;
    long DeltaY;

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

    DeltaX = ( GraalPercentZoom * GraalLambdaGridDx ) / 100;
    DeltaY = ( GraalPercentZoom * GraalLambdaGridDy ) / 100;

    if ( ( DeltaX >= 2 ) &&
         ( DeltaY >= 2 ) )
    {
      GraalAddZoom();

      GraalLambdaGridX  = GraalLambdaGridX + (DeltaX >> 1);
      GraalLambdaGridY  = GraalLambdaGridY + (DeltaY >> 1);
      GraalLambdaGridDx = GraalLambdaGridDx - DeltaX;
      GraalLambdaGridDy = GraalLambdaGridDy - DeltaY;

      GraalComputeLambdaGrid();
      GraalComputeAndDisplayMap();
      GraalDisplayFigure( 0, 0, GraalGraphicDx, GraalGraphicDy );
      GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy );
    }

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalZoomLess                        |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomLess()

  {
    long DeltaX;
    long DeltaY;

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

    DeltaX = 100 * GraalLambdaGridDx / ( 100 - GraalPercentZoom );
    DeltaY = 100 * GraalLambdaGridDy / ( 100 - GraalPercentZoom );

    GraalAddZoom();
 
    GraalLambdaGridX  = GraalLambdaGridX - ((DeltaX - GraalLambdaGridDx) >> 1);
    GraalLambdaGridY  = GraalLambdaGridY - ((DeltaY - GraalLambdaGridDy) >> 1);
    GraalLambdaGridDx = DeltaX;
    GraalLambdaGridDy = DeltaY;

    GraalComputeLambdaGrid();
    GraalComputeAndDisplayMap();
    GraalDisplayFigure( 0, 0, GraalGraphicDx, GraalGraphicDy );
    GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy );

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalZoomFit                         |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomFit()

  {
    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

    if ( GraalComputeBound() == GRAAL_FALSE )
    {
      GraalErrorMessage( GraalMainWindow, "No element to display !" );
    }
    else
    {
      GraalAddZoom();

      GraalLambdaGridX  = ( GraalBoundXmin / RDS_LAMBDA ) - 1;
      GraalLambdaGridY  = ( GraalBoundYmin / RDS_LAMBDA ) - 1;
      GraalLambdaGridDx = GraalBoundXmax / RDS_LAMBDA;
      GraalLambdaGridDy = GraalBoundYmax / RDS_LAMBDA;
      GraalLambdaGridDx = GraalLambdaGridDx - GraalLambdaGridX + 1;
      GraalLambdaGridDy = GraalLambdaGridDy - GraalLambdaGridY + 1;

      GraalComputeLambdaGrid();
      GraalComputeAndDisplayMap();
      GraalDisplayFigure( 0, 0, GraalGraphicDx, GraalGraphicDy );
      GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy );
    }

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalZoomCenter                      |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomCenter( LambdaX, LambdaY )

     long LambdaX;
     long LambdaY;
  {
    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

    GraalLambdaGridX = LambdaX - ( GraalLambdaGridDx >> 1 );
    GraalLambdaGridY = LambdaY - ( GraalLambdaGridDy >> 1 );

    GraalComputeLambdaGrid();
    GraalComputeAndDisplayMap();
    GraalDisplayFigure( 0, 0, GraalGraphicDx, GraalGraphicDy );
    GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy );

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
  }

/*------------------------------------------------------------\
|                                                             |
|                         GraalZoomIn                         |
|                                                             |
\------------------------------------------------------------*/
 
  void GraalZoomIn( LambdaX1, LambdaY1, LambdaX2, LambdaY2 )
 
     long LambdaX1;
     long LambdaY1;
     long LambdaX2;
     long LambdaY2;
  {
    long Swap;

    if ( ( LambdaX1 != LambdaX2 ) && 
         ( LambdaY1 != LambdaY2 ) )
    {
      if ( LambdaX1 > LambdaX2 ) 
      {
        Swap = LambdaX1; LambdaX1 = LambdaX2; LambdaX2 = Swap;
      }

      if ( LambdaY1 > LambdaY2 ) 
      {
        Swap = LambdaY1; LambdaY1 = LambdaY2; LambdaY2 = Swap;
      }

      GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

      GraalAddZoom();

      GraalLambdaGridX  = LambdaX1;
      GraalLambdaGridY  = LambdaY1;
      GraalLambdaGridDx = LambdaX2 - LambdaX1;
      GraalLambdaGridDy = LambdaY2 - LambdaY1;

      GraalComputeLambdaGrid();
      GraalComputeAndDisplayMap();
      GraalDisplayFigure( 0, 0, GraalGraphicDx, GraalGraphicDy );
      GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy );

      GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                         GraalZoomPan                        |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomPan( LambdaX1, LambdaY1, LambdaX2, LambdaY2 )

     long LambdaX1;
     long LambdaY1;
     long LambdaX2;
     long LambdaY2;
  {
    if ( ( LambdaX1 != LambdaX2 ) ||
         ( LambdaY1 != LambdaY2 ) )
    {
      GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );
 
      GraalLambdaGridX  = GraalLambdaGridX + ( LambdaX1 - LambdaX2 );
      GraalLambdaGridY  = GraalLambdaGridY + ( LambdaY1 - LambdaY2 );

      GraalComputeLambdaGrid();
      GraalComputeAndDisplayMap();
      GraalDisplayFigure( 0, 0, GraalGraphicDx, GraalGraphicDy );
      GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy );

      GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                         GraalZoomRefresh                    |
|                                                             |
\------------------------------------------------------------*/

  void GraalZoomRefresh()

  {
    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_WATCH_CURSOR );

    GraalDisplayFigure( 0, 0, GraalGraphicDx, GraalGraphicDy );
    GraalRefreshGraphicWindow( 0, 0, GraalGraphicDx, GraalGraphicDy );

    GraalSetMouseCursor( GraalGraphicWindow, GRAAL_NORMAL_CURSOR );
  }
