solve.cpp 40.6 KB
Newer Older
1 2 3
/*************/
/* solve.cpp */
/*************/
4 5 6 7

#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
8 9 10
#include "class_drawpanel.h"
#include "confirm.h"

11
#include "pcbnew.h"
charras's avatar
charras committed
12
#include "wxPcbStruct.h"
charras's avatar
charras committed
13
#include "class_board_design_settings.h"
14
#include "autorout.h"
15
#include "zones.h"
16 17 18 19
#include "protos.h"

#include "cell.h"

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

static int Autoroute_One_Track( WinEDA_PcbFrame* pcbframe,
                                wxDC*            DC,
                                int              two_sides,
                                int              row_source,
                                int              col_source,
                                int              row_target,
                                int              col_target,
                                RATSNEST_ITEM*   pt_chevelu );
static int Retrace( WinEDA_PcbFrame* pcbframe,
                    wxDC*            DC,
                    int,
                    int,
                    int,
                    int,
                    int,
                    int              net_code );
static void OrCell_Trace( BOARD* pcb,
                          int    col,
                          int    row,
                          int    side,
                          int    orient,
                          int    current_net_code );
43
static void Place_Piste_en_Buffer( WinEDA_PcbFrame* pcbframe, wxDC* DC );
44

45 46 47 48

static int            segm_oX, segm_oY;
static int            segm_fX, segm_fY; /* Origin and position of the current
                                         * trace segment. */
49
static RATSNEST_ITEM* pt_cur_ch;
50 51
static int            Ncurrent;     /* measures of progress */
static int            s_Clearance;  // Clearance value used in autorouter
52 53


54 55 56 57
#define NOSUCCESS       0
#define STOP_FROM_ESC   -1
#define ERR_MEMORY      -2
#define SUCCESS         1
58 59 60 61 62 63 64 65 66 67 68 69 70 71
#define TRIVIAL_SUCCESS 2

/*
** visit neighboring cells like this (where [9] is on the other side):
**
**	+---+---+---+
**	| 1 | 2 | 3 |
**	+---+---+---+
**	| 4 |[9]| 5 |
**	+---+---+---+
**	| 6 | 7 | 8 |
**	+---+---+---+
*/

72 73 74 75 76 77
/* for visiting neighbors on the same side: increments/decrements coord of
 * [] [0] = row [] (1] = col was added to the coord of the midpoint for
 * Get the coord of the 8 neighboring points.
 */
static int delta[8][2] =
{
78 79 80 81 82 83 84 85 86
    {  1, -1 },     /* northwest	*/
    {  1, 0  },     /* north		*/
    {  1, 1  },     /* northeast	*/
    {  0, -1 },     /* west		*/
    {  0, 1  },     /* east		*/
    { -1, -1 },     /* southwest	*/
    { -1, 0  },     /* south		*/
    { -1, 1  }      /* southeast	*/
};
87

88 89 90
static int ndir[8] =
{
    /* for building paths back to source */
91
    FROM_SOUTHEAST, FROM_SOUTH,     FROM_SOUTHWEST,
92
    FROM_EAST,      FROM_WEST,
93
    FROM_NORTHEAST, FROM_NORTH,     FROM_NORTHWEST
94
};
95 96

/* blocking masks for neighboring cells */
97
#define BLOCK_NORTHEAST ( DIAG_NEtoSW | BENT_StoNE | BENT_WtoNE \
98
                          | ANGLE_NEtoSE | ANGLE_NWtoNE         \
99 100
                          | SHARP_NtoNE | SHARP_EtoNE | HOLE )
#define BLOCK_SOUTHEAST ( DIAG_SEtoNW | BENT_NtoSE | BENT_WtoSE \
101
                          | ANGLE_NEtoSE | ANGLE_SEtoSW         \
102 103
                          | SHARP_EtoSE | SHARP_StoSE | HOLE )
#define BLOCK_SOUTHWEST ( DIAG_NEtoSW | BENT_NtoSW | BENT_EtoSW \
104
                          | ANGLE_SEtoSW | ANGLE_SWtoNW         \
105 106
                          | SHARP_StoSW | SHARP_WtoSW | HOLE )
#define BLOCK_NORTHWEST ( DIAG_SEtoNW | BENT_EtoNW | BENT_StoNW \
107
                          | ANGLE_SWtoNW | ANGLE_NWtoNE         \
108
                          | SHARP_WtoNW | SHARP_NtoNW | HOLE )
109 110 111 112
#define BLOCK_NORTH     ( LINE_VERTICAL | BENT_NtoSE | BENT_NtoSW      \
                          | BENT_EtoNW | BENT_WtoNE                    \
                          | BENT_StoNE | BENT_StoNW                    \
                          | CORNER_NORTHEAST | CORNER_NORTHWEST        \
113
                          | ANGLE_NEtoSE | ANGLE_SWtoNW | ANGLE_NWtoNE \
114 115
                          | DIAG_NEtoSW | DIAG_SEtoNW                  \
                          | SHARP_NtoNE | SHARP_NtoNW                  \
116
                          | SHARP_EtoNE | SHARP_WtoNW | HOLE )
117 118 119 120
#define BLOCK_EAST      ( LINE_HORIZONTAL | BENT_EtoSW | BENT_EtoNW    \
                          | BENT_NtoSE | BENT_StoNE                    \
                          | BENT_WtoNE | BENT_WtoSE                    \
                          | CORNER_NORTHEAST | CORNER_SOUTHEAST        \
121
                          | ANGLE_NEtoSE | ANGLE_SEtoSW | ANGLE_NWtoNE \
122 123
                          | DIAG_NEtoSW | DIAG_SEtoNW                  \
                          | SHARP_EtoNE | SHARP_EtoSE                  \
