/* Select on the layout the current net treeview selection */ static void netlist_select_cb (GtkWidget * widget, gpointer data) { LibraryEntryType *entry; ConnectionType conn; gint i; gboolean select_flag = GPOINTER_TO_INT (data); if (!selected_net) return; if (selected_net == node_selected_net) node_selected_net = NULL; InitConnectionLookup (); ResetConnections (true); for (i = selected_net->EntryN, entry = selected_net->Entry; i; i--, entry++) if (SeekPad (entry, &conn, false)) RatFindHook (conn.type, conn.ptr1, conn.ptr2, conn.ptr2, true, true); SelectConnection (select_flag); ResetConnections (false); FreeConnectionLookupMemory (); IncrementUndoSerialNumber (); Draw (); }
/* Select on the layout the current net treeview selection */ static void nbcb_select_common (LibraryMenuTypePtr net, int pos, int select_flag) { LibraryEntryType *entry; ConnectionType conn; int i; InitConnectionLookup (); ResetConnections (true); for (i = net->EntryN, entry = net->Entry; i; i--, entry++) if (SeekPad (entry, &conn, false)) RatFindHook (conn.type, conn.ptr1, conn.ptr2, conn.ptr2, true, true); SelectConnection (select_flag); ResetConnections (false); FreeConnectionLookupMemory (); IncrementUndoSerialNumber (); Draw (); }
/* --------------------------------------------------------------------------- * set a new mode and update X cursor */ void SetMode (int Mode) { static bool recursing = false; /* protect the cursor while changing the mode * perform some additional stuff depending on the new mode * reset 'state' of attached objects */ if (recursing) return; recursing = true; notify_crosshair_change (false); addedLines = 0; Crosshair.AttachedObject.Type = NO_TYPE; Crosshair.AttachedObject.State = STATE_FIRST; Crosshair.AttachedPolygon.PointN = 0; if (PCB->RatDraw) { if (Mode == ARC_MODE || Mode == RECTANGLE_MODE || Mode == VIA_MODE || Mode == POLYGON_MODE || Mode == POLYGONHOLE_MODE || Mode == TEXT_MODE || Mode == INSERTPOINT_MODE || Mode == THERMAL_MODE) { Message (_("That mode is NOT allowed when drawing ratlines!\n")); Mode = NO_MODE; } } if (Settings.Mode == LINE_MODE && Mode == ARC_MODE && Crosshair.AttachedLine.State != STATE_FIRST) { Crosshair.AttachedLine.State = STATE_FIRST; Crosshair.AttachedBox.State = STATE_SECOND; Crosshair.AttachedBox.Point1.X = Crosshair.AttachedBox.Point2.X = Crosshair.AttachedLine.Point1.X; Crosshair.AttachedBox.Point1.Y = Crosshair.AttachedBox.Point2.Y = Crosshair.AttachedLine.Point1.Y; AdjustAttachedObjects (); } else if (Settings.Mode == ARC_MODE && Mode == LINE_MODE && Crosshair.AttachedBox.State != STATE_FIRST) { Crosshair.AttachedBox.State = STATE_FIRST; Crosshair.AttachedLine.State = STATE_SECOND; Crosshair.AttachedLine.Point1.X = Crosshair.AttachedLine.Point2.X = Crosshair.AttachedBox.Point1.X; Crosshair.AttachedLine.Point1.Y = Crosshair.AttachedLine.Point2.Y = Crosshair.AttachedBox.Point1.Y; Settings.Mode = Mode; AdjustAttachedObjects (); } else { if (Settings.Mode == ARC_MODE || Settings.Mode == LINE_MODE) SetLocalRef (0, 0, false); Crosshair.AttachedBox.State = STATE_FIRST; Crosshair.AttachedLine.State = STATE_FIRST; if (Mode == LINE_MODE && TEST_FLAG (AUTODRCFLAG, PCB)) { if (ResetConnections (true)) { IncrementUndoSerialNumber (); Draw (); } } } Settings.Mode = Mode; if (Mode == PASTEBUFFER_MODE) /* do an update on the crosshair range */ SetCrosshairRangeToBuffer (); else SetCrosshairRange (0, 0, PCB->MaxWidth, PCB->MaxHeight); recursing = false; /* force a crosshair grid update because the valid range * may have changed */ MoveCrosshairRelative (0, 0); notify_crosshair_change (true); }
static int ReportNetLength (int argc, char **argv, int x, int y) { double length = 0; char *netname = 0; int found = 0; if (ResetConnections (true)) Draw (); /* NB: XYtoNetLength calls LookupConnection, which performs an undo * serial number update, so we don't need to add one here. */ gui->get_coords ("Click on a connection", &x, &y); length = XYtoNetLength (x, y, &found); if (!found) { gui->log ("No net under cursor.\n"); return 1; } ELEMENT_LOOP (PCB->Data); { PIN_LOOP (element); { if (TEST_FLAG (FOUNDFLAG, pin)) { int ni, nei; char *ename = element->Name[NAMEONPCB_INDEX].TextString; char *pname = pin->Number; char *n; if (ename && pname) { n = Concat (ename, "-", pname, NULL); for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) for (nei = 0; nei < PCB->NetlistLib.Menu[ni].EntryN; nei++) { if (strcmp (PCB->NetlistLib.Menu[ni].Entry[nei].ListEntry, n) == 0) { netname = PCB->NetlistLib.Menu[ni].Name + 2; goto got_net_name; /* four for loops deep */ } } } } } END_LOOP; PAD_LOOP (element); { if (TEST_FLAG (FOUNDFLAG, pad)) { int ni, nei; char *ename = element->Name[NAMEONPCB_INDEX].TextString; char *pname = pad->Number; char *n; if (ename && pname) { n = Concat (ename, "-", pname, NULL); for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) for (nei = 0; nei < PCB->NetlistLib.Menu[ni].EntryN; nei++) { if (strcmp (PCB->NetlistLib.Menu[ni].Entry[nei].ListEntry, n) == 0) { netname = PCB->NetlistLib.Menu[ni].Name + 2; goto got_net_name; /* four for loops deep */ } } } } } END_LOOP; } END_LOOP; got_net_name: HideCrosshair (false); { int prec = Settings.grid_units_mm? 4: 2; if (netname) gui->log ("Net \"%s\" length: %.*f %s\n", netname, prec, UNIT (length)); else gui->log ("Net length: %.*f %s\n", prec, UNIT (length)); } RestoreCrosshair (false); return 0; }
static int ReportAllNetLengths (int argc, char **argv, int x, int y) { int ni; int found; double length; int prec; double scale; const char *units_name; units_name = argv[0]; if (argc < 1) units_name = Settings.grid_units_mm ? "mm" : "mil"; if (strcasecmp (units_name, "mm") == 0) { prec = 4; scale = COOR_TO_MM; } else if (strcasecmp (units_name, "mil") == 0) { prec = 2; scale = .01; } else if (strcasecmp (units_name, "in") == 0) { prec = 5; scale = 1./100000; } else { prec = 0; units_name = "pcb"; scale = 1; } for (ni = 0; ni < PCB->NetlistLib.MenuN; ni++) { char *netname = PCB->NetlistLib.Menu[ni].Name + 2; char *ename = PCB->NetlistLib.Menu[ni].Entry[0].ListEntry; char *pname; ename = strdup (ename); pname = strchr (ename, '-'); if (! pname) { free (ename); continue; } *pname++ = 0; ELEMENT_LOOP (PCB->Data); { char *es = element->Name[NAMEONPCB_INDEX].TextString; if (es && strcmp (es, ename) == 0) { PIN_LOOP (element); { if (strcmp (pin->Number, pname) == 0) { x = pin->X; y = pin->Y; goto got_one; } } END_LOOP; PAD_LOOP (element); { if (strcmp (pad->Number, pname) == 0) { x = (pad->Point1.X + pad->Point2.X) / 2; y = (pad->Point1.Y + pad->Point2.Y) / 2; goto got_one; } } END_LOOP; } } END_LOOP; continue; got_one: if (ResetConnections (true)) Draw (); /* NB: XYtoNetLength calls LookupConnection, which performs an undo * serial number update, so we don't need to add one here. */ length = XYtoNetLength (x, y, &found); gui->log("Net %s length %.*f %s\n", netname, prec, length*scale, units_name); } return 0; }
/* --------------------------------------------------------------------------- * Determine existing interconnections of the net and gather into sub-nets * * initially the netlist has each connection in its own individual net * afterwards there can be many fewer nets with multiple connections each */ static bool GatherSubnets (NetListTypePtr Netl, bool NoWarn, bool AndRats) { NetTypePtr a, b; ConnectionTypePtr conn; Cardinal m, n; bool Warned = false; for (m = 0; Netl->NetN > 0 && m < Netl->NetN; m++) { a = &Netl->Net[m]; ResetConnections (false); RatFindHook (a->Connection[0].type, a->Connection[0].ptr1, a->Connection[0].ptr2, a->Connection[0].ptr2, false, AndRats); /* now anybody connected to the first point has DRCFLAG set */ /* so move those to this subnet */ CLEAR_FLAG (DRCFLAG, (PinTypePtr) a->Connection[0].ptr2); for (n = m + 1; n < Netl->NetN; n++) { b = &Netl->Net[n]; /* There can be only one connection in net b */ if (TEST_FLAG (DRCFLAG, (PinTypePtr) b->Connection[0].ptr2)) { CLEAR_FLAG (DRCFLAG, (PinTypePtr) b->Connection[0].ptr2); TransferNet (Netl, b, a); /* back up since new subnet is now at old index */ n--; } } /* now add other possible attachment points to the subnet */ /* e.g. line end-points and vias */ /* don't add non-manhattan lines, the auto-router can't route to them */ ALLLINE_LOOP (PCB->Data); { if (TEST_FLAG (DRCFLAG, line) && ((line->Point1.X == line->Point2.X) || (line->Point1.Y == line->Point2.Y))) { conn = GetConnectionMemory (a); conn->X = line->Point1.X; conn->Y = line->Point1.Y; conn->type = LINE_TYPE; conn->ptr1 = layer; conn->ptr2 = line; conn->group = GetLayerGroupNumberByPointer (layer); conn->menu = NULL; /* agnostic view of where it belongs */ conn = GetConnectionMemory (a); conn->X = line->Point2.X; conn->Y = line->Point2.Y; conn->type = LINE_TYPE; conn->ptr1 = layer; conn->ptr2 = line; conn->group = GetLayerGroupNumberByPointer (layer); conn->menu = NULL; } } ENDALL_LOOP; /* add polygons so the auto-router can see them as targets */ ALLPOLYGON_LOOP (PCB->Data); { if (TEST_FLAG (DRCFLAG, polygon)) { conn = GetConnectionMemory (a); /* make point on a vertex */ conn->X = polygon->Clipped->contours->head.point[0]; conn->Y = polygon->Clipped->contours->head.point[1]; conn->type = POLYGON_TYPE; conn->ptr1 = layer; conn->ptr2 = polygon; conn->group = GetLayerGroupNumberByPointer (layer); conn->menu = NULL; /* agnostic view of where it belongs */ } } ENDALL_LOOP; VIA_LOOP (PCB->Data); { if (TEST_FLAG (DRCFLAG, via)) { conn = GetConnectionMemory (a); conn->X = via->X; conn->Y = via->Y; conn->type = VIA_TYPE; conn->ptr1 = via; conn->ptr2 = via; conn->group = SLayer; } } END_LOOP; if (!NoWarn) Warned |= CheckShorts (a->Connection[0].menu); } ResetConnections (false); return (Warned); }