Example #1
0
/* reposition node in list */
void ReSetQueue( int r, int c, int s, int d, int a, int r2, int c2 )
{
    struct PcbQueue* p, * q;

    /* first, see if it is already in the list */
    for( q = NULL, p = Head; p; q = p, p = p->Next )
    {
        if( p->Row == r && p->Col == c && p->Side == s )
        {
            /* old one to remove */
            if( q )
            {
                if( ( q->Next = p->Next ) == NULL )
                    Tail = q;
            }
            else if( ( Head = p->Next ) == NULL )
            {
                Tail = NULL;
            }

            p->Next = Save;
            Save = p;
            OpenNodes--;
            MoveNodes++;
            qlen--;
            break;
        }
    }

    if( !p )            /* not found, it has already been closed once */
        ClosNodes--;    /* we will close it again, but just count once */

    /* if it was there, it's gone now; insert it at the proper position */
    SetQueue( r, c, s, d, a, r2, c2 );
}
Example #2
0
void TGUICopyParamType::Load(THierarchicalStorage * Storage)
{
  TCopyParamType::Load(Storage);

  SetQueue(Storage->ReadBool("Queue", GetQueue()));
  SetQueueNoConfirmation(Storage->ReadBool("QueueNoConfirmation", GetQueueNoConfirmation()));
  SetQueueIndividually(Storage->ReadBool("QueueIndividually", GetQueueIndividually()));
}
Example #3
0
void TGUICopyParamType::GUIDefault()
{
  TCopyParamType::Default();

  SetQueue(false);
  SetQueueNoConfirmation(true);
  SetQueueIndividually(false);
}
Example #4
0
/*----------------------------------------------------------------------
|       TestServer::TestServer
+---------------------------------------------------------------------*/
TestServer::TestServer()
{
    // create the message queue
    m_MessageQueue = new NPT_SimpleMessageQueue();
    
    // attach to the message queue
    SetQueue(m_MessageQueue);
    SetHandler(this);
    // start the thread
    Start();
}
/*----------------------------------------------------------------------
|    BLT_DecoderServer::BLT_DecoderServer
+---------------------------------------------------------------------*/
BLT_DecoderServer::BLT_DecoderServer(NPT_MessageReceiver* client) :
    m_Decoder(NULL),
    m_Client(client),
    m_TimeStampUpdateQuantum(1000),
    m_PositionUpdateRange(BLT_DECODER_SERVER_DEFAULT_POSITION_UPDATE_RANGE),
    m_State(STATE_STOPPED)
{
    // create a queue to receive messages
    m_MessageQueue = new NPT_SimpleMessageQueue();

    // attach the queue as the receiving queue
    SetQueue(m_MessageQueue);
    
    // register ourselves as the message handler
    SetHandler(this);

    // reset some fields
    m_DecoderStatus.position.range  = m_PositionUpdateRange;
    m_DecoderStatus.position.offset = 0;

    // setup our event listener interface
    m_EventListener.outer = this;
    ATX_SET_INTERFACE(&m_EventListener, 
                      BLT_DecoderServer_EventListenerWrapper, 
                      BLT_EventListener);

    // setup our core property listener interface
    m_CorePropertyListener.scope = BLT_PROPERTY_SCOPE_CORE;
    m_CorePropertyListener.source = NULL;
    m_CorePropertyListener.outer = this;
    ATX_SET_INTERFACE(&m_CorePropertyListener, 
                      BLT_DecoderServer_PropertyListenerWrapper, 
                      ATX_PropertyListener);

    // setup our stream property listener interface
    m_StreamPropertyListener.scope = BLT_PROPERTY_SCOPE_STREAM;
    m_StreamPropertyListener.source = NULL;
    m_StreamPropertyListener.outer = this;
    ATX_SET_INTERFACE(&m_StreamPropertyListener, 
                      BLT_DecoderServer_PropertyListenerWrapper, 
                      ATX_PropertyListener);

    // start the thread
    Start();
}
Example #6
0
/* Route a trace on the BOARD.
 * Parameters:
 * 1 side / 2 sides (0 / 1)
 * Coord source (row, col)
 * Coord destination (row, col)
 * Net_code
 * Pointer to the ratsnest reference
 *
 * Returns:
 * SUCCESS if routed
 * TRIVIAL_SUCCESS if pads are connected by overlay (no track needed)
 * If failure NOSUCCESS
 * Escape STOP_FROM_ESC if demand
 * ERR_MEMORY if memory allocation failed.
 */
