/*------------------------------------------------------------\
|                                                             |
| This file is part of the Alliance CAD System Copyright      |
| (C) Laboratoire LIP6 - Département ASIM Universite P&M Curie|
|                                                             |
| Home page      : http://www-asim.lip6.fr/alliance/          |
| E-mail         : mailto:alliance-users@asim.lip6.fr       |
|                                                             |
| This progam is  free software; you can redistribute it      |
| and/or modify it under the  terms of the GNU General Public |
| License as  published by the Free Software Foundation;      |
| either version 2 of the License, or (at your option) any    |
| later version.                                              |
|                                                             |
| Alliance VLSI  CAD System  is distributed  in the hope that |
| it  will be useful, but WITHOUT  ANY WARRANTY;              |
| without even the  implied warranty of MERCHANTABILITY or    |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General       |
| Public License for more details.                            |
|                                                             |
| You should have received a copy  of the GNU General Public  |
| License along with the GNU C Library; see the file COPYING. |
| If not, write to the Free Software Foundation, Inc.,        |
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.                     |
|                                                             |
\------------------------------------------------------------*/

/* Construction du reseau RC correspondant aux rectangles de 
   la figure */


# include "mut.h"
# include "rds.h"
# include "mlo.h"
# include "rcn.h"
# include "mph.h"
# include "rpr.h"
# include "Windows95.h"
# include "znc.h"
# include "buildrcn.h"
# include "lynxrcn.h"
# include "extract.h"
# include "mbkrds.h"
# include "inter.h"
# include "via.h"

/* A mettre en commentaire pour ne pas avoir de message de debuggage */
/*
# define BUILDRCNDEBUG
*/

/*
#define BUILDRCNCTL
*/

int RectangleValide __P((rdsrec_list*));
int RectangleDiff __P((rdsrec_list*));
void traiteinterparra __P((rdsrec_list*, chain_list*, WinZnc*));
void traiteinterperpen __P((rdsrec_list*, chain_list*, WinZnc*));
void addzncvia __P((chain_list*,WinZnc*,GrgWindow*,losig_list*));
void znc2rcn __P((WinZnc*, losig_list*));
chain_list* sortchain __P((chain_list*, char));
void sortloconnode __P((chain_list*, WinZnc*));
void sortbullelocon __P((locon_list*, chain_list*));
int isviacontact( int );
void affrec( rdsrec_list* );

#define min(a,b) ((a>b)?b:a)
#define max(a,b) ((a>b)?a:b)

/******************************************************************************/