124
                          | SHARP_NtoNE | SHARP_StoSE | HOLE )
125 126 127 128
#define BLOCK_SOUTH     ( LINE_VERTICAL | BENT_StoNE | BENT_StoNW      \
                          | BENT_EtoSW | BENT_WtoSE                    \
                          | BENT_NtoSE | BENT_NtoSW                    \
                          | CORNER_SOUTHEAST | CORNER_SOUTHWEST        \
129
                          | ANGLE_NEtoSE | ANGLE_SWtoNW | ANGLE_SEtoSW \
130 131
                          | DIAG_NEtoSW | DIAG_SEtoNW                  \
                          | SHARP_StoSE | SHARP_StoSW                  \
132
                          | SHARP_EtoSE | SHARP_WtoSW | HOLE )
133 134 135 136
#define BLOCK_WEST      ( LINE_HORIZONTAL | BENT_WtoNE | BENT_WtoSE    \
                          | BENT_NtoSW | BENT_StoNW                    \
                          | BENT_EtoSW | BENT_EtoNW                    \
                          | CORNER_SOUTHWEST | CORNER_NORTHWEST        \
137
                          | ANGLE_SWtoNW | ANGLE_SEtoSW | ANGLE_NWtoNE \
138 139
                          | DIAG_NEtoSW | DIAG_SEtoNW                  \
                          | SHARP_WtoSW | SHARP_WtoNW                  \
140
                          | SHARP_NtoNW | SHARP_StoSW | HOLE )
141 142 143 144 145 146 147 148 149

struct block
{
    int  r1, c1;
    long b1;
    int  r2, c2;
    long b2;
};

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
/* blocking masks for diagonal traces */
static struct block blocking[8] =
{ {
      0, -1,
      BLOCK_NORTHEAST,
      1, 0,
      BLOCK_SOUTHWEST
  },
  {
      0, 0, 0,
      0, 0, 0
  },
  {
      1, 0,
      BLOCK_SOUTHEAST,
      0, 1,
      BLOCK_NORTHWEST
  },
  {
      0, 0, 0,
      0, 0, 0
  },
  {
      0, 0, 0,
      0, 0, 0
  },
  {
      0, -1,
      BLOCK_SOUTHEAST,
      -1, 0,
      BLOCK_NORTHWEST
  },
  {
      0, 0, 0,
      0, 0, 0
  },
  {
      -1, 0,
      BLOCK_NORTHEAST,
      0, 1,
      BLOCK_SOUTHWEST
  } };
192 193

/* mask for hole-related blocking effects */
194 195 196 197
static struct
{
    long trace;
    int  present;
198 199 200 201 202 203 204 205 206 207
} selfok2[8] =
{
    { HOLE_NORTHWEST, 0 },
    { HOLE_NORTH,     0 },
    { HOLE_NORTHEAST, 0 },
    { HOLE_WEST,      0 },
    { HOLE_EAST,      0 },
    { HOLE_SOUTHWEST, 0 },
    { HOLE_SOUTH,     0 },
    { HOLE_SOUTHEAST, 0 }
208
};
209

210 211 212 213 214
static long newmask[8] =
{
    /* patterns to mask out in neighbor cells */
    0,
    CORNER_NORTHWEST | CORNER_NORTHEAST,
215
    0,
216 217 218 219
    CORNER_NORTHWEST | CORNER_SOUTHWEST,
    CORNER_NORTHEAST | CORNER_SOUTHEAST,
    0,
    CORNER_SOUTHWEST | CORNER_SOUTHEAST,
220
    0
221
};
222 223


224 225 226 227 228
/* Route all traces
 * Return:
 *  1 if OK
 * -1 if escape (stop being routed) request
 * -2 if default memory allocation
229
 */