static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe,
                                wxDC*           DC,
                                int             two_sides,
                                int             row_source,
                                int             col_source,
                                int             row_target,
                                int             col_target,
                                RATSNEST_ITEM*  pt_rat )
{
    int          r, c, side, d, apx_dist, nr, nc;
    int          result, skip;
    int          i;
    long         curcell, newcell, buddy, lastopen, lastclos, lastmove;
    int          newdist, olddir, _self;
    int          current_net_code;
    int          marge;
    LSET         padLayerMaskStart;    // Mask layers belonging to the starting pad.
    LSET         padLayerMaskEnd;      // Mask layers belonging to the ending pad.

    LSET         topLayerMask( g_Route_Layer_TOP );

    LSET         bottomLayerMask( g_Route_Layer_BOTTOM );

    LSET         routeLayerMask;       // Mask two layers for routing.

    LSET         tab_mask[2];           // Enables the calculation of the mask layer being
                                        // tested. (side = TOP or BOTTOM)
    int          start_mask_layer = 0;
    wxString     msg;

    // @todo this could be a bottle neck
    LSET all_cu = LSET::AllCuMask( pcbframe->GetBoard()->GetCopperLayerCount() );

    wxBusyCursor dummy_cursor;      // Set an hourglass cursor while routing a
                                    // track

    result = NOSUCCESS;

    marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 );

    // clear direction flags
    i = RoutingMatrix.m_Nrows * RoutingMatrix.m_Ncols * sizeof(DIR_CELL);

    if( two_sides )
        memset( RoutingMatrix.m_DirSide[TOP], FROM_NOWHERE, i );
    memset( RoutingMatrix.m_DirSide[BOTTOM], FROM_NOWHERE, i );

    lastopen = lastclos = lastmove = 0;

    // Set tab_masque[side] for final test of routing.
    if( two_sides )
        tab_mask[TOP] = topLayerMask;
    tab_mask[BOTTOM] = bottomLayerMask;

    // Set active layers mask.
    routeLayerMask = topLayerMask | bottomLayerMask;

    pt_cur_ch = pt_rat;

    current_net_code  = pt_rat->GetNet();
    padLayerMaskStart = pt_cur_ch->m_PadStart->GetLayerSet();

    padLayerMaskEnd = pt_cur_ch->m_PadEnd->GetLayerSet();


    /* First Test if routing possible ie if the pads are accessible
     * on the routing layers.
     */
    if( ( routeLayerMask & padLayerMaskStart ) == 0 )
        goto end_of_route;

    if( ( routeLayerMask & padLayerMaskEnd ) == 0 )
        goto end_of_route;

    /* Then test if routing possible ie if the pads are accessible
     * On the routing grid (1 grid point must be in the pad)
     */
    {
        int cX = ( RoutingMatrix.m_GridRouting * col_source )
                 + pcbframe->GetBoard()->GetBoundingBox().GetX();
        int cY = ( RoutingMatrix.m_GridRouting * row_source )
                 + pcbframe->GetBoard()->GetBoundingBox().GetY();
        int dx = pt_cur_ch->m_PadStart->GetSize().x / 2;
        int dy = pt_cur_ch->m_PadStart->GetSize().y / 2;
        int px = pt_cur_ch->m_PadStart->GetPosition().x;
        int py = pt_cur_ch->m_PadStart->GetPosition().y;

        if( ( ( int( pt_cur_ch->m_PadStart->GetOrientation() ) / 900 ) & 1 ) != 0 )
            std::swap( dx, dy );

        if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) )
            goto end_of_route;

        cX = ( RoutingMatrix.m_GridRouting * col_target )
             + pcbframe->GetBoard()->GetBoundingBox().GetX();
        cY = ( RoutingMatrix.m_GridRouting * row_target )
             + pcbframe->GetBoard()->GetBoundingBox().GetY();
        dx = pt_cur_ch->m_PadEnd->GetSize().x / 2;
        dy = pt_cur_ch->m_PadEnd->GetSize().y / 2;
        px = pt_cur_ch->m_PadEnd->GetPosition().x;
        py = pt_cur_ch->m_PadEnd->GetPosition().y;

        if( ( ( int( pt_cur_ch->m_PadEnd->GetOrientation() ) / 900) & 1 ) != 0 )
            std::swap( dx, dy );

        if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) )
            goto end_of_route;
    }

    // Test the trivial case: direct connection overlay pads.
    if( row_source == row_target  && col_source == col_target &&
            ( padLayerMaskEnd & padLayerMaskStart & all_cu ).any() )
    {
        result = TRIVIAL_SUCCESS;
        goto end_of_route;
    }

    // Placing the bit to remove obstacles on 2 pads to a link.
    pcbframe->SetStatusText( wxT( "Gen Cells" ) );

    PlacePad( pt_cur_ch->m_PadStart, CURRENT_PAD, marge, WRITE_OR_CELL );
    PlacePad( pt_cur_ch->m_PadEnd, CURRENT_PAD, marge, WRITE_OR_CELL );

    // Regenerates the remaining barriers (which may encroach on the
    // placement bits precedent)
    i = pcbframe->GetBoard()->GetPadCount();

    for( unsigned ii = 0; ii < pcbframe->GetBoard()->GetPadCount(); ii++ )
    {
        D_PAD* ptr = pcbframe->GetBoard()->GetPad( ii );

        if( ( pt_cur_ch->m_PadStart != ptr ) && ( pt_cur_ch->m_PadEnd != ptr ) )
        {
            PlacePad( ptr, ~CURRENT_PAD, marge, WRITE_AND_CELL );
        }
    }

    InitQueue(); // initialize the search queue
    apx_dist = RoutingMatrix.GetApxDist( row_source, col_source, row_target, col_target );

    // Initialize first search.
    if( two_sides )   // Preferred orientation.
    {
        if( abs( row_target - row_source ) > abs( col_target - col_source ) )
        {
            if( ( padLayerMaskStart & topLayerMask ).any() )
            {
                start_mask_layer = 2;

                if( SetQueue( row_source, col_source, TOP, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }

            if( ( padLayerMaskStart & bottomLayerMask ).any() )
            {
                start_mask_layer |= 1;

                if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
        }
        else
        {
            if( ( padLayerMaskStart & bottomLayerMask ).any() )
            {
                start_mask_layer = 1;

                if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }

            if( ( padLayerMaskStart & topLayerMask ).any() )
            {
                start_mask_layer |= 2;

                if( SetQueue( row_source, col_source, TOP, 0, apx_dist,
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
        }
    }
    else if( ( padLayerMaskStart & bottomLayerMask ).any() )
    {
        start_mask_layer = 1;

        if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist, row_target, col_target ) == 0 )
        {
            return ERR_MEMORY;
        }
    }

    // search until success or we exhaust all possibilities
    GetQueue( &r, &c, &side, &d, &apx_dist );

    for( ; r != ILLEGAL; GetQueue( &r, &c, &side, &d, &apx_dist ) )
    {
        curcell = RoutingMatrix.GetCell( r, c, side );

        if( curcell & CURRENT_PAD )
            curcell &= ~HOLE;

        if( (r == row_target) && (c == col_target)  // success if layer OK
           && (tab_mask[side] & padLayerMaskEnd).any() )
        {
            // Remove link.
            GRSetDrawMode( DC, GR_XOR );
            GRLine( pcbframe->GetCanvas()->GetClipBox(),
                    DC,
                    segm_oX,
                    segm_oY,
                    segm_fX,
                    segm_fY,
                    0,
                    WHITE );

            // Generate trace.
            if( Retrace( pcbframe, DC, row_source, col_source,
                         row_target, col_target, side, current_net_code ) )
            {
                result = SUCCESS;   // Success : Route OK
            }

            break;                  // Routing complete.
        }

        if( pcbframe->GetCanvas()->GetAbortRequest() )
        {
            result = STOP_FROM_ESC;
            break;
        }

        // report every COUNT new nodes or so
        #define COUNT 20000

        if( ( OpenNodes - lastopen > COUNT )
           || ( ClosNodes - lastclos > COUNT )
           || ( MoveNodes - lastmove > COUNT ) )
        {
            lastopen = OpenNodes;
            lastclos = ClosNodes;
            lastmove = MoveNodes;
            msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d" ),
                        OpenNodes, ClosNodes, MoveNodes );
            pcbframe->SetStatusText( msg );
        }

        _self = 0;

        if( curcell & HOLE )
        {
            _self = 5;

            // set 'present' bits
            for( i = 0; i < 8; i++ )
            {
                selfok2[i].present = 0;

                if( curcell & selfok2[i].trace )
                    selfok2[i].present = 1;
            }
        }

        for( i = 0; i < 8; i++ ) // consider neighbors
        {
            nr = r + delta[i][0];
            nc = c + delta[i][1];

            // off the edge?
            if( nr < 0 || nr >= RoutingMatrix.m_Nrows ||
                nc < 0 || nc >= RoutingMatrix.m_Ncols )
                continue;  // off the edge

            if( _self == 5 && selfok2[i].present )
                continue;

            newcell = RoutingMatrix.GetCell( nr, nc, side );

            if( newcell & CURRENT_PAD )
                newcell &= ~HOLE;

            // check for non-target hole
            if( newcell & HOLE )
            {
                if( nr != row_target || nc != col_target )
                    continue;
            }
            // check for traces
            else if( newcell & HOLE & ~(newmask[i]) )
            {
                continue;
            }

            // check blocking on corner neighbors
            if( delta[i][0] && delta[i][1] )
            {
                // check first buddy
                buddy = RoutingMatrix.GetCell( r + blocking[i].r1, c + blocking[i].c1, side );

                if( buddy & CURRENT_PAD )
                    buddy &= ~HOLE;

                if( buddy & HOLE )
                    continue;

//              if (buddy & (blocking[i].b1)) continue;
                // check second buddy
                buddy = RoutingMatrix.GetCell( r + blocking[i].r2, c + blocking[i].c2, side );

                if( buddy & CURRENT_PAD )
                    buddy &= ~HOLE;

                if( buddy & HOLE )
                    continue;

//              if (buddy & (blocking[i].b2)) continue;
            }

            olddir  = RoutingMatrix.GetDir( r, c, side );
            newdist = d + RoutingMatrix.CalcDist( ndir[i], olddir,
                                    ( olddir == FROM_OTHERSIDE ) ?
                                    RoutingMatrix.GetDir( r, c, 1 - side ) : 0, side );

            // if (a) not visited yet, or (b) we have
            // found a better path, add it to queue
            if( !RoutingMatrix.GetDir( nr, nc, side ) )
            {
                RoutingMatrix.SetDir( nr, nc, side, ndir[i] );
                RoutingMatrix.SetDist( nr, nc, side, newdist );

                if( SetQueue( nr, nc, side, newdist,
                              RoutingMatrix.GetApxDist( nr, nc, row_target, col_target ),
                              row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
            else if( newdist < RoutingMatrix.GetDist( nr, nc, side ) )
            {
                RoutingMatrix.SetDir( nr, nc, side, ndir[i] );
                RoutingMatrix.SetDist( nr, nc, side, newdist );
                ReSetQueue( nr, nc, side, newdist,
                            RoutingMatrix.GetApxDist( nr, nc, row_target, col_target ),
                            row_target, col_target );
            }
        }

        //* Test the other layer. *
        if( two_sides )
        {
            olddir = RoutingMatrix.GetDir( r, c, side );

            if( olddir == FROM_OTHERSIDE )
                continue;   // useless move, so don't bother

            if( curcell )   // can't drill via if anything here
                continue;

            // check for holes or traces on other side
            if( ( newcell = RoutingMatrix.GetCell( r, c, 1 - side ) ) != 0 )
                continue;

            // check for nearby holes or traces on both sides
            for( skip = 0, i = 0; i < 8; i++ )
            {
                nr = r + delta[i][0]; nc = c + delta[i][1];

                if( nr < 0 || nr >= RoutingMatrix.m_Nrows ||
                    nc < 0 || nc >= RoutingMatrix.m_Ncols )
                    continue;  // off the edge !!

                if( RoutingMatrix.GetCell( nr, nc, side ) /* & blocking2[i] */ )
                {
                    skip = 1; // can't drill via here
                    break;
                }

                if( RoutingMatrix.GetCell( nr, nc, 1 - side ) /* & blocking2[i] */ )
                {
                    skip = 1; // can't drill via here
                    break;
                }
            }

            if( skip )      // neighboring hole or trace?
                continue;   // yes, can't drill via here

            newdist = d + RoutingMatrix.CalcDist( FROM_OTHERSIDE, olddir, 0, side );

            /*  if (a) not visited yet,
             *  or (b) we have found a better path,
             *  add it to queue */
            if( !RoutingMatrix.GetDir( r, c, 1 - side ) )
            {
                RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
                RoutingMatrix.SetDist( r, c, 1 - side, newdist );

                if( SetQueue( r, c, 1 - side, newdist, apx_dist, row_target, col_target ) == 0 )
                {
                    return ERR_MEMORY;
                }
            }
            else if( newdist < RoutingMatrix.GetDist( r, c, 1 - side ) )
            {
                RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE );
                RoutingMatrix.SetDist( r, c, 1 - side, newdist );
                ReSetQueue( r, c,
                            1 - side,
                            newdist,
                            apx_dist,
                            row_target,
                            col_target );
            }
        }     // Finished attempt to route on other layer.
    }

end_of_route:
    PlacePad( pt_cur_ch->m_PadStart, ~CURRENT_PAD, marge, WRITE_AND_CELL );
    PlacePad( pt_cur_ch->m_PadEnd, ~CURRENT_PAD, marge, WRITE_AND_CELL );

    msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d"),
                OpenNodes, ClosNodes, MoveNodes );
    pcbframe->SetStatusText( msg );

    return result;
}
Example #7
0
void TGUICopyParamType::GUIAssign(const TGUICopyParamType * Source)
{
  SetQueue(Source->GetQueue());
  SetQueueNoConfirmation(Source->GetQueueNoConfirmation());
  SetQueueIndividually(Source->GetQueueIndividually());
}
Example #8
0
/* Route une piste du BOARD.
	Parametres:
		1 face / 2 faces ( 0 / 1)
		coord source (row,col)
		coord destination (row,col)
		net_code
		pointeur sur le chevelu de reference

	Retourne :
		SUCCESS si route trouvee
		TRIVIAL_SUCCESS si pads connectes par superposition ( pas de piste a tirer)
		NOSUCCESS si echec
		STOP_FROM_ESC si Escape demande
		ERR_MEMORY defaut alloc RAM
*/
static int Route_1_Trace(WinEDA_PcbFrame * pcbframe, wxDC * DC,
				int two_sides, int row_source,int col_source,
				int row_target,int col_target, CHEVELU * pt_chevelu )
{
int  r, c, side , d, apx_dist, nr, nc;
int result, skip;
int i;
LISTE_PAD * ptr;
long curcell, newcell, buddy, lastopen, lastclos, lastmove;
int newdist, olddir, _self;
int current_net_code;
int marge, via_marge;
int pad_masque_layer_s; /* Masque des couches appartenant au pad de depart */
int pad_masque_layer_e; /* Masque des couches appartenant au pad d'arrivee */
int masque_layer_TOP = g_TabOneLayerMask[Route_Layer_TOP];
int masque_layer_BOTTOM = g_TabOneLayerMask[Route_Layer_BOTTOM];
int masque_layers;		/* Masque des 2 couches de routage */
int tab_mask[2];		/* permet le calcul du Masque de la couche en cours
							de tst (side = TOP ou BOTTOM)*/
int start_mask_layer = 0;
wxString msg;
	
	result = NOSUCCESS;

	marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentTrackWidth / 2);
	via_marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentViaSize / 2);

	/* clear direction flags */
	i = Nrows * Ncols * sizeof(char);
	memset(Board.m_DirSide[TOP], FROM_NOWHERE, i );
	memset(Board.m_DirSide[BOTTOM], FROM_NOWHERE, i );

	lastopen = lastclos = lastmove = 0;

	/* Init tab_masque[side] pour tests de fin de routage */
	tab_mask[TOP] = masque_layer_TOP;
	tab_mask[BOTTOM] = masque_layer_BOTTOM;
	/* Init masque des couches actives */
	masque_layers = masque_layer_TOP | masque_layer_BOTTOM;

	pt_cur_ch = pt_chevelu;
	current_net_code = pt_chevelu->m_NetCode;
	pad_masque_layer_s = pt_cur_ch->pad_start->m_Masque_Layer;
	pad_masque_layer_e = pt_cur_ch->pad_end->m_Masque_Layer;

	/* Test 1 Si routage possible c.a.d si les pads sont accessibles
			sur les couches de routage */

	if( (masque_layers & pad_masque_layer_s) == 0 ) goto end_of_route;
	if( (masque_layers & pad_masque_layer_e) == 0 ) goto end_of_route;

	/* Test 2 Si routage possible c.a.d si les pads sont accessibles
		sur la grille de routage ( 1 point de grille doit etre dans le pad)*/
	{
	int cX = (pas_route * col_source) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.x;
	int cY = (pas_route * row_source) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.y;
	int dx = pt_cur_ch->pad_start->m_Size.x / 2;
	int dy = pt_cur_ch->pad_start->m_Size.y / 2;
	int px = pt_cur_ch->pad_start->m_Pos.x;
	int py = pt_cur_ch->pad_start->m_Pos.y;

	if ( ((pt_cur_ch->pad_start->m_Orient/900)&1) != 0 ) EXCHG(dx,dy) ;
	if ( (abs(cX - px) > dx ) || (abs(cY - py) > dy) ) goto end_of_route;

	cX = (pas_route * col_target) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.x;
	cY = (pas_route * row_target) + pcbframe->m_Pcb->m_BoundaryBox.m_Pos.y;
	dx = pt_cur_ch->pad_end->m_Size.x / 2;
	dy = pt_cur_ch->pad_end->m_Size.y / 2;
	px = pt_cur_ch->pad_end->m_Pos.x;
	py = pt_cur_ch->pad_end->m_Pos.y;
	if ( ((pt_cur_ch->pad_end->m_Orient/900)&1) != 0 ) EXCHG(dx,dy) ;

	if ( (abs(cX - px) > dx ) || (abs(cY - py) > dy) ) goto end_of_route;
	}

	/* Test du cas trivial: connection directe par superposition des pads */
	if( (row_source == row_target) && (col_source == col_target)
		&& ( pad_masque_layer_e & pad_masque_layer_s & g_TabAllCopperLayerMask[g_DesignSettings.m_CopperLayerCount-1]) )
	{
		result = TRIVIAL_SUCCESS;
		goto end_of_route;
	}



	/* Placement du bit de suppression d'obstacle relative aux 2 pads a relier */
	pcbframe->Affiche_Message( wxT("Gen Cells") );

	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_start,CURRENT_PAD ,marge,WRITE_OR_CELL);
	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_end, CURRENT_PAD ,marge,WRITE_OR_CELL);

	/* Regenere les barrieres restantes (qui peuvent empieter sur le placement
		des bits precedents) */
	ptr = (LISTE_PAD*) pcbframe->m_Pcb->m_Pads; i = pcbframe->m_Pcb->m_NbPads;
	for( ; i > 0 ; i-- , ptr++)
		{
		if((pt_cur_ch->pad_start != *ptr) && (pt_cur_ch->pad_end != *ptr) )
			{
			Place_1_Pad_Board(pcbframe->m_Pcb, *ptr, ~CURRENT_PAD,marge,WRITE_AND_CELL);
			}
		}

	InitQueue(); /* initialize the search queue */
	apx_dist = GetApxDist( row_source, col_source, row_target, col_target );

	/* Init 1ere recherche */
	if(two_sides)	/* orientation preferentielle */
		{
		if( abs(row_target-row_source) > abs(col_target-col_source) )
			{
			if( pad_masque_layer_s & masque_layer_TOP )
				{
				start_mask_layer = 2;
				if(SetQueue( row_source, col_source, TOP, 0, apx_dist,
							row_target, col_target ) == 0)
 					{
					return(ERR_MEMORY);
					}
				}
			if( pad_masque_layer_s & masque_layer_BOTTOM )
				{
				start_mask_layer |= 1;

				if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
							row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			}
		else
			{
			if( pad_masque_layer_s & masque_layer_BOTTOM )
				{
				start_mask_layer = 1;
				if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
							row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			if( pad_masque_layer_s & masque_layer_TOP )
				{
				start_mask_layer |= 2;

				if (SetQueue( row_source, col_source, TOP, 0, apx_dist,
							row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			}
		}

	else
		if( pad_masque_layer_s & masque_layer_BOTTOM )
			{
			start_mask_layer = 1;

			if( SetQueue( row_source, col_source, BOTTOM, 0, apx_dist,
							row_target, col_target ) == 0 )
				{
				return(ERR_MEMORY);
				}
			}

	/* search until success or we exhaust all possibilities */
	GetQueue( &r, &c, &side, &d, &apx_dist );
	for ( ; r != ILLEGAL; GetQueue( &r, &c, &side, &d, &apx_dist ) )
		{
		curcell = GetCell( r, c, side );
		if(curcell & CURRENT_PAD) curcell &= ~HOLE ;
		if( (r == row_target) && (c == col_target)  /* success si layer OK */
			&& ( tab_mask[side] & pad_masque_layer_e) )
			{
			/* Efface Liaison */
			GRSetDrawMode(DC, GR_XOR);
			GRLine(&pcbframe->DrawPanel->m_ClipBox, DC, segm_oX, segm_oY, segm_fX, segm_fY, WHITE);

			/* Generation de la trace */
			if( Retrace(pcbframe, DC, row_source, col_source,
						 row_target, col_target, side, current_net_code) )
				{
				result = SUCCESS;	/* Success : Route OK */
				}
			break;	/* Fin du routage */
			}
		/* report every 300 new nodes or so */
		if( (OpenNodes-lastopen > 300) || (ClosNodes-lastclos > 300) || (MoveNodes - lastmove > 300))
			{
			lastopen = (OpenNodes/300)*300; lastclos = (ClosNodes/300)*300;
			lastmove = (MoveNodes/300)*300;

			if( pcbframe->DrawPanel->m_AbortRequest )
				{
				result = STOP_FROM_ESC; break;
				}
			AFFICHE_ACTIVITE_ROUTE;
			}

		_self = 0;
		if (curcell & HOLE)
			{
			_self = 5;
			/* set 'present' bits */
			for (i = 0; i < 8; i++)
				{
				selfok2[i].present = 0;
				if( (curcell & selfok2[i].trace) ) selfok2[i].present = 1;
				}
			}

		for (i = 0; i < 8; i++) /* consider neighbors */
			{
			nr = r+delta[i][0]; nc = c+delta[i][1];

			/* off the edge? */
			if( nr < 0 || nr >= Nrows || nc < 0 || nc >= Ncols)
				continue; /* off the edge */

			if (_self == 5 && selfok2[i].present) continue;
			newcell = GetCell( nr, nc, side );
			if(newcell & CURRENT_PAD) newcell &= ~HOLE;

			/* check for non-target hole */
			if (newcell & HOLE)
				{
				if (nr != row_target || nc != col_target) continue;
				}

			/* check for traces */
			else if (newcell & HOLE & ~(newmask[i])) continue;

			/* check blocking on corner neighbors */
			if (delta[i][0] && delta[i][1])
				{
				/* check first buddy */
				buddy = GetCell( r+blocking[i].r1, c+blocking[i].c1, side );
				if(buddy & CURRENT_PAD) buddy &= ~HOLE;
				if (buddy & HOLE) continue;
//				if (buddy & (blocking[i].b1)) continue;
				/* check second buddy */
				buddy = GetCell( r+blocking[i].r2, c+blocking[i].c2, side );
				if(buddy & CURRENT_PAD) buddy &= ~HOLE;
				if (buddy & HOLE) continue;
//				if (buddy & (blocking[i].b2)) continue;
				}

			olddir = GetDir( r, c, side );
			newdist = d + CalcDist( ndir[i], olddir,
				(olddir == FROM_OTHERSIDE) ? GetDir( r, c, 1-side ) : 0 , side);

			/* if (a) not visited yet, or (b) we have */
			/* found a better path, add it to queue */
			if (!GetDir( nr, nc, side ))
				{
				SetDir( nr, nc, side, ndir[i] );
				SetDist( nr, nc, side, newdist );
				if( SetQueue( nr, nc, side, newdist,
					GetApxDist( nr, nc, row_target, col_target ),
						row_target, col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}

			else if (newdist < GetDist( nr, nc, side ))
				{
				SetDir( nr, nc, side, ndir[i] );
				SetDist( nr, nc, side, newdist );
				ReSetQueue( nr, nc, side, newdist,
					GetApxDist( nr, nc, row_target, col_target ),
					row_target, col_target );
				}
			}

		/** etude de l'autre couche **/
		if( (two_sides) && ! g_No_Via_Route )
			{
			olddir = GetDir( r, c, side );
			if (olddir == FROM_OTHERSIDE)
				continue; /* useless move, so don't bother */
			if (curcell) /* can't drill via if anything here */
				continue;
			/* check for holes or traces on other side */
			if( (newcell = GetCell( r, c, 1-side )) != 0 )
				continue;
			/* check for nearby holes or traces on both sides */
			for (skip = 0, i = 0; i < 8; i++)
				{
				nr = r + delta[i][0]; nc = c + delta[i][1];

				if (nr < 0 || nr >= Nrows || nc < 0 || nc >= Ncols)
					continue;  /* off the edge !! */

				if (GetCell( nr, nc, side )/* & blocking2[i]*/)
					{
					skip = 1; /* can't drill via here */
					break;
					}

				if (GetCell( nr, nc, 1-side )/* & blocking2[i]*/)
					{
					skip = 1; /* can't drill via here */
					break;
					}
				}

			if (skip) /* neighboring hole or trace? */
				continue; /* yes, can't drill via here */

			newdist = d + CalcDist( FROM_OTHERSIDE, olddir, 0 , side);

			/*  if (a) not visited yet,
				or (b) we have found a better path,
				add it to queue */
			if (!GetDir( r, c, 1-side ))
				{
				SetDir( r, c, 1-side, FROM_OTHERSIDE );
				SetDist( r, c, 1-side, newdist );
				if( SetQueue( r, c, 1-side, newdist, apx_dist, row_target,
								 col_target ) == 0 )
					{
					return(ERR_MEMORY);
					}
				}
			else if (newdist < GetDist( r, c, 1-side ))
				{
				SetDir( r, c, 1-side, FROM_OTHERSIDE );
				SetDist( r, c, 1-side, newdist );
				ReSetQueue( r, c, 1-side, newdist, apx_dist, row_target, col_target );
				}
			} /* Fin de l'exploration de l'autre couche */
		}

end_of_route:
	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_start,~CURRENT_PAD ,marge,WRITE_AND_CELL);
	Place_1_Pad_Board(pcbframe->m_Pcb, pt_cur_ch->pad_end, ~CURRENT_PAD ,marge,WRITE_AND_CELL);

	AFFICHE_ACTIVITE_ROUTE;
	return(result);
}