/*------------------------------------------------------------\
|                                                             |
| Tool    :                   LYNX                            |
|                                                             |
| File    :                  mbkrds.c                         |
|                                                             |
| Author  :               Jacomme Ludovic                     |
|                                                             |
| Date    :                  01.08.93                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                         Include Files                       |
|                                                             |
\------------------------------------------------------------*/

# include <stdio.h>
# include <string.h>

# include MUT_H
# include MLO_H
# include MPH_H
# include RDS_H
# include RUT_H
# include RPR_H
# include RFM_H
# include RWI_H

# include "share.h"
# include "cut.h"
# include "mbkrds.h"

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

  static LynxConnectorOrientTable[ 4 ] =

  {
    NORTH, SOUTH, EAST, WEST
  };

  static LynxSegmentOrientTable[ 4 ] =

  {
    UP, DOWN, RIGHT, LEFT
  };

  static char LynxReferenceBuffer[ 256 ];
  static char *LynxStaticRefRef = (char *)NULL;

/*------------------------------------------------------------\
|                                                             |
|                          Functions                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                        Lynxsegmbkrds                        |
|                                                             |
\------------------------------------------------------------*/

  void Lynxsegmbkrds( FigureRds, Segment )

    rdsfig_list *FigureRds;
    phseg_list  *Segment;
  {
    rdsrec_list *Rectangle;
    rdsrec_list *ScanRec;
    char         Orient;

    ScanRec = Rectangle = segmbkrds( FigureRds, Segment, 1 );

    SetLynxFirstLink( Rectangle );

    switch ( Segment->TYPE ) 
    {
      case UP    : Orient = LYNX_NORTH;
        break;
      case DOWN  : Orient = LYNX_SOUTH;
        break;
      case LEFT  : Orient = LYNX_WEST;
        break;
      case RIGHT : Orient = LYNX_EAST;
        break;
    }

    do
    {
      SetLynxAttribute( ScanRec, Segment->LAYER );
      SetLynxOrient(    ScanRec, Orient         );

      LYNX_LINK( ScanRec ) = (rdsrec_list *)ScanRec->USER;
      ScanRec              = (rdsrec_list *)ScanRec->USER;
    }
    while ( ScanRec != Rectangle );
  }

/*------------------------------------------------------------\
|                                                             |
|                        Lynxconmbkrds                        |
|                                                             |
\------------------------------------------------------------*/

  void Lynxconmbkrds( FigureRds, Connector )

    rdsfig_list *FigureRds;
    phcon_list  *Connector;
  {
    rdsrec_list *Rectangle;
    rdsrec_list *ScanRec;
    char         Orient;

    ScanRec = Rectangle = conmbkrds( FigureRds, Connector, 1 );

    SetLynxFirstLink( Rectangle );

    switch( Connector->ORIENT )
    {
      case NORTH : Orient = LYNX_NORTH;
        break;
      case SOUTH : Orient = LYNX_SOUTH;
        break;
      case EAST  : Orient = LYNX_EAST;
        break;
      case WEST  : Orient = LYNX_WEST;
        break;
    }

    do
    {
      SetLynxAttribute( ScanRec, Connector->LAYER );
      SetLynxOrient(    ScanRec, Orient           );

      LYNX_LINK( ScanRec ) = (rdsrec_list *)ScanRec->USER;
      ScanRec              = (rdsrec_list *)ScanRec->USER;
    }
    while ( ScanRec != Rectangle );
  }

/*------------------------------------------------------------\
|                                                             |
|                        Lynxrefmbkrds                        |
|                                                             |
\------------------------------------------------------------*/

  void Lynxrefmbkrds( FigureRds, Reference )

    rdsfig_list *FigureRds;
    phref_list  *Reference;
  {
    rdsrec_list *Rectangle;
    rdsrec_list *ScanRec;
    char        *ReferenceName;

    if ( LynxStaticRefRef == (char *)NULL )
    {
      LynxStaticRefRef = namealloc( "ref_ref" );
    }

    if ( Reference->FIGNAME == LynxStaticRefRef ) return;

    ScanRec = Rectangle = refmbkrds( FigureRds, Reference, 1 );

    SetLynxFirstLink( Rectangle );

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

      ReferenceName = strrchr( LynxReferenceBuffer, '_' );

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

      ReferenceName = namealloc( LynxReferenceBuffer );
    }
    else
    {
      ReferenceName = Rectangle->NAME;
    }

    do
    {
      ScanRec->NAME = ReferenceName;
 
      LYNX_LINK( ScanRec ) = (rdsrec_list *)ScanRec->USER;
      ScanRec              = (rdsrec_list *)ScanRec->USER;
    }
    while ( ScanRec != Rectangle );
  }