void buildrcn(fig,scansignal)
lofig_list	*fig;
losig_list	*scansignal;
{
  GrgWindow	*WindowsInfo;
  rdsrec_list	*scanrec,*irec;
  int		 EndEqui;
  WinZnc	*zncwininfo;
  chain_list	*inter_list,*parra,*perpen,*scanchain;
  ptype_list	*ptlvia;
  chain_list	*connect;
  long		 layer;
  chain_list    *scanchrec;

#ifdef BUILDRCNCTL
fprintf(stderr,"Traitement du signal %ld [%s]\n",
               scansignal->INDEX,
               getsigname(scansignal)?getsigname(scansignal):"no name");
#endif

#ifdef BUILDRCNDEBUG
fprintf(stderr,"Traitement du signal %ld [%s]\n",
               scansignal->INDEX,
               getsigname(scansignal)?getsigname(scansignal):"no name");
#endif

#ifdef BUILDRCNDEBUG
fprintf(stderr,"Construction des fenetrages\n");
#endif
#ifdef BUILDRCNCTL
fprintf(stderr,"Construction du fenetrage...                                 ");
#endif

  WindowsInfo=GrgCreatWindows(scansignal);

  zncwininfo=creatwinznc( WindowsInfo->mx,
                          WindowsInfo->my,
                          WindowsInfo->Mx,
                          WindowsInfo->My,
                          WindowsInfo->Px,
                          WindowsInfo->Py,
                          WindowsInfo->nx,
                          WindowsInfo->ny  );

  connect=NULL;
  for( scanchrec = (chain_list*)(getptype(scansignal->USER,RCN_FEQUI)->DATA) ;
       scanchrec ;
       scanchrec = scanchrec->NEXT
     )
  {
    scanrec=(rdsrec_list*)(scanchrec->DATA);

    EndEqui=0;
  
  
  #ifdef BUILDRCNCTL
  fprintf(stderr,"\rTraitement de l'equipotentielle...                         ");
  #endif
  
    while(!EndEqui)
    {
      if(RectangleValide(scanrec))
      {
  #ifdef BUILDRCNDEBUG
  fprintf(stderr,"\n\n******** Rectangle traité :\n");
  dbg_affrec(scanrec);
  #endif
        inter_list=GrgGetInterWindows(scanrec,WindowsInfo);
        parra=NULL;
        perpen=NULL;
  
        for(scanchain=inter_list;scanchain;scanchain=scanchain->NEXT)
        {
          irec=(rdsrec_list*)(scanchain->DATA);
  
          if(RectangleValide(irec))
          {
            if(Intersect(scanrec,irec)==PERPEN)
              perpen=addchain(perpen,scanchain->DATA);
            else
              parra=addchain(parra,scanchain->DATA);
          }
        }
  
        /* Traite les extremités du rectangle */
  
        if(GETDIRECTION(scanrec)==HORIZ_DIR) /* horizontal */
        {
          addznc(scanrec->X,scanrec->Y,scanrec->X,scanrec->Y+scanrec->DY,
                 GetRdsLayer(scanrec),zncwininfo);
          addznc(scanrec->X+scanrec->DX,scanrec->Y,
                 scanrec->X+scanrec->DX,scanrec->Y+scanrec->DY,
                 GetRdsLayer(scanrec),zncwininfo);
        }
        else
        {
          addznc(scanrec->X,scanrec->Y,scanrec->X+scanrec->DX,scanrec->Y,
                 GetRdsLayer(scanrec),zncwininfo);
          addznc(scanrec->X,scanrec->Y+scanrec->DY,
                 scanrec->X+scanrec->DX,scanrec->Y+scanrec->DY,
                 GetRdsLayer(scanrec),zncwininfo);
        }
  
        /* Traite les rectangles en intersection perpendiculaire */
  
        traiteinterperpen(scanrec,perpen,zncwininfo);
  
        /* Traite les rectangles en intersection parralelles */
  
        traiteinterparra(scanrec,parra,zncwininfo);
  
  
        if(perpen) freechain(perpen);
        if(parra) freechain(parra);
        if(inter_list) freechain(inter_list);
      }
      /* On ajoute les CxP et les CxN qui servent dans les transistors
         coud\'es. Ils sont fait en GATE, que l'on traite pour l'extraction
         comme du POLY. Ces morceaux seront toujours isoles a ce stade,
         on a juste qu'a ajouter une ZNC le representant */
  
      if(    IsRdsVia(scanrec) &&
           ( GetLynxAttribute(scanrec) == C_X_N ||
             GetLynxAttribute(scanrec) == C_X_P    )
        ) 
        addznc(scanrec->X,scanrec->Y,
               scanrec->X+scanrec->DX,scanrec->Y+scanrec->DY,
               RDS_POLY,zncwininfo);
  
      if(getptype(scanrec->USER,RDSLOCON))
      {
        connect=addchain(connect,scanrec);
      }
      else /* plus clean : on traite les connecteurs plus loin */
        if(RectangleDiff(scanrec))
        {
          addznc(scanrec->X,scanrec->Y,
                 scanrec->X+scanrec->DX,scanrec->Y+scanrec->DY,
                 GetRdsLayer(scanrec),zncwininfo);
        }
  
      if(IsLynxEndEqui(scanrec))
        EndEqui=1;
      else
        scanrec=LYNX_EQUI(scanrec);
    }
  }

  /* Ajoute les vias dans les znc */
  if( (ptlvia=getptype(scansignal->USER,GRGVIA)) )
    addzncvia((chain_list*)(ptlvia->DATA),zncwininfo,WindowsInfo,scansignal);


#ifdef BUILDRCNDEBUG
fprintf(stderr,"ZNC apres le traitement des vias\n");
dbg_affznc(zncwininfo);
#endif

  /* Traitement des connecteurs */

  for(scanchain=connect;scanchain;scanchain=scanchain->NEXT)
  {

    scanrec=(rdsrec_list*)(scanchain->DATA);
    layer=GetRdsLayer(scanrec);

    if(layer==RDS_GATE)
    {
      addznc(scanrec->X,scanrec->Y,scanrec->X+scanrec->DX,
             scanrec->Y+scanrec->DY,RDS_POLY,zncwininfo);
    }
    else
    { 
      addznc(scanrec->X,scanrec->Y,scanrec->X+scanrec->DX,
             scanrec->Y+scanrec->DY,layer,zncwininfo);
    }
  }

#ifdef BUILDRCNDEBUG
fprintf(stderr,"ZNC apres le traitement des connecteurs\n");
dbg_affznc(zncwininfo);
#endif


#ifdef BUILDRCNCTL
fprintf(stderr,"\rCreation des lonodes...                                    ");
#endif

  makezncnode(zncwininfo,scansignal);

#ifdef BUILDRCNCTL
fprintf(stderr,"\rConstruction de la table...                                ");
#endif

  buildtable(scansignal);

#ifdef BUILDRCNCTL
fprintf(stderr,"\rConstruction des Wires...                                  ");
#endif

  znc2rcn(zncwininfo,scansignal);

#ifdef BUILDRCNCTL
fprintf(stderr,"\rAjout des lonodes dans les locons...                       ");
#endif

  linklonodelocon( connect, scansignal, zncwininfo, WindowsInfo );

#ifdef BUILDRCNCTL
fprintf(stderr,"\rLiberation de la table...                                  ");
#endif


  freetable(scansignal);


#ifdef BUILDRCNCTL
fprintf(stderr,"\rTrie des connecteurs d'instance...                         ");
#endif

  sortloconnode(connect,zncwininfo);

  if(connect)
    freechain(connect);



#ifdef BUILDRCNDEBUG
fprintf(stderr,"Liberation du fenetrage\n");
#endif

#ifdef BUILDRCNCTL
fprintf(stderr,"\rLiberation des fenetrages...                               ");
#endif


  GrgClearWindows(WindowsInfo,scansignal);
  freewinznc(zncwininfo);

#ifdef BUILDRCNCTL
fprintf(stderr,"\rOk.                                                      \n");
#endif



#ifdef BUILDRCNDEBUG
fprintf(stderr,"fin du traitement des rectangles du signal %ld\n\n\n",
               scansignal->INDEX);
#endif
}

