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 (*)());
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
)
130 for (i
= 0; i
< element
->PadN
; i
++)
131 if (NSTRCMP (PinNum
, element
->Pad
[i
].Number
) == 0 && (!Same
138 conn
->type
= PAD_TYPE
;
139 conn
->ptr2
= &element
->Pad
[i
];
141 TEST_FLAG (ONSOLDERFLAG
, &element
->Pad
[i
]) ? SLayer
: CLayer
;
142 if (TEST_FLAG (EDGE2FLAG
, &element
->Pad
[i
]))
144 conn
->X
= element
->Pad
[i
].Point2
.X
;
145 conn
->Y
= element
->Pad
[i
].Point2
.Y
;
149 conn
->X
= element
->Pad
[i
].Point1
.X
;
150 conn
->Y
= element
->Pad
[i
].Point1
.Y
;
154 if (i
== element
->PadN
)
156 for (i
= 0; i
< element
->PinN
; i
++)
157 if (!TEST_FLAG (HOLEFLAG
, &element
->Pin
[i
]) &&
158 element
->Pin
[i
].Number
&&
159 NSTRCMP (PinNum
, element
->Pin
[i
].Number
) == 0 &&
160 (!Same
|| !TEST_FLAG (DRCFLAG
, &element
->Pin
[i
])))
162 conn
->type
= PIN_TYPE
;
163 conn
->ptr2
= &element
->Pin
[i
];
164 conn
->group
= SLayer
; /* any layer will do */
165 conn
->X
= element
->Pin
[i
].X
;
166 conn
->Y
= element
->Pin
[i
].Y
;
169 if (i
== element
->PinN
)
172 conn
->ptr1
= element
;
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
);
232 /* MYFREE (Wantlist); *//* awkward */
235 /* find layer groups of the component side and solder side */
236 SLayer
= GetLayerGroupNumberByNumber (max_layer
+ SOLDER_LAYER
);
237 CLayer
= GetLayerGroupNumberByNumber (max_layer
+ COMPONENT_LAYER
);
239 Wantlist
= MyCalloc (1, sizeof (NetListType
), "ProcNetlist()");
242 ALLPIN_LOOP (PCB
->Data
);
245 CLEAR_FLAG (DRCFLAG
, pin
);
248 ALLPAD_LOOP (PCB
->Data
);
251 CLEAR_FLAG (DRCFLAG
, pad
);
254 MENU_LOOP (net_menu
);
256 if (menu
->Name
[0] == '*' || menu
->flag
== 0)
261 net
= GetNetMemory (Wantlist
);
266 if (style
->Name
&& !NSTRCMP (style
->Name
, menu
->Style
))
274 else /* default to NULL if none found */
278 if (SeekPad (entry
, &LastPoint
, false))
280 if (TEST_FLAG (DRCFLAG
, (PinTypePtr
) LastPoint
.ptr2
))
282 ("Error! Element %s pin %s appears multiple times in the netlist file.\n"),
283 NAMEONPCB_NAME ((ElementTypePtr
) LastPoint
.ptr1
),
285 PIN_TYPE
) ? ((PinTypePtr
) LastPoint
.ptr2
)->
286 Number
: ((PadTypePtr
) LastPoint
.ptr2
)->Number
);
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
;
298 ((PadTypePtr
) LastPoint
.ptr2
)->Spare
= (void *) menu
;
303 /* check for more pins with the same number */
304 for (; SeekPad (entry
, &LastPoint
, true);)
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
;
315 ((PadTypePtr
) LastPoint
.ptr2
)->Spare
= (void *) menu
;
322 /* clear all visit marks */
323 ALLPIN_LOOP (PCB
->Data
);
325 CLEAR_FLAG (DRCFLAG
, pin
);
328 ALLPAD_LOOP (PCB
->Data
);
330 CLEAR_FLAG (DRCFLAG
, pad
);
337 * copy all connections from one net into another
338 * and then remove the first net from its netlist
341 TransferNet (NetListTypePtr Netl
, NetTypePtr SourceNet
, NetTypePtr DestNet
)
343 ConnectionTypePtr conn
;
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 new, warn
= false;
364 PointerListTypePtr generic
= MyCalloc (1, sizeof (PointerListType
),
366 /* the first connection was starting point so
367 * the menu is always non-null
369 void **menu
= GetPointerMemory (generic
);
372 ALLPIN_LOOP (PCB
->Data
);
374 if (TEST_FLAG (DRCFLAG
, pin
))
379 Message (_("Warning! Net \"%s\" is shorted to %s pin %s\n"),
381 UNKNOWN (NAMEONPCB_NAME (element
)),
382 UNKNOWN (pin
->Number
));
383 SET_FLAG (WARNFLAG
, pin
);
387 POINTER_LOOP (generic
);
389 if (*ptr
== pin
->Spare
)
398 menu
= GetPointerMemory (generic
);
400 Message (_("Warning! Net \"%s\" is shorted to net \"%s\"\n"),
402 &((LibraryMenuTypePtr
) (pin
->Spare
))->Name
[2]);
403 SET_FLAG (WARNFLAG
, pin
);
408 ALLPAD_LOOP (PCB
->Data
);
410 if (TEST_FLAG (DRCFLAG
, pad
))
415 Message (_("Warning! Net \"%s\" is shorted to %s pad %s\n"),
417 UNKNOWN (NAMEONPCB_NAME (element
)),
418 UNKNOWN (pad
->Number
));
419 SET_FLAG (WARNFLAG
, pad
);
423 POINTER_LOOP (generic
);
425 if (*ptr
== pad
->Spare
)
434 menu
= GetPointerMemory (generic
);
436 Message (_("Warning! Net \"%s\" is shorted to net \"%s\"\n"),
438 &((LibraryMenuTypePtr
) (pad
->Spare
))->Name
[2]);
439 SET_FLAG (WARNFLAG
, pad
);
444 FreePointerListMemory (generic
);
450 /* ---------------------------------------------------------------------------
451 * Determine existing interconnections of the net and gather into sub-nets
453 * initially the netlist has each connection in its own individual net
454 * afterwards there can be many fewer nets with multiple connections each
457 GatherSubnets (NetListTypePtr Netl
, bool NoWarn
, bool AndRats
)
460 ConnectionTypePtr conn
;
464 for (m
= 0; Netl
->NetN
> 0 && m
< Netl
->NetN
; m
++)
467 ResetFoundPinsViasAndPads (false);
468 ResetFoundLinesAndPolygons (false);
469 RatFindHook (a
->Connection
[0].type
, a
->Connection
[0].ptr1
,
470 a
->Connection
[0].ptr2
, a
->Connection
[0].ptr2
, false,
472 /* now anybody connected to the first point has DRCFLAG set */
473 /* so move those to this subnet */
474 CLEAR_FLAG (DRCFLAG
, (PinTypePtr
) a
->Connection
[0].ptr2
);
475 for (n
= m
+ 1; n
< Netl
->NetN
; n
++)
478 /* There can be only one connection in net b */
479 if (TEST_FLAG (DRCFLAG
, (PinTypePtr
) b
->Connection
[0].ptr2
))
481 CLEAR_FLAG (DRCFLAG
, (PinTypePtr
) b
->Connection
[0].ptr2
);
482 TransferNet (Netl
, b
, a
);
483 /* back up since new subnet is now at old index */
487 /* now add other possible attachment points to the subnet */
488 /* e.g. line end-points and vias */
489 /* don't add non-manhattan lines, the auto-router can't route to them */
490 ALLLINE_LOOP (PCB
->Data
);
492 if (TEST_FLAG (DRCFLAG
, line
)
493 && ((line
->Point1
.X
== line
->Point2
.X
)
494 || (line
->Point1
.Y
== line
->Point2
.Y
)))
496 conn
= GetConnectionMemory (a
);
497 conn
->X
= line
->Point1
.X
;
498 conn
->Y
= line
->Point1
.Y
;
499 conn
->type
= LINE_TYPE
;
502 conn
->group
= GetLayerGroupNumberByPointer (layer
);
503 conn
->menu
= NULL
; /* agnostic view of where it belongs */
504 conn
= GetConnectionMemory (a
);
505 conn
->X
= line
->Point2
.X
;
506 conn
->Y
= line
->Point2
.Y
;
507 conn
->type
= LINE_TYPE
;
510 conn
->group
= GetLayerGroupNumberByPointer (layer
);
515 /* add polygons so the auto-router can see them as targets */
516 ALLPOLYGON_LOOP (PCB
->Data
);
518 if (TEST_FLAG (DRCFLAG
, polygon
))
520 conn
= GetConnectionMemory (a
);
521 /* make point on a vertex */
522 conn
->X
= polygon
->Clipped
->contours
->head
.point
[0];
523 conn
->Y
= polygon
->Clipped
->contours
->head
.point
[1];
524 conn
->type
= POLYGON_TYPE
;
526 conn
->ptr2
= polygon
;
527 conn
->group
= GetLayerGroupNumberByPointer (layer
);
528 conn
->menu
= NULL
; /* agnostic view of where it belongs */
532 VIA_LOOP (PCB
->Data
);
534 if (TEST_FLAG (DRCFLAG
, via
))
536 conn
= GetConnectionMemory (a
);
539 conn
->type
= VIA_TYPE
;
542 conn
->group
= SLayer
;
547 Warned
|= CheckShorts (a
->Connection
[0].menu
);
549 ResetFoundPinsViasAndPads (false);
550 ResetFoundLinesAndPolygons (false);
554 /* ---------------------------------------------------------------------------
555 * Draw a rat net (tree) having the shortest lines
556 * this also frees the subnet memory as they are consumed
560 DrawShortestRats (NetListTypePtr Netl
, void (*funcp
) ())
563 register float distance
, temp
;
564 register ConnectionTypePtr conn1
, conn2
, firstpoint
, secondpoint
;
565 PolygonTypePtr polygon
;
566 bool changed
= false;
568 NetTypePtr next
, subnet
, theSubnet
= NULL
;
571 * Everything inside the NetList Netl should be connected together.
572 * Each Net in Netl is a group of Connections which are already
573 * connected together somehow, either by real wires or by rats we've
574 * already drawn. Each Connection is a vertex within that blob of
575 * connected items. This loop finds the closest vertex pairs between
576 * each blob and draws rats that merge the blobs until there's just
580 while (Netl
->NetN
> 1)
582 firstpoint
= secondpoint
= NULL
;
583 subnet
= &Netl
->Net
[0];
584 for (j
= 1; j
< Netl
->NetN
; j
++)
586 next
= &Netl
->Net
[j
];
587 for (n
= subnet
->ConnectionN
- 1; n
!= -1; n
--)
589 conn1
= &subnet
->Connection
[n
];
590 for (m
= next
->ConnectionN
- 1; m
!= -1; m
--)
592 conn2
= &next
->Connection
[m
];
594 * Prefer to connect Connections over polygons to the
595 * polygons (ie assume the user wants a via to a plane,
596 * not a daisy chain). Further prefer to pick an existing
597 * via in the Net to make that connection.
599 if (conn1
->type
== POLYGON_TYPE
&&
600 (polygon
= (PolygonTypePtr
)conn1
->ptr2
) &&
602 firstpoint
&& firstpoint
->type
== VIA_TYPE
) &&
603 IsPointInPolygonIgnoreHoles (conn2
->X
, conn2
->Y
, polygon
))
610 else if (conn2
->type
== POLYGON_TYPE
&&
611 (polygon
= (PolygonTypePtr
)conn2
->ptr2
) &&
613 firstpoint
&& firstpoint
->type
== VIA_TYPE
) &&
614 IsPointInPolygonIgnoreHoles (conn1
->X
, conn1
->Y
, polygon
))
621 else if ((temp
= SQUARE (conn1
->X
- conn2
->X
) +
622 SQUARE (conn1
->Y
- conn2
->Y
)) < distance
|| !firstpoint
)
634 (*funcp
) (firstpoint
, secondpoint
, subnet
->Style
);
638 /* found the shortest distance subnet, draw the rat */
639 if ((line
= CreateNewRat (PCB
->Data
,
640 firstpoint
->X
, firstpoint
->Y
,
641 secondpoint
->X
, secondpoint
->Y
,
642 firstpoint
->group
, secondpoint
->group
,
643 Settings
.RatThickness
,
644 NoFlags ())) != NULL
)
647 SET_FLAG (VIAFLAG
, line
);
648 AddObjectToCreateUndoList (RATLINE_TYPE
, line
, line
, line
);
654 /* copy theSubnet into the current subnet */
655 TransferNet (Netl
, theSubnet
, subnet
);
657 /* presently nothing to do with the new subnet */
658 /* so we throw it away and free the space */
659 FreeNetMemory (&Netl
->Net
[--(Netl
->NetN
)]);
660 /* Sadly adding a rat line messes up the sorted arrays in connection finder */
661 /* hace: perhaps not necessarily now that they aren't stored in normal layers */
664 FreeConnectionLookupMemory ();
665 InitConnectionLookup ();
671 /* ---------------------------------------------------------------------------
672 * AddAllRats puts the rats nest into the layout from the loaded netlist
673 * if SelectedOnly is true, it will only draw rats to selected pins and pads
676 AddAllRats (bool SelectedOnly
, void (*funcp
) ())
678 NetListTypePtr Nets
, Wantlist
;
680 ConnectionTypePtr onepin
;
681 bool changed
, Warned
= false;
683 /* the netlist library has the text form
684 * ProcNetlist fills in the Netlist
685 * structure the way the final routing
686 * is supposed to look
688 Wantlist
= ProcNetlist (&PCB
->NetlistLib
);
691 Message (_("Can't add rat lines because no netlist is loaded.\n"));
695 /* initialize finding engine */
696 InitConnectionLookup ();
697 SaveFindFlag (DRCFLAG
);
698 Nets
= MyCalloc (1, sizeof (NetListType
), "AddAllRats()");
699 /* now we build another netlist (Nets) for each
700 * net in Wantlist that shows how it actually looks now,
701 * then fill in any missing connections with rat lines.
703 * we first assume each connection is separate
704 * (no routing), then gather them into groups
705 * if the net is all routed, the new netlist (Nets)
706 * will have only one net entry.
707 * Note that DrawShortestRats consumes all nets
708 * from Nets, so *Nets is empty after the
709 * DrawShortestRats call
713 CONNECTION_LOOP (net
);
716 || TEST_FLAG (SELECTEDFLAG
, (PinTypePtr
) connection
->ptr2
))
718 lonesome
= GetNetMemory (Nets
);
719 onepin
= GetConnectionMemory (lonesome
);
720 *onepin
= *connection
;
721 lonesome
->Style
= net
->Style
;
725 Warned
|= GatherSubnets (Nets
, SelectedOnly
, true);
727 changed
|= DrawShortestRats (Nets
, funcp
);
730 FreeNetListMemory (Nets
);
732 FreeConnectionLookupMemory ();
737 if (Warned
|| changed
)
741 Settings
.RatWarn
= true;
745 IncrementUndoSerialNumber ();
746 if (PCB
->Data
->RatN
> 0)
748 Message ("%d rat line%s remaining\n", PCB
->Data
->RatN
,
749 PCB
->Data
->RatN
> 1 ? "s" : "");
753 if (!SelectedOnly
&& !Warned
)
755 if (!PCB
->Data
->RatN
&& !badnet
)
756 Message (_("Congratulations!!\n"
757 "The layout is complete and has no shorted nets.\n"));
759 Message (_("Nothing more to add, but there are\n"
760 "either rat-lines in the layout, disabled nets\n"
761 "in the net-list, or missing components\n"));
766 /* XXX: This is copied in large part from AddAllRats above; for
767 * maintainability, AddAllRats probably wants to be tweaked to use this
768 * version of the code so that we don't have duplication. */
770 CollectSubnets (bool SelectedOnly
)
772 NetListListType result
= { 0, 0, NULL
};
773 NetListTypePtr Nets
, Wantlist
;
775 ConnectionTypePtr onepin
;
777 /* the netlist library has the text form
778 * ProcNetlist fills in the Netlist
779 * structure the way the final routing
780 * is supposed to look
782 Wantlist
= ProcNetlist (&PCB
->NetlistLib
);
785 Message (_("Can't add rat lines because no netlist is loaded.\n"));
788 /* initialize finding engine */
789 InitConnectionLookup ();
790 SaveFindFlag (DRCFLAG
);
791 /* now we build another netlist (Nets) for each
792 * net in Wantlist that shows how it actually looks now,
793 * then fill in any missing connections with rat lines.
795 * we first assume each connection is separate
796 * (no routing), then gather them into groups
797 * if the net is all routed, the new netlist (Nets)
798 * will have only one net entry.
799 * Note that DrawShortestRats consumes all nets
800 * from Nets, so *Nets is empty after the
801 * DrawShortestRats call
805 Nets
= GetNetListMemory (&result
);
806 CONNECTION_LOOP (net
);
809 || TEST_FLAG (SELECTEDFLAG
, (PinTypePtr
) connection
->ptr2
))
811 lonesome
= GetNetMemory (Nets
);
812 onepin
= GetConnectionMemory (lonesome
);
813 *onepin
= *connection
;
814 lonesome
->Style
= net
->Style
;
818 /* Note that AndRats is *FALSE* here! */
819 GatherSubnets (Nets
, SelectedOnly
, false);
822 FreeConnectionLookupMemory ();
828 * Check to see if a particular name is the name of an already existing rats
832 rat_used (char *name
)
837 MENU_LOOP (&PCB
->NetlistLib
);
839 if (menu
->Name
&& (strcmp (menu
->Name
, name
) == 0))
847 /* These next two functions moved from the original netlist.c as part of the
848 | gui code separation for the Gtk port.
853 static int ratDrawn
= 0;
854 char name1
[256], *name2
;
855 Cardinal group1
, group2
;
858 void *ptr1
, *ptr2
, *ptr3
;
859 LibraryMenuTypePtr menu
;
860 LibraryEntryTypePtr entry
;
862 if (Crosshair
.AttachedLine
.Point1
.X
== Crosshair
.AttachedLine
.Point2
.X
863 && Crosshair
.AttachedLine
.Point1
.Y
== Crosshair
.AttachedLine
.Point2
.Y
)
866 found
= SearchObjectByLocation (PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr2
, &ptr3
,
867 Crosshair
.AttachedLine
.Point1
.X
,
868 Crosshair
.AttachedLine
.Point1
.Y
, 5);
869 if (found
== NO_TYPE
)
871 Message (_("No pad/pin under rat line\n"));
874 if (NAMEONPCB_NAME ((ElementTypePtr
) ptr1
) == NULL
875 || *NAMEONPCB_NAME ((ElementTypePtr
) ptr1
) == 0)
877 Message (_("You must name the starting element first\n"));
881 /* will work for pins to since the FLAG is common */
882 group1
= (TEST_FLAG (ONSOLDERFLAG
, (PadTypePtr
) ptr2
) ?
883 GetLayerGroupNumberByNumber (max_layer
+ SOLDER_LAYER
) :
884 GetLayerGroupNumberByNumber (max_layer
+ COMPONENT_LAYER
));
885 strcpy (name1
, ConnectionName (found
, ptr1
, ptr2
));
886 found
= SearchObjectByLocation (PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr2
, &ptr3
,
887 Crosshair
.AttachedLine
.Point2
.X
,
888 Crosshair
.AttachedLine
.Point2
.Y
, 5);
889 if (found
== NO_TYPE
)
891 Message (_("No pad/pin under rat line\n"));
894 if (NAMEONPCB_NAME ((ElementTypePtr
) ptr1
) == NULL
895 || *NAMEONPCB_NAME ((ElementTypePtr
) ptr1
) == 0)
897 Message (_("You must name the ending element first\n"));
900 group2
= (TEST_FLAG (ONSOLDERFLAG
, (PadTypePtr
) ptr2
) ?
901 GetLayerGroupNumberByNumber (max_layer
+ SOLDER_LAYER
) :
902 GetLayerGroupNumberByNumber (max_layer
+ COMPONENT_LAYER
));
903 name2
= ConnectionName (found
, ptr1
, ptr2
);
905 menu
= netnode_to_netname (name1
);
908 if (netnode_to_netname (name2
))
911 ("Both connections already in netlist - cannot merge nets\n"));
914 entry
= GetLibraryEntryMemory (menu
);
915 entry
->ListEntry
= MyStrdup (name2
, "AddNet");
916 netnode_to_netname (name2
);
919 /* ok, the first name did not belong to a net */
920 menu
= netnode_to_netname (name2
);
923 entry
= GetLibraryEntryMemory (menu
);
924 entry
->ListEntry
= MyStrdup (name1
, "AddNet");
925 netnode_to_netname (name1
);
930 * neither belong to a net, so create a new one.
932 * before creating a new rats here, we need to search
935 sprintf (ratname
, " ratDrawn%i", ++ratDrawn
);
936 while (rat_used (ratname
))
938 sprintf (ratname
, " ratDrawn%i", ++ratDrawn
);
941 menu
= GetLibraryMenuMemory (&PCB
->NetlistLib
);
942 menu
->Name
= MyStrdup (ratname
, "AddNet");
943 entry
= GetLibraryEntryMemory (menu
);
944 entry
->ListEntry
= MyStrdup (name1
, "AddNet");
945 entry
= GetLibraryEntryMemory (menu
);
946 entry
->ListEntry
= MyStrdup (name2
, "AddNet");
951 return (CreateNewRat (PCB
->Data
, Crosshair
.AttachedLine
.Point1
.X
,
952 Crosshair
.AttachedLine
.Point1
.Y
,
953 Crosshair
.AttachedLine
.Point2
.X
,
954 Crosshair
.AttachedLine
.Point2
.Y
,
955 group1
, group2
, Settings
.RatThickness
, NoFlags ()));
960 ConnectionName (int type
, void *ptr1
, void *ptr2
)
962 static char name
[256];
968 num
= ((PinTypePtr
) ptr2
)->Number
;
971 num
= ((PadTypePtr
) ptr2
)->Number
;
976 strcpy (name
, UNKNOWN (NAMEONPCB_NAME ((ElementTypePtr
) ptr1
)));
978 strcat (name
, UNKNOWN (num
));