230
int WinEDA_PcbFrame::Solve( wxDC* DC, int two_sides )
231
{
232 233 234
    int           current_net_code;
    int           row_source, col_source, row_target, col_target;
    int           success, nbsucces = 0, nbunsucces = 0;
235
    NETINFO_ITEM* net;
236 237
    bool          stop = FALSE;
    wxString      msg;
238 239 240 241

    DrawPanel->m_AbortRequest = FALSE;
    DrawPanel->m_AbortEnable  = TRUE;

242 243
    s_Clearance = GetBoard()->m_NetClasses.GetDefault()->GetClearance();

244 245
    Ncurrent = 0;
    MsgPanel->EraseMsgBox();
246
    msg.Printf( wxT( "%d  " ), GetBoard()->m_NbNoconnect );
247
    Affiche_1_Parametre( this, 72, wxT( "NoConn" ), msg, CYAN );
248 249 250 251


    /* go until no more work to do */
    GetWork( &row_source, &col_source, &current_net_code,
252
             &row_target, &col_target, &pt_cur_ch ); // First net to route.
253 254

    for( ; row_source != ILLEGAL; GetWork( &row_source, &col_source,
255 256
                                           &current_net_code, &row_target,
                                           &col_target,
257
                                           &pt_cur_ch ) )
258
    {
259
        /* Test to stop routing ( escape key pressed ) */
260 261 262 263 264 265 266 267 268 269 270 271 272 273
        wxYield();
        if( DrawPanel->m_AbortRequest )
        {
            if( IsOK( this, _( "Abort routing?" ) ) )
            {
                success = STOP_FROM_ESC;
                stop    = TRUE;
                break;
            }
            else
                DrawPanel->m_AbortRequest = 0;
        }

        Ncurrent++;
274 275
        net = GetBoard()->FindNet( current_net_code );
        if( net )
276
        {
277
            msg.Printf( wxT( "[%8.8s]" ), GetChars( net->GetNetname() ) );
278
            Affiche_1_Parametre( this, 1, wxT( "Net route" ), msg, BROWN );
279
            msg.Printf( wxT( "%d / %d" ), Ncurrent, Ntotal );
280
            Affiche_1_Parametre( this, 12, wxT( "Activity" ), msg, BROWN );
281 282 283
        }

        pt_cur_ch = pt_cur_ch;
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
        segm_oX = GetBoard()->m_BoundaryBox.m_Pos.x +
                  (g_GridRoutingSize * col_source);
        segm_oY = GetBoard()->m_BoundaryBox.m_Pos.y +
                  (g_GridRoutingSize * row_source);
        segm_fX = GetBoard()->m_BoundaryBox.m_Pos.x +
                  (g_GridRoutingSize * col_target);
        segm_fY = GetBoard()->m_BoundaryBox.m_Pos.y +
                  (g_GridRoutingSize * row_target);

        /* Draw segment. */
        GRLine( &DrawPanel->m_ClipBox,
                DC,
                segm_oX,
                segm_oY,
                segm_fX,
                segm_fY,
                0,
                WHITE | GR_XOR );
302 303
        pt_cur_ch->m_PadStart->Draw( DrawPanel, DC, GR_OR | GR_SURBRILL );
        pt_cur_ch->m_PadEnd->Draw( DrawPanel, DC, GR_OR | GR_SURBRILL );
304

305 306 307 308 309 310 311 312
        success = Autoroute_One_Track( this,
                                       DC,
                                       two_sides,
                                       row_source,
                                       col_source,
                                       row_target,
                                       col_target,
                                       pt_cur_ch );
313 314 315 316

        switch( success )
        {
        case NOSUCCESS:
317
            pt_cur_ch->m_Status |= CH_UNROUTABLE;
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
            nbunsucces++;
            break;

        case STOP_FROM_ESC:
            stop = TRUE;
            break;

        case ERR_MEMORY:
            stop = TRUE;
            break;

        default:
            nbsucces++;
            break;
        }

        msg.Printf( wxT( "%d  " ), nbsucces );
335
        Affiche_1_Parametre( this, 22, wxT( "Ok" ), msg, GREEN );
336
        msg.Printf( wxT( "%d  " ), nbunsucces );
337
        Affiche_1_Parametre( this, 30, wxT( "Fail" ), msg, RED );
338
        msg.Printf( wxT( "%d  " ), GetBoard()->m_NbNoconnect );
339
        Affiche_1_Parametre( this, 38, wxT( "NoConn" ), msg, CYAN );
340

341
        /* Delete routing from display. */
342 343
        pt_cur_ch->m_PadStart->Draw( DrawPanel, DC, GR_AND );
        pt_cur_ch->m_PadEnd->Draw( DrawPanel, DC, GR_AND );
344 345 346 347 348 349 350 351

        if( stop )
            break;
    }

    DrawPanel->m_AbortEnable = FALSE;

    return SUCCESS;
352 353
}

354

355 356 357 358 359 360 361
/* 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
362
 *
363 364 365 366 367 368
 * Returns:
 * SUCCESS if routed
 * TRIVIAL_SUCCESS if pads connected by overlay (no track has learned)
 * If failure NOSUCCESS
 * Escape STOP_FROM_ESC if demand
 * ERR_MEMORY if memory allocation failed.
369
 */
370 371 372 373 374 375 376 377
static int Autoroute_One_Track( WinEDA_PcbFrame* pcbframe,
                                wxDC*            DC,
                                int              two_sides,
                                int              row_source,
                                int              col_source,
                                int              row_target,
                                int              col_target,
                                RATSNEST_ITEM*   pt_chevelu )
378
{
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
    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, via_marge;
    int          pad_masque_layer_s;    /* Mask layers belonging to the
                                         *starting pad. */
    int          pad_masque_layer_e;    /* Mask layers belonging to the ending
                                         *pad. */
    int          masque_layer_TOP    = g_TabOneLayerMask[Route_Layer_TOP];
    int          masque_layer_BOTTOM = g_TabOneLayerMask[Route_Layer_BOTTOM];
    int          masque_layers;     /* Mask two layers for routing. */
    int          tab_mask[2];       /* Enables the calculation of the mask
                                     * layer being
                                     * tested. (side = TOP or BOTTOM) */
    int          start_mask_layer = 0;
    wxString     msg;

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

402 403
    result = NOSUCCESS;

404 405 406
    marge = s_Clearance +
            ( pcbframe->GetBoard()->GetCurrentTrackWidth() / 2 );
    via_marge = s_Clearance + ( pcbframe->GetBoard()->GetCurrentViaSize() / 2 );
407 408 409 410 411 412 413 414

    /* 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;

415
    /* Set tab_masque[side] for final test of routing. */
416 417
    tab_mask[TOP]    = masque_layer_TOP;
    tab_mask[BOTTOM] = masque_layer_BOTTOM;
418
    /* Set active layers mask. */
419 420 421
    masque_layers = masque_layer_TOP | masque_layer_BOTTOM;

    pt_cur_ch = pt_chevelu;
422
    current_net_code   = pt_chevelu->GetNet();
423 424
    pad_masque_layer_s = pt_cur_ch->m_PadStart->m_Masque_Layer;
    pad_masque_layer_e = pt_cur_ch->m_PadEnd->m_Masque_Layer;
425 426


427 428 429 430
    /* First Test if routing possible ie if the pads are accessible
     * on the routing layers.
     */
    if( ( masque_layers & pad_masque_layer_s ) == 0 )
431
        goto end_of_route;
432
    if( ( masque_layers & pad_masque_layer_e ) == 0 )
433 434
        goto end_of_route;

435 436 437
    /* Then test if routing possible ie if the pads are accessible
     * On the routing grid (1 grid point must be in the pad)
     */
438
    {
439 440 441 442
        int cX = ( g_GridRoutingSize * col_source )
                 + pcbframe->GetBoard()->m_BoundaryBox.m_Pos.x;
        int cY = ( g_GridRoutingSize * row_source )
                 + pcbframe->GetBoard()->m_BoundaryBox.m_Pos.y;
443 444 445 446
        int dx = pt_cur_ch->m_PadStart->m_Size.x / 2;
        int dy = pt_cur_ch->m_PadStart->m_Size.y / 2;
        int px = pt_cur_ch->m_PadStart->GetPosition().x;
        int py = pt_cur_ch->m_PadStart->GetPosition().y;
447

448
        if( ( ( pt_cur_ch->m_PadStart->m_Orient / 900 ) & 1 ) != 0 )
449
            EXCHG( dx, dy );
450
        if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) )
