/*------------------------------------------------------------\
|                                                             |
| Tool    :                   GRAAL                           |
|                                                             |
| File    :                   View.c                          |
|                                                             |
| Authors :      Venot Frederic and Jacomme Ludovic           |
|                                                             |
| Date    :                  01.08.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 GSB_H
# include GRM_H
# include GMX_H

# include "GMX_view.h" 

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

    static long         GraalGraphicX1;
    static long         GraalGraphicX2;
    static long         GraalGraphicY1;
    static long         GraalGraphicY2;
    static XFontStruct *GraalTextFont;
    static GC           GraalTextGC;
    static GC           GraalDrawGC;
    static GC           GraalFillGC;
    static graalview   *GraalHeadView = (graalview *)NULL;

/*------------------------------------------------------------\
|                                                             |
|                          Functions                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                       Alloc Functions                       |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                        GraalAllocView                       |
|                                                             |
\------------------------------------------------------------*/

   graalview *GraalAllocView()
   {
     return((graalview *)rdsalloc(sizeof(graalview), 1));
   }

/*------------------------------------------------------------\
|                                                             |
|                        Free Functions                       |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                         GraalFreeView                       |
|                                                             |
\------------------------------------------------------------*/

  void GraalFreeView( FreeView )

     graalview *FreeView;
  {
    rdsfree((char *)FreeView, sizeof(graalview));
  }

/*------------------------------------------------------------\
|                                                             |
|                       GraalAddViewLater                     |
|                                                             |
\------------------------------------------------------------*/

   void GraalAddViewLater( Rectangle )

      rdsrec_list *Rectangle;
   {
     graalview *View;

     View = GraalAllocView();

     View->RECTANGLE = Rectangle;
     View->NEXT      = GraalHeadView;
     GraalHeadView   = View;
   }

