static void nbcb_ripup (Widget w, Std_Nbcb_Func v, XmPushButtonCallbackStruct * cbs) { nbcb_std_callback (w, nbcb_find, cbs); VISIBLELINE_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, line) && !TEST_FLAG (LOCKFLAG, line)) RemoveObject (LINE_TYPE, layer, line, line); } ENDALL_LOOP; VISIBLEARC_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, arc) && !TEST_FLAG (LOCKFLAG, arc)) RemoveObject (ARC_TYPE, layer, arc, arc); } ENDALL_LOOP; if (PCB->ViaOn) VIA_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, via) && !TEST_FLAG (LOCKFLAG, via)) RemoveObject (VIA_TYPE, via, via, via); } END_LOOP; }
static void netlist_rip_up_cb (GtkWidget * widget, gpointer data) { if (!selected_net) return; netlist_find_cb(widget, data); VISIBLELINE_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, line) && !TEST_FLAG (LOCKFLAG, line)) RemoveObject (LINE_TYPE, layer, line, line); } ENDALL_LOOP; VISIBLEARC_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, arc) && !TEST_FLAG (LOCKFLAG, arc)) RemoveObject (ARC_TYPE, layer, arc, arc); } ENDALL_LOOP; if (PCB->ViaOn) VIA_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, via) && !TEST_FLAG (LOCKFLAG, via)) RemoveObject (VIA_TYPE, via, via, via); } END_LOOP; }
void MirrorBuffer (BufferType *Buffer) { int i; if (Buffer->Data->ElementN) { Message (_("You can't mirror a buffer that has elements!\n")); return; } for (i = 0; i < max_copper_layer + 2; i++) { LayerType *layer = Buffer->Data->Layer + i; if (layer->TextN) { Message (_("You can't mirror a buffer that has text!\n")); return; } } /* set buffer offset to 'mark' position */ Buffer->X = SWAP_X (Buffer->X); Buffer->Y = SWAP_Y (Buffer->Y); VIA_LOOP (Buffer->Data); { via->X = SWAP_X (via->X); via->Y = SWAP_Y (via->Y); } END_LOOP; ALLLINE_LOOP (Buffer->Data); { line->Point1.X = SWAP_X (line->Point1.X); line->Point1.Y = SWAP_Y (line->Point1.Y); line->Point2.X = SWAP_X (line->Point2.X); line->Point2.Y = SWAP_Y (line->Point2.Y); } ENDALL_LOOP; ALLARC_LOOP (Buffer->Data); { arc->X = SWAP_X (arc->X); arc->Y = SWAP_Y (arc->Y); arc->StartAngle = SWAP_ANGLE (arc->StartAngle); arc->Delta = SWAP_DELTA (arc->Delta); SetArcBoundingBox (arc); } ENDALL_LOOP; ALLPOLYGON_LOOP (Buffer->Data); { POLYGONPOINT_LOOP (polygon); { point->X = SWAP_X (point->X); point->Y = SWAP_Y (point->Y); } END_LOOP; SetPolygonBoundingBox (polygon); } ENDALL_LOOP; SetBufferBoundingBox (Buffer); SetCrosshairRangeToBuffer (); }
/* --------------------------------------------------------------------------- * rotates the contents of the pastebuffer */ void RotateBuffer (BufferType *Buffer, BYTE Number) { /* rotate vias */ VIA_LOOP (Buffer->Data); { r_delete_entry (Buffer->Data->via_tree, (BoxType *)via); ROTATE_VIA_LOWLEVEL (via, Buffer->X, Buffer->Y, Number); SetPinBoundingBox (via); r_insert_entry (Buffer->Data->via_tree, (BoxType *)via, 0); } END_LOOP; /* elements */ ELEMENT_LOOP (Buffer->Data); { RotateElementLowLevel (Buffer->Data, element, Buffer->X, Buffer->Y, Number); } END_LOOP; /* all layer related objects */ ALLLINE_LOOP (Buffer->Data); { r_delete_entry (layer->line_tree, (BoxType *)line); RotateLineLowLevel (line, Buffer->X, Buffer->Y, Number); r_insert_entry (layer->line_tree, (BoxType *)line, 0); } ENDALL_LOOP; ALLARC_LOOP (Buffer->Data); { r_delete_entry (layer->arc_tree, (BoxType *)arc); RotateArcLowLevel (arc, Buffer->X, Buffer->Y, Number); r_insert_entry (layer->arc_tree, (BoxType *)arc, 0); } ENDALL_LOOP; ALLTEXT_LOOP (Buffer->Data); { r_delete_entry (layer->text_tree, (BoxType *)text); RotateTextLowLevel (text, Buffer->X, Buffer->Y, Number); r_insert_entry (layer->text_tree, (BoxType *)text, 0); } ENDALL_LOOP; ALLPOLYGON_LOOP (Buffer->Data); { r_delete_entry (layer->polygon_tree, (BoxType *)polygon); RotatePolygonLowLevel (polygon, Buffer->X, Buffer->Y, Number); r_insert_entry (layer->polygon_tree, (BoxType *)polygon, 0); } ENDALL_LOOP; /* finally the origin and the bounding box */ ROTATE (Buffer->X, Buffer->Y, Buffer->X, Buffer->Y, Number); RotateBoxLowLevel (&Buffer->BoundingBox, Buffer->X, Buffer->Y, Number); SetCrosshairRangeToBuffer (); }
void ResetVisitPinsViasAndPads () { VIA_LOOP (PCB->Data); CLEAR_FLAG (VISITFLAG, via); END_LOOP; /* Via. */ ELEMENT_LOOP (PCB->Data); PIN_LOOP (element); CLEAR_FLAG (VISITFLAG, pin); END_LOOP; /* Pin. */ PAD_LOOP (element); CLEAR_FLAG (VISITFLAG, pad); END_LOOP; /* Pad. */ END_LOOP; /* Element. */ }
static void move_all_thermals (int old_index, int new_index) { VIA_LOOP (PCB->Data); { move_one_thermal (old_index, new_index, via); } END_LOOP; ALLPIN_LOOP (PCB->Data); { move_one_thermal (old_index, new_index, pin); } ENDALL_LOOP; }
/*! * \brief Move everything. * * Call our own 'MyMove*LowLevel' where they don't exist in move.c. * This gets very slow if there are large polygons present, since every * element move re-clears the poly, followed by the polys moving and * re-clearing everything again. */ static void MoveAll(Coord dx, Coord dy) { ELEMENT_LOOP (PCB->Data); { MoveElementLowLevel (PCB->Data, element, dx, dy); AddObjectToMoveUndoList (ELEMENT_TYPE, NULL, NULL, element, dx, dy); } END_LOOP; VIA_LOOP (PCB->Data); { MyMoveViaLowLevel (PCB->Data, via, dx, dy); AddObjectToMoveUndoList (VIA_TYPE, NULL, NULL, via, dx, dy); } END_LOOP; ALLLINE_LOOP (PCB->Data); { MyMoveLineLowLevel (PCB->Data, layer, line, dx, dy); AddObjectToMoveUndoList (LINE_TYPE, NULL, NULL, line, dx, dy); } ENDALL_LOOP; ALLARC_LOOP (PCB->Data); { MyMoveArcLowLevel (PCB->Data, layer, arc, dx, dy); AddObjectToMoveUndoList (ARC_TYPE, NULL, NULL, arc, dx, dy); } ENDALL_LOOP; ALLTEXT_LOOP (PCB->Data); { MyMoveTextLowLevel (layer, text, dx, dy); AddObjectToMoveUndoList (TEXT_TYPE, NULL, NULL, text, dx, dy); } ENDALL_LOOP; ALLPOLYGON_LOOP (PCB->Data); { /* * XXX MovePolygonLowLevel does not mean "no gui" like * XXX MoveElementLowLevel, it doesn't even handle layer * XXX tree activity. */ MyMovePolygonLowLevel (PCB->Data, layer, polygon, dx, dy); AddObjectToMoveUndoList (POLYGON_TYPE, NULL, NULL, polygon, dx, dy); } ENDALL_LOOP; }
/* --------------------------------------------------------------------------- * get next slot for a via, allocates memory if necessary */ PinTypePtr GetViaMemory (DataTypePtr Data) { PinTypePtr via = Data->Via; /* realloc new memory if necessary and clear it */ if (Data->ViaN >= Data->ViaMax) { Data->ViaMax += STEP_VIA; if (Data->via_tree) r_destroy_tree (&Data->via_tree); via = (PinTypePtr)realloc (via, Data->ViaMax * sizeof (PinType)); Data->Via = via; memset (via + Data->ViaN, 0, STEP_VIA * sizeof (PinType)); Data->via_tree = r_create_tree (NULL, 0, 0); VIA_LOOP (Data); { r_insert_entry (Data->via_tree, (BoxType *) via, 0); } END_LOOP; } return (via + Data->ViaN++); }
/*! * \brief Writes a net to the file provided. * * The net name is passed through the "net" and should be 14 characters * max.\n * The function scans through pads, pins and vias and looks for the * \c FOUNDFLAG.\n * Once the object has been added to the net list the \c VISITFLAG is * set on that object. * * \todo 1) The bottom layer is always written as layer #2 (A02).\n * It could output the actual layer number (example: A06 on a * 6 layer board).\n * But I could not find an easy way to do this... * * \todo 2) Objects with mutiple connections could have the "M" * (column 32) field written to indicate a Mid Net Point. */ void IPCD356_WriteNet (FILE * fd, char *net) { int padx, pady, tmp; ELEMENT_LOOP (PCB->Data); PAD_LOOP (element); if (TEST_FLAG (FOUNDFLAG, pad)) { fprintf (fd, "327%-17.14s", net); /* Net Name. */ fprintf (fd, "%-6.6s", element->Name[1].TextString); /* Refdes. */ fprintf (fd, "-%-4.4s", pad->Number); /* pin number. */ fprintf (fd, " "); /*! \todo Midpoint indicator (M). */ fprintf (fd, " "); /* Drilled hole Id (blank for pads). */ if (TEST_FLAG (ONSOLDERFLAG, pad) == true) { fprintf (fd, "A02"); /*! \todo Put actual layer # for bottom side. */ } else { fprintf (fd, "A01"); /* Top side. */ } padx = (pad->Point1.X + pad->Point2.X) / 2; /* X location in PCB units. */ pady = (PCB->MaxHeight - ((pad->Point1.Y + pad->Point2.Y) / 2)); /* Y location in PCB units. */ if (strcmp (Settings.grid_unit->suffix, "mil") == 0) { padx = padx / 2540; /* X location in 0.0001". */ pady = pady / 2540; /* Y location in 0.0001". */ } else { padx = padx / 1000; /* X location in 0.001 mm. */ pady = pady / 1000; /* Y location in 0.001 mm. */ } fprintf (fd, "X%+6.6d", padx); /* X Pad center. */ fprintf (fd, "Y%+6.6d", pady); /* Y pad center. */ padx = (pad->Thickness + (pad->Point2.X - pad->Point1.X)); /* Pad dimension X in PCB units. */ pady = (pad->Thickness + (pad->Point2.Y - pad->Point1.Y)); /* Pad dimension Y in PCB units. */ if (strcmp(Settings.grid_unit->suffix, "mil") == 0) { padx = padx / 2540; /* X location in 0.0001". */ pady = pady / 2540; /* Y location in 0.0001". */ } else { padx = padx / 1000; // X location in 0.001mm pady = pady / 1000; // Y location in 0.001mm } fprintf (fd, "X%4.4d", padx); fprintf (fd, "Y%4.4d", pady); fprintf (fd, "R000"); /* Rotation (0 degrees). */ fprintf (fd, " "); /* Column 72 should be left blank. */ if (pad->Mask > 0) { if (TEST_FLAG (ONSOLDERFLAG, pad) == true) { fprintf(fd, "S2"); /* Soldermask on bottom side. */ } else { fprintf(fd, "S1"); /* SolderMask on top side. */ } } else { fprintf(fd, "S3"); /* No soldermask. */ } fprintf (fd, " "); /* Padding. */ fprintf (fd, "\n"); SET_FLAG (VISITFLAG, pad); } END_LOOP; /* Pad. */ PIN_LOOP (element); if (TEST_FLAG (FOUNDFLAG, pin)) { if (TEST_FLAG (HOLEFLAG, pin)) /* Non plated? */ { fprintf (fd, "367%-17.14s", net); /* Net Name. */ } else { fprintf (fd, "317%-17.14s", net); /* Net Name. */ } fprintf (fd, "%-6.6s", element->Name[1].TextString); /* Refdes. */ fprintf (fd, "-%-4.4s", pin->Number); /* Pin number. */ fprintf (fd, " "); /*! \todo Midpoint indicator (M). */ tmp = pin->DrillingHole; if (strcmp (Settings.grid_unit->suffix, "mil") == 0) { tmp = tmp / 2540; /* 0.0001". */ } else { tmp = tmp / 1000; /* 0.001 mm. */ } if (TEST_FLAG (HOLEFLAG, pin)) { fprintf (fd, "D%-4.4dU", tmp); /* Unplated Drilled hole Id. */ } else { fprintf (fd, "D%-4.4dP", tmp); /* Plated drill hole. */ } fprintf (fd, "A00"); /* Accessible from both sides. */ padx = pin->X; /* X location in PCB units. */ pady = (PCB->MaxHeight - pin->Y); /* Y location in PCB units.*/ if (strcmp (Settings.grid_unit->suffix, "mil") == 0) { padx = padx / 2540; /* X location in 0.0001". */ pady = pady / 2540; /* Y location in 0.0001". */ } else { padx = padx / 1000; /* X location in 0.001 mm. */ pady = pady / 1000; /* Y location in 0.001 mm. */ } fprintf (fd, "X%+6.6d", padx); /* X Pad center. */ fprintf (fd, "Y%+6.6d", pady); /* Y pad center. */ padx = pin->Thickness; if (strcmp (Settings.grid_unit->suffix, "mil") == 0) { padx = padx / 2540; /* X location in 0.0001". */ } else { padx = padx / 1000; /* X location in 0.001 mm. */ } fprintf (fd, "X%4.4d", padx); /* Pad dimension X. */ if (TEST_FLAG (SQUAREFLAG, pin)) { fprintf (fd, "Y%4.4d", padx); /* Pad dimension Y. */ } else { fprintf (fd, "Y0000"); /* Y is 0 for round pins. */ } fprintf (fd, "R000"); /* Rotation (0 degrees). */ fprintf (fd, " "); /* Column 72 should be left blank.*/ if (pin->Mask > 0) { fprintf(fd, "S0"); /* No Soldermask. */ } else { fprintf(fd, "S3"); /* Soldermask on both sides. */ } fprintf (fd, " "); /* Padding. */ fprintf (fd, "\n"); SET_FLAG (VISITFLAG, pin); } END_LOOP; /* Pin. */ END_LOOP; /* Element */ VIA_LOOP (PCB->Data); if (TEST_FLAG (FOUNDFLAG, via)) { if (TEST_FLAG (HOLEFLAG, via)) /* Non plated ? */ { fprintf (fd, "367%-17.14s", net); /* Net Name. */ } else { fprintf (fd, "317%-17.14s", net); /* Net Name. */ } fprintf (fd, "VIA "); /* Refdes. */ fprintf (fd, "- "); /* Pin number. */ fprintf (fd, " "); /*! \todo Midpoint indicator (M). */ tmp = via->DrillingHole; if (strcmp (Settings.grid_unit->suffix, "mil") == 0) { tmp = tmp / 2540; /* 0.0001". */ } else { tmp = tmp / 1000; /* 0.001 mm. */ } if (TEST_FLAG (HOLEFLAG, via)) { fprintf (fd, "D%-4.4dU", tmp); /* Unplated Drilled hole Id. */ } else { fprintf (fd, "D%-4.4dP", tmp); /* Plated drill hole. */ } fprintf (fd, "A00"); /* Accessible from both sides. */ padx = via->X; /* X location in PCB units. */ pady = (PCB->MaxHeight - via->Y); /* Y location in PCB units. */ if (strcmp (Settings.grid_unit->suffix, "mil") == 0) { padx = padx / 2540; /* X location in 0.0001". */ pady = pady / 2540; /* Y location in 0.0001". */ } else { padx = padx / 1000; /* X location in 0.001 mm. */ pady = pady / 1000; /* Y location in 0.001 mm. */ } fprintf (fd, "X%+6.6d", padx); /* X Pad center. */ fprintf (fd, "Y%+6.6d", pady); /* Y pad center. */ padx = via->Thickness; if (strcmp (Settings.grid_unit->suffix, "mil") == 0) { padx = padx / 2540; /* X location in 0.0001". */ } else { padx = padx / 1000; /* X location in 0.001 mm. */ } fprintf (fd, "X%4.4d", padx); /* Pad dimension X. */ fprintf (fd, "Y0000"); /* Y is 0 for round pins (vias always round?). */ fprintf (fd, "R000"); /* Rotation (0 degrees). */ fprintf (fd, " "); /* Column 72 should be left blank. */ if (via->Mask > 0) { fprintf(fd, "S0"); /* No Soldermask. */ } else { fprintf(fd, "S3"); /* Soldermask on both sides. */ } fprintf (fd, " "); /* Padding. */ fprintf (fd, "\n"); SET_FLAG (VISITFLAG, via); } END_LOOP; /* Via. */ }
/* --------------------------------------------------------------------------- * creates a new via */ PinTypePtr CreateNewVia (DataTypePtr Data, LocationType X, LocationType Y, BDimension Thickness, BDimension Clearance, BDimension Mask, BDimension DrillingHole, char *Name, FlagType Flags) { PinTypePtr Via; if (!be_lenient) { VIA_LOOP (Data); { if (SQUARE (via->X - X) + SQUARE (via->Y - Y) <= SQUARE (via->DrillingHole / 2 + DrillingHole / 2)) { Message (_("Dropping via at (%d, %d) because it's hole would overlap with the via " "at (%d, %d)\n"), X/100, Y/100, via->X/100, via->Y/100); return (NULL); /* don't allow via stacking */ } } END_LOOP; } Via = GetViaMemory (Data); if (!Via) return (Via); /* copy values */ Via->X = X; Via->Y = Y; Via->Thickness = Thickness; Via->Clearance = Clearance; Via->Mask = Mask; Via->DrillingHole = vendorDrillMap (DrillingHole); if (Via->DrillingHole != DrillingHole) { Message (_ ("Mapped via drill hole to %.2f mils from %.2f mils per vendor table\n"), 0.01 * Via->DrillingHole, 0.01 * DrillingHole); } Via->Name = STRDUP (Name); Via->Flags = Flags; CLEAR_FLAG (WARNFLAG, Via); SET_FLAG (VIAFLAG, Via); Via->ID = ID++; /* * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure * hole) */ if (!TEST_FLAG (HOLEFLAG, Via) && (Via->Thickness < Via->DrillingHole + MIN_PINORVIACOPPER)) { Via->Thickness = Via->DrillingHole + MIN_PINORVIACOPPER; Message (_("Increased via thickness to %.2f mils to allow enough copper" " at (%.2f,%.2f).\n"), 0.01 * Via->Thickness, 0.01 * Via->X, 0.01 * Via->Y); } SetPinBoundingBox (Via); if (!Data->via_tree) Data->via_tree = r_create_tree (NULL, 0, 0); r_insert_entry (Data->via_tree, (BoxTypePtr) Via, 0); return (Via); }
/* --------------------------------------------------------------------------- * pastes the contents of the buffer to the layout. Only visible objects * are handled by the routine. */ bool CopyPastebufferToLayout (Coord X, Coord Y) { Cardinal i; bool changed = false; #ifdef DEBUG printf("Entering CopyPastebufferToLayout.....\n"); #endif /* set movement vector */ DeltaX = X - PASTEBUFFER->X, DeltaY = Y - PASTEBUFFER->Y; /* paste all layers */ for (i = 0; i < max_copper_layer + 2; i++) { LayerType *sourcelayer = &PASTEBUFFER->Data->Layer[i]; LayerType *destlayer = LAYER_PTR (i); if (destlayer->On) { changed = changed || (sourcelayer->LineN != 0) || (sourcelayer->ArcN != 0) || (sourcelayer->PolygonN != 0) || (sourcelayer->TextN != 0); LINE_LOOP (sourcelayer); { CopyLine (destlayer, line); } END_LOOP; ARC_LOOP (sourcelayer); { CopyArc (destlayer, arc); } END_LOOP; TEXT_LOOP (sourcelayer); { CopyText (destlayer, text); } END_LOOP; POLYGON_LOOP (sourcelayer); { CopyPolygon (destlayer, polygon); } END_LOOP; } } /* paste elements */ if (PCB->PinOn && PCB->ElementOn) { ELEMENT_LOOP (PASTEBUFFER->Data); { #ifdef DEBUG printf("In CopyPastebufferToLayout, pasting element %s\n", element->Name[1].TextString); #endif if (FRONT (element) || PCB->InvisibleObjectsOn) { CopyElement (element); changed = true; } } END_LOOP; } /* finally the vias */ if (PCB->ViaOn) { changed |= (PASTEBUFFER->Data->ViaN != 0); VIA_LOOP (PASTEBUFFER->Data); { CopyVia (via); } END_LOOP; } if (changed) { Draw (); IncrementUndoSerialNumber (); } #ifdef DEBUG printf(" .... Leaving CopyPastebufferToLayout.\n"); #endif return (changed); }
DrillInfoTypePtr GetDrillInfo (DataTypePtr top) { DrillInfoTypePtr AllDrills; DrillTypePtr Drill = NULL; DrillType savedrill, swapdrill; bool DrillFound = false; bool NewDrill; AllDrills = (DrillInfoTypePtr)calloc (1, sizeof (DrillInfoType)); ALLPIN_LOOP (top); { if (!DrillFound) { DrillFound = true; Drill = GetDrillInfoDrillMemory (AllDrills); InitializeDrill (Drill, pin, element); } else { if (Drill->DrillSize == pin->DrillingHole) FillDrill (Drill, element, pin); else { NewDrill = false; DRILL_LOOP (AllDrills); { if (drill->DrillSize == pin->DrillingHole) { Drill = drill; FillDrill (Drill, element, pin); break; } else if (drill->DrillSize > pin->DrillingHole) { if (!NewDrill) { NewDrill = true; InitializeDrill (&swapdrill, pin, element); Drill = GetDrillInfoDrillMemory (AllDrills); Drill->DrillSize = pin->DrillingHole + 1; Drill = drill; } savedrill = *drill; *drill = swapdrill; swapdrill = savedrill; } } END_LOOP; if (AllDrills->Drill[AllDrills->DrillN - 1].DrillSize < pin->DrillingHole) { Drill = GetDrillInfoDrillMemory (AllDrills); InitializeDrill (Drill, pin, element); } } } } ENDALL_LOOP; VIA_LOOP (top); { if (!DrillFound) { DrillFound = true; Drill = GetDrillInfoDrillMemory (AllDrills); Drill->DrillSize = via->DrillingHole; FillDrill (Drill, NULL, via); } else { if (Drill->DrillSize != via->DrillingHole) { DRILL_LOOP (AllDrills); { if (drill->DrillSize == via->DrillingHole) { Drill = drill; FillDrill (Drill, NULL, via); break; } } END_LOOP; if (Drill->DrillSize != via->DrillingHole) { Drill = GetDrillInfoDrillMemory (AllDrills); Drill->DrillSize = via->DrillingHole; FillDrill (Drill, NULL, via); } } else FillDrill (Drill, NULL, via); } } END_LOOP; qsort (AllDrills->Drill, AllDrills->DrillN, sizeof (DrillType), DrillQSort); return (AllDrills); }
/* --------------------------------------------------------------------------- * free memory used by data struct */ void FreeDataMemory (DataTypePtr Data) { LayerTypePtr layer; int i; if (Data) { VIA_LOOP (Data); { MYFREE (via->Name); } END_LOOP; ELEMENT_LOOP (Data); { FreeElementMemory (element); } END_LOOP; for (layer = Data->Layer, i = 0; i < MAX_LAYER + 2; layer++, i++) { FreeAttributeListMemory (&layer->Attributes); TEXT_LOOP (layer); { MYFREE (text->TextString); } END_LOOP; if (layer->Name) MYFREE (layer->Name); LINE_LOOP (layer); { if (line->Number) MYFREE (line->Number); } END_LOOP; MYFREE (layer->Line); MYFREE (layer->Arc); MYFREE (layer->Text); POLYGON_LOOP (layer); { FreePolygonMemory (polygon); } END_LOOP; MYFREE (layer->Polygon); if (layer->line_tree) r_destroy_tree (&layer->line_tree); if (layer->arc_tree) r_destroy_tree (&layer->arc_tree); if (layer->text_tree) r_destroy_tree (&layer->text_tree); if (layer->polygon_tree) r_destroy_tree (&layer->polygon_tree); } if (Data->element_tree) r_destroy_tree (&Data->element_tree); for (i = 0; i < MAX_ELEMENTNAMES; i++) if (Data->name_tree[i]) r_destroy_tree (&Data->name_tree[i]); if (Data->via_tree) r_destroy_tree (&Data->via_tree); if (Data->pin_tree) r_destroy_tree (&Data->pin_tree); if (Data->pad_tree) r_destroy_tree (&Data->pad_tree); if (Data->rat_tree) r_destroy_tree (&Data->rat_tree); /* clear struct */ memset (Data, 0, sizeof (DataType)); } else { fprintf (stderr, "Warning: Tried to FreeDataMemory(null)\n"); } }
/*! * \brief Creates a new via. */ PinType * CreateNewVia (DataType *Data, Coord X, Coord Y, Coord Thickness, Coord Clearance, Coord Mask, Coord DrillingHole, char *Name, FlagType Flags) { PinType *Via; if (!be_lenient) { VIA_LOOP (Data); { if (Distance (X, Y, via->X, via->Y) <= via->DrillingHole / 2 + DrillingHole / 2) { Message (_("%m+Dropping via at %$mD because it's hole would overlap with the via " "at %$mD\n"), Settings.grid_unit->allow, X, Y, via->X, via->Y); return (NULL); /* don't allow via stacking */ } } END_LOOP; } Via = GetViaMemory (Data); if (!Via) return (Via); /* copy values */ Via->X = X; Via->Y = Y; Via->Thickness = Thickness; Via->Clearance = Clearance; Via->Mask = Mask; Via->DrillingHole = vendorDrillMap (DrillingHole); if (Via->DrillingHole != DrillingHole) { Message (_("%m+Mapped via drill hole to %$mS from %$mS per vendor table\n"), Settings.grid_unit->allow, Via->DrillingHole, DrillingHole); } Via->Name = STRDUP (Name); Via->Flags = Flags; CLEAR_FLAG (WARNFLAG, Via); SET_FLAG (VIAFLAG, Via); Via->ID = ID++; /* * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure * hole) */ if (!TEST_FLAG (HOLEFLAG, Via) && (Via->Thickness < Via->DrillingHole + MIN_PINORVIACOPPER)) { Via->Thickness = Via->DrillingHole + MIN_PINORVIACOPPER; Message (_("%m+Increased via thickness to %$mS to allow enough copper" " at %$mD.\n"), Settings.grid_unit->allow, Via->Thickness, Via->X, Via->Y); } SetPinBoundingBox (Via); if (!Data->via_tree) Data->via_tree = r_create_tree (NULL, 0, 0); r_insert_entry (Data->via_tree, (BoxType *) Via, 0); return (Via); }
static void apply_vendor_map (void) { int i; int changed, tot; bool state; state = vendorMapEnable; /* enable mapping */ vendorMapEnable = true; /* reset our counts */ changed = 0; tot = 0; /* If we have loaded vendor drills, then apply them to the design */ if (n_vendor_drills > 0) { /* first all the vias */ VIA_LOOP (PCB->Data); { tot++; if (via->DrillingHole != vendorDrillMap (via->DrillingHole)) { /* only change unlocked vias */ if (!TEST_FLAG (LOCKFLAG, via)) { if (ChangeObject2ndSize (VIA_TYPE, via, NULL, NULL, vendorDrillMap (via->DrillingHole), true, false)) changed++; else { Message (_ ("Via at %.2f, %.2f not changed. Possible reasons:\n" "\t- pad size too small\n" "\t- new size would be too large or too small\n"), 0.01 * via->X, 0.01 * via->Y); } } else { Message (_("Locked via at %.2f, %.2f not changed.\n"), 0.01 * via->X, 0.01 * via->Y); } } } END_LOOP; /* and now the pins */ ELEMENT_LOOP (PCB->Data); { /* * first figure out if this element should be skipped for some * reason */ if (vendorIsElementMappable (element)) { /* the element is ok to modify, so iterate over its pins */ PIN_LOOP (element); { tot++; if (pin->DrillingHole != vendorDrillMap (pin->DrillingHole)) { if (!TEST_FLAG (LOCKFLAG, pin)) { if (ChangeObject2ndSize (PIN_TYPE, element, pin, NULL, vendorDrillMap (pin-> DrillingHole), true, false)) changed++; else { Message (_ ("Pin %s (%s) at %.2f, %.2f (element %s, %s, %s) not changed.\n" "\tPossible reasons:\n" "\t- pad size too small\n" "\t- new size would be too large or too small\n"), UNKNOWN (pin->Number), UNKNOWN (pin->Name), 0.01 * pin->X, 0.01 * pin->Y, UNKNOWN (NAMEONPCB_NAME (element)), UNKNOWN (VALUE_NAME (element)), UNKNOWN (DESCRIPTION_NAME (element))); } } else { Message (_ ("Locked pin at %-6.2f, %-6.2f not changed.\n"), 0.01 * pin->X, 0.01 * pin->Y); } } } END_LOOP; } } END_LOOP; Message (_("Updated %d drill sizes out of %d total\n"), changed, tot); /* Update the current Via */ if (Settings.ViaDrillingHole != vendorDrillMap (Settings.ViaDrillingHole)) { changed++; Settings.ViaDrillingHole = vendorDrillMap (Settings.ViaDrillingHole); Message (_("Adjusted active via hole size to be %6.2f mils\n"), 0.01 * Settings.ViaDrillingHole); } /* and update the vias for the various routing styles */ for (i = 0; i < NUM_STYLES; i++) { if (PCB->RouteStyle[i].Hole != vendorDrillMap (PCB->RouteStyle[i].Hole)) { changed++; PCB->RouteStyle[i].Hole = vendorDrillMap (PCB->RouteStyle[i].Hole); Message (_ ("Adjusted %s routing style via hole size to be %6.2f mils\n"), PCB->RouteStyle[i].Name, 0.01 * PCB->RouteStyle[i].Hole); if (PCB->RouteStyle[i].Diameter < PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER) { PCB->RouteStyle[i].Diameter = PCB->RouteStyle[i].Hole + MIN_PINORVIACOPPER; Message (_ ("Increased %s routing style via diameter to %6.2f mils\n"), PCB->RouteStyle[i].Name, 0.01 * PCB->RouteStyle[i].Diameter); } } } /* * if we've changed anything, indicate that we need to save the * file, redraw things, and make sure we can undo. */ if (changed) { SetChangedFlag (true); Redraw (); IncrementUndoSerialNumber (); } } /* restore mapping on/off */ vendorMapEnable = state; }
/* --------------------------------------------------------------------------- * searches for a object by it's unique ID. It doesn't matter if * the object is visible or not. The search is performed on a PCB, a * buffer or on the remove list. * The calling routine passes two pointers to allocated memory for storing * the results. * A type value is returned too which is NO_TYPE if no objects has been found. */ int SearchObjectByID (DataTypePtr Base, void **Result1, void **Result2, void **Result3, int ID, int type) { if (type == LINE_TYPE || type == LINEPOINT_TYPE) { ALLLINE_LOOP (Base); { if (line->ID == ID) { *Result1 = (void *) layer; *Result2 = *Result3 = (void *) line; return (LINE_TYPE); } if (line->Point1.ID == ID) { *Result1 = (void *) layer; *Result2 = (void *) line; *Result3 = (void *) &line->Point1; return (LINEPOINT_TYPE); } if (line->Point2.ID == ID) { *Result1 = (void *) layer; *Result2 = (void *) line; *Result3 = (void *) &line->Point2; return (LINEPOINT_TYPE); } } ENDALL_LOOP; } if (type == ARC_TYPE) { ALLARC_LOOP (Base); { if (arc->ID == ID) { *Result1 = (void *) layer; *Result2 = *Result3 = (void *) arc; return (ARC_TYPE); } } ENDALL_LOOP; } if (type == TEXT_TYPE) { ALLTEXT_LOOP (Base); { if (text->ID == ID) { *Result1 = (void *) layer; *Result2 = *Result3 = (void *) text; return (TEXT_TYPE); } } ENDALL_LOOP; } if (type == POLYGON_TYPE || type == POLYGONPOINT_TYPE) { ALLPOLYGON_LOOP (Base); { if (polygon->ID == ID) { *Result1 = (void *) layer; *Result2 = *Result3 = (void *) polygon; return (POLYGON_TYPE); } if (type == POLYGONPOINT_TYPE) POLYGONPOINT_LOOP (polygon); { if (point->ID == ID) { *Result1 = (void *) layer; *Result2 = (void *) polygon; *Result3 = (void *) point; return (POLYGONPOINT_TYPE); } } END_LOOP; } ENDALL_LOOP; } if (type == VIA_TYPE) { VIA_LOOP (Base); { if (via->ID == ID) { *Result1 = *Result2 = *Result3 = (void *) via; return (VIA_TYPE); } } END_LOOP; } if (type == RATLINE_TYPE || type == LINEPOINT_TYPE) { RAT_LOOP (Base); { if (line->ID == ID) { *Result1 = *Result2 = *Result3 = (void *) line; return (RATLINE_TYPE); } if (line->Point1.ID == ID) { *Result1 = (void *) NULL; *Result2 = (void *) line; *Result3 = (void *) &line->Point1; return (LINEPOINT_TYPE); } if (line->Point2.ID == ID) { *Result1 = (void *) NULL; *Result2 = (void *) line; *Result3 = (void *) &line->Point2; return (LINEPOINT_TYPE); } } END_LOOP; } if (type == ELEMENT_TYPE || type == PAD_TYPE || type == PIN_TYPE || type == ELEMENTLINE_TYPE || type == ELEMENTNAME_TYPE || type == ELEMENTARC_TYPE) /* check pins and elementnames too */ ELEMENT_LOOP (Base); { if (element->ID == ID) { *Result1 = *Result2 = *Result3 = (void *) element; return (ELEMENT_TYPE); } if (type == ELEMENTLINE_TYPE) ELEMENTLINE_LOOP (element); { if (line->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) line; return (ELEMENTLINE_TYPE); } } END_LOOP; if (type == ELEMENTARC_TYPE) ARC_LOOP (element); { if (arc->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) arc; return (ELEMENTARC_TYPE); } } END_LOOP; if (type == ELEMENTNAME_TYPE) ELEMENTTEXT_LOOP (element); { if (text->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) text; return (ELEMENTNAME_TYPE); } } END_LOOP; if (type == PIN_TYPE) PIN_LOOP (element); { if (pin->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) pin; return (PIN_TYPE); } } END_LOOP; if (type == PAD_TYPE) PAD_LOOP (element); { if (pad->ID == ID) { *Result1 = (void *) element; *Result2 = *Result3 = (void *) pad; return (PAD_TYPE); } } END_LOOP; } END_LOOP; Message ("hace: Internal error, search for ID %d failed\n", ID); return (NO_TYPE); }
/* ---------------------------------------------------------------------- * selects/unselects all visible objects within the passed box * Flag determines if the block is to be selected or unselected * returns true if the state of any object has changed */ bool SelectBlock (BoxTypePtr Box, bool Flag) { bool changed = false; if (PCB->RatOn || !Flag) RAT_LOOP (PCB->Data); { if (LINE_IN_BOX ((LineTypePtr) line, Box) && !TEST_FLAG (LOCKFLAG, line) && TEST_FLAG (SELECTEDFLAG, line) != Flag) { AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line); ASSIGN_FLAG (SELECTEDFLAG, Flag, line); if (PCB->RatOn) DrawRat (line, 0); changed = true; } } END_LOOP; /* check layers */ LAYER_LOOP(PCB->Data, max_copper_layer + 2); { if (layer == & PCB->Data->SILKLAYER) { if (! (PCB->ElementOn || !Flag)) continue; } else if (layer == & PCB->Data->BACKSILKLAYER) { if (! (PCB->InvisibleObjectsOn || !Flag)) continue; } else if (! (layer->On || !Flag)) continue; LINE_LOOP (layer); { if (LINE_IN_BOX (line, Box) && !TEST_FLAG (LOCKFLAG, line) && TEST_FLAG (SELECTEDFLAG, line) != Flag) { AddObjectToFlagUndoList (LINE_TYPE, layer, line, line); ASSIGN_FLAG (SELECTEDFLAG, Flag, line); if (layer->On) DrawLine (layer, line, 0); changed = true; } } END_LOOP; ARC_LOOP (layer); { if (ARC_IN_BOX (arc, Box) && !TEST_FLAG (LOCKFLAG, arc) && TEST_FLAG (SELECTEDFLAG, arc) != Flag) { AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc); ASSIGN_FLAG (SELECTEDFLAG, Flag, arc); if (layer->On) DrawArc (layer, arc, 0); changed = true; } } END_LOOP; TEXT_LOOP (layer); { if (!Flag || TEXT_IS_VISIBLE(PCB, layer, text)) { if (TEXT_IN_BOX (text, Box) && !TEST_FLAG (LOCKFLAG, text) && TEST_FLAG (SELECTEDFLAG, text) != Flag) { AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text); ASSIGN_FLAG (SELECTEDFLAG, Flag, text); if (TEXT_IS_VISIBLE(PCB, layer, text)) DrawText (layer, text, 0); changed = true; } } } END_LOOP; POLYGON_LOOP (layer); { if (POLYGON_IN_BOX (polygon, Box) && !TEST_FLAG (LOCKFLAG, polygon) && TEST_FLAG (SELECTEDFLAG, polygon) != Flag) { AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon); ASSIGN_FLAG (SELECTEDFLAG, Flag, polygon); if (layer->On) DrawPolygon (layer, polygon, 0); changed = true; } } END_LOOP; } END_LOOP; /* elements */ ELEMENT_LOOP (PCB->Data); { { bool gotElement = false; if ((PCB->ElementOn || !Flag) && !TEST_FLAG (LOCKFLAG, element) && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT || PCB->InvisibleObjectsOn)) { if (BOX_IN_BOX (&ELEMENT_TEXT (PCB, element).BoundingBox, Box) && !TEST_FLAG (LOCKFLAG, &ELEMENT_TEXT (PCB, element)) && TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)) != Flag) { /* select all names of element */ ELEMENTTEXT_LOOP (element); { AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text); ASSIGN_FLAG (SELECTEDFLAG, Flag, text); } END_LOOP; if (PCB->ElementOn) DrawElementName (element, 0); changed = true; } if ((PCB->PinOn || !Flag) && ELEMENT_IN_BOX (element, Box)) if (TEST_FLAG (SELECTEDFLAG, element) != Flag) { AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element); ASSIGN_FLAG (SELECTEDFLAG, Flag, element); PIN_LOOP (element); { if (TEST_FLAG (SELECTEDFLAG, pin) != Flag) { AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin); ASSIGN_FLAG (SELECTEDFLAG, Flag, pin); if (PCB->PinOn) DrawPin (pin, 0); changed = true; } } END_LOOP; PAD_LOOP (element); { if (TEST_FLAG (SELECTEDFLAG, pad) != Flag) { AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad); ASSIGN_FLAG (SELECTEDFLAG, Flag, pad); if (PCB->PinOn) DrawPad (pad, 0); changed = true; } } END_LOOP; if (PCB->PinOn) DrawElement (element, 0); changed = true; gotElement = true; } } if ((PCB->PinOn || !Flag) && !TEST_FLAG (LOCKFLAG, element) && !gotElement) { PIN_LOOP (element); { if ((VIA_OR_PIN_IN_BOX (pin, Box) && TEST_FLAG (SELECTEDFLAG, pin) != Flag)) { AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin); ASSIGN_FLAG (SELECTEDFLAG, Flag, pin); if (PCB->PinOn) DrawPin (pin, 0); changed = true; } } END_LOOP; PAD_LOOP (element); { if (PAD_IN_BOX (pad, Box) && TEST_FLAG (SELECTEDFLAG, pad) != Flag) { AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad); ASSIGN_FLAG (SELECTEDFLAG, Flag, pad); if (PCB->PinOn) DrawPad (pad, 0); changed = true; } } END_LOOP; } } } END_LOOP; /* end with vias */ if (PCB->ViaOn || !Flag) VIA_LOOP (PCB->Data); { if (VIA_OR_PIN_IN_BOX (via, Box) && !TEST_FLAG (LOCKFLAG, via) && TEST_FLAG (SELECTEDFLAG, via) != Flag) { AddObjectToFlagUndoList (VIA_TYPE, via, via, via); ASSIGN_FLAG (SELECTEDFLAG, Flag, via); if (PCB->ViaOn) DrawVia (via, 0); changed = true; } } END_LOOP; if (changed) { Draw (); IncrementUndoSerialNumber (); } return (changed); }
/*--------------------------------------------------------------------------- * * convert buffer contents into an element */ bool ConvertBufferToElement (BufferType *Buffer) { ElementType *Element; Cardinal group; Cardinal pin_n = 1; bool hasParts = false, crooked = false; int onsolder; bool warned = false; if (Buffer->Data->pcb == 0) Buffer->Data->pcb = PCB; Element = CreateNewElement (PCB->Data, &PCB->Font, NoFlags (), NULL, NULL, NULL, PASTEBUFFER->X, PASTEBUFFER->Y, 0, 100, MakeFlags (SWAP_IDENT ? ONSOLDERFLAG : NOFLAG), false); if (!Element) return (false); VIA_LOOP (Buffer->Data); { char num[8]; if (via->Mask < via->Thickness) via->Mask = via->Thickness + 2 * MASKFRAME; if (via->Name) CreateNewPin (Element, via->X, via->Y, via->Thickness, via->Clearance, via->Mask, via->DrillingHole, NULL, via->Name, MaskFlags (via->Flags, VIAFLAG | NOCOPY_FLAGS | SELECTEDFLAG | WARNFLAG)); else { sprintf (num, "%d", pin_n++); CreateNewPin (Element, via->X, via->Y, via->Thickness, via->Clearance, via->Mask, via->DrillingHole, NULL, num, MaskFlags (via->Flags, VIAFLAG | NOCOPY_FLAGS | SELECTEDFLAG | WARNFLAG)); } hasParts = true; } END_LOOP; for (onsolder = 0; onsolder < 2; onsolder ++) { int silk_layer; int onsolderflag; if ((!onsolder) == (!SWAP_IDENT)) { silk_layer = component_silk_layer; onsolderflag = NOFLAG; } else { silk_layer = solder_silk_layer; onsolderflag = ONSOLDERFLAG; } #define MAYBE_WARN() \ if (onsolder && !hasParts && !warned) \ { \ warned = true; \ Message \ (_("Warning: All of the pads are on the opposite\n" \ "side from the component - that's probably not what\n" \ "you wanted\n")); \ } \ /* get the component-side SM pads */ group = GetLayerGroupNumberByNumber (silk_layer); GROUP_LOOP (Buffer->Data, group); { char num[8]; LINE_LOOP (layer); { sprintf (num, "%d", pin_n++); CreateNewPad (Element, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness, line->Clearance, line->Thickness + line->Clearance, NULL, line->Number ? line->Number : num, MakeFlags (onsolderflag)); MAYBE_WARN(); hasParts = true; } END_LOOP; POLYGON_LOOP (layer); { Coord x1, y1, x2, y2, w, h, t; if (! polygon_is_rectangle (polygon)) { crooked = true; continue; } w = polygon->Points[2].X - polygon->Points[0].X; h = polygon->Points[1].Y - polygon->Points[0].Y; t = (w < h) ? w : h; x1 = polygon->Points[0].X + t/2; y1 = polygon->Points[0].Y + t/2; x2 = x1 + (w-t); y2 = y1 + (h-t); sprintf (num, "%d", pin_n++); CreateNewPad (Element, x1, y1, x2, y2, t, 2 * Settings.Keepaway, t + Settings.Keepaway, NULL, num, MakeFlags (SQUAREFLAG | onsolderflag)); MAYBE_WARN(); hasParts = true; } END_LOOP; } END_LOOP; } /* now add the silkscreen. NOTE: elements must have pads or pins too */ LINE_LOOP (&Buffer->Data->SILKLAYER); { if (line->Number && !NAMEONPCB_NAME (Element)) NAMEONPCB_NAME (Element) = strdup (line->Number); CreateNewLineInElement (Element, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness); hasParts = true; } END_LOOP; ARC_LOOP (&Buffer->Data->SILKLAYER); { CreateNewArcInElement (Element, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness); hasParts = true; } END_LOOP; if (!hasParts) { DestroyObject (PCB->Data, ELEMENT_TYPE, Element, Element, Element); Message (_("There was nothing to convert!\n" "Elements must have some silk, pads or pins.\n")); return (false); } if (crooked) Message (_("There were polygons that can't be made into pins!\n" "So they were not included in the element\n")); Element->MarkX = Buffer->X; Element->MarkY = Buffer->Y; if (SWAP_IDENT) SET_FLAG (ONSOLDERFLAG, Element); SetElementBoundingBox (PCB->Data, Element, &PCB->Font); ClearBuffer (Buffer); MoveObjectToBuffer (Buffer->Data, PCB->Data, ELEMENT_TYPE, Element, Element, Element); SetBufferBoundingBox (Buffer); return (true); }
/* ---------------------------------------------------------------------- * performs several operations on selected objects which are also visible * The lowlevel procedures are passed together with additional information * resets the selected flag if requested * returns true if anything has changed */ bool SelectedOperation (ObjectFunctionTypePtr F, bool Reset, int type) { bool changed = false; /* check lines */ if (type & LINE_TYPE && F->Line) VISIBLELINE_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, line)) { if (Reset) { AddObjectToFlagUndoList (LINE_TYPE, layer, line, line); CLEAR_FLAG (SELECTEDFLAG, line); } F->Line (layer, line); changed = true; } } ENDALL_LOOP; /* check arcs */ if (type & ARC_TYPE && F->Arc) VISIBLEARC_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, arc)) { if (Reset) { AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc); CLEAR_FLAG (SELECTEDFLAG, arc); } F->Arc (layer, arc); changed = true; } } ENDALL_LOOP; /* check text */ if (type & TEXT_TYPE && F->Text) ALLTEXT_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, text) && TEXT_IS_VISIBLE (PCB, layer, text)) { if (Reset) { AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text); CLEAR_FLAG (SELECTEDFLAG, text); } F->Text (layer, text); changed = true; } } ENDALL_LOOP; /* check polygons */ if (type & POLYGON_TYPE && F->Polygon) VISIBLEPOLYGON_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, polygon)) { if (Reset) { AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon); CLEAR_FLAG (SELECTEDFLAG, polygon); } F->Polygon (layer, polygon); changed = true; } } ENDALL_LOOP; /* elements silkscreen */ if (type & ELEMENT_TYPE && PCB->ElementOn && F->Element) ELEMENT_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, element)) { if (Reset) { AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element); CLEAR_FLAG (SELECTEDFLAG, element); } F->Element (element); changed = true; } } END_LOOP; if (type & ELEMENTNAME_TYPE && PCB->ElementOn && F->ElementName) ELEMENT_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element))) { if (Reset) { AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, &ELEMENT_TEXT (PCB, element), &ELEMENT_TEXT (PCB, element)); CLEAR_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)); } F->ElementName (element); changed = true; } } END_LOOP; if (type & PIN_TYPE && PCB->PinOn && F->Pin) ELEMENT_LOOP (PCB->Data); { PIN_LOOP (element); { if (TEST_FLAG (SELECTEDFLAG, pin)) { if (Reset) { AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin); CLEAR_FLAG (SELECTEDFLAG, pin); } F->Pin (element, pin); changed = true; } } END_LOOP; } END_LOOP; if (type & PAD_TYPE && PCB->PinOn && F->Pad) ELEMENT_LOOP (PCB->Data); { PAD_LOOP (element); { if (TEST_FLAG (SELECTEDFLAG, pad)) { if (Reset) { AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad); CLEAR_FLAG (SELECTEDFLAG, pad); } F->Pad (element, pad); changed = true; } } END_LOOP; } END_LOOP; /* process vias */ if (type & VIA_TYPE && PCB->ViaOn && F->Via) VIA_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, via)) { if (Reset) { AddObjectToFlagUndoList (VIA_TYPE, via, via, via); CLEAR_FLAG (SELECTEDFLAG, via); } F->Via (via); changed = true; } } END_LOOP; /* and rat-lines */ if (type & RATLINE_TYPE && PCB->RatOn && F->Rat) RAT_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, line)) { if (Reset) { AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line); CLEAR_FLAG (SELECTEDFLAG, line); } F->Rat (line); changed = true; } } END_LOOP; if (Reset && changed) IncrementUndoSerialNumber (); return (changed); }
void FreeRotateBuffer (BufferType *Buffer, Angle angle) { double cosa, sina; cosa = cos(angle * M_PI/180.0); sina = sin(angle * M_PI/180.0); /* rotate vias */ VIA_LOOP (Buffer->Data); { r_delete_entry (Buffer->Data->via_tree, (BoxType *)via); free_rotate (&via->X, &via->Y, Buffer->X, Buffer->Y, cosa, sina); SetPinBoundingBox (via); r_insert_entry (Buffer->Data->via_tree, (BoxType *)via, 0); } END_LOOP; /* elements */ ELEMENT_LOOP (Buffer->Data); { FreeRotateElementLowLevel (Buffer->Data, element, Buffer->X, Buffer->Y, cosa, sina, angle); } END_LOOP; /* all layer related objects */ ALLLINE_LOOP (Buffer->Data); { r_delete_entry (layer->line_tree, (BoxType *)line); free_rotate (&line->Point1.X, &line->Point1.Y, Buffer->X, Buffer->Y, cosa, sina); free_rotate (&line->Point2.X, &line->Point2.Y, Buffer->X, Buffer->Y, cosa, sina); SetLineBoundingBox (line); r_insert_entry (layer->line_tree, (BoxType *)line, 0); } ENDALL_LOOP; ALLARC_LOOP (Buffer->Data); { r_delete_entry (layer->arc_tree, (BoxType *)arc); free_rotate (&arc->X, &arc->Y, Buffer->X, Buffer->Y, cosa, sina); arc->StartAngle = NormalizeAngle (arc->StartAngle + angle); r_insert_entry (layer->arc_tree, (BoxType *)arc, 0); } ENDALL_LOOP; /* FIXME: rotate text */ ALLPOLYGON_LOOP (Buffer->Data); { r_delete_entry (layer->polygon_tree, (BoxType *)polygon); POLYGONPOINT_LOOP (polygon); { free_rotate (&point->X, &point->Y, Buffer->X, Buffer->Y, cosa, sina); } END_LOOP; SetPolygonBoundingBox (polygon); r_insert_entry (layer->polygon_tree, (BoxType *)polygon, 0); } ENDALL_LOOP; SetBufferBoundingBox (Buffer); SetCrosshairRangeToBuffer (); }
/* ---------------------------------------------------------------------- * selects/unselects all objects which were found during a connection scan * Flag determines if they are to be selected or unselected * returns true if the state of any object has changed * * text objects and elements cannot be selected by this routine */ bool SelectConnection (bool Flag) { bool changed = false; if (PCB->RatOn) RAT_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, line)) { AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line); ASSIGN_FLAG (SELECTEDFLAG, Flag, line); DrawRat (line, 0); changed = true; } } END_LOOP; VISIBLELINE_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, line) && !TEST_FLAG (LOCKFLAG, line)) { AddObjectToFlagUndoList (LINE_TYPE, layer, line, line); ASSIGN_FLAG (SELECTEDFLAG, Flag, line); DrawLine (layer, line, 0); changed = true; } } ENDALL_LOOP; VISIBLEARC_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, arc) && !TEST_FLAG (LOCKFLAG, arc)) { AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc); ASSIGN_FLAG (SELECTEDFLAG, Flag, arc); DrawArc (layer, arc, 0); changed = true; } } ENDALL_LOOP; VISIBLEPOLYGON_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, polygon) && !TEST_FLAG (LOCKFLAG, polygon)) { AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon); ASSIGN_FLAG (SELECTEDFLAG, Flag, polygon); DrawPolygon (layer, polygon, 0); changed = true; } } ENDALL_LOOP; if (PCB->PinOn && PCB->ElementOn) { ALLPIN_LOOP (PCB->Data); { if (!TEST_FLAG (LOCKFLAG, element) && TEST_FLAG (FOUNDFLAG, pin)) { AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin); ASSIGN_FLAG (SELECTEDFLAG, Flag, pin); DrawPin (pin, 0); changed = true; } } ENDALL_LOOP; ALLPAD_LOOP (PCB->Data); { if (!TEST_FLAG (LOCKFLAG, element) && TEST_FLAG (FOUNDFLAG, pad)) { AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad); ASSIGN_FLAG (SELECTEDFLAG, Flag, pad); DrawPad (pad, 0); changed = true; } } ENDALL_LOOP; } if (PCB->ViaOn) VIA_LOOP (PCB->Data); { if (TEST_FLAG (FOUNDFLAG, via) && !TEST_FLAG (LOCKFLAG, via)) { AddObjectToFlagUndoList (VIA_TYPE, via, via, via); ASSIGN_FLAG (SELECTEDFLAG, Flag, via); DrawVia (via, 0); changed = true; } } END_LOOP; Draw (); return (changed); }
/* --------------------------------------------------------------------------- * free memory used by data struct */ void FreeDataMemory (DataType *data) { LayerType *layer; int i; if (data == NULL) return; VIA_LOOP (data); { free (via->Name); } END_LOOP; g_list_free_full (data->Via, (GDestroyNotify)FreeVia); ELEMENT_LOOP (data); { FreeElementMemory (element); } END_LOOP; g_list_free_full (data->Element, (GDestroyNotify)FreeElement); g_list_free_full (data->Rat, (GDestroyNotify)FreeRat); for (layer = data->Layer, i = 0; i < MAX_LAYER + 2; layer++, i++) { FreeAttributeListMemory (&layer->Attributes); TEXT_LOOP (layer); { free (text->TextString); } END_LOOP; if (layer->Name) free (layer->Name); LINE_LOOP (layer); { if (line->Number) free (line->Number); } END_LOOP; g_list_free_full (layer->Line, (GDestroyNotify)FreeLine); g_list_free_full (layer->Arc, (GDestroyNotify)FreeArc); g_list_free_full (layer->Text, (GDestroyNotify)FreeText); POLYGON_LOOP (layer); { FreePolygonMemory (polygon); } END_LOOP; g_list_free_full (layer->Polygon, (GDestroyNotify)FreePolygon); if (layer->line_tree) r_destroy_tree (&layer->line_tree); if (layer->arc_tree) r_destroy_tree (&layer->arc_tree); if (layer->text_tree) r_destroy_tree (&layer->text_tree); if (layer->polygon_tree) r_destroy_tree (&layer->polygon_tree); } if (data->element_tree) r_destroy_tree (&data->element_tree); for (i = 0; i < MAX_ELEMENTNAMES; i++) if (data->name_tree[i]) r_destroy_tree (&data->name_tree[i]); if (data->via_tree) r_destroy_tree (&data->via_tree); if (data->pin_tree) r_destroy_tree (&data->pin_tree); if (data->pad_tree) r_destroy_tree (&data->pad_tree); if (data->rat_tree) r_destroy_tree (&data->rat_tree); /* clear struct */ memset (data, 0, sizeof (DataType)); }
/*! * \brief 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 (NetListType *Netl, bool NoWarn, bool AndRats) { NetType *a, *b; ConnectionType *conn; Cardinal m, n; bool Warned = false; for (m = 0; Netl->NetN > 0 && m < Netl->NetN; m++) { a = &Netl->Net[m]; ClearFlagOnAllObjects (false, DRCFLAG); RatFindHook (a->Connection[0].type, a->Connection[0].ptr1, a->Connection[0].ptr2, a->Connection[0].ptr2, false, DRCFLAG, AndRats); /* now anybody connected to the first point has DRCFLAG set */ /* so move those to this subnet */ CLEAR_FLAG (DRCFLAG, (PinType *) 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, (PinType *) b->Connection[0].ptr2)) { CLEAR_FLAG (DRCFLAG, (PinType *) 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)) { 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 = bottom_group; } } END_LOOP; if (!NoWarn) Warned |= CheckShorts (a->Connection[0].menu); } ClearFlagOnAllObjects (false, DRCFLAG); return (Warned); }
/* --------------------------------------------------------------------------- * draws all visible and attached objects of the pastebuffer */ static void XORDrawBuffer (BufferTypePtr Buffer) { Cardinal i; LocationType x, y; /* set offset */ x = Crosshair.X - Buffer->X; y = Crosshair.Y - Buffer->Y; /* draw all visible layers */ for (i = 0; i < max_copper_layer + 2; i++) if (PCB->Data->Layer[i].On) { LayerTypePtr layer = &Buffer->Data->Layer[i]; LINE_LOOP (layer); { /* XORDrawAttachedLine(x +line->Point1.X, y +line->Point1.Y, x +line->Point2.X, y +line->Point2.Y, line->Thickness); */ gui->draw_line (Crosshair.GC, x + line->Point1.X, y + line->Point1.Y, x + line->Point2.X, y + line->Point2.Y); } END_LOOP; ARC_LOOP (layer); { gui->draw_arc (Crosshair.GC, x + arc->X, y + arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); } END_LOOP; TEXT_LOOP (layer); { BoxTypePtr box = &text->BoundingBox; gui->draw_rect (Crosshair.GC, x + box->X1, y + box->Y1, x + box->X2, y + box->Y2); } END_LOOP; /* the tmp polygon has n+1 points because the first * and the last one are set to the same coordinates */ POLYGON_LOOP (layer); { XORPolygon (polygon, x, y); } END_LOOP; } /* draw elements if visible */ if (PCB->PinOn && PCB->ElementOn) ELEMENT_LOOP (Buffer->Data); { if (FRONT (element) || PCB->InvisibleObjectsOn) XORDrawElement (element, x, y); } END_LOOP; /* and the vias, move offset by thickness/2 */ if (PCB->ViaOn) VIA_LOOP (Buffer->Data); { gui->draw_arc (Crosshair.GC, x + via->X, y + via->Y, via->Thickness / 2, via->Thickness / 2, 0, 360); } END_LOOP; }
/*! * \brief The main IPC-D-356 function. * * Gets the filename for the netlist from the dialog. */ int IPCD356_Netlist (void) { FILE *fp; char nodename[256]; char net[256]; LibraryMenuType *netname; IPCD356_AliasList * aliaslist; if (IPCD356_SanityCheck()) /* Check for invalid names + numbers. */ { Message ("Aborting.\n"); return(1); } sprintf (net, "%s.ipc", PCB->Name); if (IPCD356_filename == NULL) return 1; fp = fopen (IPCD356_filename, "w+"); if (fp == NULL) { Message ("error opening %s\n", IPCD356_filename); return 1; } /* free (IPCD356_filename); */ IPCD356_WriteHeader (fp); aliaslist = CreateAliasList (); if (aliaslist == NULL) { Message ("Error Aloccating memory for IPC-D-356 AliasList\n"); return 1; } if (IPCD356_WriteAliases (fp, aliaslist)) { Message ("Error Writing IPC-D-356 AliasList\n"); return 1; } ELEMENT_LOOP (PCB->Data); PIN_LOOP (element); if (!TEST_FLAG (VISITFLAG, pin)) { ClearFlagOnLinesAndPolygons (true, FOUNDFLAG); ClearFlagOnPinsViasAndPads (true, FOUNDFLAG); LookupConnectionByPin (PIN_TYPE, pin); sprintf (nodename, "%s-%s", element->Name[1].TextString, pin->Number); netname = netnode_to_netname (nodename); /* Message("Netname: %s\n", netname->Name +2); */ if (netname) { strcpy (net, &netname->Name[2]); CheckNetLength (net, aliaslist); } else { strcpy (net, "N/C"); } IPCD356_WriteNet (fp, net); } END_LOOP; /* Pin. */ PAD_LOOP (element); if (!TEST_FLAG (VISITFLAG, pad)) { ClearFlagOnLinesAndPolygons (true, FOUNDFLAG); ClearFlagOnPinsViasAndPads (true, FOUNDFLAG); LookupConnectionByPin (PAD_TYPE, pad); sprintf (nodename, "%s-%s", element->Name[1].TextString, pad->Number); netname = netnode_to_netname (nodename); /* Message("Netname: %s\n", netname->Name +2); */ if (netname) { strcpy (net, &netname->Name[2]); CheckNetLength (net, aliaslist); } else { strcpy (net, "N/C"); } IPCD356_WriteNet (fp, net); } END_LOOP; /* Pad. */ END_LOOP; /* Element. */ VIA_LOOP (PCB->Data); if (!TEST_FLAG (VISITFLAG, via)) { ClearFlagOnLinesAndPolygons (true, FOUNDFLAG); ClearFlagOnPinsViasAndPads (true, FOUNDFLAG); LookupConnectionByPin (PIN_TYPE, via); strcpy (net, "N/C"); IPCD356_WriteNet (fp, net); } END_LOOP; /* Via. */ IPCD356_End (fp); fclose (fp); free (aliaslist); ResetVisitPinsViasAndPads (); ClearFlagOnLinesAndPolygons (true, FOUNDFLAG); ClearFlagOnPinsViasAndPads (true, FOUNDFLAG); return 0; }
/* --------------------------------------------------------------------------- * flip components/tracks from one side to the other */ static void SwapBuffer (BufferType *Buffer) { int j, k; Cardinal sgroup, cgroup; LayerType swap; ELEMENT_LOOP (Buffer->Data); { r_delete_element (Buffer->Data, element); MirrorElementCoordinates (Buffer->Data, element, 0); } END_LOOP; /* set buffer offset to 'mark' position */ Buffer->X = SWAP_X (Buffer->X); Buffer->Y = SWAP_Y (Buffer->Y); VIA_LOOP (Buffer->Data); { r_delete_entry (Buffer->Data->via_tree, (BoxType *)via); via->X = SWAP_X (via->X); via->Y = SWAP_Y (via->Y); SetPinBoundingBox (via); r_insert_entry (Buffer->Data->via_tree, (BoxType *)via, 0); } END_LOOP; ALLLINE_LOOP (Buffer->Data); { r_delete_entry (layer->line_tree, (BoxType *)line); line->Point1.X = SWAP_X (line->Point1.X); line->Point1.Y = SWAP_Y (line->Point1.Y); line->Point2.X = SWAP_X (line->Point2.X); line->Point2.Y = SWAP_Y (line->Point2.Y); SetLineBoundingBox (line); r_insert_entry (layer->line_tree, (BoxType *)line, 0); } ENDALL_LOOP; ALLARC_LOOP (Buffer->Data); { r_delete_entry (layer->arc_tree, (BoxType *)arc); arc->X = SWAP_X (arc->X); arc->Y = SWAP_Y (arc->Y); arc->StartAngle = SWAP_ANGLE (arc->StartAngle); arc->Delta = SWAP_DELTA (arc->Delta); SetArcBoundingBox (arc); r_insert_entry (layer->arc_tree, (BoxType *)arc, 0); } ENDALL_LOOP; ALLPOLYGON_LOOP (Buffer->Data); { r_delete_entry (layer->polygon_tree, (BoxType *)polygon); POLYGONPOINT_LOOP (polygon); { point->X = SWAP_X (point->X); point->Y = SWAP_Y (point->Y); } END_LOOP; SetPolygonBoundingBox (polygon); r_insert_entry (layer->polygon_tree, (BoxType *)polygon, 0); /* hmmm, how to handle clip */ } ENDALL_LOOP; ALLTEXT_LOOP (Buffer->Data); { r_delete_entry (layer->text_tree, (BoxType *)text); text->X = SWAP_X (text->X); text->Y = SWAP_Y (text->Y); TOGGLE_FLAG (ONSOLDERFLAG, text); SetTextBoundingBox (&PCB->Font, text); r_insert_entry (layer->text_tree, (BoxType *)text, 0); } ENDALL_LOOP; /* swap silkscreen layers */ swap = Buffer->Data->Layer[solder_silk_layer]; Buffer->Data->Layer[solder_silk_layer] = Buffer->Data->Layer[component_silk_layer]; Buffer->Data->Layer[component_silk_layer] = swap; /* swap layer groups when balanced */ sgroup = GetLayerGroupNumberByNumber (solder_silk_layer); cgroup = GetLayerGroupNumberByNumber (component_silk_layer); if (PCB->LayerGroups.Number[cgroup] == PCB->LayerGroups.Number[sgroup]) { for (j = k = 0; j < PCB->LayerGroups.Number[sgroup]; j++) { int t1, t2; Cardinal cnumber = PCB->LayerGroups.Entries[cgroup][k]; Cardinal snumber = PCB->LayerGroups.Entries[sgroup][j]; if (snumber >= max_copper_layer) continue; swap = Buffer->Data->Layer[snumber]; while (cnumber >= max_copper_layer) { k++; cnumber = PCB->LayerGroups.Entries[cgroup][k]; } Buffer->Data->Layer[snumber] = Buffer->Data->Layer[cnumber]; Buffer->Data->Layer[cnumber] = swap; k++; /* move the thermal flags with the layers */ ALLPIN_LOOP (Buffer->Data); { t1 = TEST_THERM (snumber, pin); t2 = TEST_THERM (cnumber, pin); ASSIGN_THERM (snumber, t2, pin); ASSIGN_THERM (cnumber, t1, pin); } ENDALL_LOOP; VIA_LOOP (Buffer->Data); { t1 = TEST_THERM (snumber, via); t2 = TEST_THERM (cnumber, via); ASSIGN_THERM (snumber, t2, via); ASSIGN_THERM (cnumber, t1, via); } END_LOOP; } } SetBufferBoundingBox (Buffer); SetCrosshairRangeToBuffer (); }
bool SelectObjectByName (int Type, char *Pattern, bool Flag) { bool changed = false; #if defined(HAVE_REGCOMP) #define REGEXEC(arg) (regexec_match_all(&compiled, (arg))) int result; regex_t compiled; /* compile the regular expression */ result = regcomp (&compiled, Pattern, REG_EXTENDED | REG_ICASE); if (result) { char errorstring[128]; regerror (result, &compiled, errorstring, 128); Message (_("regexp error: %s\n"), errorstring); regfree (&compiled); return (false); } #else #define REGEXEC(arg) (re_exec((arg)) == 1) char *compiled; /* compile the regular expression */ if ((compiled = re_comp (Pattern)) != NULL) { Message (_("re_comp error: %s\n"), compiled); return (false); } #endif /* loop over all visible objects with names */ if (Type & TEXT_TYPE) ALLTEXT_LOOP (PCB->Data); { if (!TEST_FLAG (LOCKFLAG, text) && TEXT_IS_VISIBLE (PCB, layer, text) && text->TextString && REGEXEC (text->TextString) && TEST_FLAG (SELECTEDFLAG, text) != Flag) { AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text); ASSIGN_FLAG (SELECTEDFLAG, Flag, text); DrawText (layer, text, 0); changed = true; } } ENDALL_LOOP; if (PCB->ElementOn && (Type & ELEMENT_TYPE)) ELEMENT_LOOP (PCB->Data); { if (!TEST_FLAG (LOCKFLAG, element) && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT || PCB->InvisibleObjectsOn) && TEST_FLAG (SELECTEDFLAG, element) != Flag) { String name = ELEMENT_NAME (PCB, element); if (name && REGEXEC (name)) { AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element); ASSIGN_FLAG (SELECTEDFLAG, Flag, element); PIN_LOOP (element); { AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin); ASSIGN_FLAG (SELECTEDFLAG, Flag, pin); } END_LOOP; PAD_LOOP (element); { AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad); ASSIGN_FLAG (SELECTEDFLAG, Flag, pad); } END_LOOP; ELEMENTTEXT_LOOP (element); { AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text); ASSIGN_FLAG (SELECTEDFLAG, Flag, text); } END_LOOP; DrawElementName (element, 0); DrawElement (element, 0); changed = true; } } } END_LOOP; if (PCB->PinOn && (Type & PIN_TYPE)) ALLPIN_LOOP (PCB->Data); { if (!TEST_FLAG (LOCKFLAG, element) && pin->Name && REGEXEC (pin->Name) && TEST_FLAG (SELECTEDFLAG, pin) != Flag) { AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin); ASSIGN_FLAG (SELECTEDFLAG, Flag, pin); DrawPin (pin, 0); changed = true; } } ENDALL_LOOP; if (PCB->PinOn && (Type & PAD_TYPE)) ALLPAD_LOOP (PCB->Data); { if (!TEST_FLAG (LOCKFLAG, element) && ((TEST_FLAG (ONSOLDERFLAG, pad) != 0) == SWAP_IDENT || PCB->InvisibleObjectsOn) && TEST_FLAG (SELECTEDFLAG, pad) != Flag) if (pad->Name && REGEXEC (pad->Name)) { AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad); ASSIGN_FLAG (SELECTEDFLAG, Flag, pad); DrawPad (pad, 0); changed = true; } } ENDALL_LOOP; if (PCB->ViaOn && (Type & VIA_TYPE)) VIA_LOOP (PCB->Data); { if (!TEST_FLAG (LOCKFLAG, via) && via->Name && REGEXEC (via->Name) && TEST_FLAG (SELECTEDFLAG, via) != Flag) { AddObjectToFlagUndoList (VIA_TYPE, via, via, via); ASSIGN_FLAG (SELECTEDFLAG, Flag, via); DrawVia (via, 0); changed = true; } } END_LOOP; #if defined(HAVE_REGCOMP) #if !defined(sgi) regfree (&compiled); #endif #endif if (changed) { IncrementUndoSerialNumber (); Draw (); } return (changed); }