451 452
            goto end_of_route;

453 454 455 456
        cX = ( g_GridRoutingSize * col_target )
             + pcbframe->GetBoard()->m_BoundaryBox.m_Pos.x;
        cY = ( g_GridRoutingSize * row_target )
             + pcbframe->GetBoard()->m_BoundaryBox.m_Pos.y;
457 458 459 460 461
        dx = pt_cur_ch->m_PadEnd->m_Size.x / 2;
        dy = pt_cur_ch->m_PadEnd->m_Size.y / 2;
        px = pt_cur_ch->m_PadEnd->GetPosition().x;
        py = pt_cur_ch->m_PadEnd->GetPosition().y;
        if( ( (pt_cur_ch->m_PadEnd->m_Orient / 900) & 1 ) != 0 )
462 463
            EXCHG( dx, dy );

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

468 469
    /* Test the trivial case: direct connection overlay pads. */
    if( ( row_source == row_target ) && ( col_source == col_target )
470
       && ( pad_masque_layer_e & pad_masque_layer_s &
471
            g_TabAllCopperLayerMask[pcbframe->GetBoard()->GetCopperLayerCount() - 1] ) )
472 473 474 475 476
    {
        result = TRIVIAL_SUCCESS;
        goto end_of_route;
    }

477
    /* Placing the bit to remove obstacles on 2 pads to a link. */
478 479
    pcbframe->Affiche_Message( wxT( "Gen Cells" ) );

480 481 482 483
    Place_1_Pad_Board( pcbframe->GetBoard(), pt_cur_ch->m_PadStart,
                       CURRENT_PAD, marge, WRITE_OR_CELL );
    Place_1_Pad_Board( pcbframe->GetBoard(), pt_cur_ch->m_PadEnd,
                       CURRENT_PAD, marge, WRITE_OR_CELL );
484

485 486 487 488
    /* Regenerates the remaining barriers (which may encroach on the placement
     * bits precedent)
     */
    i = pcbframe->GetBoard()->GetPadsCount();
489
    for( unsigned ii = 0; ii < pcbframe->GetBoard()->GetPadsCount(); ii++ )
490
    {
491 492
        D_PAD* ptr = pcbframe->GetBoard()->m_NetInfo->GetPad( ii );
        if( ( pt_cur_ch->m_PadStart != ptr ) && ( pt_cur_ch->m_PadEnd != ptr ) )
493
        {
494 495
            Place_1_Pad_Board( pcbframe->GetBoard(), ptr, ~CURRENT_PAD,
                               marge, WRITE_AND_CELL );
496 497 498 499 500 501
        }
    }

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

502 503
    /* Initialize first search. */
    if( two_sides )   /* Preferred orientation. */
504 505 506 507 508 509 510
    {
        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,
511
                              row_target, col_target ) == 0 )
512 513 514 515 516 517 518 519 520
                {
                    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,
521
                              row_target, col_target ) == 0 )
522 523 524 525 526 527 528 529 530 531 532
                {
                    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,
533
                              row_target, col_target ) == 0 )
534 535 536 537 538 539 540 541 542
                {
                    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,
543
                              row_target, col_target ) == 0 )
544 545 546 547 548 549 550 551 552 553 554
                {
                    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,
555
                      row_target, col_target ) == 0 )
556 557 558 559 560 561 562 563 564 565 566 567
        {
            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;
568
        if( (r == row_target) && (c == col_target)  /* success if layer OK */
569 570
           && ( tab_mask[side] & pad_masque_layer_e) )
        {
571
            /* Remove link. */
572 573
            GRSetDrawMode( DC, GR_XOR );
            GRLine( &pcbframe->DrawPanel->m_ClipBox,
574 575 576 577 578 579 580
                    DC,
                    segm_oX,
                    segm_oY,
                    segm_fX,
                    segm_fY,
                    0,
                    WHITE );
581

582
            /* Generate trace. */
583
            if( Retrace( pcbframe, DC, row_source, col_source,
584
                         row_target, col_target, side, current_net_code ) )
585 586 587
            {
                result = SUCCESS;   /* Success : Route OK */
            }
588
            break;                  /* Routing complete. */
589 590
        }

591 592
        if( pcbframe->DrawPanel->m_AbortRequest )
        {
593 594
            result = STOP_FROM_ESC;
            break;
595 596
        }

597
        /* report every COUNT new nodes or so */
charras's avatar
charras committed
598
        #define COUNT 20000
599 600 601
        if( ( OpenNodes - lastopen > COUNT )
           || ( ClosNodes - lastclos > COUNT )
           || ( MoveNodes - lastmove > COUNT ) )
602 603
        {
            lastopen = OpenNodes;
charras's avatar
charras committed
604
            lastclos = ClosNodes;
605
            lastmove = MoveNodes;
606 607 608
            msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d" ),
                        OpenNodes, ClosNodes, MoveNodes );
            pcbframe->Affiche_Message( msg );
609
        }
