/*!
* \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);
}