/*! * \file src/change.c * * \brief Functions used to change object properties. * *
* *

Copyright.

\n * * PCB, interactive printed circuit board design * * Copyright (C) 1994,1995,1996, 2005 Thomas Nau * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Contact addresses for paper mail and Email: * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany * Thomas.Nau@rz.uni-ulm.de */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "global.h" #include "change.h" #include "create.h" #include "crosshair.h" #include "data.h" #include "draw.h" #include "error.h" #include "mymem.h" #include "misc.h" #include "mirror.h" #include "polygon.h" #include "rats.h" #include "remove.h" #include "rtree.h" #include "search.h" #include "select.h" #include "set.h" #include "thermal.h" #include "undo.h" #ifdef HAVE_LIBDMALLOC #include #endif /* --------------------------------------------------------------------------- * some local prototypes */ static void *ChangePinSize (ElementType *, PinType *); static void *ChangePinClearSize (ElementType *, PinType *); static void *ChangePinMaskSize (ElementType *, PinType *); static void *ChangePadSize (ElementType *, PadType *); static void *ChangePadClearSize (ElementType *, PadType *); static void *ChangePadMaskSize (ElementType *, PadType *); static void *ChangePin2ndSize (ElementType *, PinType *); static void *ChangeElement2ndSize (ElementType *); static void *ChangeViaSize (PinType *); static void *ChangeVia2ndSize (PinType *); static void *ChangeViaClearSize (PinType *); static void *ChangeViaMaskSize (PinType *); static void *ChangeLineSize (LayerType *, LineType *); static void *ChangeLineClearSize (LayerType *, LineType *); static void *ChangePolygonClearSize (LayerType *, PolygonType *); static void *ChangeArcSize (LayerType *, ArcType *); static void *ChangeArcClearSize (LayerType *, ArcType *); static void *ChangeTextSize (LayerType *, TextType *); static void *ChangeElementSize (ElementType *); static void *ChangeElementNameSize (ElementType *); static void *ChangePinName (ElementType *, PinType *); static void *ChangePadName (ElementType *, PadType *); static void *ChangeViaName (PinType *); static void *ChangeLineName (LayerType *, LineType *); static void *ChangeElementName (ElementType *); static void *ChangeTextName (LayerType *, TextType *); static void *ChangeElementSquare (ElementType *); static void *SetElementSquare (ElementType *); static void *ClrElementSquare (ElementType *); static void *ChangeElementOctagon (ElementType *); static void *SetElementOctagon (ElementType *); static void *ClrElementOctagon (ElementType *); static void *ChangePinSquare (ElementType *, PinType *); static void *SetPinSquare (ElementType *, PinType *); static void *ClrPinSquare (ElementType *, PinType *); static void *ChangePinOctagon (ElementType *, PinType *); static void *SetPinOctagon (ElementType *, PinType *); static void *ClrPinOctagon (ElementType *, PinType *); static void *ChangeViaOctagon (PinType *); static void *SetViaOctagon (PinType *); static void *ClrViaOctagon (PinType *); static void *ChangePadSquare (ElementType *, PadType *); static void *SetPadSquare (ElementType *, PadType *); static void *ClrPadSquare (ElementType *, PadType *); static void *ChangeViaThermal (PinType *); static void *ChangePinThermal (ElementType *, PinType *); static void *ChangeLineJoin (LayerType *, LineType *); static void *SetLineJoin (LayerType *, LineType *); static void *ClrLineJoin (LayerType *, LineType *); static void *ChangeArcJoin (LayerType *, ArcType *); static void *SetArcJoin (LayerType *, ArcType *); static void *ClrArcJoin (LayerType *, ArcType *); static void *ChangeTextJoin (LayerType *, TextType *); static void *SetTextJoin (LayerType *, TextType *); static void *ClrTextJoin (LayerType *, TextType *); static void *ChangePolyClear (LayerType *, PolygonType *); /* --------------------------------------------------------------------------- * some local identifiers */ /*! Either the new value or the change in value */ static int Value; /*! Used as boolean to indicate that Value is an absolute or delta */ static int Absolute; static char *NewName; /* new name */ static ObjectFunctionType ChangeSizeFunctions = { ChangeLineSize, ChangeTextSize, ChangePolyClear, ChangeViaSize, ChangeElementSize, /* changes silk screen line width */ ChangeElementNameSize, ChangePinSize, ChangePadSize, NULL, NULL, ChangeArcSize, NULL }; static ObjectFunctionType Change2ndSizeFunctions = { NULL, NULL, NULL, ChangeVia2ndSize, ChangeElement2ndSize, NULL, ChangePin2ndSize, NULL, NULL, NULL, NULL, NULL }; static ObjectFunctionType ChangeThermalFunctions = { NULL, NULL, NULL, ChangeViaThermal, NULL, NULL, ChangePinThermal, NULL, NULL, NULL, NULL, NULL }; static ObjectFunctionType ChangeClearSizeFunctions = { ChangeLineClearSize, NULL, ChangePolygonClearSize, /* just to tell the user not to :-) */ ChangeViaClearSize, NULL, NULL, ChangePinClearSize, ChangePadClearSize, NULL, NULL, ChangeArcClearSize, NULL }; static ObjectFunctionType ChangeNameFunctions = { ChangeLineName, ChangeTextName, NULL, ChangeViaName, ChangeElementName, NULL, ChangePinName, ChangePadName, NULL, NULL, NULL, NULL }; static ObjectFunctionType ChangeSquareFunctions = { NULL, NULL, NULL, NULL, ChangeElementSquare, NULL, ChangePinSquare, ChangePadSquare, NULL, NULL, NULL, NULL }; static ObjectFunctionType ChangeJoinFunctions = { ChangeLineJoin, ChangeTextJoin, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ChangeArcJoin, NULL }; static ObjectFunctionType ChangeOctagonFunctions = { NULL, NULL, NULL, ChangeViaOctagon, ChangeElementOctagon, NULL, ChangePinOctagon, NULL, NULL, NULL, NULL, NULL }; static ObjectFunctionType ChangeMaskSizeFunctions = { NULL, NULL, NULL, ChangeViaMaskSize, #if 0 ChangeElementMaskSize, #else NULL, #endif NULL, ChangePinMaskSize, ChangePadMaskSize, NULL, NULL, NULL, NULL }; static ObjectFunctionType SetSquareFunctions = { NULL, NULL, NULL, NULL, SetElementSquare, NULL, SetPinSquare, SetPadSquare, NULL, NULL, NULL, NULL }; static ObjectFunctionType SetJoinFunctions = { SetLineJoin, SetTextJoin, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, SetArcJoin, NULL }; static ObjectFunctionType SetOctagonFunctions = { NULL, NULL, NULL, SetViaOctagon, SetElementOctagon, NULL, SetPinOctagon, NULL, NULL, NULL, NULL, NULL }; static ObjectFunctionType ClrSquareFunctions = { NULL, NULL, NULL, NULL, ClrElementSquare, NULL, ClrPinSquare, ClrPadSquare, NULL, NULL, NULL, NULL }; static ObjectFunctionType ClrJoinFunctions = { ClrLineJoin, ClrTextJoin, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ClrArcJoin, NULL }; static ObjectFunctionType ClrOctagonFunctions = { NULL, NULL, NULL, ClrViaOctagon, ClrElementOctagon, NULL, ClrPinOctagon, NULL, NULL, NULL, NULL, NULL }; /*! * \brief Changes the thermal on a via. * * \return TRUE if changed. */ static void * ChangeViaThermal (PinType *Via) { AddObjectToClearPolyUndoList (VIA_TYPE, Via, Via, Via, false); RestoreToPolygon (PCB->Data, VIA_TYPE, CURRENT, Via); AddObjectToFlagUndoList (VIA_TYPE, Via, Via, Via); if (!Value) /* remove the thermals */ CLEAR_THERM (INDEXOFCURRENT, Via); else ASSIGN_THERM (INDEXOFCURRENT, Value, Via); AddObjectToClearPolyUndoList (VIA_TYPE, Via, Via, Via, true); ClearFromPolygon (PCB->Data, VIA_TYPE, CURRENT, Via); DrawVia (Via); return Via; } /*! * \brief Changes the thermal on a pin. * * \return TRUE if changed. */ static void * ChangePinThermal (ElementType *element, PinType *Pin) { AddObjectToClearPolyUndoList (PIN_TYPE, element, Pin, Pin, false); RestoreToPolygon (PCB->Data, VIA_TYPE, CURRENT, Pin); AddObjectToFlagUndoList (PIN_TYPE, element, Pin, Pin); if (!Value) /* remove the thermals */ CLEAR_THERM (INDEXOFCURRENT, Pin); else ASSIGN_THERM (INDEXOFCURRENT, Value, Pin); AddObjectToClearPolyUndoList (PIN_TYPE, element, Pin, Pin, true); ClearFromPolygon (PCB->Data, VIA_TYPE, CURRENT, Pin); DrawPin (Pin); return Pin; } /*! * \brief Changes the size of a via. * * \return TRUE if changed. */ static void * ChangeViaSize (PinType *Via) { Coord new_value = Absolute ? Value : Via->Thickness + Value; if (TEST_FLAG (LOCKFLAG, Via)) return (NULL); if (!TEST_FLAG (HOLEFLAG, Via) && new_value <= MAX_PINORVIASIZE && new_value >= MIN_PINORVIASIZE && new_value > Via->DrillingHole && new_value != Via->Thickness) { AddObjectToSizeUndoList (VIA_TYPE, Via, Via, Via); EraseVia (Via); r_delete_entry (PCB->Data->via_tree, (BoxType *) Via); RestoreToPolygon (PCB->Data, PIN_TYPE, Via, Via); if (Via->Mask) { AddObjectToMaskSizeUndoList (VIA_TYPE, Via, Via, Via); Via->Mask += new_value - Via->Thickness; } Via->Thickness = new_value; SetPinBoundingBox (Via); r_insert_entry (PCB->Data->via_tree, (BoxType *) Via, 0); ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via); DrawVia (Via); return (Via); } return (NULL); } /*! * \brief Changes the drilling hole of a via. * * \return TRUE if changed. */ static void * ChangeVia2ndSize (PinType *Via) { Coord new_value = (Absolute) ? Value : Via->DrillingHole + Value; if (TEST_FLAG (LOCKFLAG, Via)) return (NULL); if (new_value <= MAX_PINORVIASIZE && new_value >= MIN_PINORVIAHOLE && (TEST_FLAG (HOLEFLAG, Via) || new_value < Via->Thickness) && new_value != Via->DrillingHole) { AddObjectTo2ndSizeUndoList (VIA_TYPE, Via, Via, Via); EraseVia (Via); RestoreToPolygon (PCB->Data, VIA_TYPE, Via, Via); Via->DrillingHole = new_value; if (TEST_FLAG (HOLEFLAG, Via)) { AddObjectToSizeUndoList (VIA_TYPE, Via, Via, Via); Via->Thickness = new_value; } ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via); DrawVia (Via); return (Via); } return (NULL); } /*! * \brief Changes the clearance size of a via. * * \return TRUE if changed. */ static void * ChangeViaClearSize (PinType *Via) { Coord new_value = (Absolute) ? Value : Via->Clearance + Value; if (TEST_FLAG (LOCKFLAG, Via)) return (NULL); new_value = MIN (MAX_LINESIZE, new_value); if (new_value < 0) new_value = 0; if (Value < 0 && new_value < PCB->Bloat * 2) new_value = 0; if ((Value > 0 || Absolute) && new_value < PCB->Bloat * 2) new_value = PCB->Bloat * 2 + 2; if (Via->Clearance == new_value) return NULL; RestoreToPolygon (PCB->Data, VIA_TYPE, Via, Via); AddObjectToClearSizeUndoList (VIA_TYPE, Via, Via, Via); EraseVia (Via); r_delete_entry (PCB->Data->via_tree, (BoxType *) Via); Via->Clearance = new_value; SetPinBoundingBox (Via); r_insert_entry (PCB->Data->via_tree, (BoxType *) Via, 0); ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via); DrawVia (Via); Via->Element = NULL; return (Via); } /*! * \brief Changes the size of a pin. * * \return TRUE if changed. */ static void * ChangePinSize (ElementType *Element, PinType *Pin) { Coord new_value = (Absolute) ? Value : Pin->Thickness + Value; if (TEST_FLAG (LOCKFLAG, Pin)) return (NULL); if (!TEST_FLAG (HOLEFLAG, Pin) && new_value <= MAX_PINORVIASIZE && new_value >= MIN_PINORVIASIZE && new_value > Pin->DrillingHole && new_value != Pin->Thickness) { AddObjectToSizeUndoList (PIN_TYPE, Element, Pin, Pin); AddObjectToMaskSizeUndoList (PIN_TYPE, Element, Pin, Pin); ErasePin (Pin); r_delete_entry (PCB->Data->pin_tree, &Pin->BoundingBox); RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin); Pin->Mask += new_value - Pin->Thickness; Pin->Thickness = new_value; /* SetElementBB updates all associated rtrees */ SetElementBoundingBox (PCB->Data, Element, &PCB->Font); ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin); DrawPin (Pin); return (Pin); } return (NULL); } /*! * \brief Changes the clearance size of a pin. * * \return TRUE if changed. */ static void * ChangePinClearSize (ElementType *Element, PinType *Pin) { Coord new_value = (Absolute) ? Value : Pin->Clearance + Value; if (TEST_FLAG (LOCKFLAG, Pin)) return (NULL); new_value = MIN (MAX_LINESIZE, new_value); if (new_value < 0) new_value = 0; if (Value < 0 && new_value < PCB->Bloat * 2) new_value = 0; if ((Value > 0 || Absolute) && new_value < PCB->Bloat * 2) new_value = PCB->Bloat * 2 + 2; if (Pin->Clearance == new_value) return NULL; RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin); AddObjectToClearSizeUndoList (PIN_TYPE, Element, Pin, Pin); ErasePin (Pin); r_delete_entry (PCB->Data->pin_tree, &Pin->BoundingBox); Pin->Clearance = new_value; /* SetElementBB updates all associated rtrees */ SetElementBoundingBox (PCB->Data, Element, &PCB->Font); ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin); DrawPin (Pin); return (Pin); } /*! * \brief Changes the size of a pad. * * \return TRUE if changed. */ static void * ChangePadSize (ElementType *Element, PadType *Pad) { Coord new_value = (Absolute) ? Value : Pad->Thickness + Value; if (TEST_FLAG (LOCKFLAG, Pad)) return (NULL); if (new_value <= MAX_PADSIZE && new_value >= MIN_PADSIZE && new_value != Pad->Thickness) { AddObjectToSizeUndoList (PAD_TYPE, Element, Pad, Pad); AddObjectToMaskSizeUndoList (PAD_TYPE, Element, Pad, Pad); RestoreToPolygon (PCB->Data, PAD_TYPE, Element, Pad); ErasePad (Pad); r_delete_entry (PCB->Data->pad_tree, &Pad->BoundingBox); Pad->Mask += new_value - Pad->Thickness; Pad->Thickness = new_value; /* SetElementBB updates all associated rtrees */ SetElementBoundingBox (PCB->Data, Element, &PCB->Font); ClearFromPolygon (PCB->Data, PAD_TYPE, Element, Pad); DrawPad (Pad); return (Pad); } return (NULL); } /*! * \brief Changes the clearance size of a pad. * * \return TRUE if changed. */ static void * ChangePadClearSize (ElementType *Element, PadType *Pad) { Coord new_value = (Absolute) ? Value : Pad->Clearance + Value; if (TEST_FLAG (LOCKFLAG, Pad)) return (NULL); new_value = MIN (MAX_LINESIZE, new_value); if (new_value < 0) new_value = 0; if (Value < 0 && new_value < PCB->Bloat * 2) new_value = 0; if ((Value > 0 || Absolute) && new_value < PCB->Bloat * 2) new_value = PCB->Bloat * 2 + 2; if (new_value == Pad->Clearance) return NULL; AddObjectToClearSizeUndoList (PAD_TYPE, Element, Pad, Pad); RestoreToPolygon (PCB->Data, PAD_TYPE, Element, Pad); ErasePad (Pad); r_delete_entry (PCB->Data->pad_tree, &Pad->BoundingBox); Pad->Clearance = new_value; /* SetElementBB updates all associated rtrees */ SetElementBoundingBox (PCB->Data, Element, &PCB->Font); ClearFromPolygon (PCB->Data, PAD_TYPE, Element, Pad); DrawPad (Pad); return Pad; } /*! * \brief Changes the drilling hole of all pins of an element. * * \return TRUE if changed. */ static void * ChangeElement2ndSize (ElementType *Element) { bool changed = false; Coord new_value; if (TEST_FLAG (LOCKFLAG, Element)) return (NULL); PIN_LOOP (Element); { new_value = (Absolute) ? Value : pin->DrillingHole + Value; if (new_value <= MAX_PINORVIASIZE && new_value >= MIN_PINORVIAHOLE && (TEST_FLAG (HOLEFLAG, pin) || new_value <= pin->Thickness) && new_value != pin->DrillingHole) { changed = true; AddObjectTo2ndSizeUndoList (PIN_TYPE, Element, pin, pin); ErasePin (pin); RestoreToPolygon (PCB->Data, PIN_TYPE, Element, pin); pin->DrillingHole = new_value; if (TEST_FLAG (HOLEFLAG, pin)) { AddObjectToSizeUndoList (PIN_TYPE, Element, pin, pin); pin->Thickness = new_value; } ClearFromPolygon (PCB->Data, PIN_TYPE, Element, pin); DrawPin (pin); } } END_LOOP; if (changed) return (Element); else return (NULL); } /*! * \brief Changes the drilling hole of a pin. * * \return TRUE if changed. */ static void * ChangePin2ndSize (ElementType *Element, PinType *Pin) { Coord new_value = (Absolute) ? Value : Pin->DrillingHole + Value; if (TEST_FLAG (LOCKFLAG, Pin)) return (NULL); if (new_value <= MAX_PINORVIASIZE && new_value >= MIN_PINORVIAHOLE && (TEST_FLAG (HOLEFLAG, Pin) || new_value < Pin->Thickness) && new_value != Pin->DrillingHole) { AddObjectTo2ndSizeUndoList (PIN_TYPE, Element, Pin, Pin); ErasePin (Pin); RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin); Pin->DrillingHole = new_value; if (TEST_FLAG (HOLEFLAG, Pin)) { AddObjectToSizeUndoList (PIN_TYPE, Element, Pin, Pin); Pin->Thickness = new_value; } ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin); DrawPin (Pin); return (Pin); } return (NULL); } /*! * \brief Changes the size of a line. * * \return TRUE if changed. */ static void * ChangeLineSize (LayerType *Layer, LineType *Line) { Coord new_value = (Absolute) ? Value : Line->Thickness + Value; if (TEST_FLAG (LOCKFLAG, Line)) return (NULL); if (new_value <= MAX_LINESIZE && new_value >= MIN_LINESIZE && new_value != Line->Thickness) { AddObjectToSizeUndoList (LINE_TYPE, Layer, Line, Line); EraseLine (Line); r_delete_entry (Layer->line_tree, (BoxType *) Line); RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line); Line->Thickness = new_value; SetLineBoundingBox (Line); r_insert_entry (Layer->line_tree, (BoxType *) Line, 0); ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, Line); DrawLine (Layer, Line); return (Line); } return (NULL); } /*! * \brief Changes the clearance size of a line. * * \return TRUE if changed. */ static void * ChangeLineClearSize (LayerType *Layer, LineType *Line) { Coord new_value = (Absolute) ? Value : Line->Clearance + Value; if (TEST_FLAG (LOCKFLAG, Line) || !TEST_FLAG (CLEARLINEFLAG, Line)) return (NULL); new_value = MIN (MAX_LINESIZE, MAX (new_value, PCB->Bloat * 2 + 2)); if (new_value != Line->Clearance) { AddObjectToClearSizeUndoList (LINE_TYPE, Layer, Line, Line); RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line); EraseLine (Line); r_delete_entry (Layer->line_tree, (BoxType *) Line); Line->Clearance = new_value; if (Line->Clearance == 0) { CLEAR_FLAG (CLEARLINEFLAG, Line); Line->Clearance = MIL_TO_COORD(10); } SetLineBoundingBox (Line); r_insert_entry (Layer->line_tree, (BoxType *) Line, 0); ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, Line); DrawLine (Layer, Line); return (Line); } return (NULL); } /*! * \brief Handle attempts to change the clearance of a polygon. */ static void * ChangePolygonClearSize (LayerType *Layer, PolygonType *poly) { static int shown_this_message = 0; if (!shown_this_message) { gui->confirm_dialog (_("To change the clearance of objects in a polygon, " "change the objects, not the polygon.\n" "Hint: To set a minimum clearance for a group of objects, " "select them all then :MinClearGap(Selected,=10,mil)"), "Ok", NULL); shown_this_message = 1; } return (NULL); } /*! * \brief Changes the size of an arc. * * \return TRUE if changed. */ static void * ChangeArcSize (LayerType *Layer, ArcType *Arc) { Coord new_value = (Absolute) ? Value : Arc->Thickness + Value; if (TEST_FLAG (LOCKFLAG, Arc)) return (NULL); if (new_value <= MAX_LINESIZE && new_value >= MIN_LINESIZE && new_value != Arc->Thickness) { AddObjectToSizeUndoList (ARC_TYPE, Layer, Arc, Arc); EraseArc (Arc); r_delete_entry (Layer->arc_tree, (BoxType *) Arc); RestoreToPolygon (PCB->Data, ARC_TYPE, Layer, Arc); Arc->Thickness = new_value; SetArcBoundingBox (Arc); r_insert_entry (Layer->arc_tree, (BoxType *) Arc, 0); ClearFromPolygon (PCB->Data, ARC_TYPE, Layer, Arc); DrawArc (Layer, Arc); return (Arc); } return (NULL); } /*! * \brief Changes the clearance size of an arc. * * \return TRUE if changed. */ static void * ChangeArcClearSize (LayerType *Layer, ArcType *Arc) { Coord new_value = (Absolute) ? Value : Arc->Clearance + Value; if (TEST_FLAG (LOCKFLAG, Arc) || !TEST_FLAG (CLEARLINEFLAG, Arc)) return (NULL); new_value = MIN (MAX_LINESIZE, MAX (new_value, PCB->Bloat * 2 + 2)); if (new_value != Arc->Clearance) { AddObjectToClearSizeUndoList (ARC_TYPE, Layer, Arc, Arc); EraseArc (Arc); r_delete_entry (Layer->arc_tree, (BoxType *) Arc); RestoreToPolygon (PCB->Data, ARC_TYPE, Layer, Arc); Arc->Clearance = new_value; if (Arc->Clearance == 0) { CLEAR_FLAG (CLEARLINEFLAG, Arc); Arc->Clearance = MIL_TO_COORD(10); } SetArcBoundingBox (Arc); r_insert_entry (Layer->arc_tree, (BoxType *) Arc, 0); ClearFromPolygon (PCB->Data, ARC_TYPE, Layer, Arc); DrawArc (Layer, Arc); return (Arc); } return (NULL); } /*! * \brief Changes the scaling factor of a text object. * * \return TRUE if changed. */ static void * ChangeTextSize (LayerType *Layer, TextType *Text) { int new_value = (Absolute != 0 ? 0 : Text->Scale) + (double)(Absolute != 0 ? Value : Value) / (double)FONT_CAPHEIGHT * 100.; if (TEST_FLAG (LOCKFLAG, Text)) return (NULL); if (new_value <= MAX_TEXTSCALE && new_value >= MIN_TEXTSCALE && new_value != Text->Scale) { AddObjectToSizeUndoList (TEXT_TYPE, Layer, Text, Text); EraseText (Layer, Text); r_delete_entry (Layer->text_tree, (BoxType *) Text); RestoreToPolygon (PCB->Data, TEXT_TYPE, Layer, Text); Text->Scale = new_value; SetTextBoundingBox (&PCB->Font, Text); r_insert_entry (Layer->text_tree, (BoxType *) Text, 0); ClearFromPolygon (PCB->Data, TEXT_TYPE, Layer, Text); DrawText (Layer, Text); return (Text); } return (NULL); } /*! * \brief Changes the scaling factor of an element's outline. * * \return TRUE if changed. */ static void * ChangeElementSize (ElementType *Element) { Coord new_value; bool changed = false; if (TEST_FLAG (LOCKFLAG, Element)) return (NULL); if (PCB->ElementOn) EraseElement (Element); ELEMENTLINE_LOOP (Element); { new_value = (Absolute) ? Value : line->Thickness + Value; if (new_value <= MAX_LINESIZE && new_value >= MIN_LINESIZE && new_value != line->Thickness) { AddObjectToSizeUndoList (ELEMENTLINE_TYPE, Element, line, line); line->Thickness = new_value; changed = true; } } END_LOOP; ARC_LOOP (Element); { new_value = (Absolute) ? Value : arc->Thickness + Value; if (new_value <= MAX_LINESIZE && new_value >= MIN_LINESIZE && new_value != arc->Thickness) { AddObjectToSizeUndoList (ELEMENTARC_TYPE, Element, arc, arc); arc->Thickness = new_value; changed = true; } } END_LOOP; if (PCB->ElementOn) { DrawElement (Element); } if (changed) return (Element); return (NULL); } /*! * \brief Changes the scaling factor of a elementname object. * * \return TRUE if changed. */ static void * ChangeElementNameSize (ElementType *Element) { int new_value = (Absolute != 0 ? 0 : DESCRIPTION_TEXT (Element).Scale) + (double)(Absolute != 0 ? Value : Value) / (double)FONT_CAPHEIGHT * 100.; if (TEST_FLAG (LOCKFLAG, &Element->Name[0])) return (NULL); if (new_value <= MAX_TEXTSCALE && new_value >= MIN_TEXTSCALE) { EraseElementName (Element); ELEMENTTEXT_LOOP (Element); { AddObjectToSizeUndoList (ELEMENTNAME_TYPE, Element, text, text); r_delete_entry (PCB->Data->name_tree[n], (BoxType *) text); text->Scale = new_value; SetTextBoundingBox (&PCB->Font, text); r_insert_entry (PCB->Data->name_tree[n], (BoxType *) text, 0); } END_LOOP; DrawElementName (Element); return (Element); } return (NULL); } /*! * \brief Changes the name of a via. */ static void * ChangeViaName (PinType *Via) { char *old = Via->Name; if (TEST_FLAG (DISPLAYNAMEFLAG, Via)) { ErasePinName (Via); Via->Name = NewName; DrawPinName (Via); } else Via->Name = NewName; return (old); } /*! * \brief Changes the name of a pin. */ static void * ChangePinName (ElementType *Element, PinType *Pin) { char *old = Pin->Name; (void) Element; /* get rid of 'unused...' warnings */ if (TEST_FLAG (DISPLAYNAMEFLAG, Pin)) { ErasePinName (Pin); Pin->Name = NewName; DrawPinName (Pin); } else Pin->Name = NewName; return (old); } /*! * \brief Changes the name of a pad. */ static void * ChangePadName (ElementType *Element, PadType *Pad) { char *old = Pad->Name; (void) Element; /* get rid of 'unused...' warnings */ if (TEST_FLAG (DISPLAYNAMEFLAG, Pad)) { ErasePadName (Pad); Pad->Name = NewName; DrawPadName (Pad); } else Pad->Name = NewName; return (old); } /*! * \brief Changes the name of a line. */ static void * ChangeLineName (LayerType *Layer, LineType *Line) { char *old = Line->Number; (void) Layer; Line->Number = NewName; return (old); } /*! * \brief Changes the layout-name of an element. * * Change the specified text on an element, either on the board (give * PCB, PCB->Data) or in a buffer (give NULL, Buffer->Data). * * \return The old string is returned, and must be properly freed by the * caller. */ char * ChangeElementText (PCBType *pcb, DataType *data, ElementType *Element, int which, char *new_name) { char *old = Element->Name[which].TextString; #ifdef DEBUG printf("In ChangeElementText, updating old TextString %s to %s\n", old, new_name); #endif if (pcb && which == NAME_INDEX (pcb)) EraseElementName (Element); r_delete_entry (data->name_tree[which], & Element->Name[which].BoundingBox); Element->Name[which].TextString = new_name; SetTextBoundingBox (&PCB->Font, &Element->Name[which]); r_insert_entry (data->name_tree[which], & Element->Name[which].BoundingBox, 0); if (pcb && which == NAME_INDEX (pcb)) DrawElementName (Element); return old; } static void * ChangeElementName (ElementType *Element) { if (TEST_FLAG (LOCKFLAG, &Element->Name[0])) return (NULL); if (NAME_INDEX (PCB) == NAMEONPCB_INDEX) { if (TEST_FLAG (UNIQUENAMEFLAG, PCB) && UniqueElementName (PCB->Data, NewName) != NewName) { Message (_("Error: The name \"%s\" is not unique!\n"), NewName); return ((char *) -1); } } return ChangeElementText (PCB, PCB->Data, Element, NAME_INDEX (PCB), NewName); } /*! * \brief Sets data of a text object and calculates bounding box. * * Memory must have already been allocated. * The one for the new string is allocated. * * \return True if the string has been changed. */ static void * ChangeTextName (LayerType *Layer, TextType *Text) { char *old = Text->TextString; if (TEST_FLAG (LOCKFLAG, Text)) return (NULL); EraseText (Layer, Text); r_delete_entry (Layer->text_tree, (BoxType *) Text); RestoreToPolygon (PCB->Data, TEXT_TYPE, Layer, Text); Text->TextString = NewName; /* calculate size of the bounding box */ SetTextBoundingBox (&PCB->Font, Text); r_insert_entry(Layer->text_tree, (BoxType *) Text, 0); ClearFromPolygon (PCB->Data, TEXT_TYPE, Layer, Text); DrawText (Layer, Text); return (old); } /*! * \brief Changes the name of a layout; memory has to be already * allocated. */ bool ChangeLayoutName (char *Name) { free (PCB->Name); PCB->Name = Name; hid_action ("PCBChanged"); return (true); } /*! * \brief Changes the side of the board an element is on. * * \return TRUE if done. */ bool ChangeElementSide (ElementType *Element, Coord yoff) { if (TEST_FLAG (LOCKFLAG, Element)) return (false); EraseElement (Element); AddObjectToMirrorUndoList (ELEMENT_TYPE, Element, Element, Element, yoff); MirrorElementCoordinates (PCB->Data, Element, yoff); DrawElement (Element); return (true); } /*! * \brief Changes the name of a layer; memory has to be already * allocated. */ bool ChangeLayerName (LayerType *Layer, char *Name) { free (CURRENT->Name); CURRENT->Name = Name; hid_action ("LayersChanged"); return (true); } /*! * \brief Changes the clearance flag of a line. */ static void * ChangeLineJoin (LayerType *Layer, LineType *Line) { if (TEST_FLAG (LOCKFLAG, Line)) return (NULL); EraseLine (Line); if (TEST_FLAG(CLEARLINEFLAG, Line)) { AddObjectToClearPolyUndoList (LINE_TYPE, Layer, Line, Line, false); RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line); } AddObjectToFlagUndoList (LINE_TYPE, Layer, Line, Line); TOGGLE_FLAG (CLEARLINEFLAG, Line); if (TEST_FLAG(CLEARLINEFLAG, Line)) { AddObjectToClearPolyUndoList (LINE_TYPE, Layer, Line, Line, true); ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, Line); } DrawLine (Layer, Line); return (Line); } /*! * \brief Sets the clearance flag of a line. */ static void * SetLineJoin (LayerType *Layer, LineType *Line) { if (TEST_FLAG (LOCKFLAG, Line) || TEST_FLAG (CLEARLINEFLAG, Line)) return (NULL); return ChangeLineJoin (Layer, Line); } /*! * \brief Clears the clearance flag of a line. */ static void * ClrLineJoin (LayerType *Layer, LineType *Line) { if (TEST_FLAG (LOCKFLAG, Line) || !TEST_FLAG (CLEARLINEFLAG, Line)) return (NULL); return ChangeLineJoin (Layer, Line); } /*! * \brief Changes the clearance flag of an arc. */ static void * ChangeArcJoin (LayerType *Layer, ArcType *Arc) { if (TEST_FLAG (LOCKFLAG, Arc)) return (NULL); EraseArc (Arc); if (TEST_FLAG (CLEARLINEFLAG, Arc)) { RestoreToPolygon (PCB->Data, ARC_TYPE, Layer, Arc); AddObjectToClearPolyUndoList (ARC_TYPE, Layer, Arc, Arc, false); } AddObjectToFlagUndoList (ARC_TYPE, Layer, Arc, Arc); TOGGLE_FLAG (CLEARLINEFLAG, Arc); if (TEST_FLAG (CLEARLINEFLAG, Arc)) { ClearFromPolygon (PCB->Data, ARC_TYPE, Layer, Arc); AddObjectToClearPolyUndoList (ARC_TYPE, Layer, Arc, Arc, true); } DrawArc (Layer, Arc); return (Arc); } /*! * \brief Sets the clearance flag of an arc. */ static void * SetArcJoin (LayerType *Layer, ArcType *Arc) { if (TEST_FLAG (LOCKFLAG, Arc) || TEST_FLAG (CLEARLINEFLAG, Arc)) return (NULL); return ChangeArcJoin (Layer, Arc); } /*! * \brief Clears the clearance flag of an arc. */ static void * ClrArcJoin (LayerType *Layer, ArcType *Arc) { if (TEST_FLAG (LOCKFLAG, Arc) || !TEST_FLAG (CLEARLINEFLAG, Arc)) return (NULL); return ChangeArcJoin (Layer, Arc); } /*! * \brief Changes the clearance flag of a text. */ static void * ChangeTextJoin (LayerType *Layer, TextType *Text) { if (TEST_FLAG (LOCKFLAG, Text)) return (NULL); EraseText (Layer, Text); if (TEST_FLAG(CLEARLINEFLAG, Text)) { AddObjectToClearPolyUndoList (TEXT_TYPE, Layer, Text, Text, false); RestoreToPolygon (PCB->Data, TEXT_TYPE, Layer, Text); } AddObjectToFlagUndoList (TEXT_TYPE, Layer, Text, Text); TOGGLE_FLAG (CLEARLINEFLAG, Text); if (TEST_FLAG(CLEARLINEFLAG, Text)) { AddObjectToClearPolyUndoList (TEXT_TYPE, Layer, Text, Text, true); ClearFromPolygon (PCB->Data, TEXT_TYPE, Layer, Text); } DrawText (Layer, Text); return (Text); } /*! * \brief Sets the clearance flag of a text. */ static void * SetTextJoin (LayerType *Layer, TextType *Text) { if (TEST_FLAG (LOCKFLAG, Text) || TEST_FLAG (CLEARLINEFLAG, Text)) return (NULL); return ChangeTextJoin (Layer, Text); } /*! * \brief Clears the clearance flag of a text. */ static void * ClrTextJoin (LayerType *Layer, TextType *Text) { if (TEST_FLAG (LOCKFLAG, Text) || !TEST_FLAG (CLEARLINEFLAG, Text)) return (NULL); return ChangeTextJoin (Layer, Text); } /*! * \brief Changes the square flag of all pins on an element. */ static void * ChangeElementSquare (ElementType *Element) { void *ans = NULL; if (TEST_FLAG (LOCKFLAG, Element)) return (NULL); PIN_LOOP (Element); { ans = ChangePinSquare (Element, pin); } END_LOOP; PAD_LOOP (Element); { ans = ChangePadSquare (Element, pad); } END_LOOP; return (ans); } /*! * \brief Sets the square flag of all pins on an element. */ static void * SetElementSquare (ElementType *Element) { void *ans = NULL; if (TEST_FLAG (LOCKFLAG, Element)) return (NULL); PIN_LOOP (Element); { ans = SetPinSquare (Element, pin); } END_LOOP; PAD_LOOP (Element); { ans = SetPadSquare (Element, pad); } END_LOOP; return (ans); } /*! * \brief Clears the square flag of all pins on an element. */ static void * ClrElementSquare (ElementType *Element) { void *ans = NULL; if (TEST_FLAG (LOCKFLAG, Element)) return (NULL); PIN_LOOP (Element); { ans = ClrPinSquare (Element, pin); } END_LOOP; PAD_LOOP (Element); { ans = ClrPadSquare (Element, pad); } END_LOOP; return (ans); } /*! * \brief Changes the octagon flags of all pins of an element. */ static void * ChangeElementOctagon (ElementType *Element) { void *result = NULL; if (TEST_FLAG (LOCKFLAG, Element)) return (NULL); PIN_LOOP (Element); { ChangePinOctagon (Element, pin); result = Element; } END_LOOP; return (result); } /*! * \brief Sets the octagon flags of all pins of an element. */ static void * SetElementOctagon (ElementType *Element) { void *result = NULL; if (TEST_FLAG (LOCKFLAG, Element)) return (NULL); PIN_LOOP (Element); { SetPinOctagon (Element, pin); result = Element; } END_LOOP; return (result); } /*! * \brief Clears the octagon flags of all pins of an element. */ static void * ClrElementOctagon (ElementType *Element) { void *result = NULL; if (TEST_FLAG (LOCKFLAG, Element)) return (NULL); PIN_LOOP (Element); { ClrPinOctagon (Element, pin); result = Element; } END_LOOP; return (result); } /*! * \brief Changes the square flag of a pad. */ static void * ChangePadSquare (ElementType *Element, PadType *Pad) { if (TEST_FLAG (LOCKFLAG, Pad)) return (NULL); ErasePad (Pad); AddObjectToClearPolyUndoList (PAD_TYPE, Element, Pad, Pad, false); RestoreToPolygon (PCB->Data, PAD_TYPE, Element, Pad); AddObjectToFlagUndoList (PAD_TYPE, Element, Pad, Pad); TOGGLE_FLAG (SQUAREFLAG, Pad); AddObjectToClearPolyUndoList (PAD_TYPE, Element, Pad, Pad, true); ClearFromPolygon (PCB->Data, PAD_TYPE, Element, Pad); DrawPad (Pad); return (Pad); } /*! * \brief Sets the square flag of a pad. */ static void * SetPadSquare (ElementType *Element, PadType *Pad) { if (TEST_FLAG (LOCKFLAG, Pad) || TEST_FLAG (SQUAREFLAG, Pad)) return (NULL); return (ChangePadSquare (Element, Pad)); } /*! * \brief Clears the square flag of a pad. */ static void * ClrPadSquare (ElementType *Element, PadType *Pad) { if (TEST_FLAG (LOCKFLAG, Pad) || !TEST_FLAG (SQUAREFLAG, Pad)) return (NULL); return (ChangePadSquare (Element, Pad)); } /*! * \brief Changes the square flag of a pin. */ static void * ChangePinSquare (ElementType *Element, PinType *Pin) { if (TEST_FLAG (LOCKFLAG, Pin)) return (NULL); ErasePin (Pin); AddObjectToClearPolyUndoList (PIN_TYPE, Element, Pin, Pin, false); RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin); AddObjectToFlagUndoList (PIN_TYPE, Element, Pin, Pin); TOGGLE_FLAG (SQUAREFLAG, Pin); AddObjectToClearPolyUndoList (PIN_TYPE, Element, Pin, Pin, true); ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin); DrawPin (Pin); return (Pin); } /*! * \brief Sets the square flag of a pin. */ static void * SetPinSquare (ElementType *Element, PinType *Pin) { if (TEST_FLAG (LOCKFLAG, Pin) || TEST_FLAG (SQUAREFLAG, Pin)) return (NULL); return (ChangePinSquare (Element, Pin)); } /*! * \brief Clears the square flag of a pin. */ static void * ClrPinSquare (ElementType *Element, PinType *Pin) { if (TEST_FLAG (LOCKFLAG, Pin) || !TEST_FLAG (SQUAREFLAG, Pin)) return (NULL); return (ChangePinSquare (Element, Pin)); } /*! * \brief Changes the octagon flag of a via. */ static void * ChangeViaOctagon (PinType *Via) { if (TEST_FLAG (LOCKFLAG, Via)) return (NULL); EraseVia (Via); AddObjectToClearPolyUndoList (VIA_TYPE, Via, Via, Via, false); RestoreToPolygon (PCB->Data, VIA_TYPE, Via, Via); AddObjectToFlagUndoList (VIA_TYPE, Via, Via, Via); TOGGLE_FLAG (OCTAGONFLAG, Via); AddObjectToClearPolyUndoList (VIA_TYPE, Via, Via, Via, true); ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via); DrawVia (Via); return (Via); } /*! * \brief Sets the octagon flag of a via. */ static void * SetViaOctagon (PinType *Via) { if (TEST_FLAG (LOCKFLAG, Via) || TEST_FLAG (OCTAGONFLAG, Via)) return (NULL); return (ChangeViaOctagon (Via)); } /*! * \brief Clears the octagon flag of a via. */ static void * ClrViaOctagon (PinType *Via) { if (TEST_FLAG (LOCKFLAG, Via) || !TEST_FLAG (OCTAGONFLAG, Via)) return (NULL); return (ChangeViaOctagon (Via)); } /*! * \brief Changes the octagon flag of a pin. */ static void * ChangePinOctagon (ElementType *Element, PinType *Pin) { if (TEST_FLAG (LOCKFLAG, Pin)) return (NULL); ErasePin (Pin); AddObjectToClearPolyUndoList (PIN_TYPE, Element, Pin, Pin, false); RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin); AddObjectToFlagUndoList (PIN_TYPE, Element, Pin, Pin); TOGGLE_FLAG (OCTAGONFLAG, Pin); AddObjectToClearPolyUndoList (PIN_TYPE, Element, Pin, Pin, true); ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin); DrawPin (Pin); return (Pin); } /*! * \brief Sets the octagon flag of a pin. */ static void * SetPinOctagon (ElementType *Element, PinType *Pin) { if (TEST_FLAG (LOCKFLAG, Pin) || TEST_FLAG (OCTAGONFLAG, Pin)) return (NULL); return (ChangePinOctagon (Element, Pin)); } /*! * \brief Clears the octagon flag of a pin. */ static void * ClrPinOctagon (ElementType *Element, PinType *Pin) { if (TEST_FLAG (LOCKFLAG, Pin) || !TEST_FLAG (OCTAGONFLAG, Pin)) return (NULL); return (ChangePinOctagon (Element, Pin)); } /*! * \brief Changes the hole flag of a via. */ bool ChangeHole (PinType *Via) { if (TEST_FLAG (LOCKFLAG, Via)) return (false); EraseVia (Via); AddObjectToFlagUndoList (VIA_TYPE, Via, Via, Via); AddObjectToMaskSizeUndoList (VIA_TYPE, Via, Via, Via); r_delete_entry (PCB->Data->via_tree, (BoxType *) Via); RestoreToPolygon (PCB->Data, VIA_TYPE, Via, Via); TOGGLE_FLAG (HOLEFLAG, Via); if (TEST_FLAG (HOLEFLAG, Via)) { /* A tented via becomes an minimally untented hole. An untented via retains its mask clearance. */ if (Via->Mask > Via->Thickness) { Via->Mask = (Via->DrillingHole + (Via->Mask - Via->Thickness)); } else if (Via->Mask < Via->DrillingHole) { Via->Mask = Via->DrillingHole + 2 * MASKFRAME; } } else { Via->Mask = (Via->Thickness + (Via->Mask - Via->DrillingHole)); } SetPinBoundingBox (Via); r_insert_entry (PCB->Data->via_tree, (BoxType *) Via, 0); ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via); DrawVia (Via); Draw (); return (true); } /*! * \brief Changes the nopaste flag of a pad. */ bool ChangePaste (PadType *Pad) { if (TEST_FLAG (LOCKFLAG, Pad)) return (false); ErasePad (Pad); AddObjectToFlagUndoList (PAD_TYPE, Pad, Pad, Pad); TOGGLE_FLAG (NOPASTEFLAG, Pad); DrawPad (Pad); Draw (); return (true); } /*! * \brief Changes the CLEARPOLY flag of a polygon. */ static void * ChangePolyClear (LayerType *Layer, PolygonType *Polygon) { if (TEST_FLAG (LOCKFLAG, Polygon)) return (NULL); AddObjectToClearPolyUndoList (POLYGON_TYPE, Layer, Polygon, Polygon, true); AddObjectToFlagUndoList (POLYGON_TYPE, Layer, Polygon, Polygon); TOGGLE_FLAG (CLEARPOLYFLAG, Polygon); InitClip (PCB->Data, Layer, Polygon); DrawPolygon (Layer, Polygon); return (Polygon); } /*! * \brief Changes the side of all selected and visible elements. * * \return True if anything has changed. */ bool ChangeSelectedElementSide (void) { bool change = false; /* setup identifiers */ if (PCB->PinOn && PCB->ElementOn) ELEMENT_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, element)) { change |= ChangeElementSide (element, 0); } } END_LOOP; if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the thermals on all selected and visible pins and/or * vias. * * \return True if anything has changed. */ bool ChangeSelectedThermals (int types, int therm_style) { bool change = false; Value = therm_style; change = SelectedOperation (&ChangeThermalFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the thermals on all selected and visible pins and/or * vias. * * \return True if anything has changed. */ bool ChangeSelectedViaLayers (int from, int to) { bool change = false; int new_from; int new_to; int i; VIA_LOOP (PCB->Data); { if (TEST_FLAG (LOCKFLAG, via)) continue; if (TEST_FLAG (SELECTEDFLAG, via)) { new_from = (from != -1)?from:via->BuriedFrom; new_to = (to != -1)?to:via->BuriedTo; if (new_from == new_to) continue; /* special case - changing TH via "from" layer sets "to" layer to bottom layer */ if (!VIA_IS_BURIED (via) && (to == -1)) new_to = GetMaxBottomLayer (); for (i=0; i < max_copper_layer; i++) { /* AddObjectToClearPolyUndoList (VIA_TYPE, &(PCB->Data->Layer[i]), via, via, false); not needed? */ RestoreToPolygon (PCB->Data, VIA_TYPE, &(PCB->Data->Layer[i]), via); } AddObjectToSetViaLayersUndoList (via, via, via); via->BuriedFrom = new_from; via->BuriedTo = new_to; if (VIA_IS_BURIED (via)) { SanitizeBuriedVia (via); for (i=0; i < max_copper_layer; i++) { /* AddObjectToClearPolyUndoList (VIA_TYPE, &(PCB->Data->Layer[i]), via, via, true); not needed? */ ClearFromPolygon (PCB->Data, VIA_TYPE, &(PCB->Data->Layer[i]), via); } DrawVia (via); } change = true; } } END_LOOP; if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the size of all selected and visible object types. * * \return True if anything has changed. */ bool ChangeSelectedSize (int types, Coord Difference, bool fixIt) { bool change = false; /* setup identifiers */ Absolute = (fixIt) ? 1 : 0; Value = Difference; change = SelectedOperation (&ChangeSizeFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the clearance size of all selected and visible objects. * * \return True if anything has changed. */ bool ChangeSelectedClearSize (int types, Coord Difference, bool fixIt) { bool change = false; /* setup identifiers */ Absolute = (fixIt) ? 1 : 0; Value = Difference; if (TEST_FLAG (SHOWMASKFLAG, PCB)) change = SelectedOperation (&ChangeMaskSizeFunctions, false, types); else change = SelectedOperation (&ChangeClearSizeFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the 2nd size (drilling hole) of all selected and * visible objects. * * \return True if anything has changed. */ bool ChangeSelected2ndSize (int types, Coord Difference, bool fixIt) { bool change = false; /* setup identifiers */ Absolute = (fixIt) ? 1 : 0; Value = Difference; change = SelectedOperation (&Change2ndSizeFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the clearance flag (join) of all selected and visible * lines and/or arcs. * * \return True if anything has changed. */ bool ChangeSelectedJoin (int types) { bool change = false; change = SelectedOperation (&ChangeJoinFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the clearance flag (join) of all selected and visible * lines and/or arcs. * * \return True if anything has changed. */ bool SetSelectedJoin (int types) { bool change = false; change = SelectedOperation (&SetJoinFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the clearance flag (join) of all selected and visible * lines and/or arcs. * * \return True if anything has changed. */ bool ClrSelectedJoin (int types) { bool change = false; change = SelectedOperation (&ClrJoinFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the square-flag of all selected and visible pins or * pads. * * \return True if anything has changed. */ bool ChangeSelectedSquare (int types) { bool change = false; change = SelectedOperation (&ChangeSquareFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Sets the square-flag of all selected and visible pins or pads. * * \return True if anything has changed. */ bool SetSelectedSquare (int types) { bool change = false; change = SelectedOperation (&SetSquareFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Clears the square-flag of all selected and visible pins or * pads. * * \return True if anything has changed. */ bool ClrSelectedSquare (int types) { bool change = false; change = SelectedOperation (&ClrSquareFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the octagon-flag of all selected and visible pins and * vias. * * \return True if anything has changed. */ bool ChangeSelectedOctagon (int types) { bool change = false; change = SelectedOperation (&ChangeOctagonFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Sets the octagon-flag of all selected and visible pins and * vias. * * \return True if anything has changed. */ bool SetSelectedOctagon (int types) { bool change = false; change = SelectedOperation (&SetOctagonFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Clears the octagon-flag of all selected and visible pins and * vias. * * \return True if anything has changed. */ bool ClrSelectedOctagon (int types) { bool change = false; change = SelectedOperation (&ClrOctagonFunctions, false, types); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the hole-flag of all selected and visible vias. * * \return True if anything has changed. */ bool ChangeSelectedHole (void) { bool change = false; if (PCB->ViaOn) VIA_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, via)) change |= ChangeHole (via); } END_LOOP; if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the no paste-flag of all selected and visible pads. * * \return True if anything has changed. */ bool ChangeSelectedPaste (void) { bool change = false; ALLPAD_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, pad)) change |= ChangePaste (pad); } ENDALL_LOOP; if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the size of the passed object. * * \return True if anything is changed. */ bool ChangeObjectSize (int Type, void *Ptr1, void *Ptr2, void *Ptr3, Coord Difference, bool fixIt) { bool change; /* setup identifier */ Absolute = (fixIt) ? 1 : 0; Value = Difference; change = (ObjectOperation (&ChangeSizeFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the clearance size of the passed object. * * \return True if anything is changed. */ bool ChangeObjectClearSize (int Type, void *Ptr1, void *Ptr2, void *Ptr3, Coord Difference, bool fixIt) { bool change; /* setup identifier */ Absolute = (fixIt) ? 1 : 0; Value = Difference; if (TEST_FLAG (SHOWMASKFLAG, PCB)) change = (ObjectOperation (&ChangeMaskSizeFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL); else change = (ObjectOperation (&ChangeClearSizeFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the thermal of the passed object. * * \return True if anything is changed. * */ bool ChangeObjectThermal (int Type, void *Ptr1, void *Ptr2, void *Ptr3, int therm_type) { bool change; Value = Absolute = therm_type; change = (ObjectOperation (&ChangeThermalFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the thermal of the passed object. * * \return True if anything is changed. * */ bool ChangeObjectViaLayers (void *Ptr1, void *Ptr2, void *Ptr3, int from, int to) { bool change = false; PinType *via = (PinType *) Ptr1; int new_from = (from != -1)?from:via->BuriedFrom; int new_to = (to != -1)?to:via->BuriedTo; int i; if (TEST_FLAG (LOCKFLAG, via)) return (NULL); if ((new_from == new_to) && new_from != 0) return false; /* special case - changing TH via "from" layer sets "to" layer to bottom layer */ if (!VIA_IS_BURIED (via) && (to == -1)) new_to = GetMaxBottomLayer (); for (i=0; i < max_copper_layer; i++) { /* AddObjectToClearPolyUndoList (VIA_TYPE, &(PCB->Data->Layer[i]), via, via, false); not needed? */ RestoreToPolygon (PCB->Data, VIA_TYPE, &(PCB->Data->Layer[i]), via); } if (from != -1 || to != -1) { AddObjectToSetViaLayersUndoList (via, via, via); change = true; } via->BuriedFrom = new_from; via->BuriedTo = new_to; if (VIA_IS_BURIED (via)) { SanitizeBuriedVia (via); for (i=0; i < max_copper_layer; i++) { /* AddObjectToClearPolyUndoList (VIA_TYPE, &(PCB->Data->Layer[i]), via, via, true); not needed? */ ClearFromPolygon (PCB->Data, VIA_TYPE, &(PCB->Data->Layer[i]), via); } DrawVia (via); } if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the 2nd size of the passed object. * * \return True if anything is changed. */ bool ChangeObject2ndSize (int Type, void *Ptr1, void *Ptr2, void *Ptr3, Coord Difference, bool fixIt, bool incundo) { bool change; /* setup identifier */ Absolute = (fixIt) ? 1 : 0; Value = Difference; change = (ObjectOperation (&Change2ndSizeFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL); if (change) { Draw (); if (incundo) IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the mask size of the passed object. * * \return True if anything is changed. */ bool ChangeObjectMaskSize (int Type, void *Ptr1, void *Ptr2, void *Ptr3, Coord Difference, bool fixIt) { bool change; /* setup identifier */ Absolute = (fixIt) ? 1 : 0; Value = Difference; change = (ObjectOperation (&ChangeMaskSizeFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL); if (change) { Draw (); IncrementUndoSerialNumber (); } return (change); } /*! * \brief Changes the name of the passed object. * * \warning The allocated memory isn't freed because the old string is used * by the undo module. * * \return The old name. */ void * ChangeObjectName (int Type, void *Ptr1, void *Ptr2, void *Ptr3, char *Name) { void *result; /* setup identifier */ NewName = Name; result = ObjectOperation (&ChangeNameFunctions, Type, Ptr1, Ptr2, Ptr3); Draw (); return (result); } /*! * \brief Changes the clearance-flag of the passed object. * * \return True if anything is changed. */ bool ChangeObjectJoin (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { if (ObjectOperation (&ChangeJoinFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL) { Draw (); IncrementUndoSerialNumber (); return (true); } return (false); } /*! * \brief Sets the clearance-flag of the passed object. * * \return True if anything is changed. */ bool SetObjectJoin (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { if (ObjectOperation (&SetJoinFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL) { Draw (); IncrementUndoSerialNumber (); return (true); } return (false); } /*! * \brief Clears the clearance-flag of the passed object. * * \return True if anything is changed. */ bool ClrObjectJoin (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { if (ObjectOperation (&ClrJoinFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL) { Draw (); IncrementUndoSerialNumber (); return (true); } return (false); } /*! * \brief Changes the square-flag of the passed object. * * \return True if anything is changed. */ bool ChangeObjectSquare (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { if (ObjectOperation (&ChangeSquareFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL) { Draw (); IncrementUndoSerialNumber (); return (true); } return (false); } /*! * \brief Sets the square-flag of the passed object. * * \return True if anything is changed. */ bool SetObjectSquare (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { if (ObjectOperation (&SetSquareFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL) { Draw (); IncrementUndoSerialNumber (); return (true); } return (false); } /*! * \brief Clears the square-flag of the passed object. * * \return True if anything is changed. */ bool ClrObjectSquare (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { if (ObjectOperation (&ClrSquareFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL) { Draw (); IncrementUndoSerialNumber (); return (true); } return (false); } /*! * \brief Changes the octagon-flag of the passed object. * * \return True if anything is changed. */ bool ChangeObjectOctagon (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { if (ObjectOperation (&ChangeOctagonFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL) { Draw (); IncrementUndoSerialNumber (); return (true); } return (false); } /*! * \brief Sets the octagon-flag of the passed object. * * \return True if anything is changed. */ bool SetObjectOctagon (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { if (ObjectOperation (&SetOctagonFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL) { Draw (); IncrementUndoSerialNumber (); return (true); } return (false); } /*! * \brief Clears the octagon-flag of the passed object. * * \return True if anything is changed. */ bool ClrObjectOctagon (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { if (ObjectOperation (&ClrOctagonFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL) { Draw (); IncrementUndoSerialNumber (); return (true); } return (false); } /*! * \bief Queries the user for a new object name and changes it. * * \warning The allocated memory isn't freed because the old string is used * by the undo module. */ void * QueryInputAndChangeObjectName (int Type, void *Ptr1, void *Ptr2, void *Ptr3) { char *name = NULL; char msg[513]; /* if passed an element name, make it an element reference instead */ if (Type == ELEMENTNAME_TYPE) { Type = ELEMENT_TYPE; Ptr2 = Ptr1; Ptr3 = Ptr1; } switch (Type) { case LINE_TYPE: name = gui->prompt_for (_("Linename:"), EMPTY (((LineType *) Ptr2)->Number)); break; case VIA_TYPE: name = gui->prompt_for (_("Vianame:"), EMPTY (((PinType *) Ptr2)->Name)); break; case PIN_TYPE: sprintf (msg, _("%s Pin Name:"), EMPTY (((PinType *) Ptr2)->Number)); name = gui->prompt_for (msg, EMPTY (((PinType *) Ptr2)->Name)); break; case PAD_TYPE: sprintf (msg, _("%s Pad Name:"), EMPTY (((PadType *) Ptr2)->Number)); name = gui->prompt_for (msg, EMPTY (((PadType *) Ptr2)->Name)); break; case TEXT_TYPE: name = gui->prompt_for (_("Enter text:"), EMPTY (((TextType *) Ptr2)->TextString)); break; case ELEMENT_TYPE: name = gui->prompt_for (_("Elementname:"), EMPTY (ELEMENT_NAME (PCB, (ElementType *) Ptr2))); break; } if (name) { /* NB: ChangeObjectName takes ownership of the passed memory */ char *old = (char *)ChangeObjectName (Type, Ptr1, Ptr2, Ptr3, name); if (old != (char *) -1) { AddObjectToChangeNameUndoList (Type, Ptr1, Ptr2, Ptr3, old); IncrementUndoSerialNumber (); } Draw (); return (Ptr3); } return (NULL); } /*! * \brief Changes the maximum size of a layout, adjusts the scrollbars, * releases the saved pixmap if necessary and adjusts the cursor * confinement box. */ void ChangePCBSize (Coord Width, Coord Height) { PCB->MaxWidth = Width; PCB->MaxHeight = Height; hid_action ("PCBChanged"); } /*! * \brief Changes the mask size of a pad. * * \return TRUE if changed. */ static void * ChangePadMaskSize (ElementType *Element, PadType *Pad) { Coord new_value = (Absolute) ? Value : Pad->Mask + Value; new_value = MAX (new_value, 0); if (new_value == Pad->Mask && Absolute == 0) new_value = Pad->Thickness; if (new_value != Pad->Mask) { AddObjectToMaskSizeUndoList (PAD_TYPE, Element, Pad, Pad); ErasePad (Pad); r_delete_entry (PCB->Data->pad_tree, &Pad->BoundingBox); Pad->Mask = new_value; SetElementBoundingBox (PCB->Data, Element, &PCB->Font); DrawPad (Pad); return (Pad); } return (NULL); } /*! * \brief Changes the mask size of a pin. * * \return TRUE if changed. */ static void * ChangePinMaskSize (ElementType *Element, PinType *Pin) { Coord new_value = (Absolute) ? Value : Pin->Mask + Value; new_value = MAX (new_value, 0); if (new_value == Pin->Mask && Absolute == 0) new_value = Pin->Thickness; if (new_value != Pin->Mask) { AddObjectToMaskSizeUndoList (PIN_TYPE, Element, Pin, Pin); ErasePin (Pin); r_delete_entry (PCB->Data->pin_tree, &Pin->BoundingBox); Pin->Mask = new_value; SetElementBoundingBox (PCB->Data, Element, &PCB->Font); DrawPin (Pin); return (Pin); } return (NULL); } /*! * \brief Changes the mask size of a via. * * \return TRUE if changed. */ static void * ChangeViaMaskSize (PinType *Via) { Coord new_value; new_value = (Absolute) ? Value : Via->Mask + Value; new_value = MAX (new_value, 0); if (new_value != Via->Mask) { AddObjectToMaskSizeUndoList (VIA_TYPE, Via, Via, Via); EraseVia (Via); r_delete_entry (PCB->Data->via_tree, &Via->BoundingBox); Via->Mask = new_value; SetPinBoundingBox (Via); r_insert_entry (PCB->Data->via_tree, &Via->BoundingBox, 0); DrawVia (Via); return (Via); } return (NULL); }