charras's avatar
charras committed
610

611 612 613 614 615 616 617 618
        _self = 0;
        if( curcell & HOLE )
        {
            _self = 5;
            /* set 'present' bits */
            for( i = 0; i < 8; i++ )
            {
                selfok2[i].present = 0;
619
                if( curcell & selfok2[i].trace )
620 621 622 623 624 625 626 627 628 629
                    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 )
630
                continue;  /* off the edge */
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657

            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;

658
//				if (buddy & (blocking[i].b1)) continue;
659 660 661 662 663 664 665
                /* check second buddy */
                buddy = GetCell( r + blocking[i].r2, c + blocking[i].c2, side );
                if( buddy & CURRENT_PAD )
                    buddy &= ~HOLE;
                if( buddy & HOLE )
                    continue;

666
//				if (buddy & (blocking[i].b2)) continue;
667 668 669 670
            }

            olddir  = GetDir( r, c, side );
            newdist = d + CalcDist( ndir[i], olddir,
671 672
                                    ( olddir == FROM_OTHERSIDE ) ?
                                    GetDir( r, c, 1 - side ) : 0, side );
673 674 675 676 677 678 679 680

            /* 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,
681 682
                              GetApxDist( nr, nc, row_target, col_target ),
                              row_target, col_target ) == 0 )
683 684 685 686 687 688 689 690 691
                {
                    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,
692 693
                            GetApxDist( nr, nc, row_target, col_target ),
                            row_target, col_target );
694 695 696
            }
        }

697
        /** Test the other layer. **/
698
        if( two_sides )
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
        {
            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 )
714
                    continue;  /* off the edge !! */
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741

                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,
742
                              col_target ) == 0 )
743 744 745 746 747 748 749 750
                {
                    return ERR_MEMORY;
                }
            }
            else if( newdist < GetDist( r, c, 1 - side ) )
            {
                SetDir( r, c, 1 - side, FROM_OTHERSIDE );
                SetDist( r, c, 1 - side, newdist );
751 752 753 754 755 756 757
                ReSetQueue( r,
                            c,
                            1 - side,
                            newdist,
                            apx_dist,
                            row_target,
                            col_target );
758
            }
759
        }     /* Finished attempt to route on other layer. */
760
    }
761 762

end_of_route:
763 764 765 766
    Place_1_Pad_Board( pcbframe->GetBoard(), pt_cur_ch->m_PadStart,
                       ~CURRENT_PAD, marge, WRITE_AND_CELL );
    Place_1_Pad_Board( pcbframe->GetBoard(), pt_cur_ch->m_PadEnd,
                       ~CURRENT_PAD, marge, WRITE_AND_CELL );
767

768 769 770
    msg.Printf( wxT( "Activity: Open %d   Closed %d   Moved %d"),
                OpenNodes, ClosNodes, MoveNodes );
    pcbframe->Affiche_Message( msg );
charras's avatar
charras committed
771

772
    return result;
773 774
}

775

776 777 778
static long bit[8][9] =
{
    /* OT=Otherside */
779
    /* N, NE, E, SE, S, SW, W, NW, OT */
780
/* N */
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
    { LINE_VERTICAL,
      BENT_StoNE,
      CORNER_SOUTHEAST,
      SHARP_StoSE,
      0,
      SHARP_StoSW,
      CORNER_SOUTHWEST,
      BENT_StoNW,
      ( HOLE | HOLE_SOUTH )
    },
/* NE */
    {
        BENT_NtoSW,
        DIAG_NEtoSW,
        BENT_EtoSW,
        ANGLE_SEtoSW,
        SHARP_StoSW,
        0,
        SHARP_WtoSW,
        ANGLE_SWtoNW,
        ( HOLE | HOLE_SOUTHWEST )
    },
/* E */
    {
        CORNER_NORTHWEST,
        BENT_WtoNE,
        LINE_HORIZONTAL,
        BENT_WtoSE,
        CORNER_SOUTHWEST,
        SHARP_WtoSW,
        0,
        SHARP_WtoNW,
        ( HOLE | HOLE_WEST )
    },
/* SE */
    {
        SHARP_NtoNW,
        ANGLE_NWtoNE,
        BENT_EtoNW,
        DIAG_SEtoNW,
        BENT_StoNW,
        ANGLE_SWtoNW,
        SHARP_WtoNW,
        0,
        ( HOLE | HOLE_NORTHWEST )
    },
/* S */
    {
        0,
        SHARP_NtoNE,
        CORNER_NORTHEAST,
        BENT_NtoSE,
        LINE_VERTICAL,
        BENT_NtoSW,
        CORNER_NORTHWEST,
        SHARP_NtoNW,
        ( HOLE | HOLE_NORTH )
    },
/* SW */
    {
        SHARP_NtoNE,
        0,
        SHARP_EtoNE,
        ANGLE_NEtoSE,
        BENT_StoNE,
        DIAG_NEtoSW,
        BENT_WtoNE,
        ANGLE_NWtoNE,
        ( HOLE | HOLE_NORTHEAST )
    },
/* W */
    {
        CORNER_NORTHEAST,
        SHARP_EtoNE,
        0,
        SHARP_EtoSE,
        CORNER_SOUTHEAST,
        BENT_EtoSW,
        LINE_HORIZONTAL,
        BENT_EtoNW,
        ( HOLE | HOLE_EAST )
    },
/* NW */
    {
        BENT_NtoSE,
        ANGLE_NEtoSE,
        SHARP_EtoSE,
        0,
        SHARP_StoSE,
        ANGLE_SEtoSW,
        BENT_WtoSE,
        DIAG_SEtoNW,
        ( HOLE | HOLE_SOUTHEAST )
    }
875
};
876

