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

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

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

# include "GMC_create.h"
# include "GMC_dialog.h"

/*------------------------------------------------------------\
|                                                             |
|                           Constants                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                            Types                            |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                          Variables                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                        Segment & Wire                       |
|                                                             |
\------------------------------------------------------------*/

  char  GraalSegmentLayer = ALU1;
  long  GraalSegmentWidth = -1;
  char *GraalSegmentName  = (char *)NULL;
  char  GraalSegmentWire  = GRAAL_FALSE;

/*------------------------------------------------------------\
|                                                             |
|                              Via                            |
|                                                             |
\------------------------------------------------------------*/

  char  GraalViaType      = CONT_POLY;

/*------------------------------------------------------------\
|                                                             |
|                           Transistor                        |
|                                                             |
\------------------------------------------------------------*/

  char  GraalTransistorType  = NTRANS;
  long  GraalTransistorLength = -1;
  char  GraalTransistorWire  = GRAAL_FALSE;

/*------------------------------------------------------------\
|                                                             |
|                           Connector                         |
|                                                             |
\------------------------------------------------------------*/

  char  GraalConnectorLayer  = ALU1;
  long  GraalConnectorWidth  = -1;
  char *GraalConnectorName   = (char *)NULL;
  char  GraalConnectorOrient = GRAAL_NORTH;

/*------------------------------------------------------------\
|                                                             |
|                           Reference                         |
|                                                             |
\------------------------------------------------------------*/

  char  GraalReferenceType   = MBK_REF_REF;
  char *GraalReferenceName   = (char *)NULL;

/*------------------------------------------------------------\
|                                                             |
|                           Instance                          |
|                                                             |
\------------------------------------------------------------*/

 char  GraalInstanceSym      = NOSYM;
 char *GraalInstanceName     = (char *)NULL;
 char *GraalInstanceModel    = (char *)NULL;

/*------------------------------------------------------------\
|                                                             |
|                          Functions                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                      GraalCreateFigureMbk                   |
|                                                             |
\------------------------------------------------------------*/

  void GraalCreateFigureMbk()

  {
    if ( GraalFigureMbk == (phfig_list *)NULL )
    {
      GraalFigureMbk = addphfig( GRAAL_DEFAULT_FIGURE_NAME );

      GraalAddFigure();
    }
  }  

