/*------------------------------------------------------------\
|                                                             |
| Tool    :                   GRAAL                           |
|                                                             |
| File    :                   Equi.c                          |
|                                                             |
| Authors :      Venot Frederic and Jacomme Ludovic           |
|                                                             |
| Date    :                  01.08.93                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                         Include Files                       |
|                                                             |
\------------------------------------------------------------*/

# include <stdio.h>
# include <string.h>
# include MUT_H
# include MPH_H
# include RDS_H
# include RPR_H
# include RFM_H
# include GRM_H
# include GSB_H
# include "GRM_equi.h"

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

  rdsrec_list *GraalHeadEqui = (rdsrec_list *)NULL;

  static char GraalReferenceBuffer[ GRAAL_REFERENCE_BUFFER_SIZE ];

/*------------------------------------------------------------\
|                                                             |
|                          Functions                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                         GraalCutCxN                         |
|                                                             |
\------------------------------------------------------------*/

  rdsrec_list *GraalCutCxN( Rec, X1, Y1, X2, Y2  )

    rdsrec_list *Rec;
    long         X1;
    long         Y1;
    long         X2;
    long         Y2;
  {
    void        *Pointer;
    phseg_list  *Segment;
    rdsrec_list *Diff;
    rdsrec_list *Save;
    rdsrec_list *ScanRec;
    graalrecwin *RecWin;
    graalrecwin *ScanRecWin;
    graalrecwin  StaticRecWin;
    graalwin    *ScanWin;
    graalwinrec *ScanWinRec;
    long         Xvia;
    long         Yvia;
    char         Index;
    char         Mask;

    Pointer = GRAAL_MBK( Rec );
    Mask    = 0;
    Save    = Rec;

    Xvia = ((phvia_list *)Pointer)->XVIA;
    Yvia = ((phvia_list *)Pointer)->YVIA;

    if ( IsGraalOneWindow ( Rec ) )
    {
      StaticRecWin.NEXT   = (graalrecwin *)NULL;
      StaticRecWin.WINDOW = (graalwin *)GRAAL_WINDOW( Rec );
      RecWin              = &StaticRecWin;
    }
    else
    {
      RecWin = GRAAL_WINDOW( Rec );
    }

    for ( ScanRecWin  = RecWin ;
          ScanRecWin != (graalrecwin *) NULL ;
          ScanRecWin  = ScanRecWin->NEXT )
    {
      ScanWin = ScanRecWin->WINDOW;

      for ( ScanWinRec  = ScanWin->LAYERTAB[ RDS_GATE ];
            ScanWinRec != (graalwinrec *)NULL;
            ScanWinRec  = ScanWinRec->NEXT )
      {
        for ( Index = 0; Index < GRAAL_MAX_REC; Index++ )
        {
          ScanRec = ScanWinRec->RECTAB[ Index ];

          if ( ( ScanRec != (rdsrec_list *)NULL    ) &&
               ( ! IsGraalDeleted( ScanRec )       ) &&
               (   IsRdsFigRec( ScanRec )          ) &&
               (   IsRdsSegment( ScanRec )         ) )
          {
            Segment = (phseg_list *)GRAAL_MBK( ScanRec );

            if ( Segment->LAYER == NTRANS )
            {
              if ( ( Segment->TYPE == UP   ) ||
                   ( Segment->TYPE == DOWN ) )
              {
                if ( Segment->X1 == Xvia )
                {
                  if ( Segment->Y1 == Yvia ) Mask |= GRAAL_NORTH_MASK;
                  else
                  if ( Segment->Y2 == Yvia ) Mask |= GRAAL_SOUTH_MASK;
                }
              }
              else
              {
                if ( Segment->Y1 == Yvia )
                {
                  if ( Segment->X1 == Xvia ) Mask |= GRAAL_EAST_MASK;
                  else
                  if ( Segment->X2 == Xvia ) Mask |= GRAAL_WEST_MASK;
                }
              }
            }
          }
        }
      }
    }

    if ( Mask != 0 )
    {
      Diff = (rdsrec_list *)NULL;

      for ( Index = 0; Index < 4; Index++ )
      {
        if ( GRAAL_CUT_C_X_N_TABLE[ Mask ][ Index ][0]  == -1 ) break;

        Diff = addrdsfigrec( GraalFigureRds,
                             NULL, RDS_NDIF,  
                             Rec->X + GRAAL_CUT_C_X_N_TABLE[ Mask ][ Index ][ 0 ],
                             Rec->Y + GRAAL_CUT_C_X_N_TABLE[ Mask ][ Index ][ 1 ],
                             GRAAL_CUT_C_X_N_TABLE[ Mask ][ Index ][ 2 ],
                             GRAAL_CUT_C_X_N_TABLE[ Mask ][ Index ][ 3 ] );

        GRAAL_PREVIOUS( Diff ) =

          &(GraalFigureRds->LAYERTAB[ RDS_NDIF ]);

        if ( Diff->NEXT != (rdsrec_list *)NULL )
        {
          GRAAL_PREVIOUS( Diff->NEXT ) = &Diff->NEXT;
        }

        GRAAL_MBK( Diff ) = GRAAL_MBK( Rec );

        Diff->USER = Rec->USER;
        Rec->USER  = (void *)Diff;

        SetGraalCut( Diff );
        GraalInsertRectangle( Diff );

        if ( ( ( Diff->X            ) <= X2 ) &&
             ( ( Diff->Y            ) <= Y2 ) &&
             ( ( Diff->X + Diff->DX ) >= X1 ) &&
             ( ( Diff->Y + Diff->DY ) >= Y1 ) )

        {
          Save = Diff;
        }
      }

      if ( Save != Rec ) SetGraalInvisible( Rec );
    }

    return( Save );
  }