877

878
/* work from target back to source, actually laying the traces
879 880 881 882 883 884
 *  Parameters:
 *      start on side target_side, of coordinates row_target, col_target.
 *      arrive on side masque_layer_start, coordinate row_source, col_source
 * The search is done in reverse routing, the point of arrival (target) to
 * the starting point (source)
 * The router.
885
 *
886 887
 * Target_side = symbol (TOP / BOTTOM) of departure
 * = Mask_layer_source mask layers Arrival
888
 *
889 890 891
 * Returns:
 * 0 if error
 * > 0 if Ok
892
 */
893 894 895 896
static int Retrace( WinEDA_PcbFrame* pcbframe, wxDC* DC,
                    int row_source, int col_source,
                    int row_target, int col_target, int target_side,
                    int current_net_code )
897
{
898
    int  r0, c0, s0;
899 900
    int  r1, c1, s1;    /* row, col, starting side. */
    int  r2, c2, s2;    /* row, col, ending side. */
901 902 903 904 905 906 907 908
    int  x, y = -1;
    long b;

    r1 = row_target;
    c1 = col_target;    /* start point is target ( end point is source )*/
    s1 = target_side;
    r0 = c0 = s0 = ILLEGAL;

909
    wxASSERT( g_CurrentTrackList.GetCount() == 0 );
910 911 912 913 914 915 916 917 918

    do {
        /* find where we came from to get here */
        r2 = r1; c2 = c1; s2 = s1;
        x  = GetDir( r1, c1, s1 );

        switch( x )
        {
        case FROM_NORTH:
919 920
            r2++;
            break;
921 922

        case FROM_EAST:
923 924
            c2++;
            break;
925 926

        case FROM_SOUTH:
927 928
            r2--;
            break;
929 930

        case FROM_WEST:
931 932
            c2--;
            break;
933 934

        case FROM_NORTHEAST:
935 936 937
            r2++;
            c2++;
            break;
938 939

        case FROM_SOUTHEAST:
940 941 942
            r2--;
            c2++;
            break;
943 944

        case FROM_SOUTHWEST:
945 946 947
            r2--;
            c2--;
            break;
948 949

        case FROM_NORTHWEST:
950 951 952
            r2++;
            c2--;
            break;
953 954

        case FROM_OTHERSIDE:
955 956
            s2 = 1 - s2;
            break;
957 958

        default:
959 960
            DisplayError( pcbframe,
                          wxT( "Retrace: internal error: no way back" ) );
961 962 963 964 965 966 967
            return 0;
        }

        if( r0 != ILLEGAL )
            y = GetDir( r0, c0, s0 );

        /* see if target or hole */
968 969
        if( ( ( r1 == row_target ) && ( c1 == col_target ) )
           || ( s1 != s0 ) )
970 971 972 973 974 975
        {
            int p_dir;

            switch( x )
            {
            case FROM_NORTH:
976 977
                p_dir = HOLE_NORTH;
                break;
978 979

            case FROM_EAST:
980 981
                p_dir = HOLE_EAST;
                break;
982 983

            case FROM_SOUTH:
984 985
                p_dir = HOLE_SOUTH;
                break;
986 987

            case FROM_WEST:
988 989
                p_dir = HOLE_WEST;
                break;
990 991

            case FROM_NORTHEAST:
992 993
                p_dir = HOLE_NORTHEAST;
                break;
994 995

            case FROM_SOUTHEAST:
996 997
                p_dir = HOLE_SOUTHEAST;
                break;
998 999

            case FROM_SOUTHWEST:
1000 1001
                p_dir = HOLE_SOUTHWEST;
                break;
1002 1003

            case FROM_NORTHWEST:
1004 1005
                p_dir = HOLE_NORTHWEST;
                break;
1006 1007 1008 1009 1010 1011 1012

            case FROM_OTHERSIDE:
            default:
                DisplayError( pcbframe, wxT( "Retrace: error 1" ) );
                return 0;
            }

1013 1014
            OrCell_Trace(
                pcbframe->GetBoard(), r1, c1, s1, p_dir, current_net_code );
1015 1016 1017
        }
        else
        {
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
            if( ( y == FROM_NORTH || y == FROM_NORTHEAST
                  || y == FROM_EAST || y == FROM_SOUTHEAST
                  || y == FROM_SOUTH || y == FROM_SOUTHWEST
                  || y == FROM_WEST || y == FROM_NORTHWEST )
               && ( x == FROM_NORTH || x == FROM_NORTHEAST
                    || x == FROM_EAST || x == FROM_SOUTHEAST
                    || x == FROM_SOUTH || x == FROM_SOUTHWEST
                    || x == FROM_WEST || x == FROM_NORTHWEST
                    || x == FROM_OTHERSIDE )
               && ( ( b = bit[y - 1][x - 1] ) != 0 ) )
1028
            {
1029 1030
                OrCell_Trace( pcbframe->GetBoard(), r1, c1, s1, b,
                              current_net_code );
1031
                if( b & HOLE )
1032 1033
                    OrCell_Trace( pcbframe->GetBoard(), r2, c2, s2, HOLE,
                                  current_net_code );
1034 1035 1036 1037 1038 1039 1040 1041
            }
            else
            {
                DisplayError( pcbframe, wxT( "Retrace: error 2" ) );
                return 0;
            }
        }

1042 1043
        if( ( r2 == row_source ) && ( c2 == col_source ) ) /* see if source */
        {
1044 1045 1046 1047 1048
            int p_dir;

            switch( x )
            {
            case FROM_NORTH:
1049 1050
                p_dir = HOLE_SOUTH;
                break;
1051 1052

            case FROM_EAST:
1053 1054
                p_dir = HOLE_WEST;
                break;
1055 1056

            case FROM_SOUTH:
1057 1058
                p_dir = HOLE_NORTH;
                break;
1059 1060

            case FROM_WEST:
1061 1062
                p_dir = HOLE_EAST;
                break;
1063 1064

            case FROM_NORTHEAST:
1065 1066
                p_dir = HOLE_SOUTHWEST;
                break;
1067 1068

            case FROM_SOUTHEAST:
1069 1070
                p_dir = HOLE_NORTHWEST;
                break;
1071 1072

            case FROM_SOUTHWEST:
1073 1074
                p_dir = HOLE_NORTHEAST;
                break;
1075 1076

            case FROM_NORTHWEST:
1077 1078
                p_dir = HOLE_SOUTHEAST;
                break;
1079 1080 1081 1082 1083 1084 1085

            case FROM_OTHERSIDE:
            default:
                DisplayError( pcbframe, wxT( "Retrace: error 3" ) );
                return 0;
            }

1086 1087
            OrCell_Trace( pcbframe->GetBoard(), r2, c2, s2, p_dir,
                          current_net_code );
1088 1089
        }
        /* move to next cell */
1090 1091 1092 1093 1094 1095 1096
        r0 = r1;
        c0 = c1;
        s0 = s1;
        r1 = r2;
        c1 = c2;
        s1 = s2;
    } while( !( ( r2 == row_source ) && ( c2 == col_source ) ) );
1097 1098 1099

    Place_Piste_en_Buffer( pcbframe, DC );
    return 1;
1100 1101 1102
}


