/* --------------------------------------------------------------------------- * Update the X, Y and group position information stored in the NetList after * elements have possibly been moved, rotated, flipped, etc. */ static void UpdateXY (NetListType *Nets) { Cardinal top_group, bottom_group; Cardinal i, j; /* find layer groups of the top and bottom sides */ top_group = GetLayerGroupNumberBySide (TOP_SIDE); bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE); /* update all nets */ for (i = 0; i < Nets->NetN; i++) { for (j = 0; j < Nets->Net[i].ConnectionN; j++) { ConnectionType *c = &(Nets->Net[i].Connection[j]); switch (c->type) { case PAD_TYPE: c->group = TEST_FLAG (ONSOLDERFLAG, (ElementType *) c->ptr1) ? bottom_group : top_group; c->X = ((PadType *) c->ptr2)->Point1.X; c->Y = ((PadType *) c->ptr2)->Point1.Y; break; case PIN_TYPE: c->group = bottom_group; /* any layer will do */ c->X = ((PinType *) c->ptr2)->X; c->Y = ((PinType *) c->ptr2)->Y; break; default: Message ("Odd connection type encountered in " "UpdateXY"); break; } } } }
static int info (int argc, char **argv, Coord x, Coord y) { int i, j; int top_group, bottom_group; if (!PCB || !PCB->Data || !PCB->Filename) { printf("No PCB loaded.\n"); return 0; } printf("Filename: %s\n", PCB->Filename); pcb_printf("Size: %ml x %ml mils, %mm x %mm mm\n", PCB->MaxWidth, PCB->MaxHeight, PCB->MaxWidth, PCB->MaxHeight); top_group = GetLayerGroupNumberBySide (TOP_SIDE); bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE); for (i=0; i<MAX_LAYER; i++) { int lg = GetLayerGroupNumberByNumber (i); for (j = 0; j < MAX_GROUP; j++) putchar(j==lg ? '#' : '-'); printf(" %c %s\n", lg == top_group ? 'c' : lg == bottom_group ? 's' : '-', PCB->Data->Layer[i].Name); } return 0; }
/*! * \brief Checks all visible lines which belong to the same layergroup * as the passed pad. * * If one of the endpoints of the line lays inside the pad, the line is * added to the 'rubberband' list. */ static void CheckPadForRubberbandConnection (PadType *Pad) { Coord half = Pad->Thickness / 2; Cardinal group; struct rubber_info info; info.box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - half; info.box.Y1 = MIN (Pad->Point1.Y, Pad->Point2.Y) - half; info.box.X2 = MAX (Pad->Point1.X, Pad->Point2.X) + half; info.box.Y2 = MAX (Pad->Point1.Y, Pad->Point2.Y) + half; info.radius = 0; info.line = NULL; group = GetLayerGroupNumberBySide ( TEST_FLAG (ONSOLDERFLAG, Pad) ? BOTTOM_SIDE : TOP_SIDE); /* check all visible layers in the same group */ GROUP_LOOP (PCB->Data, group); { /* check all visible lines of the group member */ info.layer = layer; if (info.layer->On) { r_search (info.layer->line_tree, &info.box, NULL, rubber_callback, &info); } } END_LOOP; }
static void CheckPadForRat (PadType *Pad) { struct rinfo info; info.group = GetLayerGroupNumberBySide ( TEST_FLAG (ONSOLDERFLAG, Pad) ? BOTTOM_SIDE : TOP_SIDE); info.pad = Pad; info.type = PAD_TYPE; r_search (PCB->Data->rat_tree, &Pad->BoundingBox, NULL, rat_callback, &info); }
/*! * \brief This function is moved from the original netlist.c as * part of the gui code separation for the Gtk port. */ RatType * AddNet (void) { static int ratDrawn = 0; char name1[256], *name2; Cardinal group1, group2; char ratname[20]; int found; void *ptr1, *ptr2, *ptr3; LibraryMenuType *menu; LibraryEntryType *entry; if (Crosshair.AttachedLine.Point1.X == Crosshair.AttachedLine.Point2.X && Crosshair.AttachedLine.Point1.Y == Crosshair.AttachedLine.Point2.Y) return (NULL); found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.AttachedLine.Point1.X, Crosshair.AttachedLine.Point1.Y, 5); if (found == NO_TYPE) { Message (_("No pad/pin under rat line\n")); return (NULL); } if (NAMEONPCB_NAME ((ElementType *) ptr1) == NULL || *NAMEONPCB_NAME ((ElementType *) ptr1) == 0) { Message (_("You must name the starting element first\n")); return (NULL); } /* will work for pins to since the FLAG is common */ group1 = GetLayerGroupNumberBySide ( TEST_FLAG (ONSOLDERFLAG, (PadType *) ptr2) ? BOTTOM_SIDE : TOP_SIDE); strcpy (name1, ConnectionName (found, ptr1, ptr2)); found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.AttachedLine.Point2.X, Crosshair.AttachedLine.Point2.Y, 5); if (found == NO_TYPE) { Message (_("No pad/pin under rat line\n")); return (NULL); } if (NAMEONPCB_NAME ((ElementType *) ptr1) == NULL || *NAMEONPCB_NAME ((ElementType *) ptr1) == 0) { Message (_("You must name the ending element first\n")); return (NULL); } group2 = GetLayerGroupNumberBySide ( TEST_FLAG (ONSOLDERFLAG, (PadType *) ptr2) ? BOTTOM_SIDE : TOP_SIDE); name2 = ConnectionName (found, ptr1, ptr2); menu = netnode_to_netname (name1); if (menu) { if (netnode_to_netname (name2)) { Message (_ ("Both connections already in netlist - cannot merge nets\n")); return (NULL); } entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name2); netnode_to_netname (name2); goto ratIt; } /* ok, the first name did not belong to a net */ menu = netnode_to_netname (name2); if (menu) { entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name1); netnode_to_netname (name1); goto ratIt; } /* * neither belong to a net, so create a new one. * * before creating a new rats here, we need to search * for a unique name. */ sprintf (ratname, " ratDrawn%i", ++ratDrawn); while (rat_used (ratname)) { sprintf (ratname, " ratDrawn%i", ++ratDrawn); } menu = GetLibraryMenuMemory (&PCB->NetlistLib); menu->Name = strdup (ratname); entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name1); entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name2); menu->flag = 1; ratIt: NetlistChanged (0); return (CreateNewRat (PCB->Data, Crosshair.AttachedLine.Point1.X, Crosshair.AttachedLine.Point1.Y, Crosshair.AttachedLine.Point2.X, Crosshair.AttachedLine.Point2.Y, group1, group2, Settings.RatThickness, NoFlags ())); }
/*! * \brief Read the library-netlist build a true Netlist structure. */ NetListType * ProcNetlist (LibraryType *net_menu) { ConnectionType *connection; ConnectionType LastPoint; NetType *net; static NetListType *Wantlist = NULL; if (!net_menu->MenuN) return (NULL); FreeNetListMemory (Wantlist); free (Wantlist); badnet = false; /* find layer groups of the component side and solder side */ bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE); top_group = GetLayerGroupNumberBySide (TOP_SIDE); Wantlist = (NetListType *)calloc (1, sizeof (NetListType)); if (Wantlist) { ALLPIN_LOOP (PCB->Data); { pin->Spare = NULL; CLEAR_FLAG (DRCFLAG, pin); } ENDALL_LOOP; ALLPAD_LOOP (PCB->Data); { pad->Spare = NULL; CLEAR_FLAG (DRCFLAG, pad); } ENDALL_LOOP; MENU_LOOP (net_menu); { if (menu->Name[0] == '*' || menu->flag == 0) { badnet = true; continue; } net = GetNetMemory (Wantlist); if (menu->Style) { STYLE_LOOP (PCB); { if (style->Name && !NSTRCMP (style->Name, menu->Style)) { net->Style = style; break; } } END_LOOP; } else /* default to NULL if none found */ net->Style = NULL; ENTRY_LOOP (menu); { if (SeekPad (entry, &LastPoint, false)) { if (TEST_FLAG (DRCFLAG, (PinType *) LastPoint.ptr2)) Message (_ ("Error! Element %s pin %s appears multiple times in the netlist file.\n"), NAMEONPCB_NAME ((ElementType *) LastPoint.ptr1), (LastPoint.type == PIN_TYPE) ? ((PinType *) LastPoint.ptr2)-> Number : ((PadType *) LastPoint.ptr2)->Number); else { connection = GetConnectionMemory (net); *connection = LastPoint; /* indicate expect net */ connection->menu = menu; /* mark as visited */ SET_FLAG (DRCFLAG, (PinType *) LastPoint.ptr2); if (LastPoint.type == PIN_TYPE) ((PinType *) LastPoint.ptr2)->Spare = (void *) menu; else ((PadType *) LastPoint.ptr2)->Spare = (void *) menu; } } else badnet = true; /* check for more pins with the same number */ for (; SeekPad (entry, &LastPoint, true);) { connection = GetConnectionMemory (net); *connection = LastPoint; /* indicate expect net */ connection->menu = menu; /* mark as visited */ SET_FLAG (DRCFLAG, (PinType *) LastPoint.ptr2); if (LastPoint.type == PIN_TYPE) ((PinType *) LastPoint.ptr2)->Spare = (void *) menu; else ((PadType *) LastPoint.ptr2)->Spare = (void *) menu; } } END_LOOP; } END_LOOP; } /* clear all visit marks */ ALLPIN_LOOP (PCB->Data); { CLEAR_FLAG (DRCFLAG, pin); } ENDALL_LOOP; ALLPAD_LOOP (PCB->Data); { CLEAR_FLAG (DRCFLAG, pad); } ENDALL_LOOP; return (Wantlist); }
/*--------------------------------------------------------------------------- * * 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 side; int onsolderflag; if ((!onsolder) == (!SWAP_IDENT)) { side = TOP_SIDE; onsolderflag = NOFLAG; } else { side = BOTTOM_SIDE; 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 = GetLayerGroupNumberBySide (side); 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); }
/*--------------------------------------------------------------------------- * * break buffer element into pieces */ bool SmashBufferElement (BufferType *Buffer) { ElementType *element; Cardinal group; LayerType *top_layer, *bottom_layer; if (Buffer->Data->ElementN != 1) { Message (_("Error! Buffer doesn't contain a single element\n")); return (false); } /* * At this point the buffer should contain just a single element. * Now we detach the single element from the buffer and then clear the * buffer, ready to receive the smashed elements. As a result of detaching * it the single element is orphaned from the buffer and thus will not be * free()'d by FreeDataMemory (called via ClearBuffer). This leaves it * around for us to smash bits off it. It then becomes our responsibility, * however, to free the single element when we're finished with it. */ element = Buffer->Data->Element->data; Buffer->Data->Element = NULL; Buffer->Data->ElementN = 0; ClearBuffer (Buffer); ELEMENTLINE_LOOP (element); { CreateNewLineOnLayer (&Buffer->Data->SILKLAYER, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness, 0, NoFlags ()); if (line) line->Number = STRDUP (NAMEONPCB_NAME (element)); } END_LOOP; ARC_LOOP (element); { CreateNewArcOnLayer (&Buffer->Data->SILKLAYER, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness, 0, NoFlags ()); } END_LOOP; PIN_LOOP (element); { FlagType f = NoFlags (); AddFlags (f, VIAFLAG); if (TEST_FLAG (HOLEFLAG, pin)) AddFlags (f, HOLEFLAG); CreateNewVia (Buffer->Data, pin->X, pin->Y, pin->Thickness, pin->Clearance, pin->Mask, pin->DrillingHole, pin->Number, f); } END_LOOP; group = GetLayerGroupNumberBySide (SWAP_IDENT ? BOTTOM_SIDE : TOP_SIDE); top_layer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]]; group = GetLayerGroupNumberBySide (SWAP_IDENT ? TOP_SIDE : BOTTOM_SIDE); bottom_layer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]]; PAD_LOOP (element); { LineType *line; line = CreateNewLineOnLayer (TEST_FLAG (ONSOLDERFLAG, pad) ? bottom_layer : top_layer, pad->Point1.X, pad->Point1.Y, pad->Point2.X, pad->Point2.Y, pad->Thickness, pad->Clearance, NoFlags ()); if (line) line->Number = STRDUP (pad->Number); } END_LOOP; FreeElementMemory (element); g_slice_free (ElementType, element); return (true); }
/* --------------------------------------------------------------------------- * flip components/tracks from one side to the other */ static void SwapBuffer (BufferType *Buffer) { int j, k; Cardinal top_group, bottom_group; 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[bottom_silk_layer]; Buffer->Data->Layer[bottom_silk_layer] = Buffer->Data->Layer[top_silk_layer]; Buffer->Data->Layer[top_silk_layer] = swap; /* swap layer groups when balanced */ top_group = GetLayerGroupNumberBySide (TOP_SIDE); bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE); if (PCB->LayerGroups.Number[top_group] == PCB->LayerGroups.Number[bottom_group]) { for (j = k = 0; j < PCB->LayerGroups.Number[bottom_group]; j++) { int t1, t2; Cardinal top_number = PCB->LayerGroups.Entries[top_group][k]; Cardinal bottom_number = PCB->LayerGroups.Entries[bottom_group][j]; if (bottom_number >= max_copper_layer) continue; swap = Buffer->Data->Layer[bottom_number]; while (top_number >= max_copper_layer) { k++; top_number = PCB->LayerGroups.Entries[top_group][k]; } Buffer->Data->Layer[bottom_number] = Buffer->Data->Layer[top_number]; Buffer->Data->Layer[top_number] = swap; k++; /* move the thermal flags with the layers */ ALLPIN_LOOP (Buffer->Data); { t1 = TEST_THERM (bottom_number, pin); t2 = TEST_THERM (top_number, pin); ASSIGN_THERM (bottom_number, t2, pin); ASSIGN_THERM (top_number, t1, pin); } ENDALL_LOOP; VIA_LOOP (Buffer->Data); { t1 = TEST_THERM (bottom_number, via); t2 = TEST_THERM (top_number, via); ASSIGN_THERM (bottom_number, t2, via); ASSIGN_THERM (top_number, t1, via); } END_LOOP; } } SetBufferBoundingBox (Buffer); SetCrosshairRangeToBuffer (); }
/*! * \brief Recalculates the passed coordinates to fit the current grid * setting. */ void FitCrosshairIntoGrid (Coord X, Coord Y) { Coord nearest_grid_x, nearest_grid_y; void *ptr1, *ptr2, *ptr3; struct snap_data snap_data; int ans; Crosshair.X = CLAMP (X, Crosshair.MinX, Crosshair.MaxX); Crosshair.Y = CLAMP (Y, Crosshair.MinY, Crosshair.MaxY); if (PCB->RatDraw) { nearest_grid_x = -MIL_TO_COORD (6); nearest_grid_y = -MIL_TO_COORD (6); } else { nearest_grid_x = GridFit (Crosshair.X, PCB->Grid, PCB->GridOffsetX); nearest_grid_y = GridFit (Crosshair.Y, PCB->Grid, PCB->GridOffsetY); if (Marked.status && TEST_FLAG (ORTHOMOVEFLAG, PCB)) { Coord dx = Crosshair.X - Marked.X; Coord dy = Crosshair.Y - Marked.Y; if (ABS (dx) > ABS (dy)) nearest_grid_y = Marked.Y; else nearest_grid_x = Marked.X; } } snap_data.crosshair = &Crosshair; snap_data.nearest_sq_dist = crosshair_sq_dist (&Crosshair, nearest_grid_x, nearest_grid_y); snap_data.nearest_is_grid = true; snap_data.x = nearest_grid_x; snap_data.y = nearest_grid_y; ans = NO_TYPE; if (!PCB->RatDraw) ans = SearchObjectByLocation (ELEMENT_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.X, Crosshair.Y, PCB->Grid / 2); if (ans & ELEMENT_TYPE) { ElementType *el = (ElementType *) ptr1; check_snap_object (&snap_data, el->MarkX, el->MarkY, false); } ans = NO_TYPE; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchObjectByLocation (PAD_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.X, Crosshair.Y, PCB->Grid / 2); /* Avoid self-snapping when moving */ if (ans != NO_TYPE && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans != NO_TYPE && ( Settings.Mode == LINE_MODE || (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE))) { PadType *pad = (PadType *) ptr2; LayerType *desired_layer; Cardinal desired_group; Cardinal bottom_group, top_group; int found_our_layer = false; desired_layer = CURRENT; if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE) { desired_layer = (LayerType *)Crosshair.AttachedObject.Ptr1; } /* find layer groups of the top and bottom sides */ top_group = GetLayerGroupNumberBySide (TOP_SIDE); bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE); desired_group = TEST_FLAG (ONSOLDERFLAG, pad) ? bottom_group : top_group; GROUP_LOOP (PCB->Data, desired_group); { if (layer == desired_layer) { found_our_layer = true; break; } } END_LOOP; if (found_our_layer == false) ans = NO_TYPE; } if (ans != NO_TYPE) { PadType *pad = (PadType *)ptr2; check_snap_object (&snap_data, pad->Point1.X + (pad->Point2.X - pad->Point1.X) / 2, pad->Point1.Y + (pad->Point2.Y - pad->Point1.Y) / 2, true); } ans = NO_TYPE; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchObjectByLocation (PIN_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.X, Crosshair.Y, PCB->Grid / 2); /* Avoid self-snapping when moving */ if (ans != NO_TYPE && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans != NO_TYPE) { PinType *pin = (PinType *)ptr2; check_snap_object (&snap_data, pin->X, pin->Y, true); } ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchObjectByLocation (VIA_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.X, Crosshair.Y, PCB->Grid / 2); /* Avoid snapping vias to any other vias */ if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == VIA_TYPE && (ans & PIN_TYPES)) ans = NO_TYPE; if (ans != NO_TYPE) { PinType *pin = (PinType *)ptr2; check_snap_object (&snap_data, pin->X, pin->Y, true); } ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchObjectByLocation (LINEPOINT_TYPE | ARCPOINT_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.X, Crosshair.Y, PCB->Grid / 2); if (ans != NO_TYPE) { PointType *pnt = (PointType *)ptr3; check_snap_object (&snap_data, pnt->X, pnt->Y, true); } check_snap_offgrid_line (&snap_data, nearest_grid_x, nearest_grid_y); ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchObjectByLocation (POLYGONPOINT_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.X, Crosshair.Y, PCB->Grid / 2); if (ans != NO_TYPE) { PointType *pnt = (PointType *)ptr3; check_snap_object (&snap_data, pnt->X, pnt->Y, true); } if (snap_data.x >= 0 && snap_data.y >= 0) { Crosshair.X = snap_data.x; Crosshair.Y = snap_data.y; } if (Settings.Mode == ARROW_MODE) { ans = SearchObjectByLocation (LINEPOINT_TYPE | ARCPOINT_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.X, Crosshair.Y, PCB->Grid / 2); if (ans == NO_TYPE) hid_action("PointCursor"); else if (!TEST_FLAG(SELECTEDFLAG, (LineType *)ptr2)) hid_actionl("PointCursor","True", NULL); } if (Settings.Mode == LINE_MODE && Crosshair.AttachedLine.State != STATE_FIRST && TEST_FLAG (AUTODRCFLAG, PCB)) EnforceLineDRC (); gui->set_crosshair (Crosshair.X, Crosshair.Y, HID_SC_DO_NOTHING); }