/*------------------------------------------------------------\
|                                                             |
|                        Lynxviambkrds                        |
|                                                             |
\------------------------------------------------------------*/

  void Lynxviambkrds( FigureRds, Via )

    rdsfig_list *FigureRds;
    phvia_list  *Via;
  {
    rdsrec_list *Rectangle;
    rdsrec_list *ScanRec;

    ScanRec = Rectangle = viambkrds( FigureRds, Via, 1 );

    SetLynxFirstLink( Rectangle );

    do
    {
      SetLynxAttribute( ScanRec, Via->TYPE );

      LYNX_LINK( ScanRec ) = (rdsrec_list *)ScanRec->USER;
      ScanRec              = (rdsrec_list *)ScanRec->USER;
    }
    while ( ScanRec != Rectangle );
  }

/*------------------------------------------------------------\
|                                                             |
|                        Lynxinsmbkrds                        |
|                                                             |
\------------------------------------------------------------*/

  void Lynxinsmbkrds( FigureRds, InstanceMbk )

     rdsfig_list *FigureRds;
     phins_list  *InstanceMbk;
  {
    rdsrec_list  *Rectangle;
    rdsrec_list  *DelRec;
    rdsrec_list **Previous;
    rdsins_list  *InstanceRds;
    char         *ReferenceName;
    char          Layer;

    InstanceRds = insmbkrds( FigureRds, InstanceMbk, 'P', 1 );

    for ( Layer = 0; Layer < RDS_MAX_LAYER; Layer++ )
    {
      Rectangle =  InstanceRds->LAYERTAB[ Layer ];
      Previous  = &InstanceRds->LAYERTAB[ Layer ];

      while ( Rectangle != (rdsrec_list *)NULL )
      {
        if ( IsRdsRefRef( Rectangle ) )
        {
          DelRec    = Rectangle;
          Rectangle = Rectangle->NEXT;
          *Previous = Rectangle;
         
          freerdsrec( DelRec, FigureRds->SIZE );
        }
        else
        {
          if ( ( IsRdsRefCon( Rectangle )        ) &&
               ( Rectangle->NAME != (char *)NULL ) )
          {
            strcpy( LynxReferenceBuffer, Rectangle->NAME );

            ReferenceName = strrchr( LynxReferenceBuffer, '_' );

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

            ReferenceName   = namealloc( LynxReferenceBuffer );
            Rectangle->NAME = ReferenceName;
          }
        
          LYNX_LINK( Rectangle ) = (rdsrec_list *)InstanceRds;
          Previous  = &Rectangle->NEXT;
          Rectangle = Rectangle->NEXT;
        }
      }
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                        Lynxfigmbkrds                        |
|                                                             |
\------------------------------------------------------------*/

  rdsfig_list *Lynxfigmbkrds( FigureMbk )
   
     phfig_list *FigureMbk;
  {
    rdsfig_list *FigureRds;
    void        *Pointer;

    FigureRds = addrdsfig( FigureMbk->NAME, LYNX_MODE );

    aboxmbkrds( FigureMbk, FigureRds );

    for ( Pointer  = (void *)(FigureMbk->PHSEG);
          Pointer != (void *)NULL;
          Pointer  = (void *)(((phseg_list *)Pointer)->NEXT))
    {
      Lynxsegmbkrds( FigureRds, (phseg_list *)Pointer, 1 );
    }

    for ( Pointer  = (void *)(FigureMbk->PHCON);
          Pointer != (void *)NULL;
          Pointer  = (void *)(((phcon_list *)Pointer)->NEXT))
    {
      Lynxconmbkrds( FigureRds, (phcon_list *)Pointer );
    }

    for ( Pointer  = (void *)(FigureMbk->PHREF);
          Pointer != (void *)NULL;
          Pointer  = (void *)(((phref_list *)Pointer)->NEXT))
    {
      Lynxrefmbkrds( FigureRds, (phref_list *)Pointer );
    }

    for ( Pointer  = (void *)(FigureMbk->PHVIA);
          Pointer != (void *)NULL;
          Pointer  = (void *)(((phvia_list *)Pointer)->NEXT))
    {
      Lynxviambkrds( FigureRds, (phvia_list *)Pointer );
    }

    for ( Pointer  = (void *)(FigureMbk->PHINS);
          Pointer != (void *)NULL;
          Pointer  = (void *)(((phins_list *)Pointer)->NEXT))
    {
      Lynxinsmbkrds( FigureRds, (phins_list *)Pointer );
    }

    return( FigureRds );
  }

/*------------------------------------------------------------\
|                                                             |
|                      LynxTreatRectangle                     |
|                                                             |
\------------------------------------------------------------*/
  
  void LynxTreatRectangle( Rectangle )
 
    rdsrec_list *Rectangle;
  {
    rdsrec_list *ScanRec;

    ScanRec = Rectangle;
 
    do
    {
      SetLynxTreat( ScanRec );

      ScanRec = LYNX_LINK( ScanRec );
    }
    while ( ScanRec != Rectangle );
  }

/*------------------------------------------------------------\
|                                                             |
|                        Lynxrecrdsmbk                        |
|                                                             |
\------------------------------------------------------------*/
  
  void Lynxrecrdsmbk( FigureMbk, Rectangle )

    phfig_list  *FigureMbk;
    rdsrec_list *Rectangle;
  {
    rdsrec_list *ScanRec;
    rdsins_list *InstanceRds;
   
    long         X1;
    long         Y1;
    long         X2;
    long         Y2;
    long         Width;
    char         Orient;
    char         Layer;
    char         LayerRds;
    long         DLR;
    long         DWR;
    long         OFFSET;
    long         WS;
    char         TRANS;         
    char         USE;
    int          Index;

    if ( Rectangle == (rdsrec_list *)NULL ) return;

    if ( IsRdsFigRec( Rectangle ) )
    {
      if ( ( ! IsLynxTreat( Rectangle ) ) &&
           ( !   IsLynxCut( Rectangle ) ) )
      {
        if ( IsRdsFigure( Rectangle ) )
        {
          FigureMbk->XAB1 = Rectangle->X  * SCALE_X / RDS_LAMBDA;
          FigureMbk->YAB1 = Rectangle->Y  * SCALE_X / RDS_LAMBDA;
          FigureMbk->XAB2 = Rectangle->DX * SCALE_X / RDS_LAMBDA;
          FigureMbk->YAB2 = Rectangle->DY * SCALE_X / RDS_LAMBDA;

          FigureMbk->XAB2 += FigureMbk->XAB1;
          FigureMbk->YAB2 += FigureMbk->YAB1;
        }
        else
        if ( IsRdsSegment( Rectangle ) )
        {
          Orient = LynxSegmentOrientTable[ GetLynxOrient( Rectangle ) ];
          Layer  = GetLynxAttribute( Rectangle );

          while ( ! IsLynxFirstLink( Rectangle ) )
          {
            Rectangle = LYNX_LINK( Rectangle );
          }

          Index    = 0;
          LayerRds = GET_SEGMENT_LAYER( Layer, 0 );

          while ( LayerRds != RDS_SEGMENT_EMPTY )
          {
            TRANS = GET_SEGMENT_TRANS( Layer, Index );
            USE   = GET_SEGMENT_USE( Layer, Index );

            if ( ( USE == RDS_USE_ALL     ) ||
                 ( USE == RDS_USE_EXTRACT ) )
            {
              if ( TRANS == RDS_TRANS_VW )
              {
                X1 = Rectangle->X;
                Y1 = Rectangle->Y;
                X2 = Rectangle->DX + X1;
                Y2 = Rectangle->DY + Y1;

                DLR    = GET_SEGMENT_DLR   ( Layer, Index );
                DWR    = GET_SEGMENT_DWR   ( Layer, Index );
                OFFSET = GET_SEGMENT_OFFSET( Layer, Index );

                switch ( Orient )
                {
                  case RIGHT  : WS = Rectangle->DY - DWR;
                                X1 = X1 + DLR;
                                Y1 = Y1 + ( ( Rectangle->DY ) >> 1 ) + OFFSET;
                                X2 = X2 - DLR;
                                Y2 = Y2 - ( ( Rectangle->DY ) >> 1 ) + OFFSET;

                              break;

                  case LEFT   : WS = Rectangle->DY - DWR;
                                X1 = X1 + DLR;
                                Y1 = Y1 + ( ( Rectangle->DY ) >> 1 ) - OFFSET;
                                X2 = X2 - DLR;
                                Y2 = Y2 - ( ( Rectangle->DY ) >> 1 ) - OFFSET;

                              break;

                  case UP     : WS = Rectangle->DX - DWR;
                                X1 = X1 + ( ( Rectangle->DX ) >> 1 ) + OFFSET;
                                Y1 = Y1 + DLR;
                                X2 = X2 - ( ( Rectangle->DX ) >> 1 ) + OFFSET;
                                Y2 = Y2 - DLR;
 
                              break;

                  case DOWN   : WS = Rectangle->DX - DWR;
                                X1 = X1 + ( ( Rectangle->DX ) >> 1 ) - OFFSET;
                                Y1 = Y1 + DLR;
                                X2 = X2 - ( ( Rectangle->DX ) >> 1 ) - OFFSET;
                                Y2 = Y2 - DLR;

                              break;
                }

                addphseg( FigureMbk,
                          Layer,
                          WS * SCALE_X / RDS_LAMBDA,
                          X1 * SCALE_X / RDS_LAMBDA,
                          Y1 * SCALE_X / RDS_LAMBDA,
                          X2 * SCALE_X / RDS_LAMBDA,
                          Y2 * SCALE_X / RDS_LAMBDA,
                          Rectangle->NAME );
                break;
              }
            }

            Rectangle = LYNX_LINK( Rectangle );
            Index     = Index + 1;
            LayerRds  = GET_SEGMENT_LAYER( Layer, Index );
          }
        }
        else
        if ( IsRdsConnector( Rectangle ) )
        {
          Orient = LynxConnectorOrientTable[ GetLynxOrient( Rectangle ) ];
          Layer  = GetLynxAttribute( Rectangle );

          X1 = Rectangle->X + ( Rectangle->DX >> 1 );
          Y1 = Rectangle->Y + ( Rectangle->DY >> 1 );

          Width = ( Rectangle->DX > Rectangle->DY ) 
                  ? Rectangle->DX : Rectangle->DY;

          addphcon( FigureMbk, 
                    Orient, 
                    Rectangle->NAME, 
                    X1 * SCALE_X / RDS_LAMBDA,
                    Y1 * SCALE_X / RDS_LAMBDA,
                    Layer,
                    Width * SCALE_X / RDS_LAMBDA );

          LynxTreatRectangle( Rectangle );
        }
        else
        if ( IsRdsVia( Rectangle ) )
        {
          X1 = Rectangle->X + ( Rectangle->DX >> 1 );
          Y1 = Rectangle->Y + ( Rectangle->DY >> 1 );
  
          addphvia( FigureMbk, 
                    GetLynxAttribute( Rectangle ), 
                    X1    * SCALE_X / RDS_LAMBDA,
                    Y1    * SCALE_X / RDS_LAMBDA );

          LynxTreatRectangle( Rectangle );
        }
        else
        if ( IsRdsReference( Rectangle ) )
        {
          X1 = Rectangle->X + ( Rectangle->DX >> 1 );
          Y1 = Rectangle->Y + ( Rectangle->DY >> 1 );

          addphref( FigureMbk,
                    ( IsRdsRefRef( Rectangle ) ) ?
                    "ref_ref" : "ref_con",
                    Rectangle->NAME,
                    X1 * SCALE_X / RDS_LAMBDA,
                    Y1 * SCALE_X / RDS_LAMBDA );
        }
      }
    }
    else
    {
      InstanceRds = (rdsins_list *)LYNX_LINK( Rectangle );
      Rectangle   = InstanceRds->LAYERTAB[ RDS_ABOX ];

      if ( ! IsLynxTreat( Rectangle ) )
      {
        addphins( FigureMbk,
                  InstanceRds->FIGNAME,
                  InstanceRds->INSNAME,
                  InstanceRds->TRANSF,
                  Rectangle->X * SCALE_X / RDS_LAMBDA,
                  Rectangle->Y * SCALE_X / RDS_LAMBDA );

        SetLynxTreat( Rectangle );
      }
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                        Lynxfigrdsmbk                        |
|                                                             |
\------------------------------------------------------------*/

  void Lynxfigrdsmbk( FigureRds, FigureMbk )

    rdsfig_list *FigureRds;
    phfig_list  *FigureMbk;
  {
    rdsins_list *InstanceRds;
    rdsrec_list *Rectangle;
    char         Layer;

    Lynxrecrdsmbk( FigureMbk, FigureRds->LAYERTAB[ RDS_ABOX ] );

    for ( Layer = 0; Layer < RDS_ABOX; Layer++ )
    {
      for ( Rectangle  = FigureRds->LAYERTAB[ Layer ];
            Rectangle != (rdsrec_list *)NULL;
            Rectangle  = Rectangle->NEXT )
      {
        Lynxrecrdsmbk( FigureMbk, Rectangle );
      }
    }

    for ( InstanceRds = FigureRds->INSTANCE;
          InstanceRds != (rdsins_list *)NULL;
          InstanceRds  = InstanceRds->NEXT )
    {
      Lynxrecrdsmbk( FigureMbk, InstanceRds->LAYERTAB[ RDS_ABOX ] );
    }
  }