1103 1104 1105
/* This function is used by Retrace and read the autorouting matrix data cells to create
 * the real track on the physical board
 */
1106 1107
static void OrCell_Trace( BOARD* pcb, int col, int row,
                          int side, int orient, int current_net_code )
1108
{
1109
    int    dx0, dy0, dx1, dy1;
1110
    TRACK* newTrack;
1111

1112
    if( orient == HOLE )  // placement of a via
1113
    {
1114
        newTrack = new SEGVIA( pcb );
1115

1116
        g_CurrentTrackList.PushBack( newTrack );
1117 1118 1119

        g_CurrentTrackSegment->SetState( SEGM_AR, ON );
        g_CurrentTrackSegment->SetLayer( 0x0F );
1120

1121
        g_CurrentTrackSegment->m_Start.x   =
1122 1123
            g_CurrentTrackSegment->m_End.x = pcb->m_BoundaryBox.m_Pos.x +
                                             ( g_GridRoutingSize * row );
1124

1125
        g_CurrentTrackSegment->m_Start.y   =
1126 1127
            g_CurrentTrackSegment->m_End.y = pcb->m_BoundaryBox.m_Pos.y +
                                             ( g_GridRoutingSize * col );
1128

1129
        g_CurrentTrackSegment->m_Width = pcb->GetCurrentViaSize();
1130
        g_CurrentTrackSegment->m_Shape = pcb->GetBoardDesignSettings()->m_CurrentViaType;
1131

1132
        g_CurrentTrackSegment->SetNet( current_net_code );
1133
    }
1134
    else    // placement of a standard segment
1135
    {
1136
        newTrack = new TRACK( pcb );
1137

1138
        g_CurrentTrackList.PushBack( newTrack );
1139 1140 1141 1142 1143 1144

        g_CurrentTrackSegment->SetLayer( Route_Layer_BOTTOM );
        if( side == TOP )
            g_CurrentTrackSegment->SetLayer( Route_Layer_TOP );

        g_CurrentTrackSegment->SetState( SEGM_AR, ON );
1145 1146 1147 1148
        g_CurrentTrackSegment->m_End.x = pcb->m_BoundaryBox.m_Pos.x +
                                         ( g_GridRoutingSize * row );
        g_CurrentTrackSegment->m_End.y = pcb->m_BoundaryBox.m_Pos.y +
                                         ( g_GridRoutingSize * col );
1149
        g_CurrentTrackSegment->SetNet( current_net_code );
1150

1151
        if( g_CurrentTrackSegment->Back() == NULL ) /* Start trace. */
1152 1153 1154 1155
        {
            g_CurrentTrackSegment->m_Start.x = segm_fX;
            g_CurrentTrackSegment->m_Start.y = segm_fY;

1156 1157 1158 1159 1160
            /* Placement on the center of the pad if outside grid. */
            dx1 = g_CurrentTrackSegment->m_End.x -
                  g_CurrentTrackSegment->m_Start.x;
            dy1 = g_CurrentTrackSegment->m_End.y -
                  g_CurrentTrackSegment->m_Start.y;
1161

1162 1163 1164 1165
            dx0 = pt_cur_ch->m_PadEnd->GetPosition().x -
                  g_CurrentTrackSegment->m_Start.x;
            dy0 = pt_cur_ch->m_PadEnd->GetPosition().y -
                  g_CurrentTrackSegment->m_Start.y;
1166

1167 1168
            /* If aligned, change the origin point. */
            if( abs( dx0 * dy1 ) == abs( dx1 * dy0 ) )
1169
            {
1170 1171
                g_CurrentTrackSegment->m_Start =
                    pt_cur_ch->m_PadEnd->GetPosition();
1172
            }
1173
            else    // Creation of a supplemental segment
1174
            {
1175 1176
                g_CurrentTrackSegment->m_Start =
                    pt_cur_ch->m_PadEnd->GetPosition();
1177

1178 1179
                newTrack = g_CurrentTrackSegment->Copy();
                newTrack->m_Start = g_CurrentTrackSegment->m_End;
1180

1181
                g_CurrentTrackList.PushBack( newTrack );
1182 1183 1184 1185
            }
        }
        else
        {
1186
            if( g_CurrentTrackSegment->Back() )
1187
            {
1188 1189
                g_CurrentTrackSegment->m_Start =
                    g_CurrentTrackSegment->Back()->m_End;
1190 1191
            }
        }
1192
        g_CurrentTrackSegment->m_Width = pcb->GetCurrentTrackWidth();
1193

1194
        if( g_CurrentTrackSegment->m_Start != g_CurrentTrackSegment->m_End )
1195
        {
1196
            /* Reduce aligned segments by one. */
1197 1198
            TRACK* oldTrack = g_CurrentTrackSegment->Back();
            if( oldTrack &&  oldTrack->Type() != TYPE_VIA )
1199
            {
1200 1201 1202 1203
                dx1 = g_CurrentTrackSegment->m_End.x -
                      g_CurrentTrackSegment->m_Start.x;
                dy1 = g_CurrentTrackSegment->m_End.y -
                      g_CurrentTrackSegment->m_Start.y;
1204 1205 1206 1207

                dx0 = oldTrack->m_End.x - oldTrack->m_Start.x;
                dy0 = oldTrack->m_End.y - oldTrack->m_Start.y;

1208
                if( abs( dx0 * dy1 ) == abs( dx1 * dy0 ) )
1209
                {
1210
                    oldTrack->m_End = g_CurrentTrackSegment->m_End;
1211 1212

                    delete g_CurrentTrackList.PopBack();
1213 1214 1215 1216
                }
            }
        }
    }
1217 1218
}