int IsRcn( R )
rdsrec_list	*R;
{
  /* Layers pour lesquels les interconnexions sont extraites */
  if(    GetRdsLayer(R)==RDS_ALU1
      || GetRdsLayer(R)==RDS_ALU2
      || GetRdsLayer(R)==RDS_ALU3
      || GetRdsLayer(R)==RDS_ALU4
      || GetRdsLayer(R)==RDS_ALU5
      || GetRdsLayer(R)==RDS_ALU6
      || GetRdsLayer(R)==RDS_POLY )
    return( 1 );
  return(0);
}

int isviacontact( int layer )
{
  /* On ne peut prendre un ieme element de la table des vias car les elements
   * C_X_N et C_X_P posent des problèmes */

  if( layer == RDS_CONT ||
      layer == RDS_VIA1 ||
      layer == RDS_VIA2 ||
      layer == RDS_VIA3 ||
      layer == RDS_VIA4 ||
      layer == RDS_VIA5
    )
    return(1);
  return(0);
}

int RectangleValide(R)
rdsrec_list	*R;
{
  if(    !IsRdsVia(R)
      && !IsRdsConnector(R)
      &&  IsRcn( R )
    )
  {
    return(1);
  }
  return(0);
}

int RectangleDiff(R)
rdsrec_list	*R;
{
  /* Layer dont on extrait pas les resistances mais qu'on considere pour
   * recuperer les locon correspondants */
  if( GetRdsLayer(R)==RDS_PDIF || 
      GetRdsLayer(R)==RDS_NDIF   )
    return(1);
  return(0);
}

void traiteinterperpen(scanrec,perpen,zncwininfo)
rdsrec_list	*scanrec;
chain_list	*perpen;
WinZnc		*zncwininfo;
{
  chain_list	*scanchain;
  rdsrec_list	*irec;
  
  for(scanchain=perpen;scanchain;scanchain=scanchain->NEXT)
  {
    irec=(rdsrec_list*)(scanchain->DATA);

    if(RectangleValide(irec))
    {
#ifdef BUILDRCNDEBUG
fprintf(stderr,"Intersection perpendiculaire : \n");
dbg_affrec(irec);
#endif

      if(GETDIRECTION(scanrec)==HORIZ_DIR) /* horizontal */
        addznc(irec->X,scanrec->Y,irec->X+irec->DX,scanrec->Y+scanrec->DY,
             GetRdsLayer(scanrec),zncwininfo);
      else /* vertical */
        addznc(scanrec->X,irec->Y,scanrec->X+scanrec->DX,irec->Y+irec->DY,
             GetRdsLayer(scanrec),zncwininfo);
    }          
  }
}