/*------------------------------------------------------------\
|                                                             |
|                     GraalCreateSegmentMbk                   |
|                                                             |
\------------------------------------------------------------*/

  void GraalCreateSegmentMbk( LambdaX1, LambdaY1, LambdaX2, LambdaY2 )

     long LambdaX1;
     long LambdaY1;
     long LambdaX2;
     long LambdaY2;
  {
    rdsrec_list *Rectangle;
    phseg_list  *Segment;
    long         Delta;

    if ( LambdaX1 == LambdaX2 )
    {
      Delta = LambdaY2 - LambdaY1;
    }
    else
    {
      Delta = LambdaX2 - LambdaX1;
    }

    if ( Delta < 0 ) Delta = - Delta;
    
    if ( Delta < GRAAL_SEGMENT_VALUE_TABLE[GraalSegmentLayer][1] )
    {
      GraalErrorMessage( GraalMainWindow, "This segment is too small !" );
      return;
    }

    GraalCreateFigureMbk();

    Segment = 

       addphseg( GraalFigureMbk, GraalSegmentLayer, 
                 GraalSegmentWidth * SCALE_X,
                 LambdaX1 * SCALE_X, LambdaY1 * SCALE_X,
                 LambdaX2 * SCALE_X, LambdaY2 * SCALE_X, 
                 GraalSegmentName );
                           
    Segment->USER = (void *)(&GraalFigureMbk->PHSEG);

    if ( Segment->NEXT != (phseg_list *)NULL )
    {
      Segment->NEXT->USER = (void *)(&Segment->NEXT);
    }

    Rectangle = GraalAddSegment( Segment );

    if ( Rectangle != (rdsrec_list *)NULL )
    {
      GraalAddUndo();
      GraalAddUndoRec( Rectangle );

      if ( ( GraalHeadEqui != (rdsrec_list *)NULL ) || 
           ( GraalHeadPeek != (graalpeek   *)NULL ) )
      {
        GraalDelEqui();
        GraalDelPeek();
        GraalZoomRefresh();
      }
      else 
      {
        GraalDisplayRectangle( Rectangle );
      }
    }
    else
    {
      delphseg( GraalFigureMbk, Segment );

      GraalErrorMessage( GraalMainWindow, "Can't create any segment of this layer !" );
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                       GraalCreateViaMbk                     |
|                                                             |
\------------------------------------------------------------*/

  void GraalCreateViaMbk( LambdaX1, LambdaY1 )

     long LambdaX1;
     long LambdaY1;
  {
    rdsrec_list *Rectangle;
    phvia_list  *Via;

    GraalCreateFigureMbk();

    Via = addphvia( GraalFigureMbk, GraalViaType, 
                    LambdaX1 * SCALE_X, LambdaY1 * SCALE_X );

    Via->USER = (void *)(&GraalFigureMbk->PHVIA);

    if ( Via->NEXT != (phvia_list *)NULL )
    {
      Via->NEXT->USER = (void *)(&Via->NEXT);
    }

    Rectangle = GraalAddVia( Via );

    if ( Rectangle != (rdsrec_list *)NULL )
    {
      GraalAddUndo();
      GraalAddUndoRec( Rectangle );

      if ( ( GraalHeadEqui != (rdsrec_list *)NULL ) || 
           ( GraalHeadPeek != (graalpeek   *)NULL ) ) 
      {
        GraalDelEqui();
        GraalDelPeek(); 
        GraalZoomRefresh();
      }
      else
      {   
        GraalDisplayRectangle( Rectangle );
      }
    }
    else
    {
      delphvia( GraalFigureMbk, Via );

      GraalErrorMessage( GraalMainWindow, "Can't create any via of this type !" );
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                    GraalCreateTransistorMbk                 |
|                                                             |
\------------------------------------------------------------*/

  void GraalCreateTransistorMbk( LambdaX1, LambdaY1, LambdaX2, LambdaY2 )

     long LambdaX1;
     long LambdaY1;
     long LambdaX2;
     long LambdaY2;
  {
    rdsrec_list *Rectangle;
    phseg_list  *Transistor;
    long         Delta;

    if ( LambdaX1 == LambdaX2 )
    {
      Delta = LambdaY2 - LambdaY1;
    } 
    else
    {   
      Delta = LambdaX2 - LambdaX1;
    } 

    if ( Delta < 0 ) Delta = - Delta;
    
    if ( Delta < GRAAL_SEGMENT_VALUE_TABLE[GraalTransistorType][1] )
    { 
      GraalErrorMessage( GraalMainWindow, "This transistor is too small !" );
      return;
    } 

    GraalCreateFigureMbk();
 
    Transistor =
 
       addphseg( GraalFigureMbk, GraalTransistorType,
                 GraalTransistorLength * SCALE_X,
                 LambdaX1 * SCALE_X, LambdaY1 * SCALE_X,
                 LambdaX2 * SCALE_X, LambdaY2 * SCALE_X,
                 NULL );
       
    Transistor->USER = (void *)(&GraalFigureMbk->PHSEG);
      
    if ( Transistor->NEXT != (phseg_list *)NULL )
    {
      Transistor->NEXT->USER = (void *)(&Transistor->NEXT);
    }
      
    Rectangle = GraalAddSegment( Transistor );

    if ( Rectangle != (rdsrec_list *)NULL )
    {
      GraalAddUndo();
      GraalAddUndoRec( Rectangle );

      if ( ( GraalHeadEqui != (rdsrec_list *)NULL ) || 
           ( GraalHeadPeek != (graalpeek   *)NULL ) ) 
      {
        GraalDelEqui();
        GraalDelPeek(); 
        GraalZoomRefresh();
      }
      else
      {   
        GraalDisplayRectangle( Rectangle );
      }
    }
    else
    {   
      delphseg( GraalFigureMbk, Transistor );

      GraalErrorMessage( GraalMainWindow, "Can't create any transistor of this type !" );
    }
  }   

/*------------------------------------------------------------\
|                                                             |
|                     GraalCreateConnectorMbk                 |
|                                                             |
\------------------------------------------------------------*/

  void GraalCreateConnectorMbk( LambdaX1, LambdaY1 )

     long LambdaX1;
     long LambdaY1;
  {
    rdsrec_list *Rectangle;
    phcon_list  *Connector;
    char         Orient;
    char         MbkOrient;

    LambdaX1 = LambdaX1 * SCALE_X;
    LambdaY1 = LambdaY1 * SCALE_X;

    Orient = 0;

    if ( ( LambdaX1 == GraalFigureMbk->XAB1 ) &&
         ( LambdaY1 >= GraalFigureMbk->YAB1 ) &&
         ( LambdaY1 <= GraalFigureMbk->YAB2 ) )
    {
      Orient |= GRAAL_WEST_MASK;
    }

    if ( ( LambdaX1 == GraalFigureMbk->XAB2 ) &&
         ( LambdaY1 >= GraalFigureMbk->YAB1 ) &&
         ( LambdaY1 <= GraalFigureMbk->YAB2 ) )
    {
      Orient |= GRAAL_EAST_MASK;
    }

    if ( ( LambdaY1 == GraalFigureMbk->YAB1 ) &&
         ( LambdaX1 >= GraalFigureMbk->XAB1 ) &&
         ( LambdaX1 <= GraalFigureMbk->XAB2 ) )
    {
      Orient |= GRAAL_SOUTH_MASK;
    }

    if ( ( LambdaY1 == GraalFigureMbk->YAB2 ) &&
         ( LambdaX1 >= GraalFigureMbk->XAB1 ) &&
         ( LambdaX1 <= GraalFigureMbk->XAB2 ) )
    {
      Orient |= GRAAL_NORTH_MASK;
    }

    if ( Orient == 0 )
    {
      GraalErrorMessage( GraalMainWindow, 
      "Connector must be on abutment box !" );

      return;
    }

    switch ( GraalConnectorOrient )
    {
      case GRAAL_NORTH : 

        if ( !( Orient & GRAAL_NORTH_MASK ) )
        {
          GraalErrorMessage( GraalMainWindow, 
          "This connector can't have NORTH orient !" );

          return;
        }
        MbkOrient = NORTH; 
        break;

      case GRAAL_SOUTH :

        if ( !( Orient & GRAAL_SOUTH_MASK ) )
        {
          GraalErrorMessage( GraalMainWindow,
          "This connector can't have SOUTH orient !" );

          return;
        }
        MbkOrient = SOUTH; 
        break; 

      case GRAAL_EAST :

        if ( !( Orient & GRAAL_EAST_MASK ) )
        {
          GraalErrorMessage( GraalMainWindow,
          "This connector can't have EAST orient !" );

          return;
        }
        MbkOrient = EAST; 
        break; 

      case GRAAL_WEST :

        if ( !( Orient & GRAAL_WEST_MASK ) )
        {
          GraalErrorMessage( GraalMainWindow,
          "This connector can't have WEST orient !" );

          return;
        }
        MbkOrient = WEST; 
        break; 
    }

    GraalEnterDialog( &GraalChangeConnectorNameDialog );

    if ( GraalCreateDialogCancel ) return;

    if ( GraalConnectorName != (char *)NULL )
    {
      GraalCreateFigureMbk();

      Connector =

         addphcon( GraalFigureMbk, MbkOrient,
                   GraalConnectorName,
                   LambdaX1, LambdaY1,
                   GraalConnectorLayer,
                   GraalConnectorWidth * SCALE_X );
       
      Connector->USER = (void *)(&GraalFigureMbk->PHCON);
        
      if ( Connector->NEXT != (phcon_list *)NULL )
      {
        Connector->NEXT->USER = (void *)(&Connector->NEXT);
      }
     
      Rectangle = GraalAddConnector( Connector );
        
      if ( Rectangle != (rdsrec_list *)NULL )
      {
        GraalAddUndo();
        GraalAddUndoRec( Rectangle );

        if ( ( GraalHeadEqui != (rdsrec_list *)NULL ) || 
             ( GraalHeadPeek != (graalpeek   *)NULL ) ) 
        {
          GraalDelEqui();
          GraalDelPeek(); 
          GraalZoomRefresh();
        }
        else
        {   
          GraalDisplayRectangle( Rectangle );
        }
      }
      else
      {   
        delphcon( GraalFigureMbk, Connector );

        GraalErrorMessage( GraalMainWindow, "Can't create any connector of this layer !" );
      }
    }
    else
    {
      GraalErrorMessage( GraalMainWindow, "Connector must have name !" );
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                    GraalCreateReferenceMbk                  |
|                                                             |
\------------------------------------------------------------*/

  void GraalCreateReferenceMbk( LambdaX1, LambdaY1 )

     long LambdaX1;
     long LambdaY1;
  {
    rdsrec_list *Rectangle;
    phref_list  *Reference;

    GraalEnterDialog( &GraalChangeReferenceNameDialog );

    if ( GraalCreateDialogCancel ) return;

    if ( GraalReferenceName != (char *)NULL )
    {
      GraalCreateFigureMbk();

      Reference = 

        addphref( GraalFigureMbk, 
                  (GraalReferenceType == MBK_REF_REF) ? "ref_ref":"ref_con" ,
                  GraalReferenceName,
                  LambdaX1 * SCALE_X, LambdaY1 * SCALE_X );

      Reference->USER = (void *)(&GraalFigureMbk->PHREF);
  
      if ( Reference->NEXT != (phref_list *)NULL )
      {
        Reference->NEXT->USER = (void *)(&Reference->NEXT);
      }
 
      Rectangle = GraalAddReference( Reference );
 
      if ( Rectangle != (rdsrec_list *)NULL )
      {
        GraalAddUndo();
        GraalAddUndoRec( Rectangle );

        if ( ( GraalHeadEqui != (rdsrec_list *)NULL ) || 
             ( GraalHeadPeek != (graalpeek   *)NULL ) ) 
        {
          GraalDelEqui();
          GraalDelPeek(); 
          GraalZoomRefresh();
        }
        else
        {   
          GraalDisplayRectangle( Rectangle );
        }
      }
      else
      {
        delphref( GraalFigureMbk, Reference );
 
        GraalErrorMessage( GraalMainWindow, "Can't create any reference of this type !" );
      }
    }
    else
    {
      GraalErrorMessage( GraalMainWindow, "Reference must have name !" );
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                     GraalCreateInstanceMbk                  |
|                                                             |
\------------------------------------------------------------*/

  void GraalCreateInstanceMbk( LambdaX1, LambdaY1 )

     long LambdaX1;
     long LambdaY1;
  {
    rdsrec_list *Rectangle;
    phins_list  *InstanceMbk;
    phins_list  *SaveInstance;
    rdsins_list *InstanceRds;

    GraalEnterDialog( &GraalChangeInstanceModelDialog );

    if ( GraalCreateDialogCancel ) return;

    if ( GraalInstanceModel != (char *)NULL )
    {
      GraalEnterDialog( &GraalChangeInstanceNameDialog  );

      if ( GraalCreateDialogCancel ) return;

      if ( GraalInstanceName != (char *)NULL )
      {
        GraalCreateFigureMbk();

        if ( GraalFigureMbk->NAME == GraalInstanceModel )
        {
          GraalErrorMessage( GraalMainWindow, 
                             "A figure cannot be part of itself !" );
          return;
        }

        for ( InstanceRds  = GraalFigureRds->INSTANCE;
              InstanceRds != (rdsins_list *)NULL;
              InstanceRds  = InstanceRds->NEXT )
        { 
          if ( InstanceRds->INSNAME == GraalInstanceName )
          {
            if ( ! IsGraalDeleted( InstanceRds->LAYERTAB[ RDS_ABOX ] ) )
            {
              GraalErrorMessage( GraalMainWindow, 
                                 "All instances must have different names !" );
              return;
            }
          }
        }

        SaveInstance          = GraalFigureMbk->PHINS;
        GraalFigureMbk->PHINS = (phins_list *)NULL;

        InstanceMbk =

          addphins( GraalFigureMbk,
                    GraalInstanceModel,
                    GraalInstanceName,
                    GraalInstanceSym,
                    LambdaX1 * SCALE_X, LambdaY1 * SCALE_X );

        InstanceMbk->NEXT = SaveInstance;
        InstanceMbk->USER = (void *)(&GraalFigureMbk->PHINS);
     
        if ( SaveInstance != (phins_list *)NULL )
        {
          SaveInstance->USER = (void *)(&InstanceMbk->NEXT);
        }
     
        InstanceRds = GraalAddInstance( InstanceMbk );

        GraalDisplayToolsMessage();

        if ( InstanceRds == (rdsins_list *)NULL )
        {
          GraalFigureMbk->PHINS = SaveInstance;
          mbkfree( InstanceMbk );

          GraalErrorMessage( GraalMainWindow, "Unable to load instance model !" );
        }
        else
        {
          GraalDelEqui();
          GraalAddUndo();
          GraalAddUndoRec( InstanceRds->LAYERTAB[ RDS_ABOX ] );
          GraalZoomRefresh();
        }
      }
      else
      {
        GraalErrorMessage( GraalMainWindow, "An instance must have a name !" );
      }
    }
    else
    {
      GraalErrorMessage( GraalMainWindow, "An instance model name must specified !" );
    }
  }

/*------------------------------------------------------------\
|                                                             |
|                   Graal Create Abutmentbox                  |
|                                                             |
\------------------------------------------------------------*/

 void GraalCreateAbutmentBoxMbk( LambdaX1, LambdaY1, LambdaX2, LambdaY2 )

   long LambdaX1;
   long LambdaY1;
   long LambdaX2;
   long LambdaY2;
 {
   rdsrec_list *Rectangle;
   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;
     }
   }  
   else
   {
     GraalErrorMessage( GraalMainWindow, "The abutment box must be rectangular !" );

     return;
   }

   GraalCreateFigureMbk();

   GraalFigureMbk->XAB1 = LambdaX1 * SCALE_X;
   GraalFigureMbk->YAB1 = LambdaY1 * SCALE_X;
   GraalFigureMbk->XAB2 = LambdaX2 * SCALE_X;
   GraalFigureMbk->YAB2 = LambdaY2 * SCALE_X;

   Rectangle = GraalAddAbox();

   if ( Rectangle != (rdsrec_list *)NULL )
   {
     GraalAddUndo();
     GraalAddUndoRec( Rectangle );

     if ( ( GraalHeadEqui != (rdsrec_list *)NULL ) || 
          ( GraalHeadPeek != (graalpeek   *)NULL ) ) 
     {
       GraalDelEqui();
       GraalDelPeek(); 
       GraalZoomRefresh();
     }
     else
     {   
       GraalDisplayRectangle( Rectangle );
     }

     GraalChangeEditMode( GRAAL_EDIT_MEASURE,
                          GraalPromptEditMeasure );
   }
   else
   {   
     GraalFigureMbk->XAB1 = 0;
     GraalFigureMbk->YAB1 = 0;
     GraalFigureMbk->XAB2 = 0;
     GraalFigureMbk->YAB2 = 0;

     GraalErrorMessage( GraalMainWindow, "Can't create this abutment box !" );
   }
 }
