6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996 Thomas Nau
9 * This module, rats.c, was written and is Copyright (C) 1997 by harry eaton
10 * this module is also subject to the GNU GPL as described below
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 * Added support for minimum length rat lines 6/13/97
31 * rat lines to nearest line/via 8/29/98
32 * support for netlist window 10/24/98
60 #ifdef HAVE_LIBDMALLOC
67 #define TRIEDFIRST 0x1
70 /* ---------------------------------------------------------------------------
71 * some forward declarations
73 static bool FindPad (char *, char *, ConnectionType
*, bool);
74 static bool ParseConnection (char *, char *, char *);
75 static bool DrawShortestRats (NetListTypePtr
, void (*)(register ConnectionTypePtr
, register ConnectionTypePtr
, register RouteStyleTypePtr
));
76 static bool GatherSubnets (NetListTypePtr
, bool, bool);
77 static bool CheckShorts (LibraryMenuTypePtr
);
78 static void TransferNet (NetListTypePtr
, NetTypePtr
, NetTypePtr
);
80 /* ---------------------------------------------------------------------------
81 * some local identifiers
83 static bool badnet
= false;
84 static Cardinal SLayer
, CLayer
; /* layer group holding solder/component side */
86 /* ---------------------------------------------------------------------------
87 * parse a connection description from a string
88 * puts the element name in the string and the pin number in
89 * the number. If a valid connection is found, it returns the
90 * number of characters processed from the string, otherwise
94 ParseConnection (char *InString
, char *ElementName
, char *PinNum
)
98 /* copy element name portion */
99 for (j
= 0; InString
[j
] != '\0' && InString
[j
] != '-'; j
++)
100 ElementName
[j
] = InString
[j
];
101 if (InString
[j
] == '-')
103 for (i
= j
; i
> 0 && ElementName
[i
- 1] >= 'a'; i
--);
104 ElementName
[i
] = '\0';
105 for (i
= 0, j
++; InString
[j
] != '\0'; i
++, j
++)
106 PinNum
[i
] = InString
[j
];
112 ElementName
[j
] = '\0';
113 Message (_("Bad net-list format encountered near: \"%s\"\n"),
119 /* ---------------------------------------------------------------------------
120 * Find a particular pad from an element name and pin number
123 FindPad (char *ElementName
, char *PinNum
, ConnectionType
* conn
, bool Same
)
125 ElementTypePtr element
;
128 if ((element
= SearchElementByName (PCB
->Data
, ElementName
)) == NULL
)
131 for (i
= element
->Pad
; i
!= NULL
; i
= g_list_next (i
))
133 PadType
*pad
= i
->data
;
135 if (NSTRCMP (PinNum
, pad
->Number
) == 0 &&
136 (!Same
|| !TEST_FLAG (DRCFLAG
, pad
)))
138 conn
->type
= PAD_TYPE
;
139 conn
->ptr1
= element
;
141 conn
->group
= TEST_FLAG (ONSOLDERFLAG
, pad
) ? SLayer
: CLayer
;
143 if (TEST_FLAG (EDGE2FLAG
, pad
))
145 conn
->X
= pad
->Point2
.X
;
146 conn
->Y
= pad
->Point2
.Y
;
150 conn
->X
= pad
->Point1
.X
;
151 conn
->Y
= pad
->Point1
.Y
;
157 for (i
= element
->Pin
; i
!= NULL
; i
= g_list_next (i
))
159 PinType
*pin
= i
->data
;
161 if (!TEST_FLAG (HOLEFLAG
, pin
) &&
162 pin
->Number
&& NSTRCMP (PinNum
, pin
->Number
) == 0 &&
163 (!Same
|| !TEST_FLAG (DRCFLAG
, pin
)))
165 conn
->type
= PIN_TYPE
;
166 conn
->ptr1
= element
;
168 conn
->group
= SLayer
; /* any layer will do */
178 /*--------------------------------------------------------------------------
179 * parse a netlist menu entry and locate the corresponding pad
180 * returns true if found, and fills in Connection information
183 SeekPad (LibraryEntryType
* entry
, ConnectionType
* conn
, bool Same
)
186 char ElementName
[256];
189 if (ParseConnection (entry
->ListEntry
, ElementName
, PinNum
))
191 for (j
= 0; PinNum
[j
] != '\0'; j
++);
194 Message (_("Error! Netlist file is missing pin!\n"
195 "white space after \"%s-\"\n"), ElementName
);
200 if (FindPad (ElementName
, PinNum
, conn
, Same
))
204 if (PinNum
[j
- 1] < '0' || PinNum
[j
- 1] > '9')
206 Message ("WARNING! Pin number ending with '%c'"
207 " encountered in netlist file\n"
208 "Probably a bad netlist file format\n", PinNum
[j
- 1]);
211 Message (_("Can't find %s pin %s called for in netlist.\n"),
212 ElementName
, PinNum
);
216 /* ---------------------------------------------------------------------------
217 * Read the library-netlist build a true Netlist structure
221 ProcNetlist (LibraryTypePtr net_menu
)
223 ConnectionTypePtr connection
;
224 ConnectionType LastPoint
;
226 static NetListTypePtr Wantlist
= NULL
;
228 if (!net_menu
->MenuN
)
230 FreeNetListMemory (Wantlist
);
234 /* find layer groups of the component side and solder side */
235 SLayer
= GetLayerGroupNumberByNumber (solder_silk_layer
);
236 CLayer
= GetLayerGroupNumberByNumber (component_silk_layer
);
238 Wantlist
= (NetListTypePtr
)calloc (1, sizeof (NetListType
));
241 ALLPIN_LOOP (PCB
->Data
);
244 CLEAR_FLAG (DRCFLAG
, pin
);
247 ALLPAD_LOOP (PCB
->Data
);
250 CLEAR_FLAG (DRCFLAG
, pad
);
253 MENU_LOOP (net_menu
);
255 if (menu
->Name
[0] == '*' || menu
->flag
== 0)
260 net
= GetNetMemory (Wantlist
);
265 if (style
->Name
&& !NSTRCMP (style
->Name
, menu
->Style
))
273 else /* default to NULL if none found */
277 if (SeekPad (entry
, &LastPoint
, false))
279 if (TEST_FLAG (DRCFLAG
, (PinTypePtr
) LastPoint
.ptr2
))
281 ("Error! Element %s pin %s appears multiple times in the netlist file.\n"),
282 NAMEONPCB_NAME ((ElementTypePtr
) LastPoint
.ptr1
),
284 PIN_TYPE
) ? ((PinTypePtr
) LastPoint
.ptr2
)->
285 Number
: ((PadTypePtr
) LastPoint
.ptr2
)->Number
);
288 connection
= GetConnectionMemory (net
);
289 *connection
= LastPoint
;
290 /* indicate expect net */
291 connection
->menu
= menu
;
292 /* mark as visited */
293 SET_FLAG (DRCFLAG
, (PinTypePtr
) LastPoint
.ptr2
);
294 if (LastPoint
.type
== PIN_TYPE
)
295 ((PinTypePtr
) LastPoint
.ptr2
)->Spare
= (void *) menu
;
297 ((PadTypePtr
) LastPoint
.ptr2
)->Spare
= (void *) menu
;
302 /* check for more pins with the same number */
303 for (; SeekPad (entry
, &LastPoint
, true);)
305 connection
= GetConnectionMemory (net
);
306 *connection
= LastPoint
;
307 /* indicate expect net */
308 connection
->menu
= menu
;
309 /* mark as visited */
310 SET_FLAG (DRCFLAG
, (PinTypePtr
) LastPoint
.ptr2
);
311 if (LastPoint
.type
== PIN_TYPE
)
312 ((PinTypePtr
) LastPoint
.ptr2
)->Spare
= (void *) menu
;
314 ((PadTypePtr
) LastPoint
.ptr2
)->Spare
= (void *) menu
;
321 /* clear all visit marks */
322 ALLPIN_LOOP (PCB
->Data
);
324 CLEAR_FLAG (DRCFLAG
, pin
);
327 ALLPAD_LOOP (PCB
->Data
);
329 CLEAR_FLAG (DRCFLAG
, pad
);
336 * copy all connections from one net into another
337 * and then remove the first net from its netlist
340 TransferNet (NetListTypePtr Netl
, NetTypePtr SourceNet
, NetTypePtr DestNet
)
342 ConnectionTypePtr conn
;
344 /* It would be worth checking if SourceNet is NULL here to avoid a segfault. Seb James. */
345 CONNECTION_LOOP (SourceNet
);
347 conn
= GetConnectionMemory (DestNet
);
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
));
361 CheckShorts (LibraryMenuTypePtr theNet
)
363 bool newone
, warn
= false;
364 PointerListTypePtr generic
= (PointerListTypePtr
)calloc (1, sizeof (PointerListType
));
365 /* the first connection was starting point so
366 * the menu is always non-null
368 void **menu
= GetPointerMemory (generic
);
371 ALLPIN_LOOP (PCB
->Data
);
373 if (TEST_FLAG (DRCFLAG
, pin
))
378 Message (_("Warning! Net \"%s\" is shorted to %s pin %s\n"),
380 UNKNOWN (NAMEONPCB_NAME (element
)),
381 UNKNOWN (pin
->Number
));
382 SET_FLAG (WARNFLAG
, pin
);
386 POINTER_LOOP (generic
);
388 if (*ptr
== pin
->Spare
)
397 menu
= GetPointerMemory (generic
);
399 Message (_("Warning! Net \"%s\" is shorted to net \"%s\"\n"),
401 &((LibraryMenuTypePtr
) (pin
->Spare
))->Name
[2]);
402 SET_FLAG (WARNFLAG
, pin
);
407 ALLPAD_LOOP (PCB
->Data
);
409 if (TEST_FLAG (DRCFLAG
, pad
))
414 Message (_("Warning! Net \"%s\" is shorted to %s pad %s\n"),
416 UNKNOWN (NAMEONPCB_NAME (element
)),
417 UNKNOWN (pad
->Number
));
418 SET_FLAG (WARNFLAG
, pad
);
422 POINTER_LOOP (generic
);
424 if (*ptr
== pad
->Spare
)
433 menu
= GetPointerMemory (generic
);
435 Message (_("Warning! Net \"%s\" is shorted to net \"%s\"\n"),
437 &((LibraryMenuTypePtr
) (pad
->Spare
))->Name
[2]);
438 SET_FLAG (WARNFLAG
, pad
);
443 FreePointerListMemory (generic
);
449 /* ---------------------------------------------------------------------------
450 * Determine existing interconnections of the net and gather into sub-nets
452 * initially the netlist has each connection in its own individual net
453 * afterwards there can be many fewer nets with multiple connections each
456 GatherSubnets (NetListTypePtr Netl
, bool NoWarn
, bool AndRats
)
459 ConnectionTypePtr conn
;
463 for (m
= 0; Netl
->NetN
> 0 && m
< Netl
->NetN
; m
++)
466 ResetConnections (false);
467 RatFindHook (a
->Connection
[0].type
, a
->Connection
[0].ptr1
,
468 a
->Connection
[0].ptr2
, a
->Connection
[0].ptr2
, false,
470 /* now anybody connected to the first point has DRCFLAG set */
471 /* so move those to this subnet */
472 CLEAR_FLAG (DRCFLAG
, (PinTypePtr
) a
->Connection
[0].ptr2
);
473 for (n
= m
+ 1; n
< Netl
->NetN
; n
++)
476 /* There can be only one connection in net b */
477 if (TEST_FLAG (DRCFLAG
, (PinTypePtr
) b
->Connection
[0].ptr2
))
479 CLEAR_FLAG (DRCFLAG
, (PinTypePtr
) b
->Connection
[0].ptr2
);
480 TransferNet (Netl
, b
, a
);
481 /* back up since new subnet is now at old index */
485 /* now add other possible attachment points to the subnet */
486 /* e.g. line end-points and vias */
487 /* don't add non-manhattan lines, the auto-router can't route to them */
488 ALLLINE_LOOP (PCB
->Data
);
490 if (TEST_FLAG (DRCFLAG
, line
)
491 && ((line
->Point1
.X
== line
->Point2
.X
)
492 || (line
->Point1
.Y
== line
->Point2
.Y
)))
494 conn
= GetConnectionMemory (a
);
495 conn
->X
= line
->Point1
.X
;
496 conn
->Y
= line
->Point1
.Y
;
497 conn
->type
= LINE_TYPE
;
500 conn
->group
= GetLayerGroupNumberByPointer (layer
);
501 conn
->menu
= NULL
; /* agnostic view of where it belongs */
502 conn
= GetConnectionMemory (a
);
503 conn
->X
= line
->Point2
.X
;
504 conn
->Y
= line
->Point2
.Y
;
505 conn
->type
= LINE_TYPE
;
508 conn
->group
= GetLayerGroupNumberByPointer (layer
);
513 /* add polygons so the auto-router can see them as targets */
514 ALLPOLYGON_LOOP (PCB
->Data
);
516 if (TEST_FLAG (DRCFLAG
, polygon
))
518 conn
= GetConnectionMemory (a
);
519 /* make point on a vertex */
520 conn
->X
= polygon
->Clipped
->contours
->head
.point
[0];
521 conn
->Y
= polygon
->Clipped
->contours
->head
.point
[1];
522 conn
->type
= POLYGON_TYPE
;
524 conn
->ptr2
= polygon
;
525 conn
->group
= GetLayerGroupNumberByPointer (layer
);
526 conn
->menu
= NULL
; /* agnostic view of where it belongs */
530 VIA_LOOP (PCB
->Data
);
532 if (TEST_FLAG (DRCFLAG
, via
))
534 conn
= GetConnectionMemory (a
);
537 conn
->type
= VIA_TYPE
;
540 conn
->group
= SLayer
;
545 Warned
|= CheckShorts (a
->Connection
[0].menu
);
547 ResetConnections (false);
551 /* ---------------------------------------------------------------------------
552 * Draw a rat net (tree) having the shortest lines
553 * this also frees the subnet memory as they are consumed
555 * Note that the Netl we are passed is NOT the main netlist - it's the
556 * connectivity for ONE net. It represents the CURRENT connectivity
557 * state for the net, with each Netl->Net[N] representing one
558 * copper-connected subset of the net.
562 DrawShortestRats (NetListTypePtr Netl
, void (*funcp
) (register ConnectionTypePtr
, register ConnectionTypePtr
, register RouteStyleTypePtr
))
565 register float distance
, temp
;
566 register ConnectionTypePtr conn1
, conn2
, firstpoint
, secondpoint
;
567 PolygonTypePtr polygon
;
568 bool changed
= false;
571 NetTypePtr next
, subnet
, theSubnet
= NULL
;
573 /* This is just a sanity check, to make sure we're passed
576 if (!Netl
|| Netl
->NetN
< 1)
580 * Everything inside the NetList Netl should be connected together.
581 * Each Net in Netl is a group of Connections which are already
582 * connected together somehow, either by real wires or by rats we've
583 * already drawn. Each Connection is a vertex within that blob of
584 * connected items. This loop finds the closest vertex pairs between
585 * each blob and draws rats that merge the blobs until there's just
588 * Just to clarify, with some examples:
590 * Each Netl is one full net from a netlist, like from gnetlist.
591 * Each Netl->Net[N] is a subset of that net that's already
592 * physically connected on the pcb.
594 * So a new design with no traces yet, would have a huge list of Net[N],
595 * each with one pin in it.
597 * A fully routed design would have one Net[N] with all the pins
598 * (for that net) in it.
602 * We keep doing this do/while loop until everything's connected.
603 * I.e. once per rat we add.
606 havepoints
= true; /* so we run the loop at least once */
607 while (Netl
->NetN
> 1 && havepoints
)
609 /* This is the top of the "find one rat" logic. */
611 firstpoint
= secondpoint
= NULL
;
613 /* Test Net[0] vs Net[N] for N=1..max. Find the shortest
614 distance between any two points in different blobs. */
615 subnet
= &Netl
->Net
[0];
616 for (j
= 1; j
< Netl
->NetN
; j
++)
619 * Scan between Net[0] blob (subnet) and Net[N] blob (next).
620 * Note the shortest distance we find.
622 next
= &Netl
->Net
[j
];
623 for (n
= subnet
->ConnectionN
- 1; n
!= -1; n
--)
625 conn1
= &subnet
->Connection
[n
];
626 for (m
= next
->ConnectionN
- 1; m
!= -1; m
--)
628 conn2
= &next
->Connection
[m
];
630 * At this point, conn1 and conn2 are two pins in
631 * different blobs of the same net. See how far
632 * apart they are, and if they're "closer" than what
637 * Prefer to connect Connections over polygons to the
638 * polygons (ie assume the user wants a via to a plane,
639 * not a daisy chain). Further prefer to pick an existing
640 * via in the Net to make that connection.
642 if (conn1
->type
== POLYGON_TYPE
&&
643 (polygon
= (PolygonTypePtr
)conn1
->ptr2
) &&
645 firstpoint
&& firstpoint
->type
== VIA_TYPE
) &&
646 IsPointInPolygonIgnoreHoles (conn2
->X
, conn2
->Y
, polygon
))
654 else if (conn2
->type
== POLYGON_TYPE
&&
655 (polygon
= (PolygonTypePtr
)conn2
->ptr2
) &&
657 firstpoint
&& firstpoint
->type
== VIA_TYPE
) &&
658 IsPointInPolygonIgnoreHoles (conn1
->X
, conn1
->Y
, polygon
))
666 else if ((temp
= SQUARE (conn1
->X
- conn2
->X
) +
667 SQUARE (conn1
->Y
- conn2
->Y
)) < distance
|| !firstpoint
)
680 * If HAVEPOINTS is true, we've found a pair of points in two
681 * separate blobs of the net, and need to connect them together.
687 (*funcp
) (firstpoint
, secondpoint
, subnet
->Style
);
691 /* found the shortest distance subnet, draw the rat */
692 if ((line
= CreateNewRat (PCB
->Data
,
693 firstpoint
->X
, firstpoint
->Y
,
694 secondpoint
->X
, secondpoint
->Y
,
695 firstpoint
->group
, secondpoint
->group
,
696 Settings
.RatThickness
,
697 NoFlags ())) != NULL
)
700 SET_FLAG (VIAFLAG
, line
);
701 AddObjectToCreateUndoList (RATLINE_TYPE
, line
, line
, line
);
707 /* copy theSubnet into the current subnet */
708 TransferNet (Netl
, theSubnet
, subnet
);
712 /* presently nothing to do with the new subnet */
713 /* so we throw it away and free the space */
714 FreeNetMemory (&Netl
->Net
[--(Netl
->NetN
)]);
715 /* Sadly adding a rat line messes up the sorted arrays in connection finder */
716 /* hace: perhaps not necessarily now that they aren't stored in normal layers */
719 FreeConnectionLookupMemory ();
720 InitConnectionLookup ();
726 /* ---------------------------------------------------------------------------
727 * AddAllRats puts the rats nest into the layout from the loaded netlist
728 * if SelectedOnly is true, it will only draw rats to selected pins and pads
731 AddAllRats (bool SelectedOnly
, void (*funcp
) (register ConnectionTypePtr
, register ConnectionTypePtr
, register RouteStyleTypePtr
))
733 NetListTypePtr Nets
, Wantlist
;
735 ConnectionTypePtr onepin
;
736 bool changed
, Warned
= false;
738 /* the netlist library has the text form
739 * ProcNetlist fills in the Netlist
740 * structure the way the final routing
741 * is supposed to look
743 Wantlist
= ProcNetlist (&PCB
->NetlistLib
);
746 Message (_("Can't add rat lines because no netlist is loaded.\n"));
750 /* initialize finding engine */
751 InitConnectionLookup ();
752 SaveFindFlag (DRCFLAG
);
753 Nets
= (NetListTypePtr
)calloc (1, sizeof (NetListType
));
754 /* now we build another netlist (Nets) for each
755 * net in Wantlist that shows how it actually looks now,
756 * then fill in any missing connections with rat lines.
758 * we first assume each connection is separate
759 * (no routing), then gather them into groups
760 * if the net is all routed, the new netlist (Nets)
761 * will have only one net entry.
762 * Note that DrawShortestRats consumes all nets
763 * from Nets, so *Nets is empty after the
764 * DrawShortestRats call
768 CONNECTION_LOOP (net
);
771 || TEST_FLAG (SELECTEDFLAG
, (PinTypePtr
) connection
->ptr2
))
773 lonesome
= GetNetMemory (Nets
);
774 onepin
= GetConnectionMemory (lonesome
);
775 *onepin
= *connection
;
776 lonesome
->Style
= net
->Style
;
780 Warned
|= GatherSubnets (Nets
, SelectedOnly
, true);
782 changed
|= DrawShortestRats (Nets
, funcp
);
785 FreeNetListMemory (Nets
);
787 FreeConnectionLookupMemory ();
792 if (Warned
|| changed
)
796 Settings
.RatWarn
= true;
800 IncrementUndoSerialNumber ();
801 if (PCB
->Data
->RatN
> 0)
803 Message ("%d rat line%s remaining\n", PCB
->Data
->RatN
,
804 PCB
->Data
->RatN
> 1 ? "s" : "");
808 if (!SelectedOnly
&& !Warned
)
810 if (!PCB
->Data
->RatN
&& !badnet
)
811 Message (_("Congratulations!!\n"
812 "The layout is complete and has no shorted nets.\n"));
814 Message (_("Nothing more to add, but there are\n"
815 "either rat-lines in the layout, disabled nets\n"
816 "in the net-list, or missing components\n"));
821 /* XXX: This is copied in large part from AddAllRats above; for
822 * maintainability, AddAllRats probably wants to be tweaked to use this
823 * version of the code so that we don't have duplication. */
825 CollectSubnets (bool SelectedOnly
)
827 NetListListType result
= { 0, 0, NULL
};
828 NetListTypePtr Nets
, Wantlist
;
830 ConnectionTypePtr onepin
;
832 /* the netlist library has the text form
833 * ProcNetlist fills in the Netlist
834 * structure the way the final routing
835 * is supposed to look
837 Wantlist
= ProcNetlist (&PCB
->NetlistLib
);
840 Message (_("Can't add rat lines because no netlist is loaded.\n"));
843 /* initialize finding engine */
844 InitConnectionLookup ();
845 SaveFindFlag (DRCFLAG
);
846 /* now we build another netlist (Nets) for each
847 * net in Wantlist that shows how it actually looks now,
848 * then fill in any missing connections with rat lines.
850 * we first assume each connection is separate
851 * (no routing), then gather them into groups
852 * if the net is all routed, the new netlist (Nets)
853 * will have only one net entry.
854 * Note that DrawShortestRats consumes all nets
855 * from Nets, so *Nets is empty after the
856 * DrawShortestRats call
860 Nets
= GetNetListMemory (&result
);
861 CONNECTION_LOOP (net
);
864 || TEST_FLAG (SELECTEDFLAG
, (PinTypePtr
) connection
->ptr2
))
866 lonesome
= GetNetMemory (Nets
);
867 onepin
= GetConnectionMemory (lonesome
);
868 *onepin
= *connection
;
869 lonesome
->Style
= net
->Style
;
873 /* Note that AndRats is *FALSE* here! */
874 GatherSubnets (Nets
, SelectedOnly
, false);
877 FreeConnectionLookupMemory ();
883 * Check to see if a particular name is the name of an already existing rats
887 rat_used (char *name
)
892 MENU_LOOP (&PCB
->NetlistLib
);
894 if (menu
->Name
&& (strcmp (menu
->Name
, name
) == 0))
902 /* These next two functions moved from the original netlist.c as part of the
903 | gui code separation for the Gtk port.
908 static int ratDrawn
= 0;
909 char name1
[256], *name2
;
910 Cardinal group1
, group2
;
913 void *ptr1
, *ptr2
, *ptr3
;
914 LibraryMenuTypePtr menu
;
915 LibraryEntryTypePtr entry
;
917 if (Crosshair
.AttachedLine
.Point1
.X
== Crosshair
.AttachedLine
.Point2
.X
918 && Crosshair
.AttachedLine
.Point1
.Y
== Crosshair
.AttachedLine
.Point2
.Y
)
921 found
= SearchObjectByLocation (PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr2
, &ptr3
,
922 Crosshair
.AttachedLine
.Point1
.X
,
923 Crosshair
.AttachedLine
.Point1
.Y
, 5);
924 if (found
== NO_TYPE
)
926 Message (_("No pad/pin under rat line\n"));
929 if (NAMEONPCB_NAME ((ElementTypePtr
) ptr1
) == NULL
930 || *NAMEONPCB_NAME ((ElementTypePtr
) ptr1
) == 0)
932 Message (_("You must name the starting element first\n"));
936 /* will work for pins to since the FLAG is common */
937 group1
= (TEST_FLAG (ONSOLDERFLAG
, (PadTypePtr
) ptr2
) ?
938 GetLayerGroupNumberByNumber (solder_silk_layer
) :
939 GetLayerGroupNumberByNumber (component_silk_layer
));
940 strcpy (name1
, ConnectionName (found
, ptr1
, ptr2
));
941 found
= SearchObjectByLocation (PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr2
, &ptr3
,
942 Crosshair
.AttachedLine
.Point2
.X
,
943 Crosshair
.AttachedLine
.Point2
.Y
, 5);
944 if (found
== NO_TYPE
)
946 Message (_("No pad/pin under rat line\n"));
949 if (NAMEONPCB_NAME ((ElementTypePtr
) ptr1
) == NULL
950 || *NAMEONPCB_NAME ((ElementTypePtr
) ptr1
) == 0)
952 Message (_("You must name the ending element first\n"));
955 group2
= (TEST_FLAG (ONSOLDERFLAG
, (PadTypePtr
) ptr2
) ?
956 GetLayerGroupNumberByNumber (solder_silk_layer
) :
957 GetLayerGroupNumberByNumber (component_silk_layer
));
958 name2
= ConnectionName (found
, ptr1
, ptr2
);
960 menu
= netnode_to_netname (name1
);
963 if (netnode_to_netname (name2
))
966 ("Both connections already in netlist - cannot merge nets\n"));
969 entry
= GetLibraryEntryMemory (menu
);
970 entry
->ListEntry
= strdup (name2
);
971 netnode_to_netname (name2
);
974 /* ok, the first name did not belong to a net */
975 menu
= netnode_to_netname (name2
);
978 entry
= GetLibraryEntryMemory (menu
);
979 entry
->ListEntry
= strdup (name1
);
980 netnode_to_netname (name1
);
985 * neither belong to a net, so create a new one.
987 * before creating a new rats here, we need to search
990 sprintf (ratname
, " ratDrawn%i", ++ratDrawn
);
991 while (rat_used (ratname
))
993 sprintf (ratname
, " ratDrawn%i", ++ratDrawn
);
996 menu
= GetLibraryMenuMemory (&PCB
->NetlistLib
);
997 menu
->Name
= strdup (ratname
);
998 entry
= GetLibraryEntryMemory (menu
);
999 entry
->ListEntry
= strdup (name1
);
1000 entry
= GetLibraryEntryMemory (menu
);
1001 entry
->ListEntry
= strdup (name2
);
1006 return (CreateNewRat (PCB
->Data
, Crosshair
.AttachedLine
.Point1
.X
,
1007 Crosshair
.AttachedLine
.Point1
.Y
,
1008 Crosshair
.AttachedLine
.Point2
.X
,
1009 Crosshair
.AttachedLine
.Point2
.Y
,
1010 group1
, group2
, Settings
.RatThickness
, NoFlags ()));
1015 ConnectionName (int type
, void *ptr1
, void *ptr2
)
1017 static char name
[256];
1023 num
= ((PinTypePtr
) ptr2
)->Number
;
1026 num
= ((PadTypePtr
) ptr2
)->Number
;
1031 strcpy (name
, UNKNOWN (NAMEONPCB_NAME ((ElementTypePtr
) ptr1
)));
1033 strcat (name
, UNKNOWN (num
));