void traiteinterparra(scanrec,parra,zncwininfo)
rdsrec_list	*scanrec;
chain_list	*parra;
WinZnc		*zncwininfo;
{
  chain_list	*scanchain,*scanchain2;
  rdsrec_list	*irec,*irec2;
  long		 mx,my,Mx,My;

  for(scanchain=parra;scanchain;scanchain=scanchain->NEXT)
  {
    irec=(rdsrec_list*)(scanchain->DATA);

    if(GETDIRECTION(scanrec)==HORIZ_DIR)
    {
      if(irec->X>=scanrec->X)
      {
        my=min(irec->Y,scanrec->Y);
        My=max(irec->Y+irec->DY,scanrec->Y+scanrec->DY);
        for(scanchain2=parra;scanchain2;scanchain2=scanchain2->NEXT)
        {
          irec2=(rdsrec_list*)(scanchain2->DATA);
          if(irec2->X<=irec->X && irec2->X+irec2->DX>=irec->X)
          {
            my=min(my,irec2->Y);
            My=max(My,irec2->Y+irec2->DY);
          }
        }
        addznc(irec->X,my,irec->X,My,GetRdsLayer(scanrec),zncwininfo);
      }

      if(irec->X+irec->DX<=scanrec->X+scanrec->DX)
      {
        my=min(irec->Y,scanrec->Y);
        My=max(irec->Y+irec->DY,scanrec->Y+scanrec->DY);
        for(scanchain2=parra;scanchain2;scanchain2=scanchain2->NEXT)
        {
          irec2=(rdsrec_list*)(scanchain2->DATA);
          if( irec2->X<=irec->X+irec->DX &&
              irec2->X+irec2->DX>=irec->X+irec->DX )
          {
            my=min(my,irec2->Y);
            My=max(My,irec2->Y+irec2->DY);
          }
        }
        addznc(irec->X+irec->DX,my,irec->X+irec->DX,My,
               GetRdsLayer(scanrec),zncwininfo);
      }
    }
    else
    {
      if(irec->Y>=scanrec->Y)
      {
        mx=min(irec->X,scanrec->X);
        Mx=max(irec->X+irec->DX,scanrec->X+scanrec->DX);
        for(scanchain2=parra;scanchain2;scanchain2=scanchain2->NEXT)
        {
          irec2=(rdsrec_list*)(scanchain2->DATA);
          if(irec2->Y<=irec->Y && irec2->Y+irec2->DY>=irec->Y)
          {
            mx=min(mx,irec2->X);
            Mx=max(Mx,irec2->X+irec2->DX);
          }
        }
        addznc(mx,irec->Y,Mx,irec->Y,GetRdsLayer(scanrec),zncwininfo);
      }

      if(irec->Y+irec->DY<=scanrec->Y+scanrec->DY)
      {
        mx=min(irec->X,scanrec->X);
        Mx=max(irec->X+irec->DX,scanrec->X+scanrec->DX);
        for(scanchain2=parra;scanchain2;scanchain2=scanchain2->NEXT)
        {
          irec2=(rdsrec_list*)(scanchain2->DATA);
          if( irec2->Y<=irec->Y+irec->DY &&
              irec2->Y+irec2->DY>=irec->Y+irec->DY )
          {
            mx=min(mx,irec2->X);
            Mx=max(Mx,irec2->X+irec2->DX);
          }
        }
        addznc(mx,irec->Y+irec->DY,Mx,irec->Y+irec->DY,
               GetRdsLayer(scanrec),zncwininfo);
      }
    }
  }
}

