/*------------------------------------------------------------\
|                                                             |
| Tool    :                   GRAAL                           |
|                                                             |
| File    :                  Modify.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 GSB_H
# include GRM_H
# include GMX_H
# include GTB_H
# include GME_H

# include "GME_modify.h"
# include "GME_panel.h"
# include "GME_edit.h"
# include "GME_message.h"

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

  char GraalModifyAbort  = 0;
  char GraalModifyLock   = 0;
  char GraalModifyApply  = 0;

/*------------------------------------------------------------\
|                                                             |
|                        Segment & Wire                       |
|                                                             |
\------------------------------------------------------------*/

  char  GraalSegmentMLayer;
  long  GraalSegmentMWidth;
  char *GraalSegmentMName;

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

  char  GraalViaMType;

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

  char  GraalTransistorMType;
  long  GraalTransistorMLength;

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

  char  GraalConnectorMLayer; 
  long  GraalConnectorMWidth; 
  char *GraalConnectorMName;  
  char  GraalConnectorMOrient;

  char  GraalSaveConnectorMOrient;

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

  char  GraalReferenceMType;  
  char *GraalReferenceMName;  

  char  GraalSaveReferenceMType;

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

 char  GraalInstanceMSym;
 char *GraalInstanceMName;
 char *GraalInstanceMModel;

/*------------------------------------------------------------\
|                                                             |
|                          Functions                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                       Changed Functions                     |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                     GraalTransistorChanged                  |
|                                                             |
\------------------------------------------------------------*/

  char GraalTransistorChanged( Transistor )

    phseg_list *Transistor; 
  {
    return 

     ( (   Transistor->LAYER             != GraalTransistorMType   ) ||
       ( ( Transistor->WIDTH / SCALE_X ) != GraalTransistorMLength ) );
  }

/*------------------------------------------------------------\
|                                                             |
|                       GraalSegmentChanged                   |
|                                                             |
\------------------------------------------------------------*/

  char GraalSegmentChanged( Segment )

    phseg_list *Segment;
  {
    return

     ( (   Segment->NAME              != GraalSegmentMName  ) ||
       (   Segment->LAYER             != GraalSegmentMLayer ) ||
       ( ( Segment->WIDTH / SCALE_X ) != GraalSegmentMWidth ) );
  }

/*------------------------------------------------------------\
|                                                             |
|                        GraalViaChanged                      |
|                                                             |
\------------------------------------------------------------*/

  char GraalViaChanged( Via )

    phseg_list *Via;
  {
    return ( Via->TYPE != GraalViaMType );
  }

/*------------------------------------------------------------\
|                                                             |
|                     GraalConnectorChanged                   |
|                                                             |
\------------------------------------------------------------*/

  char GraalConnectorChanged( Connector )

    phcon_list *Connector;
  {
    return

     ( (   Connector->NAME              != GraalConnectorMName   ) ||
       (   Connector->LAYER             != GraalConnectorMLayer  ) ||
       ( ( Connector->WIDTH / SCALE_X ) != GraalConnectorMWidth  ) ||
       (  GraalSaveConnectorMOrient     != GraalConnectorMOrient ) );
  }

/*------------------------------------------------------------\
|                                                             |
|                     GraalReferenceChanged                   |
|                                                             |
\------------------------------------------------------------*/

  char GraalReferenceChanged( Reference )

    phref_list *Reference;
  {
    return

     ( (   Reference->NAME          != GraalReferenceMName ) ||
       (   GraalSaveReferenceMType  != GraalReferenceMType ) );
  }

/*------------------------------------------------------------\
|                                                             |
|                      GraalInstanceChanged                   |
|                                                             |
\------------------------------------------------------------*/

  char GraalInstanceChanged( Instance )

    phins_list *Instance;
  {
    return

     ( ( Instance->INSNAME != GraalInstanceMName  ) ||
       ( Instance->TRANSF  != GraalInstanceMSym   ) ||
       ( Instance->FIGNAME != GraalInstanceMModel ) );
  }