1219

1220 1221 1222 1223
/* Insert the new track created in the list of tracks.
 * amend the points of beginning and end of the track so that they are
 * connected
 * Center on pads even if they are off grid.
1224
 */
1225
static void Place_Piste_en_Buffer( WinEDA_PcbFrame* pcbframe, wxDC* DC )
1226
{
1227 1228 1229 1230 1231
    if( g_FirstTrackSegment == NULL )
        return;

    int dx0, dy0, dx1, dy1;
    int marge, via_marge;
1232
    WinEDA_DrawPanel* panel = pcbframe->DrawPanel;
1233

1234 1235 1236
    marge = s_Clearance +
            ( pcbframe->GetBoard()->GetCurrentTrackWidth() / 2 );
    via_marge = s_Clearance + ( pcbframe->GetBoard()->GetCurrentViaSize() / 2 );
1237

1238 1239
    dx1 = g_CurrentTrackSegment->m_End.x - g_CurrentTrackSegment->m_Start.x;
    dy1 = g_CurrentTrackSegment->m_End.y - g_CurrentTrackSegment->m_Start.y;
1240

1241 1242 1243 1244 1245
    /* Place on center of pad if off grid. */
    dx0 = pt_cur_ch->m_PadStart->GetPosition().x -
          g_CurrentTrackSegment->m_Start.x;
    dy0 = pt_cur_ch->m_PadStart->GetPosition().y -
          g_CurrentTrackSegment->m_Start.y;
1246

1247 1248
    /* If aligned, change the origin point. */
    if( abs( dx0 * dy1 ) == abs( dx1 * dy0 ) )
1249
    {
1250
        g_CurrentTrackSegment->m_End = pt_cur_ch->m_PadStart->GetPosition();
1251
    }
1252
    else
1253
    {
1254
        TRACK* newTrack = g_CurrentTrackSegment->Copy();
1255

1256
        newTrack->m_End   = pt_cur_ch->m_PadStart->GetPosition();
1257
        newTrack->m_Start = g_CurrentTrackSegment->m_End;
1258

1259
        g_CurrentTrackList.PushBack( newTrack );
1260
    }
1261

1262 1263
    g_FirstTrackSegment->start = Locate_Pad_Connecte(
        pcbframe->GetBoard(), g_FirstTrackSegment, START );
1264 1265
    if( g_FirstTrackSegment->start )
        g_FirstTrackSegment->SetState( BEGIN_ONPAD, ON );
1266

1267 1268
    g_CurrentTrackSegment->end = Locate_Pad_Connecte(
        pcbframe->GetBoard(), g_CurrentTrackSegment, END );
1269 1270
    if( g_CurrentTrackSegment->end )
        g_CurrentTrackSegment->SetState( END_ONPAD, ON );
1271

1272
    /* Out the new track on the matrix board */
1273
    for( TRACK* track = g_FirstTrackSegment; track; track = track->Next() )
1274
    {
1275
        TraceSegmentPcb( pcbframe->GetBoard(), track, HOLE, marge, WRITE_CELL );
1276 1277
        TraceSegmentPcb( pcbframe->GetBoard(), track, VIA_IMPOSSIBLE,
                         via_marge, WRITE_OR_CELL );
1278
    }
1279

1280 1281 1282 1283 1284 1285 1286
    // Insert new segments in  real board
    int    netcode    = g_FirstTrackSegment->GetNet();
    TRACK* firstTrack = g_FirstTrackSegment;
    int    newCount   = g_CurrentTrackList.GetCount();

    // Put entire new current segment list in BOARD
    TRACK* track;
1287 1288 1289
    TRACK* insertBeforeMe =
        g_CurrentTrackSegment->GetBestInsertPoint( pcbframe->GetBoard() );

1290 1291 1292 1293 1294 1295 1296 1297 1298
    while( ( track = g_CurrentTrackList.PopFront() ) != NULL )
    {
        pcbframe->GetBoard()->m_Track.Insert( track, insertBeforeMe );
    }

    Trace_Une_Piste( panel, DC, firstTrack, newCount, GR_OR );

    pcbframe->test_1_net_connexion( DC, netcode );

1299
    ActiveScreen->SetModify();
1300
}