void addzncvia(headvia,winznc,winrec, ptsig )
chain_list	*headvia;
WinZnc		*winznc;
GrgWindow	*winrec;
losig_list      *ptsig;
{
  chain_list	*intervia;
  chain_list	*scaninter;
  long		 mx=0,my=0,Mx=0,My=0,layer=0;
  rdsrec_list	*rec;
  rdsrec_list	*scanrec;
  chain_list	*scanvia;
  ptype_list    *ptl;

#ifdef BUILDRCNDEBUG
fprintf(stderr,"Traitement des vias\n");
#endif

  for(scanvia=headvia;scanvia;scanvia=scanvia->NEXT)
  {
    intervia=NULL;
    rec = (rdsrec_list*)(scanvia->DATA);
    do
    {
      ptl = getptype( rec->USER, RCN_SIG_PTR );
      if( !ptl )
      {
        rec = LYNX_LINK( rec );
        continue;
      }
      
      if( ptl->DATA == ptsig )
      {
        layer = GetRdsLayer( rec );
        if( !isviacontact( layer ) &&
            ( IsRcn( rec ) || RectangleDiff( rec ) )
          )
        {

          mx       = rec->X;
          my       = rec->Y;
          Mx       = rec->X+rec->DX;
          My       = rec->Y+rec->DY;
          intervia = GrgGetInterWindows(rec,winrec);

          if(intervia)
          {
            for(scaninter=intervia;scaninter;scaninter=scaninter->NEXT)
            {
              scanrec=(rdsrec_list*)(scaninter->DATA);
              /*
              if(IsRcn(scanrec) || RectangleDiff( rec ) )
              */
              {
                if(GETDIRECTION(scanrec)==HORIZ_DIR)
                {
                  my=min(my,scanrec->Y);
                  My=max(My,scanrec->Y+scanrec->DY);
                }
                else
                {
                  mx=min(mx,scanrec->X);
                  Mx=max(Mx,scanrec->X+scanrec->DX);
                }
              }
            }
            addznc(mx,my,Mx,My,layer,winznc);
            freechain(intervia);
          }
          else
            addznc(mx,my,Mx,My,layer,winznc);
        }
      }
      rec = LYNX_LINK( rec );
    }
    while( rec != scanvia->DATA );
  }
}