/*------------------------------------------------------------\
|                                                             |
|                       GraalEditModify                       |
|                                                             |
\------------------------------------------------------------*/

  void GraalEditModify()

  {
    graalselect *Select;
    rdsrec_list *Rectangle;
    rdsrec_list *NewRec;
    rdsins_list *Instance;
    phins_list  *SaveInstance;
    void        *Pointer;
    void        *Element;
    char         FirstUndo;
    char         Orient;
    char         MbkOrient;

    FirstUndo = 1;

    GraalModifyAbort = 0;
    GraalModifyApply = 0;
    GraalModifyLock  = 0;
    
    for ( Select  = GraalHeadSelect;
          Select != (graalselect *)NULL;
          Select  = Select->NEXT )
    {
      Rectangle = Select->RECTANGLE;

      if ( IsRdsSegment( Rectangle ) )
      {
        Pointer = GRAAL_MBK( Rectangle );

        if ( ( ((phseg_list *)Pointer)->LAYER == NTRANS ) || 
             ( ((phseg_list *)Pointer)->LAYER == PTRANS ) )
        {
          GraalAcceptRectangle( Rectangle );
          GraalDisplayRectangle( Rectangle );

          GraalTransistorMLength = ((phseg_list *)Pointer)->WIDTH / SCALE_X;
          GraalTransistorMType   = ((phseg_list *)Pointer)->LAYER;

          GraalPromptModifyTransistor();
          GraalEnterPanel( &GraalModifyTransistorPanel );

          GraalModifyLock = GRAAL_TRUE;

          while ( GraalModifyLock )
          {
            GraalLimitedLoop( GraalModifyTransistorPanel.PANEL );
          }

          GraalRejectRectangle( Rectangle );
          GraalDisplayRectangle( Rectangle );

          if ( GraalModifyAbort ) break;

          if ( GraalModifyApply )
          {
            if ( ! GraalTransistorChanged( (phseg_list *)Pointer ) ) 

              continue; 

            if ( FirstUndo )
            {
              GraalAddUndo();

              FirstUndo = 0;
            }
   
            GraalDeleteRectangle( Rectangle );
            GraalAddUndoRec( Rectangle );

            Element = (void *)
  
              addphseg( GraalFigureMbk,
                        GraalTransistorMType ,
                        GraalTransistorMLength * SCALE_X,
                        ((phseg_list *)Pointer)->X1,
                        ((phseg_list *)Pointer)->Y1,
                        ((phseg_list *)Pointer)->X2,
                        ((phseg_list *)Pointer)->Y2,
                        NULL );

            ((phseg_list *)Element)->TYPE = ((phseg_list *)Pointer)->TYPE;
            ((phseg_list *)Element)->USER = (void *)(&GraalFigureMbk->PHSEG);

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

            NewRec = GraalAddSegment( ((phseg_list *)Element) );
            GraalAddUndoRec( NewRec );

            GraalDisplayRectangle( NewRec );
          }
        }
      }
    }

    XtUnmanageChild( GraalModifyTransistorPanel.PANEL );

    if ( ! GraalModifyAbort )

    for ( Select  = GraalHeadSelect;
          Select != (graalselect *)NULL;
          Select  = Select->NEXT )
    {
      Rectangle = Select->RECTANGLE;

      Pointer = GRAAL_MBK( Rectangle );

      if ( IsRdsSegment( Rectangle ) )
      {
        if ( ( ((phseg_list *)Pointer)->LAYER != NTRANS ) &&
             ( ((phseg_list *)Pointer)->LAYER != PTRANS ) )
        {
          GraalAcceptRectangle( Rectangle );
          GraalDisplayRectangle( Rectangle );

          GraalSegmentMWidth = ((phseg_list *)Pointer)->WIDTH / SCALE_X;
          GraalSegmentMLayer = ((phseg_list *)Pointer)->LAYER;
          GraalSegmentMName  = ((phseg_list *)Pointer)->NAME;

          GraalPromptModifySegment();
          GraalEnterPanel( &GraalModifySegmentPanel );

          GraalModifyLock = GRAAL_TRUE;

          while ( GraalModifyLock )
          {
            GraalLimitedLoop( GraalModifySegmentPanel.PANEL );
          }

          GraalRejectRectangle( Rectangle );
          GraalDisplayRectangle( Rectangle );
    
          if ( GraalModifyAbort ) break;

          if ( GraalModifyApply )
          {
            if ( ! GraalSegmentChanged( (phseg_list *)Pointer ) ) 

              continue; 

            if ( FirstUndo )
            {
              GraalAddUndo();

              FirstUndo = 0;
            }
   
            GraalDeleteRectangle( Rectangle );
            GraalAddUndoRec( Rectangle );

            Element = (void *)
  
              addphseg( GraalFigureMbk,
                        GraalSegmentMLayer,
                        GraalSegmentMWidth * SCALE_X,
                        ((phseg_list *)Pointer)->X1,
                        ((phseg_list *)Pointer)->Y1,
                        ((phseg_list *)Pointer)->X2,
                        ((phseg_list *)Pointer)->Y2,
                        GraalSegmentMName );

            ((phseg_list *)Element)->TYPE = ((phseg_list *)Pointer)->TYPE;
            ((phseg_list *)Element)->USER = (void *)(&GraalFigureMbk->PHSEG);
    
            if ( ((phseg_list *)Element)->NEXT != (phseg_list *)NULL )
            {
              ((phseg_list *)Element)->NEXT->USER = (void *)(&((phseg_list *)Element)->NEXT);
            }

            NewRec = GraalAddSegment( ((phseg_list *)Element) );
            GraalAddUndoRec( NewRec );

            GraalDisplayRectangle( NewRec );
          }
        }
      }
    }

    XtUnmanageChild( GraalModifySegmentPanel.PANEL );

    if ( ! GraalModifyAbort )

    for ( Select  = GraalHeadSelect;
          Select != (graalselect *)NULL;
          Select  = Select->NEXT )
    {
      Rectangle = Select->RECTANGLE;

      if ( IsRdsVia( Rectangle ) )
      {
        GraalAcceptRectangle( Rectangle );
        GraalDisplayRectangle( Rectangle );

        Pointer = GRAAL_MBK( Rectangle );

        GraalViaMType = ((phvia_list *)Pointer)->TYPE;

        GraalPromptModifyVia();
        GraalEnterPanel( &GraalModifyViaPanel );

        GraalModifyLock = GRAAL_TRUE;

        while ( GraalModifyLock )
        {
          GraalLimitedLoop( GraalModifyViaPanel.PANEL );
        }

        GraalRejectRectangle( Rectangle );
        GraalDisplayRectangle( Rectangle );

        if ( GraalModifyAbort ) break;

        if ( GraalModifyApply )
        {
          if ( ! GraalViaChanged( (phvia_list *)Pointer ) )

            continue;

          if ( FirstUndo )
          {
            GraalAddUndo();

            FirstUndo = 0;
          }
   
          GraalDeleteRectangle( Rectangle );
          GraalAddUndoRec( Rectangle );

          Element = (void *)

             addphvia( GraalFigureMbk,
                       GraalViaMType, 
                       ((phvia_list *)Pointer)->XVIA,
                       ((phvia_list *)Pointer)->YVIA );
 
          ((phvia_list *)Element)->USER = (void *)(&GraalFigureMbk->PHVIA);
 
          if ( ((phvia_list *)Element)->NEXT != (phvia_list *)NULL )
          {
            ((phvia_list *)Element)->NEXT->USER = (void *)(&((phvia_list *)Element)->NEXT);
          }
 
          NewRec = GraalAddVia( ((phvia_list *)Element) );
          GraalAddUndoRec( NewRec );

          GraalDisplayRectangle( NewRec );
        }
      }
    }

    XtUnmanageChild( GraalModifyViaPanel.PANEL );

    if ( ! GraalModifyAbort )

    for ( Select  = GraalHeadSelect;
          Select != (graalselect *)NULL;
          Select  = Select->NEXT )
    {
      Rectangle = Select->RECTANGLE;

      if ( IsRdsReference( Rectangle ) )
      {
        GraalAcceptRectangle( Rectangle );
        GraalDisplayRectangle( Rectangle );

        Pointer = GRAAL_MBK( Rectangle );

        GraalReferenceMName = ((phref_list *)Pointer)->NAME;
        GraalReferenceMType = 
 
           (strcmp( ((phref_list *)Pointer)->FIGNAME, "ref_ref" )) ?
            MBK_REF_CON : MBK_REF_REF;

        GraalSaveReferenceMType = GraalReferenceMType;

        GraalPromptModifyReference();
        GraalEnterPanel( &GraalModifyReferencePanel );

        GraalModifyLock = GRAAL_TRUE;

        while ( GraalModifyLock )
        {
          GraalLimitedLoop( GraalModifyReferencePanel.PANEL ); 
        }

        GraalRejectRectangle( Rectangle );
        GraalDisplayRectangle( Rectangle );

        if ( GraalModifyAbort ) break;

        if ( GraalModifyApply )
        {
          if ( ! GraalReferenceChanged( (phref_list *)Pointer ) )

           continue;

          if ( FirstUndo )
          {
            GraalAddUndo();

            FirstUndo = 0;
          }
   
          GraalDeleteRectangle( Rectangle );
          GraalAddUndoRec( Rectangle );

          Element = (void *)

             addphref( GraalFigureMbk,
                       (GraalReferenceMType == MBK_REF_REF) ? "ref_ref":"ref_con" ,
                       GraalReferenceMName,
                       ((phref_list *)Pointer)->XREF,
                       ((phref_list *)Pointer)->YREF );
 
          ((phref_list *)Element)->USER = (void *)(&GraalFigureMbk->PHREF);
 
          if ( ((phref_list *)Element)->NEXT != (phref_list *)NULL )
          {
            ((phref_list *)Element)->NEXT->USER = (void *)(&((phref_list *)Element)->NEXT);
          }
 
          NewRec = GraalAddReference( ((phref_list *)Element) );
          GraalAddUndoRec( NewRec );

          GraalDisplayRectangle( NewRec );
        }
      }
    }

    XtUnmanageChild( GraalModifyReferencePanel.PANEL );

    if ( ! GraalModifyAbort )

    for ( Select  = GraalHeadSelect;
          Select != (graalselect *)NULL;
          Select  = Select->NEXT )
    {
      Rectangle = Select->RECTANGLE;

      if ( IsRdsConnector( Rectangle ) )
      {
        GraalAcceptRectangle( Rectangle );
        GraalDisplayRectangle( Rectangle );
 
        Pointer = GRAAL_MBK( Rectangle );

        GraalConnectorMName   = ((phcon_list *)Pointer)->NAME;
        GraalConnectorMLayer  = ((phcon_list *)Pointer)->LAYER;
        GraalConnectorMWidth  = ((phcon_list *)Pointer)->WIDTH / SCALE_X;

        switch( ((phcon_list *)Pointer)->ORIENT )
        {
          case NORTH : GraalConnectorMOrient = GRAAL_NORTH; break;
          case SOUTH : GraalConnectorMOrient = GRAAL_SOUTH; break;
          case EAST  : GraalConnectorMOrient = GRAAL_EAST;  break;
          case WEST  : GraalConnectorMOrient = GRAAL_WEST;  break;
        }

        GraalSaveConnectorMOrient = GraalConnectorMOrient;

        GraalPromptModifyConnector();
        GraalEnterPanel( &GraalModifyConnectorPanel );

        GraalModifyLock = GRAAL_TRUE;

        while ( GraalModifyLock )
        {
          GraalLimitedLoop( GraalModifyConnectorPanel.PANEL );
        }

        GraalRejectRectangle( Rectangle );
        GraalDisplayRectangle( Rectangle );

        if ( GraalModifyAbort ) break;

        if ( GraalModifyApply )
        {
          if ( ! GraalConnectorChanged( (phcon_list *)Pointer ) )

            continue;

          Orient = 0;
 
          if ( ((phcon_list *)Pointer)->XCON == GraalFigureMbk->XAB1 ) Orient |= GRAAL_WEST_MASK;
          if ( ((phcon_list *)Pointer)->XCON == GraalFigureMbk->XAB2 ) Orient |= GRAAL_EAST_MASK;
          if ( ((phcon_list *)Pointer)->YCON == GraalFigureMbk->YAB1 ) Orient |= GRAAL_SOUTH_MASK;
          if ( ((phcon_list *)Pointer)->YCON == GraalFigureMbk->YAB2 ) Orient |= GRAAL_NORTH_MASK;

          switch ( GraalConnectorMOrient )
          {
            case GRAAL_NORTH :

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

                Orient = 0;
              }
              MbkOrient = NORTH;
              break;

            case GRAAL_SOUTH :

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

                Orient = 0;
              }
              MbkOrient = SOUTH;
              break;
 
            case GRAAL_EAST :
 
              if ( !( Orient & GRAAL_EAST_MASK ) )
              {
                GraalErrorMessage( GraalMainWindow,
                "This connector can't have EAST orient !" );
 
                Orient = 0;
              }
              MbkOrient = EAST;
              break;
 
           case GRAAL_WEST :
 
             if ( !( Orient & GRAAL_WEST_MASK ) )
             {
               GraalErrorMessage( GraalMainWindow,
               "This connector can't have WEST orient !" );
 
               Orient = 0;
             }
             MbkOrient = WEST;
             break;
          }

          if ( Orient != 0 )
          {
            if ( FirstUndo )
            {
              GraalAddUndo();

              FirstUndo = 0;
            }
   
            GraalDeleteRectangle( Rectangle );
            GraalAddUndoRec( Rectangle );

            Element = (void *)

             addphcon( GraalFigureMbk, MbkOrient,
                       GraalConnectorMName,
                       ((phcon_list *)Pointer)->XCON,
                       ((phcon_list *)Pointer)->YCON,
                       GraalConnectorMLayer,
                       GraalConnectorMWidth * SCALE_X );
 
            ((phcon_list *)Element)->USER = (void *)(&GraalFigureMbk->PHCON);
 
            if ( ((phcon_list *)Element)->NEXT != (phcon_list *)NULL )
            {
              ((phcon_list *)Element)->NEXT->USER = (void *)(&((phcon_list *)Element)->NEXT);
            }
 
            NewRec = GraalAddConnector( ((phcon_list *)Element) );
            GraalAddUndoRec( NewRec );

            GraalDisplayRectangle( NewRec );
          }
        }
      }
    }

    XtUnmanageChild( GraalModifyConnectorPanel.PANEL );

    if ( ! GraalModifyAbort )

    for ( Select  = GraalHeadSelect;
          Select != (graalselect *)NULL;
          Select  = Select->NEXT )
    {
      Rectangle = Select->RECTANGLE;

      if ( IsRdsInstance( Rectangle ) )
      {
        GraalAcceptRectangle( Rectangle );
        GraalDisplayRectangle( Rectangle );
 
        Pointer = GRAAL_MBK( Rectangle );

        GraalInstanceMName  = ((phins_list *)Pointer)->INSNAME;
        GraalInstanceMModel = ((phins_list *)Pointer)->FIGNAME;
        GraalInstanceMSym   = ((phins_list *)Pointer)->TRANSF;

        GraalPromptModifyInstance();
        GraalEnterPanel( &GraalModifyInstancePanel );

        GraalModifyLock = GRAAL_TRUE;

        while ( GraalModifyLock )
        {
          GraalLimitedLoop( GraalModifyInstancePanel.PANEL );
        }

        GraalRejectRectangle( Rectangle );
        GraalDisplayRectangle( Rectangle );

        if ( GraalModifyAbort ) break;

        if ( GraalModifyApply )
        {
          if ( ! GraalInstanceChanged( (phins_list *)Pointer ) )

            continue;

          GraalDeleteRectangle( Rectangle );

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

          if ( Instance == (rdsins_list *)NULL )
          {
            if ( FirstUndo )
            {
              GraalAddUndo();

              FirstUndo = 0;
            }
   
            GraalAddUndoRec( Rectangle );

            SaveInstance          = GraalFigureMbk->PHINS;
            GraalFigureMbk->PHINS = (phins_list *)NULL;
 
            Element = (void *)
 
              addphins( GraalFigureMbk,
                        GraalInstanceMModel,
                        GraalInstanceMName,
                        GraalInstanceMSym,
                        ((phins_list *)Pointer)->XINS,
                        ((phins_list *)Pointer)->YINS );
 
            ((phins_list *)Element)->NEXT = SaveInstance;
            ((phins_list *)Element)->USER = (void *)(&GraalFigureMbk->PHINS);
      
            if ( SaveInstance != (phins_list *)NULL )
            {
              SaveInstance->USER = (void *)(&((phins_list *)Element)->NEXT);
            }
 
            Instance = GraalAddInstance( ((phins_list *)Element) );

            GraalDisplayToolsMessage();

            if ( Instance == (rdsins_list *)NULL )
            {
              GraalFigureMbk->PHINS = SaveInstance;
              mbkfree( Element );

              GraalErrorMessage( GraalMainWindow, "Unable to load instance model !" );
            }
            else
            {   
              NewRec = Instance->LAYERTAB[ RDS_ABOX ];

              GraalAddUndoRec( NewRec );
            }

            GraalZoomRefresh();
          }
          else
          {
            GraalUndeleteRectangle( Rectangle );
          }
        }
      }  
    } 

    XtUnmanageChild( GraalModifyInstancePanel.PANEL );

    GraalDelEqui();
    GraalDelPeek();
    GraalDelSelect();
    GraalZoomRefresh();
  }
