~ubuntu-branches/ubuntu/precise/pcb/precise

« back to all changes in this revision

Viewing changes to src/rats.c

  • Committer: Bazaar Package Importer
  • Author(s): Hamish Moffatt
  • Date: 2005-02-20 13:14:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050220131400-pfz66g5vhx0azl8f
Tags: 1.99j+20050127-2
* Improved package description: (closes: #295405)
* Fixed dependency: tk84 -> tk8.4 (closes: #295404)
* Updated README.debian (closes: #269578)
* Applied patch to src/djopt.c to allow compilation with gcc-4.0
  (closes: #294319), thanks to Andreas Jochens for the patch.
* Prevent example files from being compressed

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: rats.c,v 1.17 2004/11/19 03:08:10 haceaton Exp $ */
 
2
 
1
3
/*
2
4
 *                            COPYRIGHT
3
5
 *
28
30
 * Added support for minimum length rat lines 6/13/97
29
31
 * rat lines to nearest line/via 8/29/98
30
32
 * support for netlist window 10/24/98
31
 
 */ 
 
33
 */
32
34
 
33
35
/* rats nest routines
34
36
 */
 
37
#ifdef HAVE_CONFIG_H
 
38
#include "config.h"
 
39
#endif
 
40
 
35
41
#include <math.h>
36
42
#include <stdio.h>
37
43
 
50
56
#include "set.h"
51
57
#include "undo.h"
52
58
 
 
59
#ifdef HAVE_LIBDMALLOC
 
60
#include <dmalloc.h>
 
61
#endif
 
62
 
 
63
RCSID("$Id: rats.c,v 1.17 2004/11/19 03:08:10 haceaton Exp $");
 
64
 
 
65
 
53
66
#define TRIEDFIRST 0x1
54
67
#define BESTFOUND 0x2
55
68
 
56
69
/* ---------------------------------------------------------------------------
57
70
 * some forward declarations
58
71
 */
59
 
static  NetListTypePtr  ProcNetlist(LibraryTypePtr);
60
 
static  Boolean         FindPad(char *, char *, ConnectionType *);
61
 
static  Boolean         ParseConnection(char *, char *, char *);
62
 
static  Boolean         DrawShortestRats(NetListTypePtr);
63
 
static  Boolean         GatherSubnets(NetListTypePtr, Boolean);
64
 
static  Boolean         CheckShorts(LibraryMenuTypePtr);
65
 
static  void            TransferNet(NetListTypePtr, NetTypePtr, NetTypePtr);
 
72
static Boolean FindPad (char *, char *, ConnectionType *, Boolean);
 
73
static Boolean ParseConnection (char *, char *, char *);
 
74
static Boolean DrawShortestRats (NetListTypePtr, void (*)());
 
75
static Boolean GatherSubnets (NetListTypePtr, Boolean, Boolean);
 
76
static Boolean CheckShorts (LibraryMenuTypePtr);
 
77
static void TransferNet (NetListTypePtr, NetTypePtr, NetTypePtr);
66
78
 
67
79
/* ---------------------------------------------------------------------------
68
80
 * some local identifiers
69
81
 */
70
 
static  Boolean                 badnet = False;
71
 
static  Cardinal                SLayer, CLayer;  /* layer group holding solder/component side */
 
82
static Boolean badnet = False;
 
83
static Cardinal SLayer, CLayer; /* layer group holding solder/component side */
72
84
 
73
85
/* ---------------------------------------------------------------------------
74
86
 * parse a connection description from a string
77
89
 * number of characters processed from the string, otherwise
78
90
 * it returns 0
79
91
 */
80
 
static Boolean ParseConnection(char *InString, char *ElementName, char *PinNum)
 
92
static Boolean
 
93
ParseConnection (char *InString, char *ElementName, char *PinNum)
81
94
{
82
 
        int     i, j;
 
95
  int i, j;
83
96
 
84
 
                /* copy element name portion */
85
 
        for (j = 0; InString[j] != '\0' && InString[j] != '-';  j++)
86
 
                ElementName[j] = InString[j];
87
 
        if (InString[j] == '-')
88
 
        {
89
 
                for (i = j; i > 0 && ElementName[i-1] >= 'a'; i--);
90
 
                ElementName[i] = '\0';
91
 
                for (i = 0, j++; InString[j] != '\0'; i++, j++)
92
 
                        PinNum[i] = InString[j];
93
 
                PinNum[i] = '\0';
94
 
                return(False);
95
 
        }
96
 
        else
97
 
        {
98
 
                ElementName[j] = '\0';
99
 
                Message("Bad net-list format encountered near: \"%s\"\n",
100
 
                        ElementName);
101
 
                return(True);
102
 
        }
 
97
  /* copy element name portion */
 
98
  for (j = 0; InString[j] != '\0' && InString[j] != '-'; j++)
 
99
    ElementName[j] = InString[j];
 
100
  if (InString[j] == '-')
 
101
    {
 
102
      for (i = j; i > 0 && ElementName[i - 1] >= 'a'; i--);
 
103
      ElementName[i] = '\0';
 
104
      for (i = 0, j++; InString[j] != '\0'; i++, j++)
 
105
        PinNum[i] = InString[j];
 
106
      PinNum[i] = '\0';
 
107
      return (False);
 
108
    }
 
109
  else
 
110
    {
 
111
      ElementName[j] = '\0';
 
112
      Message ("Bad net-list format encountered near: \"%s\"\n", ElementName);
 
113
      return (True);
 
114
    }
103
115
}
104
 
                        
 
116
 
105
117
/* ---------------------------------------------------------------------------
106
118
 * Find a particular pad from an element name and pin number
107
119
 */
108
 
static  Boolean FindPad(char *ElementName, char *PinNum, ConnectionType *conn)
 
120
static Boolean
 
121
FindPad (char *ElementName, char *PinNum, ConnectionType * conn, Boolean Same)
109
122
{
110
 
        ElementTypePtr  element;
111
 
        Cardinal        i;
112
 
        
113
 
        if ((element = SearchElementByName(PCB->Data, ElementName)) != NULL)
 
123
  ElementTypePtr element;
 
124
  Cardinal i;
 
125
 
 
126
  if ((element = SearchElementByName (PCB->Data, ElementName)) != NULL)
 
127
    {
 
128
      for (i = 0; i < element->PadN; i++)
 
129
        if (NSTRCMP (PinNum, element->Pad[i].Number) == 0 && (!Same
 
130
                                                             ||
 
131
                                                             !TEST_FLAG
 
132
                                                             (DRCFLAG,
 
133
                                                              &element->
 
134
                                                              Pad[i])))
 
135
          {
 
136
            conn->type = PAD_TYPE;
 
137
            conn->ptr2 = &element->Pad[i];
 
138
            conn->group =
 
139
              TEST_FLAG (ONSOLDERFLAG, &element->Pad[i]) ? SLayer : CLayer;
 
140
            if (TEST_FLAG (EDGE2FLAG, &element->Pad[i]))
 
141
              {
 
142
                conn->X = element->Pad[i].Point2.X;
 
143
                conn->Y = element->Pad[i].Point2.Y;
 
144
              }
 
145
            else
 
146
              {
 
147
                conn->X = element->Pad[i].Point1.X;
 
148
                conn->Y = element->Pad[i].Point1.Y;
 
149
              }
 
150
            break;
 
151
          }
 
152
      if (i == element->PadN)
114
153
        {
115
 
                for (i = 0; i < element->PadN; i++)
116
 
                        if (strcmp(PinNum, element->Pad[i].Number) == 0)
117
 
                        {
118
 
                                conn->type = PAD_TYPE;
119
 
                                conn->ptr2 = &element->Pad[i];
120
 
                                conn->group = TEST_FLAG(ONSOLDERFLAG, element) ? SLayer : CLayer;
121
 
                                conn->X = element->Pad[i].Point1.X;
122
 
                                conn->Y = element->Pad[i].Point1.Y;
123
 
                                break;
124
 
                        }
125
 
                if (i == element->PadN)
126
 
                {
127
 
                        for (i = 0; i < element->PinN; i++)
128
 
                                if (strcmp(PinNum, element->Pin[i].Number) == 0)
129
 
                                {
130
 
                                        conn->type = PIN_TYPE;
131
 
                                        conn->ptr2 = &element->Pin[i];
132
 
                                        conn->group = SLayer; /* any layer will do */
133
 
                                        conn->X = element->Pin[i].X;
134
 
                                        conn->Y = element->Pin[i].Y;
135
 
                                        break;
136
 
                                }
137
 
                        if (i == element->PinN)
138
 
                                return(False);
139
 
                }
140
 
                conn->ptr1 = element;
141
 
                return(True);
 
154
          for (i = 0; i < element->PinN; i++)
 
155
            if (!TEST_FLAG (HOLEFLAG, &element->Pin[i]) &&
 
156
                element->Pin[i].Number &&
 
157
                NSTRCMP (PinNum, element->Pin[i].Number) == 0 &&
 
158
                (!Same || !TEST_FLAG (DRCFLAG, &element->Pin[i])))
 
159
              {
 
160
                conn->type = PIN_TYPE;
 
161
                conn->ptr2 = &element->Pin[i];
 
162
                conn->group = SLayer;   /* any layer will do */
 
163
                conn->X = element->Pin[i].X;
 
164
                conn->Y = element->Pin[i].Y;
 
165
                break;
 
166
              }
 
167
          if (i == element->PinN)
 
168
            return (False);
142
169
        }
143
 
        return(False);
 
170
      conn->ptr1 = element;
 
171
      return (True);
 
172
    }
 
173
  return (False);
144
174
}
145
175
 
146
176
/*--------------------------------------------------------------------------
147
177
 * parse a netlist menu entry and locate the cooresponding pad
148
178
 * returns True if found, and fills in Connection information
149
179
 */
150
 
Boolean SeekPad(LibraryEntryType *entry, ConnectionType *conn)
 
180
Boolean
 
181
SeekPad (LibraryEntryType * entry, ConnectionType * conn, Boolean Same)
151
182
{
152
 
        int     j;
153
 
        char    ElementName[256];
154
 
        char    PinNum[256];
 
183
  int j;
 
184
  char ElementName[256];
 
185
  char PinNum[256];
155
186
 
156
 
        if (ParseConnection(entry->ListEntry, ElementName, PinNum))
157
 
                return(False);
158
 
        for (j = 0; PinNum[j] != '\0'; j++) ;
159
 
        if (j == 0)
160
 
        {
161
 
                Message("ERROR! Netlist file is missing pin!\n"
162
 
                        "white space after \"%s-\"\n", ElementName);
163
 
                badnet = True;
164
 
        }
165
 
        else
166
 
        {
167
 
                if (PinNum[j -1] < '0' || PinNum[j -1] > '9')
168
 
                {
169
 
                        Message("WARNING! Pin number ending with '%c'"
170
 
                                " encountered in netlist file\n"
171
 
                                "Probably a bad netlist file format\n", PinNum[j-1]);
172
 
                }
173
 
                if (FindPad(ElementName, PinNum, conn))
174
 
                        return(True);
175
 
        }
176
 
        Message("Can't find %s pin %s called for in netlist.\n",
177
 
                ElementName, PinNum);
178
 
        return(False);
 
187
  if (ParseConnection (entry->ListEntry, ElementName, PinNum))
 
188
    return (False);
 
189
  for (j = 0; PinNum[j] != '\0'; j++);
 
190
  if (j == 0)
 
191
    {
 
192
      Message ("ERROR! Netlist file is missing pin!\n"
 
193
               "white space after \"%s-\"\n", ElementName);
 
194
      badnet = True;
 
195
    }
 
196
  else
 
197
    {
 
198
      if (FindPad (ElementName, PinNum, conn, Same))
 
199
        return (True);
 
200
      if (Same)
 
201
        return (False);
 
202
      if (PinNum[j - 1] < '0' || PinNum[j - 1] > '9')
 
203
        {
 
204
          Message ("WARNING! Pin number ending with '%c'"
 
205
                   " encountered in netlist file\n"
 
206
                   "Probably a bad netlist file format\n", PinNum[j - 1]);
 
207
        }
 
208
    }
 
209
  Message ("Can't find %s pin %s called for in netlist.\n",
 
210
           ElementName, PinNum);
 
211
  return (False);
179
212
}
180
213
 
181
214
/* ---------------------------------------------------------------------------
182
215
 * Read the library-netlist build a true Netlist structure
183
216
 */
184
 
 
185
 
 static NetListTypePtr ProcNetlist(LibraryTypePtr net_menu)
186
 
 {
187
 
        ConnectionTypePtr       connection;
188
 
        ConnectionType          LastPoint;
189
 
        NetTypePtr              net;
190
 
        static NetListTypePtr   Wantlist = NULL;
191
 
        
192
 
        if (!net_menu->MenuN)
193
 
                return(NULL);
194
 
        FreeNetListMemory(Wantlist);
195
 
        badnet = False;
196
 
 
197
 
                /* find layer groups of the component side and solder side */
198
 
        SLayer = GetLayerGroupNumberByNumber(MAX_LAYER + SOLDER_LAYER);
199
 
        CLayer = GetLayerGroupNumberByNumber(MAX_LAYER + COMPONENT_LAYER);
200
 
 
201
 
        Wantlist = MyCalloc(1, sizeof(NetListType), "ProcNetlist()");
202
 
        if (Wantlist)
 
217
 
 
218
NetListTypePtr
 
219
ProcNetlist (LibraryTypePtr net_menu)
 
220
{
 
221
  ConnectionTypePtr connection;
 
222
  ConnectionType LastPoint;
 
223
  NetTypePtr net;
 
224
  static NetListTypePtr Wantlist = NULL;
 
225
 
 
226
  if (!net_menu->MenuN)
 
227
    return (NULL);
 
228
  FreeNetListMemory (Wantlist);
 
229
  MyFree ((char **) &Wantlist);
 
230
  badnet = False;
 
231
 
 
232
  /* find layer groups of the component side and solder side */
 
233
  SLayer = GetLayerGroupNumberByNumber (MAX_LAYER + SOLDER_LAYER);
 
234
  CLayer = GetLayerGroupNumberByNumber (MAX_LAYER + COMPONENT_LAYER);
 
235
 
 
236
  Wantlist = MyCalloc (1, sizeof (NetListType), "ProcNetlist()");
 
237
  if (Wantlist)
 
238
    {
 
239
      ALLPIN_LOOP (PCB->Data);
 
240
      {
 
241
        pin->Spare = NULL;
 
242
        CLEAR_FLAG (DRCFLAG, pin);
 
243
      }
 
244
      ENDALL_LOOP;
 
245
      ALLPAD_LOOP (PCB->Data);
 
246
      {
 
247
        pad->Spare = NULL;
 
248
        CLEAR_FLAG (DRCFLAG, pad);
 
249
      }
 
250
      ENDALL_LOOP;
 
251
      MENU_LOOP (net_menu);
 
252
      {
 
253
        if (menu->Name[0] == '*')
 
254
          {
 
255
            badnet = True;
 
256
            continue;
 
257
          }
 
258
        net = GetNetMemory (Wantlist);
 
259
        if (menu->Style)
 
260
          {
 
261
            STYLE_LOOP (PCB);
 
262
            {
 
263
              if (style->Name && !NSTRCMP (style->Name, menu->Style))
 
264
                {
 
265
                  net->Style = style;
 
266
                  break;
 
267
                }
 
268
            }
 
269
            END_LOOP;
 
270
          }
 
271
        else                    /* default to NULL if none found */
 
272
          net->Style = NULL;
 
273
        ENTRY_LOOP (menu);
203
274
        {
204
 
                ALLPIN_LOOP(PCB->Data, pin->Spare = NULL);
205
 
                ALLPAD_LOOP(PCB->Data, pad->Spare = NULL);
206
 
                MENU_LOOP(net_menu,
207
 
                        if (menu->Name[0] == '*')
208
 
                        {
209
 
                                badnet = True;
210
 
                                continue;
211
 
                        }
212
 
                        net = GetNetMemory(Wantlist);
213
 
                        ENTRY_LOOP(menu,
214
 
                                if (SeekPad(entry, &LastPoint))
215
 
                                {
216
 
                                        if (TEST_FLAG(DRCFLAG, (PinTypePtr) LastPoint.ptr2))
217
 
                                                Message("Argh - element %s pin %s appears multiple times\n"
218
 
                                                        "in the netlist file.   That's a problem.\n",
219
 
                                                        ((ElementTypePtr) LastPoint.ptr1)->Name,
220
 
                                                        (LastPoint.type == PIN_TYPE) ?
221
 
                                                        ((PinTypePtr) LastPoint.ptr2)->Number
222
 
                                                        : ((PadTypePtr) LastPoint.ptr2)->Number);
223
 
                                        else
224
 
                                        {
225
 
                                                connection = GetConnectionMemory(net);
226
 
                                                *connection = LastPoint;
227
 
                                                        /* indicate expect net */
228
 
                                                connection->menu = menu;
229
 
                                                        /* mark as visited */
230
 
                                                SET_FLAG(DRCFLAG, (PinTypePtr) LastPoint.ptr2);
231
 
                                                if (LastPoint.type == PIN_TYPE)
232
 
                                                        ((PinTypePtr) LastPoint.ptr2)->Spare =
233
 
                                                        (void *) menu;
234
 
                                                else
235
 
                                                        ((PadTypePtr) LastPoint.ptr2)->Spare =
236
 
                                                        (void *) menu;
237
 
                                        }
238
 
                                }
239
 
                                else
240
 
                                        badnet = True;
241
 
                        );
242
 
                );
 
275
          if (SeekPad (entry, &LastPoint, False))
 
276
            {
 
277
              if (TEST_FLAG (DRCFLAG, (PinTypePtr) LastPoint.ptr2))
 
278
                Message
 
279
                  ("Argh - element %s pin %s appears multiple times\n"
 
280
                   "in the netlist file.   That's a problem.\n",
 
281
                   NAMEONPCB_NAME ((ElementTypePtr)
 
282
                                   LastPoint.ptr1),
 
283
                   (LastPoint.type ==
 
284
                    PIN_TYPE) ? ((PinTypePtr) LastPoint.
 
285
                                 ptr2)->Number : ((PadTypePtr)
 
286
                                                  LastPoint.ptr2)->Number);
 
287
              else
 
288
                {
 
289
                  connection = GetConnectionMemory (net);
 
290
                  *connection = LastPoint;
 
291
                  /* indicate expect net */
 
292
                  connection->menu = menu;
 
293
                  /* mark as visited */
 
294
                  SET_FLAG (DRCFLAG, (PinTypePtr) LastPoint.ptr2);
 
295
                  if (LastPoint.type == PIN_TYPE)
 
296
                    ((PinTypePtr) LastPoint.ptr2)->Spare = (void *) menu;
 
297
                  else
 
298
                    ((PadTypePtr) LastPoint.ptr2)->Spare = (void *) menu;
 
299
                }
 
300
            }
 
301
          else
 
302
            badnet = True;
 
303
          /* check for more pins with the same number */
 
304
          for (; SeekPad (entry, &LastPoint, True);)
 
305
            {
 
306
              connection = GetConnectionMemory (net);
 
307
              *connection = LastPoint;
 
308
              /* indicate expect net */
 
309
              connection->menu = menu;
 
310
              /* mark as visited */
 
311
              SET_FLAG (DRCFLAG, (PinTypePtr) LastPoint.ptr2);
 
312
              if (LastPoint.type == PIN_TYPE)
 
313
                ((PinTypePtr) LastPoint.ptr2)->Spare = (void *) menu;
 
314
              else
 
315
                ((PadTypePtr) LastPoint.ptr2)->Spare = (void *) menu;
 
316
            }
243
317
        }
244
 
                /* clear all visit marks */
245
 
        ALLPIN_LOOP(PCB->Data, CLEAR_FLAG(DRCFLAG, pin));
246
 
        ALLPAD_LOOP(PCB->Data, CLEAR_FLAG(DRCFLAG, pad));
247
 
        return(Wantlist);
 
318
        END_LOOP;
 
319
      }
 
320
      END_LOOP;
 
321
    }
 
322
  /* clear all visit marks */
 
323
  ALLPIN_LOOP (PCB->Data);
 
324
  {
 
325
    CLEAR_FLAG (DRCFLAG, pin);
 
326
  }
 
327
  ENDALL_LOOP;
 
328
  ALLPAD_LOOP (PCB->Data);
 
329
  {
 
330
    CLEAR_FLAG (DRCFLAG, pad);
 
331
  }
 
332
  ENDALL_LOOP;
 
333
  return (Wantlist);
248
334
}
249
335
 
250
336
/*
251
337
 * copy all connections from one net into another
252
338
 * and then remove the first net from its netlist
253
339
 */
254
 
static void TransferNet(NetListTypePtr Netl, NetTypePtr SourceNet, NetTypePtr DestNet)
255
 
{
256
 
        ConnectionTypePtr conn;
257
 
 
258
 
        CONNECTION_LOOP(SourceNet,
259
 
                conn = GetConnectionMemory(DestNet);
260
 
                *conn = *connection;
261
 
        );
262
 
                /* free the connection memory */
263
 
        FreeNetMemory(SourceNet);
264
 
                /* remove SourceNet from its netlist */
265
 
        *SourceNet = Netl->Net[--(Netl->NetN)];
266
 
                /* zero out old garbage */
267
 
        memset(&Netl->Net[Netl->NetN], 0, sizeof(NetType));
268
 
}
269
 
 
270
 
static Boolean CheckShorts(LibraryMenuTypePtr theNet)
271
 
{
272
 
        Boolean new, warn = False;
273
 
        PointerListTypePtr generic = MyCalloc(1, sizeof(PointerListType),
274
 
                "CheckShorts");
275
 
                /* the first connection was starting point so
276
 
                 * the menu is always non-null
277
 
                 */
278
 
        void **menu = GetPointerMemory(generic);
279
 
 
280
 
        *menu = theNet;
281
 
        ALLPIN_LOOP(PCB->Data,
282
 
                if (TEST_FLAG(DRCFLAG, pin))
283
 
                {
284
 
                        warn = True;
285
 
                        if (!pin->Spare)
286
 
                        {
287
 
                                Message("WARNING!! net \"%s\" is shorted"
288
 
                                " to %s pin %s\n", &theNet->Name[2],
289
 
                                NAMEONPCB_NAME(element), pin->Number);
290
 
                                SET_FLAG(WARNFLAG, pin);
291
 
                                continue;
292
 
                        }
293
 
                        new = True;
294
 
                        POINTER_LOOP(generic,
295
 
                                if (*ptr == pin->Spare)
296
 
                                {
297
 
                                        new = False;
298
 
                                        break;
299
 
                                }
300
 
                        );
301
 
                        if (new)
302
 
                        {
303
 
                                menu = GetPointerMemory(generic);
304
 
                                *menu = pin->Spare; 
305
 
                                Message("WARNING!! net \"%s\" is shorted"
306
 
                                " to net \"%s\"\n",
307
 
                                &theNet->Name[2],
308
 
                                &((LibraryMenuTypePtr) (pin->Spare))->Name[2]);
309
 
                        }
310
 
                }
311
 
        );
312
 
        ALLPAD_LOOP(PCB->Data,
313
 
                if (TEST_FLAG(DRCFLAG, pad))
314
 
                {
315
 
                        warn = True;
316
 
                        if (!pad->Spare)
317
 
                        {
318
 
                                Message("WARNING!! net \"%s\" is shorted"
319
 
                                " to %s pad %s\n", &theNet->Name[2],
320
 
                                NAMEONPCB_NAME(element), pad->Number);
321
 
                                SET_FLAG(WARNFLAG, pad);
322
 
                                continue;
323
 
                        }
324
 
                        new = True;
325
 
                        POINTER_LOOP(generic,
326
 
                                if (*ptr == pad->Spare)
327
 
                                {
328
 
                                        new = False;
329
 
                                        break;
330
 
                                }
331
 
                        );
332
 
                        if (new)
333
 
                        {
334
 
                                menu = GetPointerMemory(generic);
335
 
                                *menu = pad->Spare; 
336
 
                                Message("WARNING!! net \"%s\" is shorted"
337
 
                                " to net \"%s\"\n", &theNet->Name[2],
338
 
                                &((LibraryMenuTypePtr) (pad->Spare))->Name[2]);
339
 
                        }
340
 
                }
341
 
        );
342
 
        FreePointerListMemory(generic);
343
 
        SaveFree(generic);
344
 
        return(warn);
345
 
}
346
 
        
 
340
static void
 
341
TransferNet (NetListTypePtr Netl, NetTypePtr SourceNet, NetTypePtr DestNet)
 
342
{
 
343
  ConnectionTypePtr conn;
 
344
 
 
345
  CONNECTION_LOOP (SourceNet);
 
346
  {
 
347
    conn = GetConnectionMemory (DestNet);
 
348
    *conn = *connection;
 
349
  }
 
350
  END_LOOP;
 
351
  DestNet->Style = SourceNet->Style;
 
352
  /* free the connection memory */
 
353
  FreeNetMemory (SourceNet);
 
354
  /* remove SourceNet from its netlist */
 
355
  *SourceNet = Netl->Net[--(Netl->NetN)];
 
356
  /* zero out old garbage */
 
357
  memset (&Netl->Net[Netl->NetN], 0, sizeof (NetType));
 
358
}
 
359
 
 
360
static Boolean
 
361
CheckShorts (LibraryMenuTypePtr theNet)
 
362
{
 
363
  Boolean new, warn = False;
 
364
  PointerListTypePtr generic = MyCalloc (1, sizeof (PointerListType),
 
365
                                         "CheckShorts");
 
366
  /* the first connection was starting point so
 
367
   * the menu is always non-null
 
368
   */
 
369
  void **menu = GetPointerMemory (generic);
 
370
 
 
371
  *menu = theNet;
 
372
  ALLPIN_LOOP (PCB->Data);
 
373
  {
 
374
    if (TEST_FLAG (DRCFLAG, pin))
 
375
      {
 
376
        warn = True;
 
377
        if (!pin->Spare)
 
378
          {
 
379
            Message ("WARNING!! net \"%s\" is shorted"
 
380
                     " to %s pin %s\n", &theNet->Name[2],
 
381
                     UNKNOWN(NAMEONPCB_NAME (element)), UNKNOWN(pin->Number));
 
382
            SET_FLAG (WARNFLAG, pin);
 
383
            continue;
 
384
          }
 
385
        new = True;
 
386
        POINTER_LOOP (generic);
 
387
        {
 
388
          if (*ptr == pin->Spare)
 
389
            {
 
390
              new = False;
 
391
              break;
 
392
            }
 
393
        }
 
394
        END_LOOP;
 
395
        if (new)
 
396
          {
 
397
            menu = GetPointerMemory (generic);
 
398
            *menu = pin->Spare;
 
399
            Message ("WARNING!! net \"%s\" is shorted"
 
400
                     " to net \"%s\"\n",
 
401
                     &theNet->Name[2],
 
402
                     &((LibraryMenuTypePtr) (pin->Spare))->Name[2]);
 
403
            SET_FLAG (WARNFLAG, pin);
 
404
          }
 
405
      }
 
406
  }
 
407
  ENDALL_LOOP;
 
408
  ALLPAD_LOOP (PCB->Data);
 
409
  {
 
410
    if (TEST_FLAG (DRCFLAG, pad))
 
411
      {
 
412
        warn = True;
 
413
        if (!pad->Spare)
 
414
          {
 
415
            Message ("WARNING!! net \"%s\" is shorted"
 
416
                     " to %s pad %s\n", &theNet->Name[2],
 
417
                     UNKNOWN(NAMEONPCB_NAME (element)), UNKNOWN(pad->Number));
 
418
            SET_FLAG (WARNFLAG, pad);
 
419
            continue;
 
420
          }
 
421
        new = True;
 
422
        POINTER_LOOP (generic);
 
423
        {
 
424
          if (*ptr == pad->Spare)
 
425
            {
 
426
              new = False;
 
427
              break;
 
428
            }
 
429
        }
 
430
        END_LOOP;
 
431
        if (new)
 
432
          {
 
433
            menu = GetPointerMemory (generic);
 
434
            *menu = pad->Spare;
 
435
            Message ("WARNING!! net \"%s\" is shorted"
 
436
                     " to net \"%s\"\n", &theNet->Name[2],
 
437
                     &((LibraryMenuTypePtr) (pad->Spare))->Name[2]);
 
438
            SET_FLAG (WARNFLAG, pad);
 
439
          }
 
440
      }
 
441
  }
 
442
  ENDALL_LOOP;
 
443
  FreePointerListMemory (generic);
 
444
  SaveFree (generic);
 
445
  return (warn);
 
446
}
 
447
 
347
448
 
348
449
/* ---------------------------------------------------------------------------
349
450
 * Determine existing interconnections of the net and gather into sub-nets
351
452
 * initially the netlist has each connection in its own individual net
352
453
 * afterwards there can be many fewer nets with multiple connections each
353
454
 */
354
 
static  Boolean         GatherSubnets(NetListTypePtr Netl, Boolean NoWarn)
 
455
static Boolean
 
456
GatherSubnets (NetListTypePtr Netl, Boolean NoWarn, Boolean AndRats)
355
457
{
356
 
        NetTypePtr              a,b;
357
 
        ConnectionTypePtr       conn;
358
 
        Cardinal                m,n;
359
 
        Boolean                 Warned = False;
 
458
  NetTypePtr a, b;
 
459
  ConnectionTypePtr conn;
 
460
  Cardinal m, n;
 
461
  Boolean Warned = False;
360
462
 
361
 
        for (m = 0; Netl->NetN > 0 && m < Netl->NetN; m++)
 
463
  for (m = 0; Netl->NetN > 0 && m < Netl->NetN; m++)
 
464
    {
 
465
      a = &Netl->Net[m];
 
466
      ResetFoundPinsViasAndPads (False);
 
467
      ResetFoundLinesAndPolygons (False);
 
468
      RatFindHook (a->Connection[0].type, a->Connection[0].ptr1,
 
469
                   a->Connection[0].ptr2, a->Connection[0].ptr2, False,
 
470
                   AndRats);
 
471
      /* now anybody connected to the first point has DRCFLAG set */
 
472
      /* so move those to this subnet */
 
473
      CLEAR_FLAG (DRCFLAG, (PinTypePtr) a->Connection[0].ptr2);
 
474
      for (n = m + 1; n < Netl->NetN; n++)
362
475
        {
363
 
                a = &Netl->Net[m];
364
 
                ResetFoundPinsViasAndPads(False);
365
 
                ResetFoundLinesAndPolygons(False);
366
 
                RatFindHook(a->Connection[0].type, a->Connection[0].ptr1, 
367
 
                        a->Connection[0].ptr2, a->Connection[0].ptr2, False);
368
 
                        /* now anybody connected to the first point has DRCFLAG set */
369
 
                        /* so move those to this subnet */
370
 
                CLEAR_FLAG(DRCFLAG, (PinTypePtr)a->Connection[0].ptr2);
371
 
                for (n = m + 1; n < Netl->NetN; n++) 
372
 
                {
373
 
                        b = &Netl->Net[n];
374
 
                           /* There can be only one connection in net b */
375
 
                        if (TEST_FLAG(DRCFLAG, (PinTypePtr) b->Connection[0].ptr2))
376
 
                        {
377
 
                                CLEAR_FLAG(DRCFLAG, (PinTypePtr) b->Connection[0].ptr2);
378
 
                                TransferNet(Netl, b, a);
379
 
                           /* back up since new subnet is now at old index */
380
 
                                n--;
381
 
                        }
382
 
                }
383
 
                /* now add other possible attachment points to the subnet */
384
 
                /* e.g. line end-points and vias */
385
 
                ALLLINE_LOOP(PCB->Data,
386
 
                        if (TEST_FLAG(DRCFLAG, line))
387
 
                        {
388
 
                                conn = GetConnectionMemory(a);
389
 
                                conn->X = line->Point1.X;
390
 
                                conn->Y = line->Point1.Y;
391
 
                                conn->type = LINE_TYPE;
392
 
                                conn->ptr1 = layer;
393
 
                                conn->ptr2 = line;
394
 
                                conn->group = GetLayerGroupNumberByPointer(layer);
395
 
                                conn->menu = NULL; /* agnostic view of where it belongs */
396
 
                                conn = GetConnectionMemory(a);
397
 
                                conn->X = line->Point2.X;
398
 
                                conn->Y = line->Point2.Y;
399
 
                                conn->type = LINE_TYPE;
400
 
                                conn->ptr1 = layer;
401
 
                                conn->ptr2 = line;
402
 
                                conn->group = GetLayerGroupNumberByPointer(layer);
403
 
                                conn->menu = NULL;
404
 
                        }
405
 
                );
406
 
                VIA_LOOP(PCB->Data,
407
 
                        if (TEST_FLAG(DRCFLAG, via))
408
 
                        {
409
 
                                conn = GetConnectionMemory(a);
410
 
                                conn->X = via->X;
411
 
                                conn->Y = via->Y;
412
 
                                conn->type = VIA_TYPE;
413
 
                                conn->ptr1 = via;
414
 
                                conn->ptr2 = via;
415
 
                                conn->group = SLayer;
416
 
                        }
417
 
                );
418
 
                if (!NoWarn)
419
 
                        Warned |= CheckShorts(a->Connection[0].menu);
 
476
          b = &Netl->Net[n];
 
477
          /* There can be only one connection in net b */
 
478
          if (TEST_FLAG (DRCFLAG, (PinTypePtr) b->Connection[0].ptr2))
 
479
            {
 
480
              CLEAR_FLAG (DRCFLAG, (PinTypePtr) b->Connection[0].ptr2);
 
481
              TransferNet (Netl, b, a);
 
482
              /* back up since new subnet is now at old index */
 
483
              n--;
 
484
            }
420
485
        }
421
 
        ResetFoundPinsViasAndPads(False);
422
 
        ResetFoundLinesAndPolygons(False);
423
 
        return(Warned);
 
486
      /* now add other possible attachment points to the subnet */
 
487
      /* e.g. line end-points and vias */
 
488
      ALLLINE_LOOP (PCB->Data);
 
489
      {
 
490
        if (TEST_FLAG (DRCFLAG, line))
 
491
          {
 
492
            conn = GetConnectionMemory (a);
 
493
            conn->X = line->Point1.X;
 
494
            conn->Y = line->Point1.Y;
 
495
            conn->type = LINE_TYPE;
 
496
            conn->ptr1 = layer;
 
497
            conn->ptr2 = line;
 
498
            conn->group = GetLayerGroupNumberByPointer (layer);
 
499
            conn->menu = NULL;  /* agnostic view of where it belongs */
 
500
            conn = GetConnectionMemory (a);
 
501
            conn->X = line->Point2.X;
 
502
            conn->Y = line->Point2.Y;
 
503
            conn->type = LINE_TYPE;
 
504
            conn->ptr1 = layer;
 
505
            conn->ptr2 = line;
 
506
            conn->group = GetLayerGroupNumberByPointer (layer);
 
507
            conn->menu = NULL;
 
508
          }
 
509
      }
 
510
      ENDALL_LOOP;
 
511
      /* add rectangular polygons so the auto-router can see them as targets */
 
512
      ALLPOLYGON_LOOP (PCB->Data);
 
513
      {
 
514
        if (TEST_FLAG (DRCFLAG, polygon) && polygon->PointN == 4)
 
515
          {
 
516
            if (polygon->Points[0].X != polygon->Points[1].X &&
 
517
                polygon->Points[0].Y != polygon->Points[1].Y)
 
518
              continue;
 
519
            if (polygon->Points[1].X != polygon->Points[2].X &&
 
520
                polygon->Points[1].Y != polygon->Points[2].Y)
 
521
              continue;
 
522
            if (polygon->Points[2].X != polygon->Points[3].X &&
 
523
                polygon->Points[2].Y != polygon->Points[3].Y)
 
524
              continue;
 
525
            if (polygon->Points[0].X != polygon->Points[3].X &&
 
526
                polygon->Points[0].Y != polygon->Points[3].Y)
 
527
              continue;
 
528
            conn = GetConnectionMemory (a);
 
529
            /* make point just inside rectangle */
 
530
            conn->X = polygon->BoundingBox.X1+1;
 
531
            conn->Y = polygon->BoundingBox.Y1+1;
 
532
            conn->type = POLYGON_TYPE;
 
533
            conn->ptr1 = layer;
 
534
            conn->ptr2 = polygon;
 
535
            conn->group = GetLayerGroupNumberByPointer (layer);
 
536
            conn->menu = NULL;  /* agnostic view of where it belongs */
 
537
          }
 
538
      }
 
539
      ENDALL_LOOP;
 
540
      VIA_LOOP (PCB->Data);
 
541
      {
 
542
        if (TEST_FLAG (DRCFLAG, via))
 
543
          {
 
544
            conn = GetConnectionMemory (a);
 
545
            conn->X = via->X;
 
546
            conn->Y = via->Y;
 
547
            conn->type = VIA_TYPE;
 
548
            conn->ptr1 = via;
 
549
            conn->ptr2 = via;
 
550
            conn->group = SLayer;
 
551
          }
 
552
      }
 
553
      END_LOOP;
 
554
      if (!NoWarn)
 
555
        Warned |= CheckShorts (a->Connection[0].menu);
 
556
    }
 
557
  ResetFoundPinsViasAndPads (False);
 
558
  ResetFoundLinesAndPolygons (False);
 
559
  return (Warned);
424
560
}
425
561
 
426
562
/* ---------------------------------------------------------------------------
428
564
 * this also frees the subnet memory as they are consumed
429
565
 */
430
566
 
431
 
static  Boolean DrawShortestRats(NetListTypePtr Netl)
 
567
static Boolean
 
568
DrawShortestRats (NetListTypePtr Netl, void (*funcp) ())
432
569
{
433
 
        RatTypePtr                      line;
434
 
        register float                  distance, temp;
435
 
        register ConnectionTypePtr      conn1, conn2,
436
 
                                        firstpoint, secondpoint;
437
 
        Boolean                         changed = False;
438
 
        Cardinal                        n, m, j;
439
 
        NetTypePtr                      next, subnet, theSubnet;
 
570
  RatTypePtr line;
 
571
  register float distance, temp;
 
572
  register ConnectionTypePtr conn1, conn2, firstpoint, secondpoint;
 
573
  Boolean changed = False;
 
574
  Cardinal n, m, j;
 
575
  NetTypePtr next, subnet, theSubnet;
440
576
 
441
 
        while (Netl->NetN > 1)
 
577
  firstpoint = secondpoint = NULL;
 
578
  while (Netl->NetN > 1)
 
579
    {
 
580
      subnet = &Netl->Net[0];
 
581
      distance = SQUARE (MAX_COORD);
 
582
      for (j = 1; j < Netl->NetN; j++)
442
583
        {
443
 
           subnet = &Netl->Net[0];
444
 
           distance = 5e32;
445
 
           for (j = 1; j < Netl->NetN; j++)
446
 
           {
447
 
                next = &Netl->Net[j];
448
 
                for (n = subnet->ConnectionN -1; n != -1; n--)
 
584
          next = &Netl->Net[j];
 
585
          for (n = subnet->ConnectionN - 1; n != -1; n--)
 
586
            {
 
587
              conn1 = &subnet->Connection[n];
 
588
              for (m = next->ConnectionN - 1; m != -1; m--)
449
589
                {
450
 
                        conn1 = &subnet->Connection[n];
451
 
                        for (m = next->ConnectionN -1; m != -1; m--)
452
 
                        {
453
 
                                conn2 = &next->Connection[m];
454
 
                                if ((temp = (conn1->X - conn2->X)*(conn1->X - conn2->X) +
455
 
                                    (conn1->Y - conn2->Y)*(conn1->Y - conn2->Y)) < distance)
456
 
                                {
457
 
                                        distance = temp;
458
 
                                        firstpoint = conn1;
459
 
                                        secondpoint = conn2;
460
 
                                        theSubnet = next;
461
 
                                }
462
 
                        }
 
590
                  conn2 = &next->Connection[m];
 
591
                  if ((temp = SQUARE (conn1->X - conn2->X) +
 
592
                       SQUARE (conn1->Y - conn2->Y)) < distance)
 
593
                    {
 
594
                      distance = temp;
 
595
                      firstpoint = conn1;
 
596
                      secondpoint = conn2;
 
597
                      theSubnet = next;
 
598
                    }
463
599
                }
464
 
           }
465
 
                /* found the shortest distance subnet, draw the rat */
466
 
           if ((line = CreateNewRat(PCB->Data,
467
 
                firstpoint->X, firstpoint->Y, secondpoint->X, secondpoint->Y, 
468
 
                firstpoint->group, secondpoint->group, Settings.RatThickness,
469
 
                NOFLAG)) != NULL)
470
 
           {
471
 
                AddObjectToCreateUndoList(RATLINE_TYPE, line, line, line);
472
 
                DrawRat(line, 0);
473
 
                changed = True;
474
 
           }
475
 
           
476
 
                        /* copy theSubnet into the current subnet */
477
 
           TransferNet(Netl, theSubnet, subnet);
478
 
        }
479
 
                /* presently nothing to do with the new subnet */
480
 
                /* so we throw it away and free the space */
481
 
        FreeNetMemory(&Netl->Net[--(Netl->NetN)]);
482
 
                /* Sadly adding a rat line messes up the sorted arrays in connection finder */
483
 
                /* hace: perhaps not necessarily now that they aren't stored in normal layers */
484
 
        if (changed)
485
 
        {
486
 
                FreeConnectionLookupMemory();
487
 
                InitConnectionLookup();
488
 
        }
489
 
        return(changed);
 
600
            }
 
601
        }
 
602
      if (funcp)
 
603
        {
 
604
          (*funcp) (firstpoint, secondpoint, subnet->Style);
 
605
        }
 
606
      else
 
607
        {
 
608
          /* found the shortest distance subnet, draw the rat */
 
609
          if ((line = CreateNewRat (PCB->Data,
 
610
                                    firstpoint->X, firstpoint->Y,
 
611
                                    secondpoint->X, secondpoint->Y,
 
612
                                    firstpoint->group, secondpoint->group,
 
613
                                    Settings.RatThickness, NOFLAG)) != NULL)
 
614
            {
 
615
              AddObjectToCreateUndoList (RATLINE_TYPE, line, line, line);
 
616
              DrawRat (line, 0);
 
617
              changed = True;
 
618
            }
 
619
        }
 
620
 
 
621
      /* copy theSubnet into the current subnet */
 
622
      TransferNet (Netl, theSubnet, subnet);
 
623
    }
 
624
  /* presently nothing to do with the new subnet */
 
625
  /* so we throw it away and free the space */
 
626
  FreeNetMemory (&Netl->Net[--(Netl->NetN)]);
 
627
  /* Sadly adding a rat line messes up the sorted arrays in connection finder */
 
628
  /* hace: perhaps not necessarily now that they aren't stored in normal layers */
 
629
  if (changed)
 
630
    {
 
631
      FreeConnectionLookupMemory ();
 
632
      InitConnectionLookup ();
 
633
    }
 
634
  return (changed);
490
635
}
491
636
 
492
637
 
494
639
 *  AddAllRats puts the rats nest into the layout from the loaded netlist
495
640
 *  if SelectedOnly is true, it will only draw rats to selected pins and pads
496
641
 */
497
 
Boolean AddAllRats(Boolean SelectedOnly)
498
 
{
499
 
        NetListTypePtr          Nets, Wantlist;
500
 
        NetTypePtr              lonesome;
501
 
        ConnectionTypePtr       onepin;
502
 
        Boolean         changed, Warned = False;
503
 
 
504
 
                /* the netlist library has the text form
505
 
                 * ProcNetlist fills in the Netlist
506
 
                 * structure the way the final routing
507
 
                 * is supposed to look
508
 
                 */
509
 
        Wantlist = ProcNetlist(&PCB->NetlistLib);
510
 
        if (!Wantlist)
511
 
        {
512
 
                Message("Can't add rat lines because no netlist is loaded.\n");
513
 
                return(False);
514
 
        }
515
 
        changed = False;
516
 
                /* initialize finding engine */
517
 
        InitConnectionLookup();
518
 
        SaveFindFlag(DRCFLAG);
519
 
        Nets = MyCalloc(1, sizeof(NetListType), "AddAllRats()");
520
 
                        /* now we build another netlist (Nets) for each
521
 
                         * net in Wantlist that shows how it actually looks now,
522
 
                         * then fill in any missing connections with rat lines.
523
 
                         *
524
 
                         * we first assume each connection is separate
525
 
                         * (no routing), then gather them into groups
526
 
                         * if the net is all routed, the new netlist (Nets)
527
 
                         * will have only one net entry.
528
 
                         * Note that DrawShortestRats consumes all nets
529
 
                         * from Nets, so *Nets is empty after the
530
 
                         * DrawShortestRats call
531
 
                         */
532
 
        NET_LOOP(Wantlist,
533
 
                CONNECTION_LOOP(net,
534
 
                        if (!SelectedOnly || TEST_FLAG(SELECTEDFLAG, (PinTypePtr) connection->ptr2))
535
 
                        {
536
 
                                lonesome = GetNetMemory(Nets);
537
 
                                onepin = GetConnectionMemory(lonesome);
538
 
                                *onepin = *connection;
539
 
                        }
540
 
                );
541
 
                Warned |= GatherSubnets(Nets, SelectedOnly);
542
 
                if (Nets->NetN > 0)
543
 
                        changed |= DrawShortestRats(Nets);
544
 
        );
545
 
        FreeNetListMemory(Nets);
546
 
        FreeConnectionLookupMemory();
547
 
        RestoreFindFlag();
548
 
        if (Warned || changed)
549
 
                Draw();
550
 
        if (Warned)
551
 
                Settings.RatWarn = True;
552
 
        if (changed)
553
 
        {
554
 
                IncrementUndoSerialNumber();
555
 
                return(True);
556
 
        }
557
 
        if (!SelectedOnly && !Warned)
558
 
        {
559
 
                if (!PCB->Data->RatN && !badnet)
560
 
                        Message("Congratulations!!\n"
561
 
                          "The layout is complete!\n"
562
 
                          "And has no shorted nets.\n");
563
 
                else
564
 
                        Message("Nothing more to add, but there are\n"
565
 
                                "rat-lines in the layout, or disabled nets\n"
566
 
                                "in the net-list.\n");
567
 
        }
568
 
        return(False);
 
642
Boolean
 
643
AddAllRats (Boolean SelectedOnly, void (*funcp) ())
 
644
{
 
645
  NetListTypePtr Nets, Wantlist;
 
646
  NetTypePtr lonesome;
 
647
  ConnectionTypePtr onepin;
 
648
  Boolean changed, Warned = False;
 
649
 
 
650
  /* the netlist library has the text form
 
651
   * ProcNetlist fills in the Netlist
 
652
   * structure the way the final routing
 
653
   * is supposed to look
 
654
   */
 
655
  Wantlist = ProcNetlist (&PCB->NetlistLib);
 
656
  if (!Wantlist)
 
657
    {
 
658
      Message ("Can't add rat lines because no netlist is loaded.\n");
 
659
      return (False);
 
660
    }
 
661
  changed = False;
 
662
  /* initialize finding engine */
 
663
  InitConnectionLookup ();
 
664
  SaveFindFlag (DRCFLAG);
 
665
  Nets = MyCalloc (1, sizeof (NetListType), "AddAllRats()");
 
666
  /* now we build another netlist (Nets) for each
 
667
   * net in Wantlist that shows how it actually looks now,
 
668
   * then fill in any missing connections with rat lines.
 
669
   *
 
670
   * we first assume each connection is separate
 
671
   * (no routing), then gather them into groups
 
672
   * if the net is all routed, the new netlist (Nets)
 
673
   * will have only one net entry.
 
674
   * Note that DrawShortestRats consumes all nets
 
675
   * from Nets, so *Nets is empty after the
 
676
   * DrawShortestRats call
 
677
   */
 
678
  NET_LOOP (Wantlist);
 
679
  {
 
680
    CONNECTION_LOOP (net);
 
681
    {
 
682
      if (!SelectedOnly
 
683
          || TEST_FLAG (SELECTEDFLAG, (PinTypePtr) connection->ptr2))
 
684
        {
 
685
          lonesome = GetNetMemory (Nets);
 
686
          onepin = GetConnectionMemory (lonesome);
 
687
          *onepin = *connection;
 
688
          lonesome->Style = net->Style;
 
689
        }
 
690
    }
 
691
    END_LOOP;
 
692
    Warned |= GatherSubnets (Nets, SelectedOnly, True);
 
693
    if (Nets->NetN > 0)
 
694
      changed |= DrawShortestRats (Nets, funcp);
 
695
  }
 
696
  END_LOOP;
 
697
  FreeNetListMemory (Nets);
 
698
  FreeConnectionLookupMemory ();
 
699
  RestoreFindFlag ();
 
700
  if (funcp)
 
701
    return (True);
 
702
  if (Warned || changed)
 
703
    Draw ();
 
704
  if (Warned)
 
705
    Settings.RatWarn = True;
 
706
  if (changed)
 
707
    {
 
708
      IncrementUndoSerialNumber ();
 
709
      return (True);
 
710
    }
 
711
  if (!SelectedOnly && !Warned)
 
712
    {
 
713
      if (!PCB->Data->RatN && !badnet)
 
714
        Message ("Congratulations!!\n"
 
715
                 "The layout is complete!\n" "And has no shorted nets.\n");
 
716
      else
 
717
        Message ("Nothing more to add, but there are\n"
 
718
                 "either rat-lines in the layout, disabled nets\n"
 
719
                 "in the net-list, or missing components\n");
 
720
    }
 
721
  return (False);
 
722
}
 
723
 
 
724
/* XXX: This is copied in large part from AddAllRats above; for
 
725
 * maintainability, AddAllRats probably wants to be tweaked to use this
 
726
 * version of the code so that we don't have duplication. */
 
727
NetListListType
 
728
CollectSubnets (Boolean SelectedOnly)
 
729
{
 
730
  NetListListType result = { 0, 0, NULL };
 
731
  NetListTypePtr Nets, Wantlist;
 
732
  NetTypePtr lonesome;
 
733
  ConnectionTypePtr onepin;
 
734
 
 
735
  /* the netlist library has the text form
 
736
   * ProcNetlist fills in the Netlist
 
737
   * structure the way the final routing
 
738
   * is supposed to look
 
739
   */
 
740
  Wantlist = ProcNetlist (&PCB->NetlistLib);
 
741
  if (!Wantlist)
 
742
    {
 
743
      Message ("Can't add rat lines because no netlist is loaded.\n");
 
744
      return result;
 
745
    }
 
746
  /* initialize finding engine */
 
747
  InitConnectionLookup ();
 
748
  SaveFindFlag (DRCFLAG);
 
749
  /* now we build another netlist (Nets) for each
 
750
   * net in Wantlist that shows how it actually looks now,
 
751
   * then fill in any missing connections with rat lines.
 
752
   *
 
753
   * we first assume each connection is separate
 
754
   * (no routing), then gather them into groups
 
755
   * if the net is all routed, the new netlist (Nets)
 
756
   * will have only one net entry.
 
757
   * Note that DrawShortestRats consumes all nets
 
758
   * from Nets, so *Nets is empty after the
 
759
   * DrawShortestRats call
 
760
   */
 
761
  NET_LOOP (Wantlist);
 
762
  {
 
763
    Nets = GetNetListMemory (&result);
 
764
    CONNECTION_LOOP (net);
 
765
    {
 
766
      if (!SelectedOnly
 
767
          || TEST_FLAG (SELECTEDFLAG, (PinTypePtr) connection->ptr2))
 
768
        {
 
769
          lonesome = GetNetMemory (Nets);
 
770
          onepin = GetConnectionMemory (lonesome);
 
771
          *onepin = *connection;
 
772
          lonesome->Style = net->Style;
 
773
        }
 
774
    }
 
775
    END_LOOP;
 
776
    /* Note that AndRats is *FALSE* here! */
 
777
    GatherSubnets (Nets, SelectedOnly, False);
 
778
  }
 
779
  END_LOOP;
 
780
  FreeConnectionLookupMemory ();
 
781
  RestoreFindFlag ();
 
782
  return result;
569
783
}