void znc2rcn(win,sig)
WinZnc		*win;
losig_list	*sig;
{
  rdsrec_list	*scanrec,*r;
  short		 EndEqui;
  znc		 elem,*noeud1,*noeud2=NULL;
  chain_list	*interznc,*scaninter;
  chain_list	*scanchain,*scanchain1,*scanchain2;
  long		 n1=0,n2=0;
  long		 N1,N2;
  long		 rcntype;
  float		 rcnresi=0.0,rcncapa;
  long		 x,y,dx,dy,mx1,my1,mx2,my2;
  ptype_list	*ptl;
  lowire_list	*w;
  chain_list    *scanchrec;
  chain_list    *scanvia;
  int            layer;
  rdsrec_list   *rec;
  ptype_list    *ptl2;

#ifdef BUILDRCNDEBUG
  fprintf(stderr,"\n\nConstruction des wires \n\n");
#endif

/* On place dans les intersections les rectangles qui les composent */

  for( scanchrec = (chain_list*)(getptype(sig->USER,RCN_FEQUI)->DATA) ;
       scanchrec ;
       scanchrec = scanchrec->NEXT
     )
  {
    scanrec=(rdsrec_list*)(scanchrec->DATA);

    EndEqui=0;
    while(!EndEqui)
    {
      if(RectangleValide(scanrec))
      {
        elem.x1=scanrec->X;
        elem.y1=scanrec->Y;
        elem.x2=scanrec->X+scanrec->DX;
        elem.y2=scanrec->Y+scanrec->DY;
        elem.layer=GetRdsLayer(scanrec);
        elem.NEXT=NULL;
  
        interznc=getwininterznc(&elem,win,1);
        for(scaninter=interznc;scaninter;scaninter=scaninter->NEXT)
        {
          noeud1=(znc*)(scaninter->DATA);
          for(scanchain=noeud1->rec;scanchain;scanchain=scanchain->NEXT)
            if(scanchain->DATA==scanrec)
              break;
          if(!scanchain)
            noeud1->rec=addchain(noeud1->rec,scanrec);
        }
      }
  
      if(IsLynxEndEqui(scanrec))
        EndEqui=1;
      else
        scanrec=LYNX_EQUI(scanrec);
    }
  }
  
  for( scanchrec = (chain_list*)(getptype(sig->USER,RCN_FEQUI)->DATA) ;
       scanchrec ;
       scanchrec = scanchrec->NEXT
     )
  {
    scanrec=(rdsrec_list*)(scanchrec->DATA);

    EndEqui=0;

    while(!EndEqui)
    {
      if(RectangleValide(scanrec))
      {
        elem.x1=scanrec->X;
        elem.y1=scanrec->Y;
        elem.x2=scanrec->X+scanrec->DX;
        elem.y2=scanrec->Y+scanrec->DY;
        elem.layer=GetRdsLayer(scanrec);
        elem.NEXT=NULL;
  
        interznc=getwininterznc(&elem,win,1);
  
  
        if(interznc)
        {
  #ifdef   BUILDRCNDEBUG
  fprintf(stderr,"Traite   le rectangle (%ld,%ld)-(%ld,%ld)\n",
            scanrec->X,scanrec->Y,scanrec->X+scanrec->DX,scanrec->Y+scanrec->DY);
  #endif
  
          if(GETDIRECTION(scanrec)==HORIZ_DIR)
            interznc=sortchain(interznc,'X');
          else
            interznc=sortchain(interznc,'Y');
  
          n1=0l;
          n2=0l;
  
          for(scaninter=interznc;scaninter;scaninter=scaninter->NEXT)
          {
            noeud1=(znc*)(scaninter->DATA);
            n1=noeud1->node;
      
            if(n1 && n2 && getlowire(sig,n1,n2)==NULL)
            {
              /* Place les rectangles communs au noeud1 et au noeud2 dans une
                 chain_list */
  
              mx1=scanrec->X;
              mx2=mx1+scanrec->DX;
              my1=scanrec->Y;
              my2=my1+scanrec->DY;
              for(scanchain1=noeud1->rec;scanchain1;scanchain1=scanchain1->NEXT)
              {
                for(scanchain2=noeud2->rec;scanchain2;scanchain2=scanchain2->NEXT)
                  if(scanchain1->DATA==scanchain2->DATA)
                  {
                    r=(rdsrec_list*)(scanchain1->DATA);
                    mx1=min(mx1,r->X);
                    mx2=max(mx2,r->X+r->DX);
                    my1=min(my1,r->Y);
                    my2=max(my2,r->Y+r->DY);
                  }
              }
  
              if(GETDIRECTION(scanrec)==HORIZ_DIR)
              {
                x=(noeud2->x2-noeud2->x1)/2 + noeud2->x1;
                dx=(noeud1->x2-noeud1->x1)/2 + noeud1->x1 - x;
                y=scanrec->Y+ scanrec->DY/2;
                dy=my2-my1;
                rcnresi=dx/dy*GET_LYNX_RESISTOR_LAYER(GetRdsLayer(scanrec));
                rcncapa=2*dx*GET_LYNX_PERIMETER_CAPA_LAYER(GetRdsLayer(scanrec))+
                        dx*dy*GET_LYNX_SURFACE_CAPA_LAYER(GetRdsLayer(scanrec));
              }
              else
              {
                x=scanrec->X+scanrec->DX/2;
                dx=mx2-mx1;
                y=(noeud2->y2-noeud2->y1)/2 + noeud2->y1;
                dy=(noeud1->y2-noeud1->y1)/2 + noeud1->y1 -y;
     
                rcnresi=dy/dx*GET_LYNX_RESISTOR_LAYER(GetRdsLayer(scanrec));
                rcncapa=2*dy*GET_LYNX_PERIMETER_CAPA_LAYER(GetRdsLayer(scanrec))+
                        dx*dy*GET_LYNX_SURFACE_CAPA_LAYER(GetRdsLayer(scanrec));
              }
  
              rcntype=RCN_WIRE_UNKNOW;
  
              if( GetRdsLayer(scanrec)==RDS_ALU1 ) rcntype=RCN_WIRE_ALU1;
              if( GetRdsLayer(scanrec)==RDS_ALU2 ) rcntype=RCN_WIRE_ALU2;
              if( GetRdsLayer(scanrec)==RDS_POLY ) rcntype=RCN_WIRE_POLY;
  
            
  #ifdef   BUILDRCNDEBUG
  fprintf(stderr,"Ajout   d'un wire en (%ld,%ld) de dimensions (%ld,%ld)\n",
                   x,y,dx,dy);
  #endif
  
              if(dx>dy)
              {
                if( noeud1->x1 < noeud2->x1 )
                {
                  N1=n1;
                  N2=n2;
                }
                else
                {
                  N1=n2;
                  N2=n1;
                }
              }
              else
              {
                if(noeud1->y1 < noeud2->y1)
                {
                  N1=n1;
                  N2=n2;
                }
                else
                {
                  N1=n2;
                  N2=n1;
                }
              } 
              addlowire( sig, rcntype, 0, rcnresi, rcncapa, x, y, dx, dy, N1, N2);
            }
            n2=n1;
            noeud2=noeud1;
          }
  
          freechain(interznc);
        }
      }
  
      if(IsLynxEndEqui(scanrec))
        EndEqui=1;
      else
        scanrec=LYNX_EQUI(scanrec);
    }
  }

  /* On s'occupe maintenant des vias */
  if( (ptl=getptype(sig->USER,GRGVIA)) )
  {
    for(scanvia=(chain_list*)(ptl->DATA);scanvia;scanvia=scanvia->NEXT)
    {
      layer=-1;
      rec = (rdsrec_list*)(scanvia->DATA);
      n1 = 0;
      n2 = 0;
      do
      {
        ptl2 = getptype( rec->USER, RCN_SIG_PTR );
        if( !ptl2 )
        {
          rec = LYNX_LINK( rec );
          continue;
        }
        if( ptl2->DATA == sig )
        {
          layer = GetRdsLayer( rec );
          if( !isviacontact( layer )                     && 
              ( IsRcn( rec ) || RectangleDiff( rec ) )
            )
          {
            
            elem.x1    = rec->X ;
            elem.y1    = rec->Y ;
            elem.x2    = rec->DX + elem.x1 ;
            elem.y2    = rec->DY + elem.y1 ;
            elem.layer = layer ;
            scanchain1 = getwininterznc( &elem, win, 1 ) ;
            if( n1 == 0 )
              n1=((znc*)(scanchain1->DATA))->node;
            else
              n2=((znc*)(scanchain1->DATA))->node;
            freechain(scanchain1);
          }
          else
          {
            if( isviacontact( layer ) )
              rcnresi=GET_LYNX_RESISTOR_LAYER(layer);
          }
        }
        rec = LYNX_LINK( rec );
      }
      while( rec != scanvia->DATA );

      if( n1>0 && n2>0 )
      {
        if((w=getlowire(sig,n1,n2))==NULL)
        {
          addlowire(sig,RCN_WIRE_CONT_VIA,0,rcnresi,0.0,
                    (elem.x2-elem.x1)/2+elem.x1,
                    (elem.y2-elem.y1)/2+elem.y1,0,0,n1,n2);
        }
        else
        {
          addpararesiwire(w,rcnresi);
        }
      }
    }
  }
}