/*------------------------------------------------------------\
|                                                             |
|                         GraalCutCxP                         |
|                                                             |
\------------------------------------------------------------*/

  rdsrec_list *GraalCutCxP( Rec, X1, Y1, X2, Y2  )

    rdsrec_list *Rec;
    long         X1;
    long         Y1;
    long         X2;
    long         Y2;
  {
    void        *Pointer;
    phseg_list  *Segment;
    rdsrec_list *Diff;
    rdsrec_list *Save;
    rdsrec_list *ScanRec;
    graalrecwin *RecWin;
    graalrecwin *ScanRecWin;
    graalrecwin  StaticRecWin;
    graalwin    *ScanWin;
    graalwinrec *ScanWinRec;
    long         Xvia;
    long         Yvia;
    char         Index;
    char         Mask;

    Pointer = GRAAL_MBK( Rec );
    Mask    = 0;
    Save    = Rec;

    Xvia = ((phvia_list *)Pointer)->XVIA;
    Yvia = ((phvia_list *)Pointer)->YVIA;

    if ( IsGraalOneWindow ( Rec ) )
    {
      StaticRecWin.NEXT   = (graalrecwin *)NULL;
      StaticRecWin.WINDOW = (graalwin *)GRAAL_WINDOW( Rec );
      RecWin              = &StaticRecWin;
    }
    else
    {
      RecWin = GRAAL_WINDOW( Rec );
    }

    for ( ScanRecWin  = RecWin ;
          ScanRecWin != (graalrecwin *) NULL ;
          ScanRecWin  = ScanRecWin->NEXT )
    {
      ScanWin = ScanRecWin->WINDOW;

      for ( ScanWinRec  = ScanWin->LAYERTAB[ RDS_GATE ];
            ScanWinRec != (graalwinrec *)NULL;
            ScanWinRec  = ScanWinRec->NEXT )
      {
        for ( Index = 0; Index < GRAAL_MAX_REC; Index++ )
        {
          ScanRec = ScanWinRec->RECTAB[ Index ];

          if ( ( ScanRec != (rdsrec_list *)NULL    ) &&
               ( ! IsGraalDeleted( ScanRec )       ) &&
               (   IsRdsFigRec( ScanRec )          ) &&
               (   IsRdsSegment( ScanRec )         ) )
          {
            Segment = (phseg_list *)GRAAL_MBK( ScanRec );

            if ( Segment->LAYER == PTRANS )
            {
              if ( ( Segment->TYPE == UP   ) ||
                   ( Segment->TYPE == DOWN ) )
              {
                if ( Segment->X1 == Xvia )
                {
                  if ( Segment->Y1 == Yvia ) Mask |= GRAAL_NORTH_MASK;
                  else
                  if ( Segment->Y2 == Yvia ) Mask |= GRAAL_SOUTH_MASK;
                }
              }
              else
              {
                if ( Segment->Y1 == Yvia )
                {
                  if ( Segment->X1 == Xvia ) Mask |= GRAAL_EAST_MASK;
                  else
                  if ( Segment->X2 == Xvia ) Mask |= GRAAL_WEST_MASK;
                }
              }
            }
          }
        }
      }
    }

    if ( Mask != 0 )
    {
      Diff = (rdsrec_list *)NULL;

      for ( Index = 0; Index < 4; Index++ )
      {
        if ( GRAAL_CUT_C_X_P_TABLE[ Mask ][ Index ][0]  == -1 ) break;

        Diff = addrdsfigrec( GraalFigureRds,
                             NULL, RDS_PDIF,  
                             Rec->X + GRAAL_CUT_C_X_P_TABLE[ Mask ][ Index ][ 0 ],
                             Rec->Y + GRAAL_CUT_C_X_P_TABLE[ Mask ][ Index ][ 1 ],
                             GRAAL_CUT_C_X_P_TABLE[ Mask ][ Index ][ 2 ],
                             GRAAL_CUT_C_X_P_TABLE[ Mask ][ Index ][ 3 ] );

        GRAAL_PREVIOUS( Diff ) =

          &(GraalFigureRds->LAYERTAB[ RDS_PDIF ]);

        if ( Diff->NEXT != (rdsrec_list *)NULL )
        {
          GRAAL_PREVIOUS( Diff->NEXT ) = &Diff->NEXT;
        }

        GRAAL_MBK( Diff ) = GRAAL_MBK( Rec );

        Diff->USER = Rec->USER;
        Rec->USER  = (void *)Diff;

        SetGraalCut( Diff );
        SetRdsVia( Diff );
        GraalInsertRectangle( Diff );

        if ( ( ( Diff->X            ) <= X2 ) &&
             ( ( Diff->Y            ) <= Y2 ) &&
             ( ( Diff->X + Diff->DX ) >= X1 ) &&
             ( ( Diff->Y + Diff->DY ) >= Y1 ) )

        {
          Save = Diff;
        }
      }

      if ( Save != Rec ) SetGraalInvisible( Rec );
    }

    return( Save );
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalExtractEqui                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalExtractEqui( Rec ) 

    rdsrec_list *Rec;
  {
    rdsrec_list *LastRec;
    rdsrec_list *ScanRec;
    rdsrec_list *ScanInsRec;
    rdsins_list *ScanIns;
    graalrecwin *RecWin;
    graalrecwin *ScanRecWin;
    graalrecwin  StaticRecWin;
    graalwin    *ScanWin;
    graalwinrec *ScanWinRec;
    char        *RefName;
    char        *ScanRecName;
    char        *ScanInsRecName;
    void        *Pointer;
    char         Index;
    char         LayerIns;
    char         LayerRec;
    char         Layer;
    char         Counter;
    long         X1;
    long         X2;
    long         Y1;
    long         Y2;

    if ( GraalHeadEqui != (rdsrec_list *)NULL )
    {
      GraalDelEqui();
    }

    GraalHeadEqui     = Rec;
    LastRec           = Rec;
    StaticRecWin.NEXT = (graalrecwin *)NULL;

    SetGraalTreated( Rec );

    do
    {
      X1 = Rec->X;
      Y1 = Rec->Y;
      X2 = Rec->DX + X1;
      Y2 = Rec->DY + Y1;

      if ( IsGraalOneWindow ( Rec ) )
      {
        StaticRecWin.WINDOW = (graalwin *)GRAAL_WINDOW( Rec );
        RecWin               = &StaticRecWin;
      }
      else
      {  
        RecWin = GRAAL_WINDOW( Rec );
      }
 
      LayerRec = GetRdsLayer ( Rec );
 
      for ( ScanRecWin  = RecWin ;
            ScanRecWin != (graalrecwin *) NULL ;
            ScanRecWin  = ScanRecWin->NEXT )
      {
        ScanWin = ScanRecWin->WINDOW;

        Index = 0;

        while ( ( Layer = GET_LYNX_GRAPH_LAYER ( LayerRec, Index ) ) != RDS_LYNX_GRAPH_EMPTY )
        {
          for ( ScanWinRec  = ScanWin->LAYERTAB[ Layer ];
                ScanWinRec != (graalwinrec *)NULL;
                ScanWinRec  = ScanWinRec->NEXT )
          {
            for ( Counter = 0; Counter < GRAAL_MAX_REC; Counter++ )
            {
              ScanRec = ScanWinRec->RECTAB[ Counter ];
 
              if ( ( ScanRec != (rdsrec_list *)NULL     ) && 
                   ( ! IsGraalDeleted( ScanRec )        ) &&
                   ( ! IsGraalTreated( ScanRec )        ) &&
                   ( ! IsGraalInvisible( ScanRec )      ) &&
                   ( ( ScanRec->X               ) <= X2 ) &&
                   ( ( ScanRec->Y               ) <= Y2 ) &&
                   ( ( ScanRec->X + ScanRec->DX ) >= X1 ) &&
                   ( ( ScanRec->Y + ScanRec->DY ) >= Y1 ) )
              {
                if ( IsRdsFigRec( ScanRec ) )
                {
                  if ( ( IsRdsVia( ScanRec           ) ) &&
                       (   IsRdsFigRec( ScanRec      ) ) &&
                       ( ! IsGraalInvisible( ScanRec ) ) &&
                       ( ! IsGraalCut( ScanRec       ) ) )
                  {
                    Pointer = GRAAL_MBK( ScanRec );

                    if ( (  Layer                        == RDS_NDIF ) &&
                         ( ((phvia_list *)Pointer)->TYPE == C_X_N    ) )
                    {
                      ScanRec = GraalCutCxN( ScanRec, X1, Y1, X2, Y2 );
                    }
                    else
                    if ( (  Layer                        == RDS_PDIF ) &&
                         ( ((phvia_list *)Pointer)->TYPE == C_X_P    ) )
                    {
                      ScanRec = GraalCutCxP( ScanRec, X1, Y1, X2, Y2 );
                    }
                  }

                  SetGraalTreated( ScanRec );

                  GRAAL_EQUI( LastRec ) = ScanRec;
                  LastRec               = ScanRec;
                }
                else
                if ( ( IsRdsConInter( ScanRec ) ) ||
                     ( IsRdsRefCon( ScanRec   ) ) )
                {
                  SetGraalTreated( ScanRec );

                  if ( ( IsRdsRefCon( ScanRec )        ) &&
                       ( ScanRec->NAME != (char *)NULL ) )
                  {
                    strcpy( GraalReferenceBuffer, ScanRec->NAME );

                    RefName = strrchr( GraalReferenceBuffer, '_' );

                    if ( RefName != (char *)NULL )
                    {
                      *RefName = '\0';
                    }

                    ScanRecName = namealloc( GraalReferenceBuffer );
                  }
                  else
                  {
                    ScanRecName = ScanRec->NAME;
                  }

                  GRAAL_EQUI( LastRec ) = ScanRec;
                  LastRec               = ScanRec;

                  ScanIns = (rdsins_list *)GRAAL_PREVIOUS( ScanRec );
 
                  if ( ! IsGraalDeleted( ScanIns->LAYERTAB[ RDS_ABOX ] ) )
                  {
                    for ( LayerIns = 0 ; LayerIns < RDS_MAX_LAYER ; LayerIns ++ )
                    {
                      for ( ScanInsRec  = ScanIns->LAYERTAB[ LayerIns ];
                            ScanInsRec != (rdsrec_list *)NULL;
                            ScanInsRec  = ScanInsRec->NEXT )
                      {
                        if ( ! IsGraalTreated( ScanInsRec ) )
                        {
                          if ( ( IsRdsRefCon( ScanInsRec )        ) &&
                               ( ScanInsRec->NAME != (char *)NULL ) )
                          {
                            strcpy( GraalReferenceBuffer, ScanInsRec->NAME );

                            RefName = strrchr( GraalReferenceBuffer, '_' );

                            if ( RefName != (char *)NULL )
                            {
                              *RefName = '\0';
                            }

                            ScanInsRecName = namealloc( GraalReferenceBuffer );
                          }
                          else
                          {
                            ScanInsRecName = ScanInsRec->NAME;
                          }

                          if ( ( ( IsRdsConInter( ScanInsRec ) ) ||
                                 ( IsRdsRefCon( ScanInsRec )   ) ) && 
                               ( ScanRecName == ScanInsRecName   ) )
                          {
                            SetGraalTreated( ScanInsRec );

                            GRAAL_EQUI( LastRec ) = ScanInsRec;
                            LastRec               = ScanInsRec;
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
 
          Index = Index + 1;
        }
      }

      Rec = GRAAL_EQUI( Rec );
    }
    while ( Rec != (rdsrec_list *)NULL );
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalDelEqui                         |
|                                                             |
\------------------------------------------------------------*/

  void GraalDelEqui() 

  {
    rdsrec_list  *Rec;
    rdsrec_list  *ScanRec;
    rdsrec_list  *DelEqui;
    rdsrec_list  *DelRec;
    rdsrec_list  *FirstRec;
    void        **Previous;

    Rec = GraalHeadEqui;

    while ( Rec != (rdsrec_list *)NULL )
    {
      ClearGraalTreated( Rec );

      DelEqui = Rec;
      Rec     = GRAAL_EQUI( Rec );

      GRAAL_EQUI( DelEqui ) = (rdsrec_list *)NULL;

      if ( IsGraalCut( DelEqui  ) )
      {
        ScanRec  = DelEqui;
        Previous = &ScanRec->USER;
        FirstRec = ScanRec;
        ScanRec  = (rdsrec_list *)(ScanRec->USER);

        do
        {
          if ( ( IsGraalCut( ScanRec )                        ) &&
               ( GRAAL_EQUI( ScanRec ) == (rdsrec_list *)NULL ) )
          {
            *Previous = ScanRec->USER;
            DelRec    = ScanRec;
            ScanRec   = (rdsrec_list *)(ScanRec->USER);
     
            *(GRAAL_PREVIOUS( DelRec )) = DelRec->NEXT;

            if ( DelRec->NEXT != (rdsrec_list *)NULL )
            {
              GRAAL_PREVIOUS( DelRec->NEXT ) = GRAAL_PREVIOUS( DelRec );
            }

            GraalEraseRectangle( DelRec );

            freerdsrec( DelRec, GRAAL_SIZE );
          }
          else
          {
            ClearGraalInvisible( ScanRec );

            Previous = &(ScanRec->USER);
            ScanRec  = (rdsrec_list *)(ScanRec->USER);
          }
        }
        while ( ScanRec != FirstRec );

        if ( ( IsGraalCut( ScanRec )                        ) &&
             ( GRAAL_EQUI( ScanRec ) == (rdsrec_list *)NULL ) )
        {
          *Previous = ScanRec->USER;
          DelRec    = ScanRec;
          ScanRec   = (rdsrec_list *)(ScanRec->USER);
    
          *(GRAAL_PREVIOUS( DelRec )) = DelRec->NEXT;

          if ( DelRec->NEXT != (rdsrec_list *)NULL )
          {
            GRAAL_PREVIOUS( DelRec->NEXT ) = GRAAL_PREVIOUS( DelRec );
          }

          GraalEraseRectangle( DelRec );

          freerdsrec( DelRec, GRAAL_SIZE );
        }
        else
        {
          ClearGraalInvisible( ScanRec );
        }
      }
    }

    GraalHeadEqui = (rdsrec_list *)NULL;
  }