/*------------------------------------------------------------\
|                                                             |
|                       GraalDelView                          |
|                                                             |
\------------------------------------------------------------*/

  void GraalDelView()
  {
    graalview    *DelView;
    graalview    *View;

    View          = GraalHeadView;
    GraalHeadView = (graalview *)NULL;

    while( View != (graalview *)NULL )
    {
      DelView  = View;
      View     = View->NEXT;

      GraalFreeView( DelView );
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                 GraalDisplayOneRectangle                    |
|                                                             |
\------------------------------------------------------------*/

  void GraalDisplayOneRectangle( Rec )

    rdsrec_list *Rec;
  {
    long X1r;
    long X2r;
    long Y1r;
    long Y2r;
    long WidthText;
    long HeightText;
    char DrawLine;

    HeightText = GraalTextFont->ascent;

    X1r  = (float)( Rec->X ) * GraalLambdaGridStep;
    Y1r  = (float)( Rec->Y ) * GraalLambdaGridStep;
    X2r  = (float)( Rec->X + Rec->DX ) * GraalLambdaGridStep;
    Y2r  = (float)( Rec->Y + Rec->DY ) * GraalLambdaGridStep;

    X1r  = ( X1r / RDS_LAMBDA ) - GraalPixelGridX;
    X2r  = ( X2r / RDS_LAMBDA ) - GraalPixelGridX;
    Y1r  = ( Y1r / RDS_LAMBDA ) - GraalPixelGridY;
    Y2r  = ( Y2r / RDS_LAMBDA ) - GraalPixelGridY;

    DrawLine = 0;

    if ( X1r < GraalGraphicX1 ) 
    { 
      X1r = GraalGraphicX1; DrawLine |= GRAAL_WEST_MASK;  
    }

    if ( X2r > GraalGraphicX2 ) 
    { 
      X2r = GraalGraphicX2; DrawLine |= GRAAL_EAST_MASK;  
    }

    if ( Y1r < GraalGraphicY1 ) 
    {
      Y1r = GraalGraphicY1; DrawLine |= GRAAL_SOUTH_MASK; 
    }

    if ( Y2r > GraalGraphicY2 ) 
    {
      Y2r = GraalGraphicY2; DrawLine |= GRAAL_NORTH_MASK; 
    }

    if ( ( X1r <= X2r ) &&
         ( Y1r <= Y2r ) )
    {
      if ( DrawLine == 0 )
      {
        XDrawRectangle( XtDisplay( GraalGraphicWindow ),
                        GraalGraphicPixmap,
                        GraalDrawGC,
                        X1r, GraalGraphicDy - Y2r,
                        X2r - X1r,
                        Y2r - Y1r );
      }
      else
      {
        if ( ( DrawLine & GRAAL_WEST_MASK ) == 0 )
        {
          XDrawLine( XtDisplay( GraalGraphicWindow ),
                     GraalGraphicPixmap,
                     GraalDrawGC,
                     X1r, GraalGraphicDy - Y2r,
                     X1r, GraalGraphicDy - Y1r );
        }

        if ( ( DrawLine & GRAAL_EAST_MASK ) == 0 )
        {
          XDrawLine( XtDisplay( GraalGraphicWindow ),
                     GraalGraphicPixmap,
                     GraalDrawGC,
                     X2r, GraalGraphicDy - Y2r,
                     X2r, GraalGraphicDy - Y1r );
        }

        if ( ( DrawLine & GRAAL_SOUTH_MASK ) == 0 )
        {
          XDrawLine( XtDisplay( GraalGraphicWindow ),
                     GraalGraphicPixmap,
                     GraalDrawGC,
                     X1r, GraalGraphicDy - Y1r,
                     X2r, GraalGraphicDy - Y1r );
        }

        if ( ( DrawLine & GRAAL_NORTH_MASK ) == 0 )
        {
          XDrawLine( XtDisplay( GraalGraphicWindow ),
                     GraalGraphicPixmap,
                     GraalDrawGC,
                     X1r, GraalGraphicDy - Y2r,
                     X2r, GraalGraphicDy - Y2r );
        }
      }
 
      if ( GetRdsLayer( Rec ) != RDS_ABOX )
      {
        XFillRectangle( XtDisplay( GraalGraphicWindow ),
                        GraalGraphicPixmap,
                        GraalFillGC,
                        X1r, GraalGraphicDy - Y2r,
                        X2r - X1r,
                        Y2r - Y1r );
      }

      if ( ( DrawLine == 0          ) &&
           ( Rec->NAME != NULL      ) &&
           ( IsGraalDrawText( Rec ) ) )
      {
        WidthText = XTextWidth( GraalTextFont,
                                Rec->NAME, strlen( Rec->NAME ) );

        XDrawString( XtDisplay( GraalGraphicWindow ),
                     GraalGraphicPixmap,
                     GraalTextGC,
                     (( X1r + X2r - WidthText ) >> 1),
                     GraalGraphicDy - (( Y1r + Y2r - HeightText ) >> 1),
                     Rec->NAME, strlen( Rec->NAME ) );
      }
    }

    ClearGraalDrawText( Rec );
  }

/*------------------------------------------------------------\
|                                                             |
|                    GraalDisplayFigure                       |
|                                                             |
\------------------------------------------------------------*/

  void GraalDisplayFigure( GraphicX1, GraphicY1, GraphicX2, GraphicY2 )

     long GraphicX1;
     long GraphicY1;
     long GraphicX2;
     long GraphicY2;
  {
    long         Offset;
    graalwin    *ScanWin;
    graalwinrec *ScanWinRec;
    rdsrec_list *Rec;
    rdsins_list *Instance;
    char         ScanRec;
    char         Layer;
    long         X1;
    long         Y1;
    long         X2;
    long         Y2;
    long         X1r;
    long         Y1r;
    long         X;
    long         Y;
    long         Xmin;
    long         Xmax;
    long         Ymin;
    long         Ymax;
    long         LambdaMin;
    char         DrawText;
    char         DrawTextFig;
    char         DrawTextFigCon;
    char         DrawTextFigSeg;
    char         DrawTextFigRef;
    char         DrawTextIns;
    char         DrawTextInsCon;
    char         DrawTextInsSeg;
    char         DrawTextInsRef;
    graalview   *View;

    GraalTextGC    = GraalSmallTextGC;
    GraalTextFont  = GraalSmallTextFont;
    DrawTextFig    = 0;
    DrawTextFigCon = 0;
    DrawTextFigSeg = 0;
    DrawTextFigRef = 0;
    DrawTextIns    = 0;
    DrawTextInsCon = 0;
    DrawTextInsSeg = 0;
    DrawTextInsRef = 0;
    GraalGraphicX1 = GraphicX1;
    GraalGraphicX2 = GraphicX2;
    GraalGraphicY1 = GraphicY1;
    GraalGraphicY2 = GraphicY2;

    if ( GraalLambdaGridStep > GRAAL_LOWER_FIGURE_STEP )
    {
      DrawTextFig = GRAAL_RDS_ACTIVE_NAME_TABLE[ GRAAL_FIGURE_NAME ];
    }

    if ( GraalLambdaGridStep > GRAAL_LOWER_INSTANCE_STEP )
    {
      DrawTextIns = GRAAL_RDS_ACTIVE_NAME_TABLE[ GRAAL_INSTANCE_NAME ];
    }
   
    if ( GraalLambdaGridStep > GRAAL_LOWER_CONNECTOR_STEP )
    {
      DrawTextInsCon = GRAAL_RDS_ACTIVE_NAME_TABLE[ GRAAL_INSTANCE_CONNECTOR_NAME ];
      DrawTextFigCon = GRAAL_RDS_ACTIVE_NAME_TABLE[ GRAAL_FIGURE_CONNECTOR_NAME ];
      GraalTextGC    = GraalMediumTextGC;
      GraalTextFont  = GraalMediumTextFont;
    }

    if ( GraalLambdaGridStep > GRAAL_LOWER_SEGMENT_STEP )
    {
      DrawTextFigSeg = GRAAL_RDS_ACTIVE_NAME_TABLE[ GRAAL_FIGURE_SEGMENT_NAME ];
      DrawTextInsSeg = GRAAL_RDS_ACTIVE_NAME_TABLE[ GRAAL_INSTANCE_SEGMENT_NAME ];
    }

    if ( GraalLambdaGridStep > GRAAL_LOWER_REFERENCE_STEP )
    {
      DrawTextFigRef = GRAAL_RDS_ACTIVE_NAME_TABLE[ GRAAL_FIGURE_REFERENCE_NAME ];
      DrawTextInsRef = GRAAL_RDS_ACTIVE_NAME_TABLE[ GRAAL_INSTANCE_REFERENCE_NAME ];
      GraalTextGC    = GraalLargeTextGC;
      GraalTextFont  = GraalLargeTextFont;
    }

    GraalClearGraphicWindow( GraphicX1, 
                             GraalGraphicDy - GraphicY2,
                             GraphicX2 - GraphicX1,
                             GraphicY2 - GraphicY1 );

    if ( GraalFigureMbk == (phfig_list *)NULL ) return;

    LambdaMin = (float)(4.0 / ( GraalLambdaGridStep ));

    X1 = GraphicX1 + GraalPixelGridX;
    X2 = GraphicX2 + GraalPixelGridX;
    Y1 = GraphicY1 + GraalPixelGridY;
    Y2 = GraphicY2 + GraalPixelGridY;

    X1 = ( X1 / GraalLambdaGridStep );
    Y1 = ( Y1 / GraalLambdaGridStep );
    X2 = ( X2 / GraalLambdaGridStep );
    Y2 = ( Y2 / GraalLambdaGridStep );

    if ( X2 >= 0 ) { X2 = X2 + 1; }
    if ( Y2 >= 0 ) { Y2 = Y2 + 1; }
    if ( X1 <= 0 ) { X1 = X1 - 1; }
    if ( Y1 <= 0 ) { Y1 = Y1 - 1; }

    X1 = X1 * RDS_LAMBDA; 
    X2 = X2 * RDS_LAMBDA; 
    Y1 = Y1 * RDS_LAMBDA; 
    Y2 = Y2 * RDS_LAMBDA; 

    Xmin = ( X1 - GraalWindowXmin ) / GraalWindowSide;
    Xmax = ( X2 - GraalWindowXmin ) / GraalWindowSide;
    Ymin = ( Y1 - GraalWindowYmin ) / GraalWindowSide;
    Ymax = ( Y2 - GraalWindowYmin ) / GraalWindowSide;

    for ( Layer = 0; Layer < RDS_MAX_LAYER; Layer++ ) 
    {
      if ( GRAAL_RDS_ACTIVE_LAYER_TABLE[ Layer ] == 0 ) continue; 

      Y = Ymin;

      while ( Y <= Ymax )
      {
        X = Xmin;

        while ( X <= Xmax )
        {
          Offset = Y * GraalWindowDx + X;

          if ( ( ScanWin = GraalWindowTable[ Offset ] ) != (graalwin *)NULL )
          {
            for ( ScanWinRec  = ScanWin->LAYERTAB[ Layer ];
                  ScanWinRec != (graalwinrec *)NULL;
                  ScanWinRec  = ScanWinRec->NEXT )
            {
              for ( ScanRec = 0; ScanRec < GRAAL_MAX_REC ; ScanRec++ )
              {
                Rec = ScanWinRec->RECTAB[ ScanRec ];

                if ( ( Rec != (rdsrec_list *)NULL  ) &&
                     ( ! IsGraalDeleted( Rec )     ) &&
                     ( ! IsGraalInvisible( Rec )   ) &&
                     ( Rec->X               <=  X2 ) &&
                     ( Rec->Y               <=  Y2 ) &&
                     ( ( Rec->X + Rec->DX ) >=  X1 ) &&
                     ( ( Rec->Y + Rec->DY ) >=  Y1 ) )
                {
                  if ( ( Rec->DX < LambdaMin ) &&
                       ( Rec->DY < LambdaMin ) )  continue;

                  if ( ! IsGraalOneWindow( Rec ) )
                  {
                    X1r = ( Rec->X - GraalWindowXmin ) / GraalWindowSide;
                    Y1r = ( Rec->Y - GraalWindowYmin ) / GraalWindowSide;

                    if ( X1r < Xmin ) X1r = Xmin;
                    if ( Y1r < Ymin ) Y1r = Ymin;

                    if ( ( X1r != X ) || ( Y1r != Y ) ) continue;
                  }

                  if ( ! IsRdsFigRec( Rec ) )
                  {
                    Instance = (rdsins_list *)GRAAL_PREVIOUS( Rec );

                    if ( IsGraalDeleted( Instance->LAYERTAB[ RDS_ABOX ] ) ) continue;

                    if ( IsRdsConnector( Rec ) )
                    {
                      DrawText = DrawTextInsCon;
                    }
                    else
                    if ( IsRdsReference( Rec ) )
                    {
                      DrawText = DrawTextInsRef;
                    }
                    else
                    if ( IsRdsSegment( Rec ) )
                    {
                      DrawText = DrawTextInsSeg;
                    }
                    else
                    {
                      DrawText = DrawTextIns;
                    }
                  }
                  else
                  {
                    if ( IsRdsConnector( Rec ) )
                    {
                      DrawText = DrawTextFigCon;
                    }
                    else
                    if ( IsRdsReference( Rec ) )
                    {
                      DrawText = DrawTextFigRef;
                    }
                    else
                    if ( IsRdsSegment( Rec ) )
                    {
                      DrawText = DrawTextFigSeg;
                    }
                    else
                    {
                      DrawText = DrawTextFig;
                    }
                  } 

                  if ( DrawText ) SetGraalDrawText( Rec );

                  if ( ( IsGraalAccepted( Rec ) != 0 ) || 
                       ( IsGraalTreated( Rec )  != 0 ) ||
                       ( IsGraalDruc( Rec )     != 0 ) )
                  {
                    GraalAddViewLater( Rec );
                  }
                  else
                  {
                    GraalDrawGC = GraalLayerDrawGC[ Layer ];
                    GraalFillGC = GraalLayerFillGC[ Layer ];

                    GraalDisplayOneRectangle( Rec );
                  }
                }
              }
            }
          }

          X = X + 1;
        }

        Y = Y + 1;
      }

      for ( View  = GraalHeadView;
            View != (graalview *)NULL;
            View  = View->NEXT )
      {
        Rec = View->RECTANGLE;

        if ( IsGraalAccepted( Rec ) != 0 )
        {
          GraalDrawGC = GraalAcceptDrawGC;
          GraalFillGC = GraalLayerAcceptGC[ Layer ];
        }
        else
        if ( IsGraalTreated( Rec ) != 0 )
        {
          GraalDrawGC = GraalEquiDrawGC;
          GraalFillGC = GraalLayerEquiGC[ Layer ];
        }
        else
        {
          GraalDrawGC = GraalDrucDrawGC;
          GraalFillGC = GraalLayerDrucGC[ Layer ];
        }

        GraalDisplayOneRectangle( Rec );
      }

      GraalDelView();
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                    GraalDisplayRectangle                    |
|                                                             |
\------------------------------------------------------------*/

  void GraalDisplayRectangle( Rectangle )

     rdsrec_list *Rectangle;
  {
    rdsins_list *Instance;
    rdsrec_list *ScanRec;
    long         Xmin;
    long         Ymin;
    long         Xmax;
    long         Ymax;
    char         Layer;

    Xmin = Rectangle->X;
    Ymin = Rectangle->Y;
    Xmax = Xmin + Rectangle->DX;
    Ymax = Ymin + Rectangle->DY;

    ScanRec = (rdsrec_list *)(Rectangle->USER);

    while ( ScanRec != Rectangle )
    {
      if ( Xmin > ScanRec->X )
      {
        Xmin = ScanRec->X;
      }

      if ( Xmax < ( ScanRec->X + ScanRec->DX ) )
      {
        Xmax = ScanRec->X + ScanRec->DX;
      }

      if ( Ymin > ScanRec->Y )
      { 
        Ymin = ScanRec->Y;
      }

      if ( Ymax < ( ScanRec->Y + ScanRec->DY ) )
      { 
        Ymax = ScanRec->Y + ScanRec->DY;
      }

      ScanRec = (rdsrec_list *)(ScanRec->USER);
    }

    Xmin = (float)( Xmin ) * GraalLambdaGridStep;
    Ymin = (float)( Ymin ) * GraalLambdaGridStep;
    Xmax = (float)( Xmax ) * GraalLambdaGridStep;
    Ymax = (float)( Ymax ) * GraalLambdaGridStep;

    Xmin = ( Xmin / RDS_LAMBDA ) - GraalPixelGridX - 1;
    Xmax = ( Xmax / RDS_LAMBDA ) - GraalPixelGridX + 1;
    Ymin = ( Ymin / RDS_LAMBDA ) - GraalPixelGridY - 1;
    Ymax = ( Ymax / RDS_LAMBDA ) - GraalPixelGridY + 1;

    if ( Xmin < 0 ) Xmin = 0;
    if ( Ymin < 0 ) Ymin = 0;

    if ( Xmax > GraalGraphicDx ) Xmax = GraalGraphicDx;
    if ( Ymax > GraalGraphicDy ) Ymax = GraalGraphicDy;

    if ( ( Xmax > 0              ) &&
         ( Ymax > 0              ) &&
         ( Xmin < GraalGraphicDx ) &&
         ( Ymin < GraalGraphicDy ) )
    {
      GraalDisplayFigure( Xmin, Ymin , Xmax, Ymax );

      GraalRefreshGraphicWindow( Xmin, GraalGraphicDy - Ymax, 
                                 Xmax - Xmin, Ymax - Ymin );
    }
  }