chain_list* sortchain(entree,champ)
chain_list	*entree;
char		 champ;
{
  chain_list	*scanchain,*sortie,*last,*prevmax,*eff;
  znc		*maxi,*z;

  /* tri a bulle de la liste des znc */

  /* On veut faire un tri par ordre croissant en utilisant la fonction
     chain_list qui ajoute les elements a l'envers : on va donc faire
     un tri par ordre decroissant */

  if(!entree)
  {
    fprintf(stderr,"Trie de chaine (null). \n");
    exit(-1);
  }

  if(entree->NEXT==NULL)
    return(entree);

  sortie=NULL;

  while(entree)
  {
    /* il faut debuter avec qqchose */
    maxi=(znc*)entree->DATA;

    /* recherche de l'element le plus grand dans la liste */
    last=NULL;
    prevmax=NULL;

    for(scanchain=entree;scanchain;scanchain=scanchain->NEXT)
    {
      z=(znc*)(scanchain->DATA);
 
      if( ( champ=='X' && z->x1 > maxi->x1 ) ||
          ( champ=='Y' && z->y1 > maxi->y1 )    )
      { 
        maxi = z;
        prevmax=last;
      }
      last=scanchain;
    }

    /* maitenant qu'on l'a trouve, on le met dans la chainlist de sortie */
    sortie=addchain(sortie,maxi);

    /* efface l'element de la liste chainee d'entree */
    if(prevmax)
    {
      eff=prevmax->NEXT;
      prevmax->NEXT=prevmax->NEXT->NEXT;
    }
    else
    {
      eff=entree;
      entree=entree->NEXT;
    }
    if(!eff)
    {
      fprintf(stderr,"eff=null\n");  
      exit(-1);
    }
    eff->NEXT=NULL;
    freechain(eff);
  }

#ifdef BUILDRCNDEBUG
{
  chain_list	*scan;
  for(scan=sortie;scan;scan=scan->NEXT)
    fprintf(stderr,"znc : (%ld,%ld)-(%ld,%ld) [%ld] lonode :%ld\n",
      ((znc*)(scan->DATA))->x1,
      ((znc*)(scan->DATA))->y1,
      ((znc*)(scan->DATA))->x2,
      ((znc*)(scan->DATA))->y2,
      ((znc*)(scan->DATA))->layer,
      ((znc*)(scan->DATA))->node);
}
#endif
  return(sortie);
}

