4 * \brief Rats nest routines.
8 * <h1><b>Copyright.</b></h1>\n
10 * PCB, interactive printed circuit board design
12 * Copyright (C) 1994,1995,1996 Thomas Nau
14 * Copyright (C) 1997, harry eaton
16 * This module, rats.c, was written and is Copyright (C) 1997 by
19 * This module is also subject to the GNU GPL as described below.
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38 * Added support for minimum length rat lines 6/13/97
39 * rat lines to nearest line/via 8/29/98
40 * support for netlist window 10/24/98
66 #ifdef HAVE_LIBDMALLOC
70 #define TRIEDFIRST 0x1
73 /* ---------------------------------------------------------------------------
74 * some forward declarations
76 static bool FindPad (char *, char *, ConnectionType
*, bool);
77 static bool ParseConnection (char *, char *, char *);
78 static bool DrawShortestRats (NetListType
*, void (*)(register ConnectionType
*, register ConnectionType
*, register RouteStyleType
*));
79 static bool GatherSubnets (NetListType
*, bool, bool);
80 static bool CheckShorts (LibraryMenuType
*);
81 static void TransferNet (NetListType
*, NetType
*, NetType
*);
83 /* ---------------------------------------------------------------------------
84 * some local identifiers
86 static bool badnet
= false;
87 static Cardinal top_group
, bottom_group
; /* layer group holding top/bottom side */
90 * \brief Parse a connection description from a string.
92 * Puts the element name in the string and the pin number in
95 * \return If a valid connection is found, it returns the number of characters
96 * processed from the string, otherwise it returns 0.
99 ParseConnection (char *InString
, char *ElementName
, char *PinNum
)
103 /* copy element name portion */
104 for (j
= 0; InString
[j
] != '\0' && InString
[j
] != '-'; j
++)
105 ElementName
[j
] = InString
[j
];
106 if (InString
[j
] == '-')
108 for (i
= j
; i
> 0 && ElementName
[i
- 1] >= 'a'; i
--);
109 ElementName
[i
] = '\0';
110 for (i
= 0, j
++; InString
[j
] != '\0'; i
++, j
++)
111 PinNum
[i
] = InString
[j
];
117 ElementName
[j
] = '\0';
118 Message (_("Bad net-list format encountered near: \"%s\"\n"),
125 * \brief Find a particular pad from an element name and pin number.
128 FindPad (char *ElementName
, char *PinNum
, ConnectionType
* conn
, bool Same
)
130 ElementType
*element
;
133 if ((element
= SearchElementByName (PCB
->Data
, ElementName
)) == NULL
)
136 for (i
= element
->Pad
; i
!= NULL
; i
= g_list_next (i
))
138 PadType
*pad
= i
->data
;
140 if (NSTRCMP (PinNum
, pad
->Number
) == 0 &&
141 (!Same
|| !TEST_FLAG (DRCFLAG
, pad
)))
143 conn
->type
= PAD_TYPE
;
144 conn
->ptr1
= element
;
146 conn
->group
= TEST_FLAG (ONSOLDERFLAG
, pad
) ? bottom_group
: top_group
;
148 if (TEST_FLAG (EDGE2FLAG
, pad
))
150 conn
->X
= pad
->Point2
.X
;
151 conn
->Y
= pad
->Point2
.Y
;
155 conn
->X
= pad
->Point1
.X
;
156 conn
->Y
= pad
->Point1
.Y
;
162 for (i
= element
->Pin
; i
!= NULL
; i
= g_list_next (i
))
164 PinType
*pin
= i
->data
;
166 if (!TEST_FLAG (HOLEFLAG
, pin
) &&
167 pin
->Number
&& NSTRCMP (PinNum
, pin
->Number
) == 0 &&
168 (!Same
|| !TEST_FLAG (DRCFLAG
, pin
)))
170 conn
->type
= PIN_TYPE
;
171 conn
->ptr1
= element
;
173 conn
->group
= bottom_group
; /* any layer will do */
184 * \brief Parse a netlist menu entry and locate the corresponding pad.
186 * \return true if found, and fills in Connection information.
189 SeekPad (LibraryEntryType
* entry
, ConnectionType
* conn
, bool Same
)
192 char ElementName
[256];
195 if (ParseConnection (entry
->ListEntry
, ElementName
, PinNum
))
197 for (j
= 0; PinNum
[j
] != '\0'; j
++);
200 Message (_("Error! Netlist file is missing pin!\n"
201 "white space after \"%s-\"\n"), ElementName
);
206 if (FindPad (ElementName
, PinNum
, conn
, Same
))
210 if (PinNum
[j
- 1] < '0' || PinNum
[j
- 1] > '9')
212 Message ("WARNING! Pin number ending with '%c'"
213 " encountered in netlist file\n"
214 "Probably a bad netlist file format\n", PinNum
[j
- 1]);
217 Message (_("Can't find %s pin %s called for in netlist.\n"),
218 ElementName
, PinNum
);
223 * \brief Read the library-netlist build a true Netlist structure.
226 ProcNetlist (LibraryType
*net_menu
)
228 ConnectionType
*connection
;
229 ConnectionType LastPoint
;
231 static NetListType
*Wantlist
= NULL
;
233 if (!net_menu
->MenuN
)
235 FreeNetListMemory (Wantlist
);
239 /* find layer groups of the component side and solder side */
240 bottom_group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
241 top_group
= GetLayerGroupNumberBySide (TOP_SIDE
);
243 Wantlist
= (NetListType
*)calloc (1, sizeof (NetListType
));
246 ALLPIN_LOOP (PCB
->Data
);
249 CLEAR_FLAG (DRCFLAG
, pin
);
252 ALLPAD_LOOP (PCB
->Data
);
255 CLEAR_FLAG (DRCFLAG
, pad
);
258 MENU_LOOP (net_menu
);
260 if (menu
->Name
[0] == '*' || menu
->flag
== 0)
265 net
= GetNetMemory (Wantlist
);
270 if (style
->Name
&& !NSTRCMP (style
->Name
, menu
->Style
))
278 else /* default to NULL if none found */
282 if (SeekPad (entry
, &LastPoint
, false))
284 if (TEST_FLAG (DRCFLAG
, (PinType
*) LastPoint
.ptr2
))
286 ("Error! Element %s pin %s appears multiple times in the netlist file.\n"),
287 NAMEONPCB_NAME ((ElementType
*) LastPoint
.ptr1
),
289 PIN_TYPE
) ? ((PinType
*) LastPoint
.ptr2
)->
290 Number
: ((PadType
*) LastPoint
.ptr2
)->Number
);
293 connection
= GetConnectionMemory (net
);
294 *connection
= LastPoint
;
295 /* indicate expect net */
296 connection
->menu
= menu
;
297 /* mark as visited */
298 SET_FLAG (DRCFLAG
, (PinType
*) LastPoint
.ptr2
);
299 if (LastPoint
.type
== PIN_TYPE
)
300 ((PinType
*) LastPoint
.ptr2
)->Spare
= (void *) menu
;
302 ((PadType
*) LastPoint
.ptr2
)->Spare
= (void *) menu
;
307 /* check for more pins with the same number */
308 for (; SeekPad (entry
, &LastPoint
, true);)
310 connection
= GetConnectionMemory (net
);
311 *connection
= LastPoint
;
312 /* indicate expect net */
313 connection
->menu
= menu
;
314 /* mark as visited */
315 SET_FLAG (DRCFLAG
, (PinType
*) LastPoint
.ptr2
);
316 if (LastPoint
.type
== PIN_TYPE
)
317 ((PinType
*) LastPoint
.ptr2
)->Spare
= (void *) menu
;
319 ((PadType
*) LastPoint
.ptr2
)->Spare
= (void *) menu
;
326 /* clear all visit marks */
327 ALLPIN_LOOP (PCB
->Data
);
329 CLEAR_FLAG (DRCFLAG
, pin
);
332 ALLPAD_LOOP (PCB
->Data
);
334 CLEAR_FLAG (DRCFLAG
, pad
);
341 * \brief Copy all connections from one net into another and then remove
342 * the first net from its netlist.
345 TransferNet (NetListType
*Netl
, NetType
*SourceNet
, NetType
*DestNet
)
347 ConnectionType
*conn
;
349 /* It would be worth checking if SourceNet is NULL here to avoid a segfault. Seb James. */
350 CONNECTION_LOOP (SourceNet
);
352 conn
= GetConnectionMemory (DestNet
);
356 DestNet
->Style
= SourceNet
->Style
;
357 /* free the connection memory */
358 FreeNetMemory (SourceNet
);
359 /* remove SourceNet from its netlist */
360 *SourceNet
= Netl
->Net
[--(Netl
->NetN
)];
361 /* zero out old garbage */
362 memset (&Netl
->Net
[Netl
->NetN
], 0, sizeof (NetType
));
366 CheckShorts (LibraryMenuType
*theNet
)
368 bool newone
, warn
= false;
369 PointerListType
*generic
= (PointerListType
*)calloc (1, sizeof (PointerListType
));
370 /* the first connection was starting point so
371 * the menu is always non-null
373 void **menu
= GetPointerMemory (generic
);
376 ALLPIN_LOOP (PCB
->Data
);
378 if (TEST_FLAG (DRCFLAG
, pin
))
383 Message (_("Warning! Net \"%s\" is shorted to %s pin %s\n"),
385 UNKNOWN (NAMEONPCB_NAME (element
)),
386 UNKNOWN (pin
->Number
));
387 SET_FLAG (WARNFLAG
, pin
);
391 POINTER_LOOP (generic
);
393 if (*ptr
== pin
->Spare
)
402 menu
= GetPointerMemory (generic
);
404 Message (_("Warning! Net \"%s\" is shorted to net \"%s\"\n"),
406 &((LibraryMenuType
*) (pin
->Spare
))->Name
[2]);
407 SET_FLAG (WARNFLAG
, pin
);
412 ALLPAD_LOOP (PCB
->Data
);
414 if (TEST_FLAG (DRCFLAG
, pad
))
419 Message (_("Warning! Net \"%s\" is shorted to %s pad %s\n"),
421 UNKNOWN (NAMEONPCB_NAME (element
)),
422 UNKNOWN (pad
->Number
));
423 SET_FLAG (WARNFLAG
, pad
);
427 POINTER_LOOP (generic
);
429 if (*ptr
== pad
->Spare
)
438 menu
= GetPointerMemory (generic
);
440 Message (_("Warning! Net \"%s\" is shorted to net \"%s\"\n"),
442 &((LibraryMenuType
*) (pad
->Spare
))->Name
[2]);
443 SET_FLAG (WARNFLAG
, pad
);
448 FreePointerListMemory (generic
);
455 * \brief Determine existing interconnections of the net and gather into
458 * Initially the netlist has each connection in its own individual net
459 * afterwards there can be many fewer nets with multiple connections
463 GatherSubnets (NetListType
*Netl
, bool NoWarn
, bool AndRats
)
466 ConnectionType
*conn
;
470 for (m
= 0; Netl
->NetN
> 0 && m
< Netl
->NetN
; m
++)
473 ClearFlagOnAllObjects (false, DRCFLAG
, false);
474 RatFindHook (a
->Connection
[0].type
, a
->Connection
[0].ptr1
,
475 a
->Connection
[0].ptr2
, a
->Connection
[0].ptr2
,
476 false, DRCFLAG
, AndRats
);
477 /* now anybody connected to the first point has DRCFLAG set */
478 /* so move those to this subnet */
479 CLEAR_FLAG (DRCFLAG
, (PinType
*) a
->Connection
[0].ptr2
);
480 for (n
= m
+ 1; n
< Netl
->NetN
; n
++)
483 /* There can be only one connection in net b */
484 if (TEST_FLAG (DRCFLAG
, (PinType
*) b
->Connection
[0].ptr2
))
486 CLEAR_FLAG (DRCFLAG
, (PinType
*) b
->Connection
[0].ptr2
);
487 TransferNet (Netl
, b
, a
);
488 /* back up since new subnet is now at old index */
492 /* now add other possible attachment points to the subnet */
493 /* e.g. line end-points and vias */
494 /* don't add non-manhattan lines, the auto-router can't route to them */
495 ALLLINE_LOOP (PCB
->Data
);
497 if (TEST_FLAG (DRCFLAG
, line
))
499 conn
= GetConnectionMemory (a
);
500 conn
->X
= line
->Point1
.X
;
501 conn
->Y
= line
->Point1
.Y
;
502 conn
->type
= LINE_TYPE
;
505 conn
->group
= GetLayerGroupNumberByPointer (layer
);
506 conn
->menu
= NULL
; /* agnostic view of where it belongs */
507 conn
= GetConnectionMemory (a
);
508 conn
->X
= line
->Point2
.X
;
509 conn
->Y
= line
->Point2
.Y
;
510 conn
->type
= LINE_TYPE
;
513 conn
->group
= GetLayerGroupNumberByPointer (layer
);
518 /* add polygons so the auto-router can see them as targets */
519 ALLPOLYGON_LOOP (PCB
->Data
);
521 if (TEST_FLAG (DRCFLAG
, polygon
))
523 conn
= GetConnectionMemory (a
);
524 /* make point on a vertex */
525 conn
->X
= polygon
->Clipped
->contours
->head
.point
[0];
526 conn
->Y
= polygon
->Clipped
->contours
->head
.point
[1];
527 conn
->type
= POLYGON_TYPE
;
529 conn
->ptr2
= polygon
;
530 conn
->group
= GetLayerGroupNumberByPointer (layer
);
531 conn
->menu
= NULL
; /* agnostic view of where it belongs */
535 VIA_LOOP (PCB
->Data
);
537 if (TEST_FLAG (DRCFLAG
, via
))
539 conn
= GetConnectionMemory (a
);
542 conn
->type
= VIA_TYPE
;
545 conn
->group
= bottom_group
;
550 Warned
|= CheckShorts (a
->Connection
[0].menu
);
552 ClearFlagOnAllObjects (false, DRCFLAG
, false);
557 * \brief Draw a rat net (tree) having the shortest lines.
559 * This also frees the subnet memory as they are consumed.
561 * \note The \c Netl we are passed is NOT the main netlist - it's the
562 * connectivity for ONE net.
563 * It represents the CURRENT connectivity state for the net, with each
564 * Netl->Net[N] representing one copper-connected subset of the net.
566 * Everything inside the NetList Netl should be connected together.
568 * Each Net in \c Netl is a group of Connections which are already
569 * connected together somehow, either by real wires or by rats we've
572 * Each Connection is a vertex within that blob of connected items.
574 * This loop finds the closest vertex pairs between each blob and draws
575 * rats that merge the blobs until there's just one big blob.
577 * Just to clarify, with some examples:
579 * Each \c Netl is one full net from a netlist, like from gnetlist.
581 * Each Netl->Net[N] is a subset of that net that's already
582 * physically connected on the pcb.
584 * So a new design with no traces yet, would have a huge list of Net[N],
585 * each with one pin in it.
587 * A fully routed design would have one Net[N] with all the pins
588 * (for that net) in it.
591 DrawShortestRats (NetListType
*Netl
, void (*funcp
) (register ConnectionType
*, register ConnectionType
*, register RouteStyleType
*))
594 register float distance
, temp
;
595 register ConnectionType
*conn1
, *conn2
, *firstpoint
, *secondpoint
;
596 PolygonType
*polygon
;
597 bool changed
= false;
600 NetType
*next
, *subnet
, *theSubnet
= NULL
;
602 /* This is just a sanity check, to make sure we're passed
605 if (!Netl
|| Netl
->NetN
< 1)
609 * We keep doing this do/while loop until everything's connected.
610 * I.e. once per rat we add.
613 havepoints
= true; /* so we run the loop at least once */
614 while (Netl
->NetN
> 1 && havepoints
)
616 /* This is the top of the "find one rat" logic. */
618 firstpoint
= secondpoint
= NULL
;
620 /* Test Net[0] vs Net[N] for N=1..max. Find the shortest
621 distance between any two points in different blobs. */
622 subnet
= &Netl
->Net
[0];
623 for (j
= 1; j
< Netl
->NetN
; j
++)
626 * Scan between Net[0] blob (subnet) and Net[N] blob (next).
627 * Note the shortest distance we find.
629 next
= &Netl
->Net
[j
];
630 for (n
= subnet
->ConnectionN
- 1; n
!= -1; n
--)
632 conn1
= &subnet
->Connection
[n
];
633 for (m
= next
->ConnectionN
- 1; m
!= -1; m
--)
635 conn2
= &next
->Connection
[m
];
637 * At this point, conn1 and conn2 are two pins in
638 * different blobs of the same net. See how far
639 * apart they are, and if they're "closer" than what
644 * Prefer to connect Connections over polygons to the
645 * polygons (ie assume the user wants a via to a plane,
646 * not a daisy chain). Further prefer to pick an existing
647 * via in the Net to make that connection.
649 if (conn1
->type
== POLYGON_TYPE
&&
650 (polygon
= (PolygonType
*)conn1
->ptr2
) &&
652 firstpoint
&& firstpoint
->type
== VIA_TYPE
) &&
653 IsPointInPolygonIgnoreHoles (conn2
->X
, conn2
->Y
, polygon
))
661 else if (conn2
->type
== POLYGON_TYPE
&&
662 (polygon
= (PolygonType
*)conn2
->ptr2
) &&
664 firstpoint
&& firstpoint
->type
== VIA_TYPE
) &&
665 IsPointInPolygonIgnoreHoles (conn1
->X
, conn1
->Y
, polygon
))
673 else if ((temp
= SQUARE (conn1
->X
- conn2
->X
) +
674 SQUARE (conn1
->Y
- conn2
->Y
)) < distance
|| !firstpoint
)
687 * If HAVEPOINTS is true, we've found a pair of points in two
688 * separate blobs of the net, and need to connect them together.
694 (*funcp
) (firstpoint
, secondpoint
, subnet
->Style
);
698 /* found the shortest distance subnet, draw the rat */
699 if ((line
= CreateNewRat (PCB
->Data
,
700 firstpoint
->X
, firstpoint
->Y
,
701 secondpoint
->X
, secondpoint
->Y
,
702 firstpoint
->group
, secondpoint
->group
,
703 Settings
.RatThickness
,
704 NoFlags ())) != NULL
)
707 SET_FLAG (VIAFLAG
, line
);
708 AddObjectToCreateUndoList (RATLINE_TYPE
, line
, line
, line
);
714 /* copy theSubnet into the current subnet */
715 TransferNet (Netl
, theSubnet
, subnet
);
719 /* presently nothing to do with the new subnet */
720 /* so we throw it away and free the space */
721 FreeNetMemory (&Netl
->Net
[--(Netl
->NetN
)]);
722 /* Sadly adding a rat line messes up the sorted arrays in connection finder */
723 /* hace: perhaps not necessarily now that they aren't stored in normal layers */
726 FreeConnectionLookupMemory ();
727 InitConnectionLookup ();
734 * \brief AddAllRats puts the rats nest into the layout from the loaded
737 * If SelectedOnly is true, it will only draw rats to selected pins and
741 AddAllRats (bool SelectedOnly
, void (*funcp
) (register ConnectionType
*, register ConnectionType
*, register RouteStyleType
*))
743 NetListType
*Nets
, *Wantlist
;
745 ConnectionType
*onepin
;
746 bool changed
, Warned
= false;
748 /* the netlist library has the text form
749 * ProcNetlist fills in the Netlist
750 * structure the way the final routing
751 * is supposed to look
753 Wantlist
= ProcNetlist (&PCB
->NetlistLib
);
756 Message (_("Can't add rat lines because no netlist is loaded.\n"));
760 /* initialize finding engine */
761 InitConnectionLookup ();
762 Nets
= (NetListType
*)calloc (1, sizeof (NetListType
));
763 /* now we build another netlist (Nets) for each
764 * net in Wantlist that shows how it actually looks now,
765 * then fill in any missing connections with rat lines.
767 * we first assume each connection is separate
768 * (no routing), then gather them into groups
769 * if the net is all routed, the new netlist (Nets)
770 * will have only one net entry.
771 * Note that DrawShortestRats consumes all nets
772 * from Nets, so *Nets is empty after the
773 * DrawShortestRats call
777 CONNECTION_LOOP (net
);
780 || TEST_FLAG (SELECTEDFLAG
, (PinType
*) connection
->ptr2
))
782 lonesome
= GetNetMemory (Nets
);
783 onepin
= GetConnectionMemory (lonesome
);
784 *onepin
= *connection
;
785 lonesome
->Style
= net
->Style
;
789 Warned
|= GatherSubnets (Nets
, SelectedOnly
, true);
791 changed
|= DrawShortestRats (Nets
, funcp
);
794 FreeNetListMemory (Nets
);
796 FreeConnectionLookupMemory ();
800 if (Warned
|| changed
)
804 Settings
.RatWarn
= true;
808 IncrementUndoSerialNumber ();
809 if (PCB
->Data
->RatN
> 0)
811 Message ("%d rat line%s remaining\n", PCB
->Data
->RatN
,
812 PCB
->Data
->RatN
> 1 ? "s" : "");
816 if (!SelectedOnly
&& !Warned
)
818 if (!PCB
->Data
->RatN
&& !badnet
)
819 Message (_("Congratulations!!\n"
820 "The layout is complete and has no shorted nets.\n"));
822 Message (_("Nothing more to add, but there are\n"
823 "either rat-lines in the layout, disabled nets\n"
824 "in the net-list, or missing components\n"));
830 * \todo This is copied in large part from AddAllRats above; for
831 * maintainability, AddAllRats probably wants to be tweaked to use this
832 * version of the code so that we don't have duplication.
835 CollectSubnets (bool SelectedOnly
)
837 NetListListType result
= { 0, 0, NULL
};
838 NetListType
*Nets
, *Wantlist
;
840 ConnectionType
*onepin
;
842 /* the netlist library has the text form
843 * ProcNetlist fills in the Netlist
844 * structure the way the final routing
845 * is supposed to look
847 Wantlist
= ProcNetlist (&PCB
->NetlistLib
);
850 Message (_("Can't add rat lines because no netlist is loaded.\n"));
853 /* initialize finding engine */
854 InitConnectionLookup ();
855 /* now we build another netlist (Nets) for each
856 * net in Wantlist that shows how it actually looks now,
857 * then fill in any missing connections with rat lines.
859 * we first assume each connection is separate
860 * (no routing), then gather them into groups
861 * if the net is all routed, the new netlist (Nets)
862 * will have only one net entry.
863 * Note that DrawShortestRats consumes all nets
864 * from Nets, so *Nets is empty after the
865 * DrawShortestRats call
869 Nets
= GetNetListMemory (&result
);
870 CONNECTION_LOOP (net
);
873 || TEST_FLAG (SELECTEDFLAG
, (PinType
*) connection
->ptr2
))
875 lonesome
= GetNetMemory (Nets
);
876 onepin
= GetConnectionMemory (lonesome
);
877 *onepin
= *connection
;
878 lonesome
->Style
= net
->Style
;
882 /* Note that AndRats is *FALSE* here! */
883 GatherSubnets (Nets
, SelectedOnly
, false);
886 FreeConnectionLookupMemory ();
891 * \brief Check to see if a particular name is the name of an already
892 * existing rats line.
895 rat_used (char *name
)
900 MENU_LOOP (&PCB
->NetlistLib
);
902 if (menu
->Name
&& (strcmp (menu
->Name
, name
) == 0))
911 * \brief This function is moved from the original netlist.c as
912 * part of the gui code separation for the Gtk port.
917 static int ratDrawn
= 0;
918 char name1
[256], *name2
;
919 Cardinal group1
, group2
;
922 void *ptr1
, *ptr2
, *ptr3
;
923 LibraryMenuType
*menu
;
924 LibraryEntryType
*entry
;
926 if (Crosshair
.AttachedLine
.Point1
.X
== Crosshair
.AttachedLine
.Point2
.X
927 && Crosshair
.AttachedLine
.Point1
.Y
== Crosshair
.AttachedLine
.Point2
.Y
)
930 found
= SearchObjectByLocation (PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr2
, &ptr3
,
931 Crosshair
.AttachedLine
.Point1
.X
,
932 Crosshair
.AttachedLine
.Point1
.Y
, 5);
933 if (found
== NO_TYPE
)
935 Message (_("No pad/pin under rat line\n"));
938 if (NAMEONPCB_NAME ((ElementType
*) ptr1
) == NULL
939 || *NAMEONPCB_NAME ((ElementType
*) ptr1
) == 0)
941 Message (_("You must name the starting element first\n"));
945 /* will work for pins to since the FLAG is common */
946 group1
= GetLayerGroupNumberBySide (
947 TEST_FLAG (ONSOLDERFLAG
, (PadType
*) ptr2
) ? BOTTOM_SIDE
: TOP_SIDE
);
948 strcpy (name1
, ConnectionName (found
, ptr1
, ptr2
));
949 found
= SearchObjectByLocation (PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr2
, &ptr3
,
950 Crosshair
.AttachedLine
.Point2
.X
,
951 Crosshair
.AttachedLine
.Point2
.Y
, 5);
952 if (found
== NO_TYPE
)
954 Message (_("No pad/pin under rat line\n"));
957 if (NAMEONPCB_NAME ((ElementType
*) ptr1
) == NULL
958 || *NAMEONPCB_NAME ((ElementType
*) ptr1
) == 0)
960 Message (_("You must name the ending element first\n"));
963 group2
= GetLayerGroupNumberBySide (
964 TEST_FLAG (ONSOLDERFLAG
, (PadType
*) ptr2
) ? BOTTOM_SIDE
: TOP_SIDE
);
965 name2
= ConnectionName (found
, ptr1
, ptr2
);
967 menu
= netnode_to_netname (name1
);
970 if (netnode_to_netname (name2
))
973 ("Both connections already in netlist - cannot merge nets\n"));
976 entry
= GetLibraryEntryMemory (menu
);
977 entry
->ListEntry
= strdup (name2
);
978 netnode_to_netname (name2
);
981 /* ok, the first name did not belong to a net */
982 menu
= netnode_to_netname (name2
);
985 entry
= GetLibraryEntryMemory (menu
);
986 entry
->ListEntry
= strdup (name1
);
987 netnode_to_netname (name1
);
992 * neither belong to a net, so create a new one.
994 * before creating a new rats here, we need to search
997 sprintf (ratname
, " ratDrawn%i", ++ratDrawn
);
998 while (rat_used (ratname
))
1000 sprintf (ratname
, " ratDrawn%i", ++ratDrawn
);
1003 menu
= GetLibraryMenuMemory (&PCB
->NetlistLib
);
1004 menu
->Name
= strdup (ratname
);
1005 entry
= GetLibraryEntryMemory (menu
);
1006 entry
->ListEntry
= strdup (name1
);
1007 entry
= GetLibraryEntryMemory (menu
);
1008 entry
->ListEntry
= strdup (name2
);
1013 return (CreateNewRat (PCB
->Data
, Crosshair
.AttachedLine
.Point1
.X
,
1014 Crosshair
.AttachedLine
.Point1
.Y
,
1015 Crosshair
.AttachedLine
.Point2
.X
,
1016 Crosshair
.AttachedLine
.Point2
.Y
,
1017 group1
, group2
, Settings
.RatThickness
, NoFlags ()));
1021 * \brief This function is moved from the original netlist.c as
1022 * part of the gui code separation for the Gtk port.
1025 ConnectionName (int type
, void *ptr1
, void *ptr2
)
1027 static char name
[256];
1033 num
= ((PinType
*) ptr2
)->Number
;
1036 num
= ((PadType
*) ptr2
)->Number
;
1041 strcpy (name
, UNKNOWN (NAMEONPCB_NAME ((ElementType
*) ptr1
)));
1043 strcat (name
, UNKNOWN (num
));