void sortloconnode(connect,winznc)
chain_list	*connect;
WinZnc		*winznc;
{

  chain_list	*scanchain;
  rdsrec_list	*rec;
  ptype_list	*ptl;
  locon_list	*logical_connector;

  struct ssort
  {
    struct ssort	*NEXT;
    locon_list		*connector;
    chain_list		*conlofig;
  } *sort,*scansort;


  /* Recupere la liste des connecteurs de la figure */
  sort=NULL;
  for(scanchain=connect;scanchain;scanchain=scanchain->NEXT)
  {
    rec=(rdsrec_list*)(scanchain->DATA);
    if( (ptl=getptype(rec->USER,RDSLOCON)) )
    {
      logical_connector=(locon_list*)(ptl->DATA);
      if( !logical_connector )
        continue; /* cas des connecteurs superposes */
      
      if(logical_connector->TYPE=='I' ||
         logical_connector->TYPE=='E'    )
      {

        for(scansort=sort;scansort;scansort=scansort->NEXT)
        {
          if(scansort->connector == logical_connector)
            break;
        }

        if(scansort)
        {
          scansort->conlofig=addchain(scansort->conlofig,rec);
        }
        else
        {
          scansort=mbkalloc(sizeof(struct ssort));
          scansort->NEXT=sort;
          scansort->connector=logical_connector;
          scansort->conlofig=addchain(NULL,rec);

          sort=scansort;
        }
      }
    }
  }

  for(scansort=sort;scansort;scansort=scansort->NEXT)
  {
    if(! scansort->conlofig) 
    {
      fprintf(stderr,"Connecteur-> %s\n",scansort->connector->NAME);
      exit(1);
    }
    sortbullelocon(scansort->connector,scansort->conlofig);
  }
}

void sortbullelocon(logical_connector,conlofig)
locon_list	*logical_connector;
chain_list	*conlofig;
{
  chain_list	*scanchain,*trie;
  rdsrec_list	*rec,*maxi;
  chain_list	*prevmax,*last;
  chain_list	*eff;
  ptype_list	*ptl;
  num_list	*node;

  /* Dans la chain_list conlofig on a la liste des rectangles connecteurs 
     de la figure */

  /* on effectue un trie a bulle sur le champ Y */  

  if(conlofig->NEXT!=NULL)
  {
    trie=NULL;
    while(conlofig)
    {
      maxi=(rdsrec_list*)conlofig->DATA;
      last=NULL;
      prevmax=NULL;

      for(scanchain=conlofig;scanchain;scanchain=scanchain->NEXT)
      {
        rec=(rdsrec_list*)(scanchain->DATA);
        if( rec->Y < maxi->Y )
        {
          maxi=rec;
          prevmax=last;
        }
        else
        {
          if(rec->Y == maxi->Y)
            if(rec->X < maxi->X)
            {
              maxi=rec;
              prevmax=last;
            }
        }
        
        last=scanchain;
      }

      trie=addchain(trie,maxi);

      if(prevmax)
      {
        eff=prevmax->NEXT;
        prevmax->NEXT=prevmax->NEXT->NEXT;
      }
      else
      {
        eff=conlofig;
        conlofig=conlofig->NEXT;
      }
      eff->NEXT=NULL;
      freechain(eff);
    }
  }
  else
    trie=conlofig;

  node=NULL;
  for(scanchain=trie;scanchain;scanchain=scanchain->NEXT)
  {
    rec=((rdsrec_list*)(scanchain->DATA));
    ptl=getptype(rec->USER,TMPLONODE);
    if(!ptl)
    {
      fprintf(stderr,"Un connecteur (%s) n'est relie a aucun lonode. %c\n",
                     logical_connector->NAME,
                     logical_connector->TYPE);
      exit(1);
    }
    node=addnum(node,((long)(ptl->DATA)));
  }

  /* on a la liste des connecteurs triee dans la chain_list trie */
  
  freenum(logical_connector->PNODE);
  logical_connector->PNODE = node;
  freechain(trie);
}

void affrec( rdsrec_list *r)
{
  printf( "%s (%ld,%ld)-(%ld,%ld) Cont=%d Rcn=%d Diff=%d Val=%d\n",
          RDS_LAYER_NAME[GetRdsLayer(r)],
          r->X,
          r->Y,
          r->X+r->DX,
          r->Y+r->DY,
          isviacontact( GetRdsLayer(r) ),
          IsRcn(r),
          RectangleDiff(r),
          RectangleValide(r)
        );
}
