1 /*!
2  * \file src/change.c
3  *
4  * \brief Functions used to change object properties.
5  *
6  * <hr>
7  *
8  * <h1><b>Copyright.</b></h1>\n
9  *
10  * PCB, interactive printed circuit board design
11  *
12  * Copyright (C) 1994,1995,1996, 2005 Thomas Nau
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27  *
28  * Contact addresses for paper mail and Email:
29  * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
30  * Thomas.Nau@rz.uni-ulm.de
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #include <stdlib.h>
38 #include <stdio.h>
39 
40 #include "global.h"
41 
42 #include "change.h"
43 #include "create.h"
44 #include "crosshair.h"
45 #include "data.h"
46 #include "draw.h"
47 #include "error.h"
48 #include "mymem.h"
49 #include "misc.h"
50 #include "mirror.h"
51 #include "polygon.h"
52 #include "rats.h"
53 #include "remove.h"
54 #include "rtree.h"
55 #include "search.h"
56 #include "select.h"
57 #include "set.h"
58 #include "thermal.h"
59 #include "undo.h"
60 
61 #ifdef HAVE_LIBDMALLOC
62 #include <dmalloc.h>
63 #endif
64 
65 /* ---------------------------------------------------------------------------
66  * some local prototypes
67  */
68 static void *ChangePinSize (ElementType *, PinType *);
69 static void *ChangePinClearSize (ElementType *, PinType *);
70 static void *ChangePinMaskSize (ElementType *, PinType *);
71 static void *ChangePadSize (ElementType *, PadType *);
72 static void *ChangePadClearSize (ElementType *, PadType *);
73 static void *ChangePadMaskSize (ElementType *, PadType *);
74 static void *ChangePin2ndSize (ElementType *, PinType *);
75 static void *ChangeElement2ndSize (ElementType *);
76 static void *ChangeViaSize (PinType *);
77 static void *ChangeVia2ndSize (PinType *);
78 static void *ChangeViaClearSize (PinType *);
79 static void *ChangeViaMaskSize (PinType *);
80 static void *ChangeLineSize (LayerType *, LineType *);
81 static void *ChangeLineClearSize (LayerType *, LineType *);
82 static void *ChangePolygonClearSize (LayerType *, PolygonType *);
83 static void *ChangeArcSize (LayerType *, ArcType *);
84 static void *ChangeArcClearSize (LayerType *, ArcType *);
85 static void *ChangeTextSize (LayerType *, TextType *);
86 static void *ChangeElementSize (ElementType *);
87 static void *ChangeElementNameSize (ElementType *);
88 static void *ChangePinName (ElementType *, PinType *);
89 static void *ChangePadName (ElementType *, PadType *);
90 static void *ChangeViaName (PinType *);
91 static void *ChangeLineName (LayerType *, LineType *);
92 static void *ChangeElementName (ElementType *);
93 static void *ChangeTextName (LayerType *, TextType *);
94 static void *ChangeElementSquare (ElementType *);
95 static void *SetElementSquare (ElementType *);
96 static void *ClrElementSquare (ElementType *);
97 static void *ChangeElementOctagon (ElementType *);
98 static void *SetElementOctagon (ElementType *);
99 static void *ClrElementOctagon (ElementType *);
100 static void *ChangePinSquare (ElementType *, PinType *);
101 static void *SetPinSquare (ElementType *, PinType *);
102 static void *ClrPinSquare (ElementType *, PinType *);
103 static void *ChangePinOctagon (ElementType *, PinType *);
104 static void *SetPinOctagon (ElementType *, PinType *);
105 static void *ClrPinOctagon (ElementType *, PinType *);
106 static void *ChangeViaOctagon (PinType *);
107 static void *SetViaOctagon (PinType *);
108 static void *ClrViaOctagon (PinType *);
109 static void *ChangePadSquare (ElementType *, PadType *);
110 static void *SetPadSquare (ElementType *, PadType *);
111 static void *ClrPadSquare (ElementType *, PadType *);
112 static void *ChangeViaThermal (PinType *);
113 static void *ChangePinThermal (ElementType *, PinType *);
114 static void *ChangeLineJoin (LayerType *, LineType *);
115 static void *SetLineJoin (LayerType *, LineType *);
116 static void *ClrLineJoin (LayerType *, LineType *);
117 static void *ChangeArcJoin (LayerType *, ArcType *);
118 static void *SetArcJoin (LayerType *, ArcType *);
119 static void *ClrArcJoin (LayerType *, ArcType *);
120 static void *ChangeTextJoin (LayerType *, TextType *);
121 static void *SetTextJoin (LayerType *, TextType *);
122 static void *ClrTextJoin (LayerType *, TextType *);
123 static void *ChangePolyClear (LayerType *, PolygonType *);
124 
125 /* ---------------------------------------------------------------------------
126  * some local identifiers
127  */
128 /*! Either the new value or the change in value  */
129 static int Value;
130 /*! Used as boolean to indicate that Value is an absolute or delta */
131 static int Absolute;
132 static char *NewName;		/* new name */
133 static ObjectFunctionType ChangeSizeFunctions = {
134   ChangeLineSize,
135   ChangeTextSize,
136   ChangePolyClear,
137   ChangeViaSize,
138   ChangeElementSize,		/* changes silk screen line width */
139   ChangeElementNameSize,
140   ChangePinSize,
141   ChangePadSize,
142   NULL,
143   NULL,
144   ChangeArcSize,
145   NULL
146 };
147 static ObjectFunctionType Change2ndSizeFunctions = {
148   NULL,
149   NULL,
150   NULL,
151   ChangeVia2ndSize,
152   ChangeElement2ndSize,
153   NULL,
154   ChangePin2ndSize,
155   NULL,
156   NULL,
157   NULL,
158   NULL,
159   NULL
160 };
161 static ObjectFunctionType ChangeThermalFunctions = {
162   NULL,
163   NULL,
164   NULL,
165   ChangeViaThermal,
166   NULL,
167   NULL,
168   ChangePinThermal,
169   NULL,
170   NULL,
171   NULL,
172   NULL,
173   NULL
174 };
175 static ObjectFunctionType ChangeClearSizeFunctions = {
176   ChangeLineClearSize,
177   NULL,
178   ChangePolygonClearSize, /* just to tell the user not to :-) */
179   ChangeViaClearSize,
180   NULL,
181   NULL,
182   ChangePinClearSize,
183   ChangePadClearSize,
184   NULL,
185   NULL,
186   ChangeArcClearSize,
187   NULL
188 };
189 static ObjectFunctionType ChangeNameFunctions = {
190   ChangeLineName,
191   ChangeTextName,
192   NULL,
193   ChangeViaName,
194   ChangeElementName,
195   NULL,
196   ChangePinName,
197   ChangePadName,
198   NULL,
199   NULL,
200   NULL,
201   NULL
202 };
203 static ObjectFunctionType ChangeSquareFunctions = {
204   NULL,
205   NULL,
206   NULL,
207   NULL,
208   ChangeElementSquare,
209   NULL,
210   ChangePinSquare,
211   ChangePadSquare,
212   NULL,
213   NULL,
214   NULL,
215   NULL
216 };
217 static ObjectFunctionType ChangeJoinFunctions = {
218   ChangeLineJoin,
219   ChangeTextJoin,
220   NULL,
221   NULL,
222   NULL,
223   NULL,
224   NULL,
225   NULL,
226   NULL,
227   NULL,
228   ChangeArcJoin,
229   NULL
230 };
231 static ObjectFunctionType ChangeOctagonFunctions = {
232   NULL,
233   NULL,
234   NULL,
235   ChangeViaOctagon,
236   ChangeElementOctagon,
237   NULL,
238   ChangePinOctagon,
239   NULL,
240   NULL,
241   NULL,
242   NULL,
243   NULL
244 };
245 static ObjectFunctionType ChangeMaskSizeFunctions = {
246   NULL,
247   NULL,
248   NULL,
249   ChangeViaMaskSize,
250 #if 0
251   ChangeElementMaskSize,
252 #else
253   NULL,
254 #endif
255   NULL,
256   ChangePinMaskSize,
257   ChangePadMaskSize,
258   NULL,
259   NULL,
260   NULL,
261   NULL
262 };
263 static ObjectFunctionType SetSquareFunctions = {
264   NULL,
265   NULL,
266   NULL,
267   NULL,
268   SetElementSquare,
269   NULL,
270   SetPinSquare,
271   SetPadSquare,
272   NULL,
273   NULL,
274   NULL,
275   NULL
276 };
277 static ObjectFunctionType SetJoinFunctions = {
278   SetLineJoin,
279   SetTextJoin,
280   NULL,
281   NULL,
282   NULL,
283   NULL,
284   NULL,
285   NULL,
286   NULL,
287   NULL,
288   SetArcJoin,
289   NULL
290 };
291 static ObjectFunctionType SetOctagonFunctions = {
292   NULL,
293   NULL,
294   NULL,
295   SetViaOctagon,
296   SetElementOctagon,
297   NULL,
298   SetPinOctagon,
299   NULL,
300   NULL,
301   NULL,
302   NULL,
303   NULL
304 };
305 static ObjectFunctionType ClrSquareFunctions = {
306   NULL,
307   NULL,
308   NULL,
309   NULL,
310   ClrElementSquare,
311   NULL,
312   ClrPinSquare,
313   ClrPadSquare,
314   NULL,
315   NULL,
316   NULL,
317   NULL
318 };
319 static ObjectFunctionType ClrJoinFunctions = {
320   ClrLineJoin,
321   ClrTextJoin,
322   NULL,
323   NULL,
324   NULL,
325   NULL,
326   NULL,
327   NULL,
328   NULL,
329   NULL,
330   ClrArcJoin,
331   NULL
332 };
333 static ObjectFunctionType ClrOctagonFunctions = {
334   NULL,
335   NULL,
336   NULL,
337   ClrViaOctagon,
338   ClrElementOctagon,
339   NULL,
340   ClrPinOctagon,
341   NULL,
342   NULL,
343   NULL,
344   NULL,
345   NULL
346 };
347 
348 /*!
349  * \brief Changes the thermal on a via.
350  *
351  * \return TRUE if changed.
352  */
353 static void *
ChangeViaThermal(PinType * Via)354 ChangeViaThermal (PinType *Via)
355 {
356   AddObjectToClearPolyUndoList (VIA_TYPE, Via, Via, Via, false);
357   RestoreToPolygon (PCB->Data, VIA_TYPE, CURRENT, Via);
358   AddObjectToFlagUndoList (VIA_TYPE, Via, Via, Via);
359   if (!Value)			/* remove the thermals */
360     CLEAR_THERM (INDEXOFCURRENT, Via);
361   else
362     ASSIGN_THERM (INDEXOFCURRENT, Value, Via);
363   AddObjectToClearPolyUndoList (VIA_TYPE, Via, Via, Via, true);
364   ClearFromPolygon (PCB->Data, VIA_TYPE, CURRENT, Via);
365   DrawVia (Via);
366   return Via;
367 }
368 
369 /*!
370  * \brief Changes the thermal on a pin.
371  *
372  * \return TRUE if changed.
373  */
374 static void *
ChangePinThermal(ElementType * element,PinType * Pin)375 ChangePinThermal (ElementType *element, PinType *Pin)
376 {
377   AddObjectToClearPolyUndoList (PIN_TYPE, element, Pin, Pin, false);
378   RestoreToPolygon (PCB->Data, VIA_TYPE, CURRENT, Pin);
379   AddObjectToFlagUndoList (PIN_TYPE, element, Pin, Pin);
380   if (!Value)			/* remove the thermals */
381     CLEAR_THERM (INDEXOFCURRENT, Pin);
382   else
383     ASSIGN_THERM (INDEXOFCURRENT, Value, Pin);
384   AddObjectToClearPolyUndoList (PIN_TYPE, element, Pin, Pin, true);
385   ClearFromPolygon (PCB->Data, VIA_TYPE, CURRENT, Pin);
386   DrawPin (Pin);
387   return Pin;
388 }
389 
390 /*!
391  * \brief Changes the size of a via.
392  *
393  * \return TRUE if changed.
394  */
395 static void *
ChangeViaSize(PinType * Via)396 ChangeViaSize (PinType *Via)
397 {
398   Coord new_value = Absolute ? Value : Via->Thickness + Value;
399 
400   if (TEST_FLAG (LOCKFLAG, Via))
401     return (NULL);
402   if (!TEST_FLAG (HOLEFLAG, Via) && new_value <= MAX_PINORVIASIZE &&
403       new_value >= MIN_PINORVIASIZE &&
404       new_value > Via->DrillingHole &&
405       new_value != Via->Thickness)
406     {
407       AddObjectToSizeUndoList (VIA_TYPE, Via, Via, Via);
408       EraseVia (Via);
409       r_delete_entry (PCB->Data->via_tree, (BoxType *) Via);
410       RestoreToPolygon (PCB->Data, PIN_TYPE, Via, Via);
411       if (Via->Mask)
412 	{
413 	  AddObjectToMaskSizeUndoList (VIA_TYPE, Via, Via, Via);
414 	  Via->Mask += new_value - Via->Thickness;
415 	}
416       Via->Thickness = new_value;
417       SetPinBoundingBox (Via);
418       r_insert_entry (PCB->Data->via_tree, (BoxType *) Via, 0);
419       ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via);
420       DrawVia (Via);
421       return (Via);
422     }
423   return (NULL);
424 }
425 
426 /*!
427  * \brief Changes the drilling hole of a via.
428  *
429  * \return TRUE if changed.
430  */
431 static void *
ChangeVia2ndSize(PinType * Via)432 ChangeVia2ndSize (PinType *Via)
433 {
434   Coord new_value = (Absolute) ? Value : Via->DrillingHole + Value;
435 
436   if (TEST_FLAG (LOCKFLAG, Via))
437     return (NULL);
438   if (new_value <= MAX_PINORVIASIZE &&
439       new_value >= MIN_PINORVIAHOLE && (TEST_FLAG (HOLEFLAG, Via) ||
440 				    new_value < Via->Thickness)
441       && new_value != Via->DrillingHole)
442     {
443       AddObjectTo2ndSizeUndoList (VIA_TYPE, Via, Via, Via);
444       EraseVia (Via);
445       RestoreToPolygon (PCB->Data, VIA_TYPE, Via, Via);
446       Via->DrillingHole = new_value;
447       if (TEST_FLAG (HOLEFLAG, Via))
448 	{
449 	  AddObjectToSizeUndoList (VIA_TYPE, Via, Via, Via);
450 	  Via->Thickness = new_value;
451 	}
452       ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via);
453       DrawVia (Via);
454       return (Via);
455     }
456   return (NULL);
457 }
458 
459 /*!
460  * \brief Changes the clearance size of a via.
461  *
462  * \return TRUE if changed.
463  */
464 static void *
ChangeViaClearSize(PinType * Via)465 ChangeViaClearSize (PinType *Via)
466 {
467   Coord new_value = (Absolute) ? Value : Via->Clearance + Value;
468 
469   if (TEST_FLAG (LOCKFLAG, Via))
470     return (NULL);
471   new_value = MIN (MAX_LINESIZE, new_value);
472   if (new_value < 0)
473     new_value = 0;
474   if (Value < 0 && new_value < PCB->Bloat * 2)
475     new_value = 0;
476   if ((Value > 0 || Absolute) && new_value < PCB->Bloat * 2)
477     new_value = PCB->Bloat * 2 + 2;
478   if (Via->Clearance == new_value)
479     return NULL;
480   RestoreToPolygon (PCB->Data, VIA_TYPE, Via, Via);
481   AddObjectToClearSizeUndoList (VIA_TYPE, Via, Via, Via);
482   EraseVia (Via);
483   r_delete_entry (PCB->Data->via_tree, (BoxType *) Via);
484   Via->Clearance = new_value;
485   SetPinBoundingBox (Via);
486   r_insert_entry (PCB->Data->via_tree, (BoxType *) Via, 0);
487   ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via);
488   DrawVia (Via);
489   Via->Element = NULL;
490   return (Via);
491 }
492 
493 
494 /*!
495  * \brief Changes the size of a pin.
496  *
497  * \return TRUE if changed.
498  */
499 static void *
ChangePinSize(ElementType * Element,PinType * Pin)500 ChangePinSize (ElementType *Element, PinType *Pin)
501 {
502   Coord new_value = (Absolute) ? Value : Pin->Thickness + Value;
503 
504   if (TEST_FLAG (LOCKFLAG, Pin))
505     return (NULL);
506   if (!TEST_FLAG (HOLEFLAG, Pin) && new_value <= MAX_PINORVIASIZE &&
507       new_value >= MIN_PINORVIASIZE &&
508       new_value > Pin->DrillingHole &&
509       new_value != Pin->Thickness)
510     {
511       AddObjectToSizeUndoList (PIN_TYPE, Element, Pin, Pin);
512       AddObjectToMaskSizeUndoList (PIN_TYPE, Element, Pin, Pin);
513       ErasePin (Pin);
514       r_delete_entry (PCB->Data->pin_tree, &Pin->BoundingBox);
515       RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin);
516       Pin->Mask += new_value - Pin->Thickness;
517       Pin->Thickness = new_value;
518       /* SetElementBB updates all associated rtrees */
519       SetElementBoundingBox (PCB->Data, Element, &PCB->Font);
520       ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin);
521       DrawPin (Pin);
522       return (Pin);
523     }
524   return (NULL);
525 }
526 
527 /*!
528  * \brief Changes the clearance size of a pin.
529  *
530  * \return TRUE if changed.
531  */
532 static void *
ChangePinClearSize(ElementType * Element,PinType * Pin)533 ChangePinClearSize (ElementType *Element, PinType *Pin)
534 {
535   Coord new_value = (Absolute) ? Value : Pin->Clearance + Value;
536 
537   if (TEST_FLAG (LOCKFLAG, Pin))
538     return (NULL);
539   new_value = MIN (MAX_LINESIZE, new_value);
540   if (new_value < 0)
541     new_value = 0;
542   if (Value < 0 && new_value < PCB->Bloat * 2)
543     new_value = 0;
544   if ((Value > 0 || Absolute) && new_value < PCB->Bloat * 2)
545     new_value = PCB->Bloat * 2 + 2;
546   if (Pin->Clearance == new_value)
547     return NULL;
548   RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin);
549   AddObjectToClearSizeUndoList (PIN_TYPE, Element, Pin, Pin);
550   ErasePin (Pin);
551   r_delete_entry (PCB->Data->pin_tree, &Pin->BoundingBox);
552   Pin->Clearance = new_value;
553   /* SetElementBB updates all associated rtrees */
554   SetElementBoundingBox (PCB->Data, Element, &PCB->Font);
555   ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin);
556   DrawPin (Pin);
557   return (Pin);
558 }
559 
560 /*!
561  * \brief Changes the size of a pad.
562  *
563  * \return TRUE if changed.
564  */
565 static void *
ChangePadSize(ElementType * Element,PadType * Pad)566 ChangePadSize (ElementType *Element, PadType *Pad)
567 {
568   Coord new_value = (Absolute) ? Value : Pad->Thickness + Value;
569 
570   if (TEST_FLAG (LOCKFLAG, Pad))
571     return (NULL);
572   if (new_value <= MAX_PADSIZE && new_value >= MIN_PADSIZE && new_value != Pad->Thickness)
573     {
574       AddObjectToSizeUndoList (PAD_TYPE, Element, Pad, Pad);
575       AddObjectToMaskSizeUndoList (PAD_TYPE, Element, Pad, Pad);
576       RestoreToPolygon (PCB->Data, PAD_TYPE, Element, Pad);
577       ErasePad (Pad);
578       r_delete_entry (PCB->Data->pad_tree, &Pad->BoundingBox);
579       Pad->Mask += new_value - Pad->Thickness;
580       Pad->Thickness = new_value;
581       /* SetElementBB updates all associated rtrees */
582       SetElementBoundingBox (PCB->Data, Element, &PCB->Font);
583       ClearFromPolygon (PCB->Data, PAD_TYPE, Element, Pad);
584       DrawPad (Pad);
585       return (Pad);
586     }
587   return (NULL);
588 }
589 
590 /*!
591  * \brief Changes the clearance size of a pad.
592  *
593  * \return TRUE if changed.
594  */
595 static void *
ChangePadClearSize(ElementType * Element,PadType * Pad)596 ChangePadClearSize (ElementType *Element, PadType *Pad)
597 {
598   Coord new_value = (Absolute) ? Value : Pad->Clearance + Value;
599 
600   if (TEST_FLAG (LOCKFLAG, Pad))
601     return (NULL);
602   new_value = MIN (MAX_LINESIZE, new_value);
603   if (new_value < 0)
604     new_value = 0;
605   if (Value < 0 && new_value < PCB->Bloat * 2)
606     new_value = 0;
607   if ((Value > 0 || Absolute) && new_value < PCB->Bloat * 2)
608     new_value = PCB->Bloat * 2 + 2;
609   if (new_value == Pad->Clearance)
610     return NULL;
611   AddObjectToClearSizeUndoList (PAD_TYPE, Element, Pad, Pad);
612   RestoreToPolygon (PCB->Data, PAD_TYPE, Element, Pad);
613   ErasePad (Pad);
614   r_delete_entry (PCB->Data->pad_tree, &Pad->BoundingBox);
615   Pad->Clearance = new_value;
616   /* SetElementBB updates all associated rtrees */
617   SetElementBoundingBox (PCB->Data, Element, &PCB->Font);
618   ClearFromPolygon (PCB->Data, PAD_TYPE, Element, Pad);
619   DrawPad (Pad);
620   return Pad;
621 }
622 
623 /*!
624  * \brief Changes the drilling hole of all pins of an element.
625  *
626  * \return TRUE if changed.
627  */
628 static void *
ChangeElement2ndSize(ElementType * Element)629 ChangeElement2ndSize (ElementType *Element)
630 {
631   bool changed = false;
632   Coord new_value;
633 
634   if (TEST_FLAG (LOCKFLAG, Element))
635     return (NULL);
636   PIN_LOOP (Element);
637   {
638     new_value = (Absolute) ? Value : pin->DrillingHole + Value;
639     if (new_value <= MAX_PINORVIASIZE &&
640 	new_value >= MIN_PINORVIAHOLE && (TEST_FLAG (HOLEFLAG, pin) ||
641 				      new_value <= pin->Thickness)
642 	&& new_value != pin->DrillingHole)
643       {
644 	changed = true;
645 	AddObjectTo2ndSizeUndoList (PIN_TYPE, Element, pin, pin);
646 	ErasePin (pin);
647 	RestoreToPolygon (PCB->Data, PIN_TYPE, Element, pin);
648 	pin->DrillingHole = new_value;
649 	if (TEST_FLAG (HOLEFLAG, pin))
650 	  {
651 	    AddObjectToSizeUndoList (PIN_TYPE, Element, pin, pin);
652 	    pin->Thickness = new_value;
653 	  }
654 	ClearFromPolygon (PCB->Data, PIN_TYPE, Element, pin);
655 	DrawPin (pin);
656       }
657   }
658   END_LOOP;
659   if (changed)
660     return (Element);
661   else
662     return (NULL);
663 }
664 
665 /*!
666  * \brief Changes the drilling hole of a pin.
667  *
668  * \return TRUE if changed.
669  */
670 static void *
ChangePin2ndSize(ElementType * Element,PinType * Pin)671 ChangePin2ndSize (ElementType *Element, PinType *Pin)
672 {
673   Coord new_value = (Absolute) ? Value : Pin->DrillingHole + Value;
674 
675   if (TEST_FLAG (LOCKFLAG, Pin))
676     return (NULL);
677   if (new_value <= MAX_PINORVIASIZE &&
678       new_value >= MIN_PINORVIAHOLE && (TEST_FLAG (HOLEFLAG, Pin) ||
679 				    new_value < Pin->Thickness)
680       && new_value != Pin->DrillingHole)
681     {
682       AddObjectTo2ndSizeUndoList (PIN_TYPE, Element, Pin, Pin);
683       ErasePin (Pin);
684       RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin);
685       Pin->DrillingHole = new_value;
686       if (TEST_FLAG (HOLEFLAG, Pin))
687 	{
688 	  AddObjectToSizeUndoList (PIN_TYPE, Element, Pin, Pin);
689 	  Pin->Thickness = new_value;
690 	}
691       ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin);
692       DrawPin (Pin);
693       return (Pin);
694     }
695   return (NULL);
696 }
697 
698 /*!
699  * \brief Changes the size of a line.
700  *
701  * \return TRUE if changed.
702  */
703 static void *
ChangeLineSize(LayerType * Layer,LineType * Line)704 ChangeLineSize (LayerType *Layer, LineType *Line)
705 {
706   Coord new_value = (Absolute) ? Value : Line->Thickness + Value;
707 
708   if (TEST_FLAG (LOCKFLAG, Line))
709     return (NULL);
710   if (new_value <= MAX_LINESIZE && new_value >= MIN_LINESIZE &&
711       new_value != Line->Thickness)
712     {
713       AddObjectToSizeUndoList (LINE_TYPE, Layer, Line, Line);
714       EraseLine (Line);
715       r_delete_entry (Layer->line_tree, (BoxType *) Line);
716       RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line);
717       Line->Thickness = new_value;
718       SetLineBoundingBox (Line);
719       r_insert_entry (Layer->line_tree, (BoxType *) Line, 0);
720       ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, Line);
721       DrawLine (Layer, Line);
722       return (Line);
723     }
724   return (NULL);
725 }
726 
727 /*!
728  * \brief Changes the clearance size of a line.
729  *
730  * \return TRUE if changed.
731  */
732 static void *
ChangeLineClearSize(LayerType * Layer,LineType * Line)733 ChangeLineClearSize (LayerType *Layer, LineType *Line)
734 {
735   Coord new_value = (Absolute) ? Value : Line->Clearance + Value;
736 
737   if (TEST_FLAG (LOCKFLAG, Line) || !TEST_FLAG (CLEARLINEFLAG, Line))
738     return (NULL);
739   new_value = MIN (MAX_LINESIZE, MAX (new_value, PCB->Bloat * 2 + 2));
740   if (new_value != Line->Clearance)
741     {
742       AddObjectToClearSizeUndoList (LINE_TYPE, Layer, Line, Line);
743       RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line);
744       EraseLine (Line);
745       r_delete_entry (Layer->line_tree, (BoxType *) Line);
746       Line->Clearance = new_value;
747       if (Line->Clearance == 0)
748 	{
749 	  CLEAR_FLAG (CLEARLINEFLAG, Line);
750 	  Line->Clearance = MIL_TO_COORD(10);
751 	}
752       SetLineBoundingBox (Line);
753       r_insert_entry (Layer->line_tree, (BoxType *) Line, 0);
754       ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, Line);
755       DrawLine (Layer, Line);
756       return (Line);
757     }
758   return (NULL);
759 }
760 
761 /*!
762  * \brief Handle attempts to change the clearance of a polygon.
763  */
764 static void *
ChangePolygonClearSize(LayerType * Layer,PolygonType * poly)765 ChangePolygonClearSize (LayerType *Layer, PolygonType *poly)
766 {
767   static int shown_this_message = 0;
768   if (!shown_this_message)
769     {
770       gui->confirm_dialog (_("To change the clearance of objects in a polygon, "
771 			   "change the objects, not the polygon.\n"
772 			   "Hint: To set a minimum clearance for a group of objects, "
773 			   "select them all then :MinClearGap(Selected,=10,mil)"),
774 			   "Ok", NULL);
775       shown_this_message = 1;
776     }
777 
778   return (NULL);
779 }
780 
781 /*!
782  * \brief Changes the size of an arc.
783  *
784  * \return TRUE if changed.
785  */
786 static void *
ChangeArcSize(LayerType * Layer,ArcType * Arc)787 ChangeArcSize (LayerType *Layer, ArcType *Arc)
788 {
789   Coord new_value = (Absolute) ? Value : Arc->Thickness + Value;
790 
791   if (TEST_FLAG (LOCKFLAG, Arc))
792     return (NULL);
793   if (new_value <= MAX_LINESIZE && new_value >= MIN_LINESIZE &&
794       new_value != Arc->Thickness)
795     {
796       AddObjectToSizeUndoList (ARC_TYPE, Layer, Arc, Arc);
797       EraseArc (Arc);
798       r_delete_entry (Layer->arc_tree, (BoxType *) Arc);
799       RestoreToPolygon (PCB->Data, ARC_TYPE, Layer, Arc);
800       Arc->Thickness = new_value;
801       SetArcBoundingBox (Arc);
802       r_insert_entry (Layer->arc_tree, (BoxType *) Arc, 0);
803       ClearFromPolygon (PCB->Data, ARC_TYPE, Layer, Arc);
804       DrawArc (Layer, Arc);
805       return (Arc);
806     }
807   return (NULL);
808 }
809 
810 /*!
811  * \brief Changes the clearance size of an arc.
812  *
813  * \return TRUE if changed.
814  */
815 static void *
ChangeArcClearSize(LayerType * Layer,ArcType * Arc)816 ChangeArcClearSize (LayerType *Layer, ArcType *Arc)
817 {
818   Coord new_value = (Absolute) ? Value : Arc->Clearance + Value;
819 
820   if (TEST_FLAG (LOCKFLAG, Arc) || !TEST_FLAG (CLEARLINEFLAG, Arc))
821     return (NULL);
822   new_value = MIN (MAX_LINESIZE, MAX (new_value, PCB->Bloat * 2 + 2));
823   if (new_value != Arc->Clearance)
824     {
825       AddObjectToClearSizeUndoList (ARC_TYPE, Layer, Arc, Arc);
826       EraseArc (Arc);
827       r_delete_entry (Layer->arc_tree, (BoxType *) Arc);
828       RestoreToPolygon (PCB->Data, ARC_TYPE, Layer, Arc);
829       Arc->Clearance = new_value;
830       if (Arc->Clearance == 0)
831 	{
832 	  CLEAR_FLAG (CLEARLINEFLAG, Arc);
833 	  Arc->Clearance = MIL_TO_COORD(10);
834 	}
835       SetArcBoundingBox (Arc);
836       r_insert_entry (Layer->arc_tree, (BoxType *) Arc, 0);
837       ClearFromPolygon (PCB->Data, ARC_TYPE, Layer, Arc);
838       DrawArc (Layer, Arc);
839       return (Arc);
840     }
841   return (NULL);
842 }
843 
844 /*!
845  * \brief Changes the scaling factor of a text object.
846  *
847  * \return TRUE if changed.
848  */
849 static void *
ChangeTextSize(LayerType * Layer,TextType * Text)850 ChangeTextSize (LayerType *Layer, TextType *Text)
851 {
852   int new_value = (Absolute != 0 ? 0 : Text->Scale) +
853               (double)(Absolute != 0 ? Value : Value)
854                 / (double)FONT_CAPHEIGHT * 100.;
855 
856   if (TEST_FLAG (LOCKFLAG, Text))
857     return (NULL);
858   if (new_value <= MAX_TEXTSCALE && new_value >= MIN_TEXTSCALE &&
859       new_value != Text->Scale)
860     {
861       AddObjectToSizeUndoList (TEXT_TYPE, Layer, Text, Text);
862       EraseText (Layer, Text);
863       r_delete_entry (Layer->text_tree, (BoxType *) Text);
864       RestoreToPolygon (PCB->Data, TEXT_TYPE, Layer, Text);
865       Text->Scale = new_value;
866       SetTextBoundingBox (&PCB->Font, Text);
867       r_insert_entry (Layer->text_tree, (BoxType *) Text, 0);
868       ClearFromPolygon (PCB->Data, TEXT_TYPE, Layer, Text);
869       DrawText (Layer, Text);
870       return (Text);
871     }
872   return (NULL);
873 }
874 
875 /*!
876  * \brief Changes the scaling factor of an element's outline.
877  *
878  * \return TRUE if changed.
879  */
880 static void *
ChangeElementSize(ElementType * Element)881 ChangeElementSize (ElementType *Element)
882 {
883   Coord new_value;
884   bool changed = false;
885 
886   if (TEST_FLAG (LOCKFLAG, Element))
887     return (NULL);
888   if (PCB->ElementOn)
889     EraseElement (Element);
890   ELEMENTLINE_LOOP (Element);
891   {
892     new_value = (Absolute) ? Value : line->Thickness + Value;
893     if (new_value <= MAX_LINESIZE && new_value >= MIN_LINESIZE &&
894 	new_value != line->Thickness)
895       {
896 	AddObjectToSizeUndoList (ELEMENTLINE_TYPE, Element, line, line);
897 	line->Thickness = new_value;
898 	changed = true;
899       }
900   }
901   END_LOOP;
902   ARC_LOOP (Element);
903   {
904     new_value = (Absolute) ? Value : arc->Thickness + Value;
905     if (new_value <= MAX_LINESIZE && new_value >= MIN_LINESIZE &&
906 	new_value != arc->Thickness)
907       {
908 	AddObjectToSizeUndoList (ELEMENTARC_TYPE, Element, arc, arc);
909 	arc->Thickness = new_value;
910 	changed = true;
911       }
912   }
913   END_LOOP;
914   if (PCB->ElementOn)
915     {
916       DrawElement (Element);
917     }
918   if (changed)
919     return (Element);
920   return (NULL);
921 }
922 
923 /*!
924  * \brief Changes the scaling factor of a elementname object.
925  *
926  * \return TRUE if changed.
927  */
928 static void *
ChangeElementNameSize(ElementType * Element)929 ChangeElementNameSize (ElementType *Element)
930 {
931   int new_value = (Absolute != 0 ? 0 : DESCRIPTION_TEXT (Element).Scale) +
932               (double)(Absolute != 0 ? Value : Value)
933                 / (double)FONT_CAPHEIGHT * 100.;
934 
935   if (TEST_FLAG (LOCKFLAG, &Element->Name[0]))
936     return (NULL);
937   if (new_value <= MAX_TEXTSCALE && new_value >= MIN_TEXTSCALE)
938     {
939       EraseElementName (Element);
940       ELEMENTTEXT_LOOP (Element);
941       {
942 	AddObjectToSizeUndoList (ELEMENTNAME_TYPE, Element, text, text);
943 	r_delete_entry (PCB->Data->name_tree[n], (BoxType *) text);
944 	text->Scale = new_value;
945 	SetTextBoundingBox (&PCB->Font, text);
946 	r_insert_entry (PCB->Data->name_tree[n], (BoxType *) text, 0);
947       }
948       END_LOOP;
949       DrawElementName (Element);
950       return (Element);
951     }
952   return (NULL);
953 }
954 
955 /*!
956  * \brief Changes the name of a via.
957  */
958 static void *
ChangeViaName(PinType * Via)959 ChangeViaName (PinType *Via)
960 {
961   char *old = Via->Name;
962 
963   if (TEST_FLAG (DISPLAYNAMEFLAG, Via))
964     {
965       ErasePinName (Via);
966       Via->Name = NewName;
967       DrawPinName (Via);
968     }
969   else
970     Via->Name = NewName;
971   return (old);
972 }
973 
974 /*!
975  * \brief Changes the name of a pin.
976  */
977 static void *
ChangePinName(ElementType * Element,PinType * Pin)978 ChangePinName (ElementType *Element, PinType *Pin)
979 {
980   char *old = Pin->Name;
981 
982   (void) Element;		/* get rid of 'unused...' warnings */
983   if (TEST_FLAG (DISPLAYNAMEFLAG, Pin))
984     {
985       ErasePinName (Pin);
986       Pin->Name = NewName;
987       DrawPinName (Pin);
988     }
989   else
990     Pin->Name = NewName;
991   return (old);
992 }
993 
994 /*!
995  * \brief Changes the name of a pad.
996  */
997 static void *
ChangePadName(ElementType * Element,PadType * Pad)998 ChangePadName (ElementType *Element, PadType *Pad)
999 {
1000   char *old = Pad->Name;
1001 
1002   (void) Element;		/* get rid of 'unused...' warnings */
1003   if (TEST_FLAG (DISPLAYNAMEFLAG, Pad))
1004     {
1005       ErasePadName (Pad);
1006       Pad->Name = NewName;
1007       DrawPadName (Pad);
1008     }
1009   else
1010     Pad->Name = NewName;
1011   return (old);
1012 }
1013 
1014 /*!
1015  * \brief Changes the name of a line.
1016  */
1017 static void *
ChangeLineName(LayerType * Layer,LineType * Line)1018 ChangeLineName (LayerType *Layer, LineType *Line)
1019 {
1020   char *old = Line->Number;
1021 
1022   (void) Layer;
1023   Line->Number = NewName;
1024   return (old);
1025 }
1026 
1027 /*!
1028  * \brief Changes the layout-name of an element.
1029  *
1030  * Change the specified text on an element, either on the board (give
1031  * PCB, PCB->Data) or in a buffer (give NULL, Buffer->Data).
1032  *
1033  * \return The old string is returned, and must be properly freed by the
1034  * caller.
1035  */
1036 char *
ChangeElementText(PCBType * pcb,DataType * data,ElementType * Element,int which,char * new_name)1037 ChangeElementText (PCBType *pcb, DataType *data, ElementType *Element, int which, char *new_name)
1038 {
1039   char *old = Element->Name[which].TextString;
1040 
1041 #ifdef DEBUG
1042   printf("In ChangeElementText, updating old TextString %s to %s\n", old, new_name);
1043 #endif
1044 
1045   if (pcb && which == NAME_INDEX (pcb))
1046     EraseElementName (Element);
1047 
1048   r_delete_entry (data->name_tree[which],
1049 		  & Element->Name[which].BoundingBox);
1050 
1051   Element->Name[which].TextString = new_name;
1052   SetTextBoundingBox (&PCB->Font, &Element->Name[which]);
1053 
1054   r_insert_entry (data->name_tree[which],
1055 		  & Element->Name[which].BoundingBox, 0);
1056 
1057   if (pcb && which == NAME_INDEX (pcb))
1058     DrawElementName (Element);
1059 
1060   return old;
1061 }
1062 
1063 static void *
ChangeElementName(ElementType * Element)1064 ChangeElementName (ElementType *Element)
1065 {
1066   if (TEST_FLAG (LOCKFLAG, &Element->Name[0]))
1067     return (NULL);
1068   if (NAME_INDEX (PCB) == NAMEONPCB_INDEX)
1069     {
1070       if (TEST_FLAG (UNIQUENAMEFLAG, PCB) &&
1071 	  UniqueElementName (PCB->Data, NewName) != NewName)
1072 	{
1073 	  Message (_("Error: The name \"%s\" is not unique!\n"), NewName);
1074 	  return ((char *) -1);
1075 	}
1076     }
1077 
1078   return ChangeElementText (PCB, PCB->Data, Element, NAME_INDEX (PCB), NewName);
1079 }
1080 
1081 /*!
1082  * \brief Sets data of a text object and calculates bounding box.
1083  *
1084  * Memory must have already been allocated.
1085  * The one for the new string is allocated.
1086  *
1087  * \return True if the string has been changed.
1088  */
1089 static void *
ChangeTextName(LayerType * Layer,TextType * Text)1090 ChangeTextName (LayerType *Layer, TextType *Text)
1091 {
1092   char *old = Text->TextString;
1093 
1094   if (TEST_FLAG (LOCKFLAG, Text))
1095     return (NULL);
1096   EraseText (Layer, Text);
1097   r_delete_entry (Layer->text_tree, (BoxType *) Text);
1098   RestoreToPolygon (PCB->Data, TEXT_TYPE, Layer, Text);
1099   Text->TextString = NewName;
1100 
1101   /* calculate size of the bounding box */
1102   SetTextBoundingBox (&PCB->Font, Text);
1103   r_insert_entry(Layer->text_tree, (BoxType *) Text, 0);
1104   ClearFromPolygon (PCB->Data, TEXT_TYPE, Layer, Text);
1105   DrawText (Layer, Text);
1106   return (old);
1107 }
1108 
1109 /*!
1110  * \brief Changes the name of a layout; memory has to be already
1111  * allocated.
1112  */
1113 bool
ChangeLayoutName(char * Name)1114 ChangeLayoutName (char *Name)
1115 {
1116   free (PCB->Name);
1117   PCB->Name = Name;
1118   hid_action ("PCBChanged");
1119   return (true);
1120 }
1121 
1122 /*!
1123  * \brief Changes the side of the board an element is on.
1124  *
1125  * \return TRUE if done.
1126  */
1127 bool
ChangeElementSide(ElementType * Element,Coord yoff)1128 ChangeElementSide (ElementType *Element, Coord yoff)
1129 {
1130   if (TEST_FLAG (LOCKFLAG, Element))
1131     return (false);
1132   EraseElement (Element);
1133   AddObjectToMirrorUndoList (ELEMENT_TYPE, Element, Element, Element, yoff);
1134   MirrorElementCoordinates (PCB->Data, Element, yoff);
1135   DrawElement (Element);
1136   return (true);
1137 }
1138 
1139 /*!
1140  * \brief Changes the name of a layer; memory has to be already
1141  * allocated.
1142  */
1143 bool
ChangeLayerName(LayerType * Layer,char * Name)1144 ChangeLayerName (LayerType *Layer, char *Name)
1145 {
1146   free (CURRENT->Name);
1147   CURRENT->Name = Name;
1148   hid_action ("LayersChanged");
1149   return (true);
1150 }
1151 
1152 /*!
1153  * \brief Changes the clearance flag of a line.
1154  */
1155 static void *
ChangeLineJoin(LayerType * Layer,LineType * Line)1156 ChangeLineJoin (LayerType *Layer, LineType *Line)
1157 {
1158   if (TEST_FLAG (LOCKFLAG, Line))
1159     return (NULL);
1160   EraseLine (Line);
1161   if (TEST_FLAG(CLEARLINEFLAG, Line))
1162   {
1163   AddObjectToClearPolyUndoList (LINE_TYPE, Layer, Line, Line, false);
1164   RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line);
1165   }
1166   AddObjectToFlagUndoList (LINE_TYPE, Layer, Line, Line);
1167   TOGGLE_FLAG (CLEARLINEFLAG, Line);
1168   if (TEST_FLAG(CLEARLINEFLAG, Line))
1169   {
1170   AddObjectToClearPolyUndoList (LINE_TYPE, Layer, Line, Line, true);
1171   ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, Line);
1172   }
1173   DrawLine (Layer, Line);
1174   return (Line);
1175 }
1176 
1177 /*!
1178  * \brief Sets the clearance flag of a line.
1179  */
1180 static void *
SetLineJoin(LayerType * Layer,LineType * Line)1181 SetLineJoin (LayerType *Layer, LineType *Line)
1182 {
1183   if (TEST_FLAG (LOCKFLAG, Line) || TEST_FLAG (CLEARLINEFLAG, Line))
1184     return (NULL);
1185   return ChangeLineJoin (Layer, Line);
1186 }
1187 
1188 /*!
1189  * \brief Clears the clearance flag of a line.
1190  */
1191 static void *
ClrLineJoin(LayerType * Layer,LineType * Line)1192 ClrLineJoin (LayerType *Layer, LineType *Line)
1193 {
1194   if (TEST_FLAG (LOCKFLAG, Line) || !TEST_FLAG (CLEARLINEFLAG, Line))
1195     return (NULL);
1196   return ChangeLineJoin (Layer, Line);
1197 }
1198 
1199 /*!
1200  * \brief Changes the clearance flag of an arc.
1201  */
1202 static void *
ChangeArcJoin(LayerType * Layer,ArcType * Arc)1203 ChangeArcJoin (LayerType *Layer, ArcType *Arc)
1204 {
1205   if (TEST_FLAG (LOCKFLAG, Arc))
1206     return (NULL);
1207   EraseArc (Arc);
1208   if (TEST_FLAG (CLEARLINEFLAG, Arc))
1209   {
1210     RestoreToPolygon (PCB->Data, ARC_TYPE, Layer, Arc);
1211     AddObjectToClearPolyUndoList (ARC_TYPE, Layer, Arc, Arc, false);
1212     }
1213   AddObjectToFlagUndoList (ARC_TYPE, Layer, Arc, Arc);
1214   TOGGLE_FLAG (CLEARLINEFLAG, Arc);
1215   if (TEST_FLAG (CLEARLINEFLAG, Arc))
1216   {
1217     ClearFromPolygon (PCB->Data, ARC_TYPE, Layer, Arc);
1218   AddObjectToClearPolyUndoList (ARC_TYPE, Layer, Arc, Arc, true);
1219   }
1220   DrawArc (Layer, Arc);
1221   return (Arc);
1222 }
1223 
1224 /*!
1225  * \brief Sets the clearance flag of an arc.
1226  */
1227 static void *
SetArcJoin(LayerType * Layer,ArcType * Arc)1228 SetArcJoin (LayerType *Layer, ArcType *Arc)
1229 {
1230   if (TEST_FLAG (LOCKFLAG, Arc) || TEST_FLAG (CLEARLINEFLAG, Arc))
1231     return (NULL);
1232   return ChangeArcJoin (Layer, Arc);
1233 }
1234 
1235 /*!
1236  * \brief Clears the clearance flag of an arc.
1237  */
1238 static void *
ClrArcJoin(LayerType * Layer,ArcType * Arc)1239 ClrArcJoin (LayerType *Layer, ArcType *Arc)
1240 {
1241   if (TEST_FLAG (LOCKFLAG, Arc) || !TEST_FLAG (CLEARLINEFLAG, Arc))
1242     return (NULL);
1243   return ChangeArcJoin (Layer, Arc);
1244 }
1245 
1246 /*!
1247  * \brief Changes the clearance flag of a text.
1248  */
1249 static void *
ChangeTextJoin(LayerType * Layer,TextType * Text)1250 ChangeTextJoin (LayerType *Layer, TextType *Text)
1251 {
1252   if (TEST_FLAG (LOCKFLAG, Text))
1253     return (NULL);
1254   EraseText (Layer, Text);
1255   if (TEST_FLAG(CLEARLINEFLAG, Text))
1256   {
1257   AddObjectToClearPolyUndoList (TEXT_TYPE, Layer, Text, Text, false);
1258   RestoreToPolygon (PCB->Data, TEXT_TYPE, Layer, Text);
1259   }
1260   AddObjectToFlagUndoList (TEXT_TYPE, Layer, Text, Text);
1261   TOGGLE_FLAG (CLEARLINEFLAG, Text);
1262   if (TEST_FLAG(CLEARLINEFLAG, Text))
1263   {
1264   AddObjectToClearPolyUndoList (TEXT_TYPE, Layer, Text, Text, true);
1265   ClearFromPolygon (PCB->Data, TEXT_TYPE, Layer, Text);
1266   }
1267   DrawText (Layer, Text);
1268   return (Text);
1269 }
1270 
1271 /*!
1272  * \brief Sets the clearance flag of a text.
1273  */
1274 static void *
SetTextJoin(LayerType * Layer,TextType * Text)1275 SetTextJoin (LayerType *Layer, TextType *Text)
1276 {
1277   if (TEST_FLAG (LOCKFLAG, Text) || TEST_FLAG (CLEARLINEFLAG, Text))
1278     return (NULL);
1279   return ChangeTextJoin (Layer, Text);
1280 }
1281 
1282 /*!
1283  * \brief Clears the clearance flag of a text.
1284  */
1285 static void *
ClrTextJoin(LayerType * Layer,TextType * Text)1286 ClrTextJoin (LayerType *Layer, TextType *Text)
1287 {
1288   if (TEST_FLAG (LOCKFLAG, Text) || !TEST_FLAG (CLEARLINEFLAG, Text))
1289     return (NULL);
1290   return ChangeTextJoin (Layer, Text);
1291 }
1292 
1293 /*!
1294  * \brief Changes the square flag of all pins on an element.
1295  */
1296 static void *
ChangeElementSquare(ElementType * Element)1297 ChangeElementSquare (ElementType *Element)
1298 {
1299   void *ans = NULL;
1300 
1301   if (TEST_FLAG (LOCKFLAG, Element))
1302     return (NULL);
1303   PIN_LOOP (Element);
1304   {
1305     ans = ChangePinSquare (Element, pin);
1306   }
1307   END_LOOP;
1308   PAD_LOOP (Element);
1309   {
1310     ans = ChangePadSquare (Element, pad);
1311   }
1312   END_LOOP;
1313   return (ans);
1314 }
1315 
1316 /*!
1317  * \brief Sets the square flag of all pins on an element.
1318  */
1319 static void *
SetElementSquare(ElementType * Element)1320 SetElementSquare (ElementType *Element)
1321 {
1322   void *ans = NULL;
1323 
1324   if (TEST_FLAG (LOCKFLAG, Element))
1325     return (NULL);
1326   PIN_LOOP (Element);
1327   {
1328     ans = SetPinSquare (Element, pin);
1329   }
1330   END_LOOP;
1331   PAD_LOOP (Element);
1332   {
1333     ans = SetPadSquare (Element, pad);
1334   }
1335   END_LOOP;
1336   return (ans);
1337 }
1338 
1339 /*!
1340  * \brief Clears the square flag of all pins on an element.
1341  */
1342 static void *
ClrElementSquare(ElementType * Element)1343 ClrElementSquare (ElementType *Element)
1344 {
1345   void *ans = NULL;
1346 
1347   if (TEST_FLAG (LOCKFLAG, Element))
1348     return (NULL);
1349   PIN_LOOP (Element);
1350   {
1351     ans = ClrPinSquare (Element, pin);
1352   }
1353   END_LOOP;
1354   PAD_LOOP (Element);
1355   {
1356     ans = ClrPadSquare (Element, pad);
1357   }
1358   END_LOOP;
1359   return (ans);
1360 }
1361 
1362 /*!
1363  * \brief Changes the octagon flags of all pins of an element.
1364  */
1365 static void *
ChangeElementOctagon(ElementType * Element)1366 ChangeElementOctagon (ElementType *Element)
1367 {
1368   void *result = NULL;
1369 
1370   if (TEST_FLAG (LOCKFLAG, Element))
1371     return (NULL);
1372   PIN_LOOP (Element);
1373   {
1374     ChangePinOctagon (Element, pin);
1375     result = Element;
1376   }
1377   END_LOOP;
1378   return (result);
1379 }
1380 
1381 /*!
1382  * \brief Sets the octagon flags of all pins of an element.
1383  */
1384 static void *
SetElementOctagon(ElementType * Element)1385 SetElementOctagon (ElementType *Element)
1386 {
1387   void *result = NULL;
1388 
1389   if (TEST_FLAG (LOCKFLAG, Element))
1390     return (NULL);
1391   PIN_LOOP (Element);
1392   {
1393     SetPinOctagon (Element, pin);
1394     result = Element;
1395   }
1396   END_LOOP;
1397   return (result);
1398 }
1399 
1400 /*!
1401  * \brief Clears the octagon flags of all pins of an element.
1402  */
1403 static void *
ClrElementOctagon(ElementType * Element)1404 ClrElementOctagon (ElementType *Element)
1405 {
1406   void *result = NULL;
1407 
1408   if (TEST_FLAG (LOCKFLAG, Element))
1409     return (NULL);
1410   PIN_LOOP (Element);
1411   {
1412     ClrPinOctagon (Element, pin);
1413     result = Element;
1414   }
1415   END_LOOP;
1416   return (result);
1417 }
1418 
1419 /*!
1420  * \brief Changes the square flag of a pad.
1421  */
1422 static void *
ChangePadSquare(ElementType * Element,PadType * Pad)1423 ChangePadSquare (ElementType *Element, PadType *Pad)
1424 {
1425   if (TEST_FLAG (LOCKFLAG, Pad))
1426     return (NULL);
1427   ErasePad (Pad);
1428   AddObjectToClearPolyUndoList (PAD_TYPE, Element, Pad, Pad, false);
1429   RestoreToPolygon (PCB->Data, PAD_TYPE, Element, Pad);
1430   AddObjectToFlagUndoList (PAD_TYPE, Element, Pad, Pad);
1431   TOGGLE_FLAG (SQUAREFLAG, Pad);
1432   AddObjectToClearPolyUndoList (PAD_TYPE, Element, Pad, Pad, true);
1433   ClearFromPolygon (PCB->Data, PAD_TYPE, Element, Pad);
1434   DrawPad (Pad);
1435   return (Pad);
1436 }
1437 
1438 /*!
1439  * \brief Sets the square flag of a pad.
1440  */
1441 static void *
SetPadSquare(ElementType * Element,PadType * Pad)1442 SetPadSquare (ElementType *Element, PadType *Pad)
1443 {
1444 
1445   if (TEST_FLAG (LOCKFLAG, Pad) || TEST_FLAG (SQUAREFLAG, Pad))
1446     return (NULL);
1447 
1448   return (ChangePadSquare (Element, Pad));
1449 }
1450 
1451 
1452 /*!
1453  * \brief Clears the square flag of a pad.
1454  */
1455 static void *
ClrPadSquare(ElementType * Element,PadType * Pad)1456 ClrPadSquare (ElementType *Element, PadType *Pad)
1457 {
1458 
1459   if (TEST_FLAG (LOCKFLAG, Pad) || !TEST_FLAG (SQUAREFLAG, Pad))
1460     return (NULL);
1461 
1462   return (ChangePadSquare (Element, Pad));
1463 }
1464 
1465 
1466 /*!
1467  * \brief Changes the square flag of a pin.
1468  */
1469 static void *
ChangePinSquare(ElementType * Element,PinType * Pin)1470 ChangePinSquare (ElementType *Element, PinType *Pin)
1471 {
1472   if (TEST_FLAG (LOCKFLAG, Pin))
1473     return (NULL);
1474   ErasePin (Pin);
1475   AddObjectToClearPolyUndoList (PIN_TYPE, Element, Pin, Pin, false);
1476   RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin);
1477   AddObjectToFlagUndoList (PIN_TYPE, Element, Pin, Pin);
1478   TOGGLE_FLAG (SQUAREFLAG, Pin);
1479   AddObjectToClearPolyUndoList (PIN_TYPE, Element, Pin, Pin, true);
1480   ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin);
1481   DrawPin (Pin);
1482   return (Pin);
1483 }
1484 
1485 /*!
1486  * \brief Sets the square flag of a pin.
1487  */
1488 static void *
SetPinSquare(ElementType * Element,PinType * Pin)1489 SetPinSquare (ElementType *Element, PinType *Pin)
1490 {
1491   if (TEST_FLAG (LOCKFLAG, Pin) || TEST_FLAG (SQUAREFLAG, Pin))
1492     return (NULL);
1493 
1494   return (ChangePinSquare (Element, Pin));
1495 }
1496 
1497 /*!
1498  * \brief Clears the square flag of a pin.
1499  */
1500 static void *
ClrPinSquare(ElementType * Element,PinType * Pin)1501 ClrPinSquare (ElementType *Element, PinType *Pin)
1502 {
1503   if (TEST_FLAG (LOCKFLAG, Pin) || !TEST_FLAG (SQUAREFLAG, Pin))
1504     return (NULL);
1505 
1506   return (ChangePinSquare (Element, Pin));
1507 }
1508 
1509 /*!
1510  * \brief Changes the octagon flag of a via.
1511  */
1512 static void *
ChangeViaOctagon(PinType * Via)1513 ChangeViaOctagon (PinType *Via)
1514 {
1515   if (TEST_FLAG (LOCKFLAG, Via))
1516     return (NULL);
1517   EraseVia (Via);
1518   AddObjectToClearPolyUndoList (VIA_TYPE, Via, Via, Via, false);
1519   RestoreToPolygon (PCB->Data, VIA_TYPE, Via, Via);
1520   AddObjectToFlagUndoList (VIA_TYPE, Via, Via, Via);
1521   TOGGLE_FLAG (OCTAGONFLAG, Via);
1522   AddObjectToClearPolyUndoList (VIA_TYPE, Via, Via, Via, true);
1523   ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via);
1524   DrawVia (Via);
1525   return (Via);
1526 }
1527 
1528 /*!
1529  * \brief Sets the octagon flag of a via.
1530  */
1531 static void *
SetViaOctagon(PinType * Via)1532 SetViaOctagon (PinType *Via)
1533 {
1534   if (TEST_FLAG (LOCKFLAG, Via) || TEST_FLAG (OCTAGONFLAG, Via))
1535     return (NULL);
1536 
1537   return (ChangeViaOctagon (Via));
1538 }
1539 
1540 /*!
1541  * \brief Clears the octagon flag of a via.
1542  */
1543 static void *
ClrViaOctagon(PinType * Via)1544 ClrViaOctagon (PinType *Via)
1545 {
1546   if (TEST_FLAG (LOCKFLAG, Via) || !TEST_FLAG (OCTAGONFLAG, Via))
1547     return (NULL);
1548 
1549   return (ChangeViaOctagon (Via));
1550 }
1551 
1552 /*!
1553  * \brief Changes the octagon flag of a pin.
1554  */
1555 static void *
ChangePinOctagon(ElementType * Element,PinType * Pin)1556 ChangePinOctagon (ElementType *Element, PinType *Pin)
1557 {
1558   if (TEST_FLAG (LOCKFLAG, Pin))
1559     return (NULL);
1560   ErasePin (Pin);
1561   AddObjectToClearPolyUndoList (PIN_TYPE, Element, Pin, Pin, false);
1562   RestoreToPolygon (PCB->Data, PIN_TYPE, Element, Pin);
1563   AddObjectToFlagUndoList (PIN_TYPE, Element, Pin, Pin);
1564   TOGGLE_FLAG (OCTAGONFLAG, Pin);
1565   AddObjectToClearPolyUndoList (PIN_TYPE, Element, Pin, Pin, true);
1566   ClearFromPolygon (PCB->Data, PIN_TYPE, Element, Pin);
1567   DrawPin (Pin);
1568   return (Pin);
1569 }
1570 
1571 /*!
1572  * \brief Sets the octagon flag of a pin.
1573  */
1574 static void *
SetPinOctagon(ElementType * Element,PinType * Pin)1575 SetPinOctagon (ElementType *Element, PinType *Pin)
1576 {
1577   if (TEST_FLAG (LOCKFLAG, Pin) || TEST_FLAG (OCTAGONFLAG, Pin))
1578     return (NULL);
1579 
1580   return (ChangePinOctagon (Element, Pin));
1581 }
1582 
1583 /*!
1584  * \brief Clears the octagon flag of a pin.
1585  */
1586 static void *
ClrPinOctagon(ElementType * Element,PinType * Pin)1587 ClrPinOctagon (ElementType *Element, PinType *Pin)
1588 {
1589   if (TEST_FLAG (LOCKFLAG, Pin) || !TEST_FLAG (OCTAGONFLAG, Pin))
1590     return (NULL);
1591 
1592   return (ChangePinOctagon (Element, Pin));
1593 }
1594 
1595 /*!
1596  * \brief Changes the hole flag of a via.
1597  */
1598 bool
ChangeHole(PinType * Via)1599 ChangeHole (PinType *Via)
1600 {
1601   if (TEST_FLAG (LOCKFLAG, Via))
1602     return (false);
1603   EraseVia (Via);
1604   AddObjectToFlagUndoList (VIA_TYPE, Via, Via, Via);
1605   AddObjectToMaskSizeUndoList (VIA_TYPE, Via, Via, Via);
1606   r_delete_entry (PCB->Data->via_tree, (BoxType *) Via);
1607   RestoreToPolygon (PCB->Data, VIA_TYPE, Via, Via);
1608   TOGGLE_FLAG (HOLEFLAG, Via);
1609 
1610   if (TEST_FLAG (HOLEFLAG, Via))
1611     {
1612       /* A tented via becomes an minimally untented hole.  An untented
1613 	 via retains its mask clearance.  */
1614       if (Via->Mask > Via->Thickness)
1615 	{
1616 	  Via->Mask = (Via->DrillingHole
1617 		       + (Via->Mask - Via->Thickness));
1618 	}
1619       else if (Via->Mask < Via->DrillingHole)
1620 	{
1621 	  Via->Mask = Via->DrillingHole + 2 * MASKFRAME;
1622 	}
1623     }
1624   else
1625     {
1626       Via->Mask = (Via->Thickness
1627 		   + (Via->Mask - Via->DrillingHole));
1628     }
1629 
1630   SetPinBoundingBox (Via);
1631   r_insert_entry (PCB->Data->via_tree, (BoxType *) Via, 0);
1632   ClearFromPolygon (PCB->Data, VIA_TYPE, Via, Via);
1633   DrawVia (Via);
1634   Draw ();
1635   return (true);
1636 }
1637 
1638 /*!
1639  * \brief Changes the nopaste flag of a pad.
1640  */
1641 bool
ChangePaste(PadType * Pad)1642 ChangePaste (PadType *Pad)
1643 {
1644   if (TEST_FLAG (LOCKFLAG, Pad))
1645     return (false);
1646   ErasePad (Pad);
1647   AddObjectToFlagUndoList (PAD_TYPE, Pad, Pad, Pad);
1648   TOGGLE_FLAG (NOPASTEFLAG, Pad);
1649   DrawPad (Pad);
1650   Draw ();
1651   return (true);
1652 }
1653 
1654 /*!
1655  * \brief Changes the CLEARPOLY flag of a polygon.
1656  */
1657 static void *
ChangePolyClear(LayerType * Layer,PolygonType * Polygon)1658 ChangePolyClear (LayerType *Layer, PolygonType *Polygon)
1659 {
1660   if (TEST_FLAG (LOCKFLAG, Polygon))
1661     return (NULL);
1662   AddObjectToClearPolyUndoList (POLYGON_TYPE, Layer, Polygon, Polygon, true);
1663   AddObjectToFlagUndoList (POLYGON_TYPE, Layer, Polygon, Polygon);
1664   TOGGLE_FLAG (CLEARPOLYFLAG, Polygon);
1665   InitClip (PCB->Data, Layer, Polygon);
1666   DrawPolygon (Layer, Polygon);
1667   return (Polygon);
1668 }
1669 
1670 /*!
1671  * \brief Changes the side of all selected and visible elements.
1672  *
1673  * \return True if anything has changed.
1674  */
1675 bool
ChangeSelectedElementSide(void)1676 ChangeSelectedElementSide (void)
1677 {
1678   bool change = false;
1679 
1680   /* setup identifiers */
1681   if (PCB->PinOn && PCB->ElementOn)
1682     ELEMENT_LOOP (PCB->Data);
1683   {
1684     if (TEST_FLAG (SELECTEDFLAG, element))
1685       {
1686 	change |= ChangeElementSide (element, 0);
1687       }
1688   }
1689   END_LOOP;
1690   if (change)
1691     {
1692       Draw ();
1693       IncrementUndoSerialNumber ();
1694     }
1695   return (change);
1696 }
1697 
1698 /*!
1699  * \brief Changes the thermals on all selected and visible pins and/or
1700  * vias.
1701  *
1702  * \return True if anything has changed.
1703  */
1704 bool
ChangeSelectedThermals(int types,int therm_style)1705 ChangeSelectedThermals (int types, int therm_style)
1706 {
1707   bool change = false;
1708 
1709   Value = therm_style;
1710   change = SelectedOperation (&ChangeThermalFunctions, false, types);
1711   if (change)
1712     {
1713       Draw ();
1714       IncrementUndoSerialNumber ();
1715     }
1716   return (change);
1717 }
1718 
1719 
1720 /*!
1721  * \brief Changes the thermals on all selected and visible pins and/or
1722  * vias.
1723  *
1724  * \return True if anything has changed.
1725  */
1726 bool
ChangeSelectedViaLayers(int from,int to)1727 ChangeSelectedViaLayers (int from, int to)
1728 {
1729   bool change = false;
1730   int new_from;
1731   int new_to;
1732   int i;
1733 
1734   VIA_LOOP (PCB->Data);
1735     {
1736       if (TEST_FLAG (LOCKFLAG, via))
1737         continue;
1738       if (TEST_FLAG (SELECTEDFLAG, via))
1739         {
1740 
1741           new_from = (from != -1)?from:via->BuriedFrom;
1742           new_to = (to != -1)?to:via->BuriedTo;
1743 
1744 	  if (new_from == new_to)
1745 	    continue;
1746 
1747           /* special case - changing TH via "from" layer sets "to" layer to bottom layer */
1748           if (!VIA_IS_BURIED (via)
1749                && (to == -1))
1750              new_to = GetMaxBottomLayer ();
1751 
1752           for (i=0; i < max_copper_layer; i++)
1753             {
1754               /* AddObjectToClearPolyUndoList (VIA_TYPE, &(PCB->Data->Layer[i]), via, via, false); not needed? */
1755               RestoreToPolygon (PCB->Data, VIA_TYPE, &(PCB->Data->Layer[i]), via);
1756             }
1757 
1758 	    AddObjectToSetViaLayersUndoList (via, via, via);
1759             via->BuriedFrom = new_from;
1760             via->BuriedTo = new_to;
1761 
1762             if (VIA_IS_BURIED (via))
1763 	      {
1764 	        SanitizeBuriedVia (via);
1765                 for (i=0; i < max_copper_layer; i++)
1766                   {
1767                     /* AddObjectToClearPolyUndoList (VIA_TYPE, &(PCB->Data->Layer[i]), via, via, true);  not needed? */
1768                     ClearFromPolygon (PCB->Data, VIA_TYPE, &(PCB->Data->Layer[i]), via);
1769                   }
1770                 DrawVia (via);
1771 	      }
1772             change = true;
1773 	}
1774     }
1775   END_LOOP;
1776   if (change)
1777     {
1778       Draw ();
1779       IncrementUndoSerialNumber ();
1780     }
1781   return (change);
1782 }
1783 
1784 /*!
1785  * \brief Changes the size of all selected and visible object types.
1786  *
1787  * \return True if anything has changed.
1788  */
1789 bool
ChangeSelectedSize(int types,Coord Difference,bool fixIt)1790 ChangeSelectedSize (int types, Coord Difference, bool fixIt)
1791 {
1792   bool change = false;
1793 
1794   /* setup identifiers */
1795   Absolute = (fixIt) ? 1 : 0;
1796   Value = Difference;
1797 
1798   change = SelectedOperation (&ChangeSizeFunctions, false, types);
1799   if (change)
1800     {
1801       Draw ();
1802       IncrementUndoSerialNumber ();
1803     }
1804   return (change);
1805 }
1806 
1807 /*!
1808  * \brief Changes the clearance size of all selected and visible objects.
1809  *
1810  * \return True if anything has changed.
1811  */
1812 bool
ChangeSelectedClearSize(int types,Coord Difference,bool fixIt)1813 ChangeSelectedClearSize (int types, Coord Difference, bool fixIt)
1814 {
1815   bool change = false;
1816 
1817   /* setup identifiers */
1818   Absolute = (fixIt) ? 1 : 0;
1819   Value = Difference;
1820   if (TEST_FLAG (SHOWMASKFLAG, PCB))
1821     change = SelectedOperation (&ChangeMaskSizeFunctions, false, types);
1822   else
1823     change = SelectedOperation (&ChangeClearSizeFunctions, false, types);
1824   if (change)
1825     {
1826       Draw ();
1827       IncrementUndoSerialNumber ();
1828     }
1829   return (change);
1830 }
1831 
1832 /*!
1833  * \brief Changes the 2nd size (drilling hole) of all selected and
1834  * visible objects.
1835  *
1836  * \return True if anything has changed.
1837  */
1838 bool
ChangeSelected2ndSize(int types,Coord Difference,bool fixIt)1839 ChangeSelected2ndSize (int types, Coord Difference, bool fixIt)
1840 {
1841   bool change = false;
1842 
1843   /* setup identifiers */
1844   Absolute = (fixIt) ? 1 : 0;
1845   Value = Difference;
1846   change = SelectedOperation (&Change2ndSizeFunctions, false, types);
1847   if (change)
1848     {
1849       Draw ();
1850       IncrementUndoSerialNumber ();
1851     }
1852   return (change);
1853 }
1854 
1855 /*!
1856  * \brief Changes the clearance flag (join) of all selected and visible
1857  * lines and/or arcs.
1858  *
1859  * \return True if anything has changed.
1860  */
1861 bool
ChangeSelectedJoin(int types)1862 ChangeSelectedJoin (int types)
1863 {
1864   bool change = false;
1865 
1866   change = SelectedOperation (&ChangeJoinFunctions, false, types);
1867   if (change)
1868     {
1869       Draw ();
1870       IncrementUndoSerialNumber ();
1871     }
1872   return (change);
1873 }
1874 
1875 /*!
1876  * \brief Changes the clearance flag (join) of all selected and visible
1877  * lines and/or arcs.
1878  *
1879  * \return True if anything has changed.
1880  */
1881 bool
SetSelectedJoin(int types)1882 SetSelectedJoin (int types)
1883 {
1884   bool change = false;
1885 
1886   change = SelectedOperation (&SetJoinFunctions, false, types);
1887   if (change)
1888     {
1889       Draw ();
1890       IncrementUndoSerialNumber ();
1891     }
1892   return (change);
1893 }
1894 
1895 /*!
1896  * \brief Changes the clearance flag (join) of all selected and visible
1897  * lines and/or arcs.
1898  *
1899  * \return True if anything has changed.
1900  */
1901 bool
ClrSelectedJoin(int types)1902 ClrSelectedJoin (int types)
1903 {
1904   bool change = false;
1905 
1906   change = SelectedOperation (&ClrJoinFunctions, false, types);
1907   if (change)
1908     {
1909       Draw ();
1910       IncrementUndoSerialNumber ();
1911     }
1912   return (change);
1913 }
1914 
1915 /*!
1916  * \brief Changes the square-flag of all selected and visible pins or
1917  * pads.
1918  *
1919  * \return True if anything has changed.
1920  */
1921 bool
ChangeSelectedSquare(int types)1922 ChangeSelectedSquare (int types)
1923 {
1924   bool change = false;
1925 
1926   change = SelectedOperation (&ChangeSquareFunctions, false, types);
1927   if (change)
1928     {
1929       Draw ();
1930       IncrementUndoSerialNumber ();
1931     }
1932   return (change);
1933 }
1934 
1935 /*!
1936  * \brief Sets the square-flag of all selected and visible pins or pads.
1937  *
1938  * \return True if anything has changed.
1939  */
1940 bool
SetSelectedSquare(int types)1941 SetSelectedSquare (int types)
1942 {
1943   bool change = false;
1944 
1945   change = SelectedOperation (&SetSquareFunctions, false, types);
1946   if (change)
1947     {
1948       Draw ();
1949       IncrementUndoSerialNumber ();
1950     }
1951   return (change);
1952 }
1953 
1954 /*!
1955  * \brief Clears the square-flag of all selected and visible pins or
1956  * pads.
1957  *
1958  * \return True if anything has changed.
1959  */
1960 bool
ClrSelectedSquare(int types)1961 ClrSelectedSquare (int types)
1962 {
1963   bool change = false;
1964 
1965   change = SelectedOperation (&ClrSquareFunctions, false, types);
1966   if (change)
1967     {
1968       Draw ();
1969       IncrementUndoSerialNumber ();
1970     }
1971   return (change);
1972 }
1973 
1974 /*!
1975  * \brief Changes the octagon-flag of all selected and visible pins and
1976  * vias.
1977  *
1978  * \return True if anything has changed.
1979  */
1980 bool
ChangeSelectedOctagon(int types)1981 ChangeSelectedOctagon (int types)
1982 {
1983   bool change = false;
1984 
1985   change = SelectedOperation (&ChangeOctagonFunctions, false, types);
1986   if (change)
1987     {
1988       Draw ();
1989       IncrementUndoSerialNumber ();
1990     }
1991   return (change);
1992 }
1993 
1994 /*!
1995  * \brief Sets the octagon-flag of all selected and visible pins and
1996  * vias.
1997  *
1998  * \return True if anything has changed.
1999  */
2000 bool
SetSelectedOctagon(int types)2001 SetSelectedOctagon (int types)
2002 {
2003   bool change = false;
2004 
2005   change = SelectedOperation (&SetOctagonFunctions, false, types);
2006   if (change)
2007     {
2008       Draw ();
2009       IncrementUndoSerialNumber ();
2010     }
2011   return (change);
2012 }
2013 
2014 /*!
2015  * \brief Clears the octagon-flag of all selected and visible pins and
2016  * vias.
2017  *
2018  * \return True if anything has changed.
2019  */
2020 bool
ClrSelectedOctagon(int types)2021 ClrSelectedOctagon (int types)
2022 {
2023   bool change = false;
2024 
2025   change = SelectedOperation (&ClrOctagonFunctions, false, types);
2026   if (change)
2027     {
2028       Draw ();
2029       IncrementUndoSerialNumber ();
2030     }
2031   return (change);
2032 }
2033 
2034 /*!
2035  * \brief Changes the hole-flag of all selected and visible vias.
2036  *
2037  * \return True if anything has changed.
2038  */
2039 bool
ChangeSelectedHole(void)2040 ChangeSelectedHole (void)
2041 {
2042   bool change = false;
2043 
2044   if (PCB->ViaOn)
2045     VIA_LOOP (PCB->Data);
2046   {
2047     if (TEST_FLAG (SELECTEDFLAG, via))
2048       change |= ChangeHole (via);
2049   }
2050   END_LOOP;
2051   if (change)
2052     {
2053       Draw ();
2054       IncrementUndoSerialNumber ();
2055     }
2056   return (change);
2057 }
2058 
2059 /*!
2060  * \brief Changes the no paste-flag of all selected and visible pads.
2061  *
2062  * \return True if anything has changed.
2063  */
2064 bool
ChangeSelectedPaste(void)2065 ChangeSelectedPaste (void)
2066 {
2067   bool change = false;
2068 
2069   ALLPAD_LOOP (PCB->Data);
2070   {
2071     if (TEST_FLAG (SELECTEDFLAG, pad))
2072       change |= ChangePaste (pad);
2073   }
2074   ENDALL_LOOP;
2075   if (change)
2076     {
2077       Draw ();
2078       IncrementUndoSerialNumber ();
2079     }
2080   return (change);
2081 }
2082 
2083 
2084 /*!
2085  * \brief Changes the size of the passed object.
2086  *
2087  * \return True if anything is changed.
2088  */
2089 bool
ChangeObjectSize(int Type,void * Ptr1,void * Ptr2,void * Ptr3,Coord Difference,bool fixIt)2090 ChangeObjectSize (int Type, void *Ptr1, void *Ptr2, void *Ptr3,
2091 		  Coord Difference, bool fixIt)
2092 {
2093   bool change;
2094 
2095   /* setup identifier */
2096   Absolute = (fixIt) ? 1 : 0;
2097   Value = Difference;
2098   change =
2099     (ObjectOperation (&ChangeSizeFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL);
2100   if (change)
2101     {
2102       Draw ();
2103       IncrementUndoSerialNumber ();
2104     }
2105   return (change);
2106 }
2107 
2108 /*!
2109  * \brief Changes the clearance size of the passed object.
2110  *
2111  * \return True if anything is changed.
2112  */
2113 bool
ChangeObjectClearSize(int Type,void * Ptr1,void * Ptr2,void * Ptr3,Coord Difference,bool fixIt)2114 ChangeObjectClearSize (int Type, void *Ptr1, void *Ptr2, void *Ptr3,
2115 		       Coord Difference, bool fixIt)
2116 {
2117   bool change;
2118 
2119   /* setup identifier */
2120   Absolute = (fixIt) ? 1 : 0;
2121   Value = Difference;
2122   if (TEST_FLAG (SHOWMASKFLAG, PCB))
2123     change =
2124       (ObjectOperation (&ChangeMaskSizeFunctions, Type, Ptr1, Ptr2, Ptr3) !=
2125        NULL);
2126   else
2127     change =
2128       (ObjectOperation (&ChangeClearSizeFunctions, Type, Ptr1, Ptr2, Ptr3) !=
2129        NULL);
2130   if (change)
2131     {
2132       Draw ();
2133       IncrementUndoSerialNumber ();
2134     }
2135   return (change);
2136 }
2137 
2138 /*!
2139  * \brief Changes the thermal of the passed object.
2140  *
2141  * \return True if anything is changed.
2142  *
2143  */
2144 bool
ChangeObjectThermal(int Type,void * Ptr1,void * Ptr2,void * Ptr3,int therm_type)2145 ChangeObjectThermal (int Type, void *Ptr1, void *Ptr2, void *Ptr3,
2146 		     int therm_type)
2147 {
2148   bool change;
2149 
2150   Value = Absolute = therm_type;
2151   change =
2152     (ObjectOperation (&ChangeThermalFunctions, Type, Ptr1, Ptr2, Ptr3) !=
2153      NULL);
2154   if (change)
2155     {
2156       Draw ();
2157       IncrementUndoSerialNumber ();
2158     }
2159   return (change);
2160 }
2161 
2162 /*!
2163  * \brief Changes the thermal of the passed object.
2164  *
2165  * \return True if anything is changed.
2166  *
2167  */
2168 bool
ChangeObjectViaLayers(void * Ptr1,void * Ptr2,void * Ptr3,int from,int to)2169 ChangeObjectViaLayers (void *Ptr1, void *Ptr2, void *Ptr3,
2170 		     int from, int to)
2171 {
2172   bool change = false;
2173   PinType *via = (PinType *) Ptr1;
2174   int new_from = (from != -1)?from:via->BuriedFrom;
2175   int new_to = (to != -1)?to:via->BuriedTo;
2176   int i;
2177 
2178   if (TEST_FLAG (LOCKFLAG, via))
2179     return (NULL);
2180 
2181   if ((new_from == new_to)
2182       && new_from != 0)
2183     return false;
2184 
2185   /* special case - changing TH via "from" layer sets "to" layer to bottom layer */
2186   if (!VIA_IS_BURIED (via)
2187        && (to == -1))
2188      new_to = GetMaxBottomLayer ();
2189 
2190   for (i=0; i < max_copper_layer; i++)
2191     {
2192       /* AddObjectToClearPolyUndoList (VIA_TYPE, &(PCB->Data->Layer[i]), via, via, false);  not needed? */
2193       RestoreToPolygon (PCB->Data, VIA_TYPE, &(PCB->Data->Layer[i]), via);
2194     }
2195 
2196   if (from != -1 || to != -1)
2197     {
2198       AddObjectToSetViaLayersUndoList (via, via, via);
2199       change = true;
2200     }
2201 
2202   via->BuriedFrom = new_from;
2203   via->BuriedTo = new_to;
2204 
2205   if (VIA_IS_BURIED (via))
2206     {
2207       SanitizeBuriedVia (via);
2208       for (i=0; i < max_copper_layer; i++)
2209         {
2210           /* AddObjectToClearPolyUndoList (VIA_TYPE, &(PCB->Data->Layer[i]), via, via, true);  not needed? */
2211           ClearFromPolygon (PCB->Data, VIA_TYPE, &(PCB->Data->Layer[i]), via);
2212         }
2213       DrawVia (via);
2214     }
2215 
2216   if (change)
2217     {
2218       Draw ();
2219       IncrementUndoSerialNumber ();
2220     }
2221   return (change);
2222 }
2223 
2224 /*!
2225  * \brief Changes the 2nd size of the passed object.
2226  *
2227  * \return True if anything is changed.
2228  */
2229 bool
ChangeObject2ndSize(int Type,void * Ptr1,void * Ptr2,void * Ptr3,Coord Difference,bool fixIt,bool incundo)2230 ChangeObject2ndSize (int Type, void *Ptr1, void *Ptr2, void *Ptr3,
2231 		     Coord Difference, bool fixIt, bool incundo)
2232 {
2233   bool change;
2234 
2235   /* setup identifier */
2236   Absolute = (fixIt) ? 1 : 0;
2237   Value = Difference;
2238   change =
2239     (ObjectOperation (&Change2ndSizeFunctions, Type, Ptr1, Ptr2, Ptr3) !=
2240      NULL);
2241   if (change)
2242     {
2243       Draw ();
2244       if (incundo)
2245 	IncrementUndoSerialNumber ();
2246     }
2247   return (change);
2248 }
2249 
2250 /*!
2251  * \brief Changes the mask size of the passed object.
2252  *
2253  * \return True if anything is changed.
2254  */
2255 bool
ChangeObjectMaskSize(int Type,void * Ptr1,void * Ptr2,void * Ptr3,Coord Difference,bool fixIt)2256 ChangeObjectMaskSize (int Type, void *Ptr1, void *Ptr2, void *Ptr3,
2257 		      Coord Difference, bool fixIt)
2258 {
2259   bool change;
2260 
2261   /* setup identifier */
2262   Absolute = (fixIt) ? 1 : 0;
2263   Value = Difference;
2264   change =
2265     (ObjectOperation (&ChangeMaskSizeFunctions, Type, Ptr1, Ptr2, Ptr3) !=
2266      NULL);
2267   if (change)
2268     {
2269       Draw ();
2270       IncrementUndoSerialNumber ();
2271     }
2272   return (change);
2273 }
2274 
2275 /*!
2276  * \brief Changes the name of the passed object.
2277  *
2278  * \warning The allocated memory isn't freed because the old string is used
2279  * by the undo module.
2280  *
2281  * \return The old name.
2282  */
2283 void *
ChangeObjectName(int Type,void * Ptr1,void * Ptr2,void * Ptr3,char * Name)2284 ChangeObjectName (int Type, void *Ptr1, void *Ptr2, void *Ptr3, char *Name)
2285 {
2286   void *result;
2287   /* setup identifier */
2288   NewName = Name;
2289   result = ObjectOperation (&ChangeNameFunctions, Type, Ptr1, Ptr2, Ptr3);
2290   Draw ();
2291   return (result);
2292 }
2293 
2294 /*!
2295  * \brief Changes the clearance-flag of the passed object.
2296  *
2297  * \return True if anything is changed.
2298  */
2299 bool
ChangeObjectJoin(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2300 ChangeObjectJoin (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2301 {
2302   if (ObjectOperation (&ChangeJoinFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL)
2303     {
2304       Draw ();
2305       IncrementUndoSerialNumber ();
2306       return (true);
2307     }
2308   return (false);
2309 }
2310 
2311 /*!
2312  * \brief Sets the clearance-flag of the passed object.
2313  *
2314  * \return True if anything is changed.
2315  */
2316 bool
SetObjectJoin(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2317 SetObjectJoin (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2318 {
2319   if (ObjectOperation (&SetJoinFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL)
2320     {
2321       Draw ();
2322       IncrementUndoSerialNumber ();
2323       return (true);
2324     }
2325   return (false);
2326 }
2327 
2328 /*!
2329  * \brief Clears the clearance-flag of the passed object.
2330  *
2331  * \return True if anything is changed.
2332  */
2333 bool
ClrObjectJoin(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2334 ClrObjectJoin (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2335 {
2336   if (ObjectOperation (&ClrJoinFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL)
2337     {
2338       Draw ();
2339       IncrementUndoSerialNumber ();
2340       return (true);
2341     }
2342   return (false);
2343 }
2344 
2345 /*!
2346  * \brief Changes the square-flag of the passed object.
2347  *
2348  * \return True if anything is changed.
2349  */
2350 bool
ChangeObjectSquare(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2351 ChangeObjectSquare (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2352 {
2353   if (ObjectOperation (&ChangeSquareFunctions, Type, Ptr1, Ptr2, Ptr3) !=
2354       NULL)
2355     {
2356       Draw ();
2357       IncrementUndoSerialNumber ();
2358       return (true);
2359     }
2360   return (false);
2361 }
2362 
2363 /*!
2364  * \brief Sets the square-flag of the passed object.
2365  *
2366  * \return True if anything is changed.
2367  */
2368 bool
SetObjectSquare(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2369 SetObjectSquare (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2370 {
2371   if (ObjectOperation (&SetSquareFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL)
2372     {
2373       Draw ();
2374       IncrementUndoSerialNumber ();
2375       return (true);
2376     }
2377   return (false);
2378 }
2379 
2380 /*!
2381  * \brief Clears the square-flag of the passed object.
2382  *
2383  * \return True if anything is changed.
2384  */
2385 bool
ClrObjectSquare(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2386 ClrObjectSquare (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2387 {
2388   if (ObjectOperation (&ClrSquareFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL)
2389     {
2390       Draw ();
2391       IncrementUndoSerialNumber ();
2392       return (true);
2393     }
2394   return (false);
2395 }
2396 
2397 /*!
2398  * \brief Changes the octagon-flag of the passed object.
2399  *
2400  * \return True if anything is changed.
2401  */
2402 bool
ChangeObjectOctagon(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2403 ChangeObjectOctagon (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2404 {
2405   if (ObjectOperation (&ChangeOctagonFunctions, Type, Ptr1, Ptr2, Ptr3) !=
2406       NULL)
2407     {
2408       Draw ();
2409       IncrementUndoSerialNumber ();
2410       return (true);
2411     }
2412   return (false);
2413 }
2414 
2415 /*!
2416  * \brief Sets the octagon-flag of the passed object.
2417  *
2418  * \return True if anything is changed.
2419  */
2420 bool
SetObjectOctagon(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2421 SetObjectOctagon (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2422 {
2423   if (ObjectOperation (&SetOctagonFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL)
2424     {
2425       Draw ();
2426       IncrementUndoSerialNumber ();
2427       return (true);
2428     }
2429   return (false);
2430 }
2431 
2432 /*!
2433  * \brief Clears the octagon-flag of the passed object.
2434  *
2435  * \return True if anything is changed.
2436  */
2437 bool
ClrObjectOctagon(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2438 ClrObjectOctagon (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2439 {
2440   if (ObjectOperation (&ClrOctagonFunctions, Type, Ptr1, Ptr2, Ptr3) != NULL)
2441     {
2442       Draw ();
2443       IncrementUndoSerialNumber ();
2444       return (true);
2445     }
2446   return (false);
2447 }
2448 
2449 /*!
2450  * \bief Queries the user for a new object name and changes it.
2451  *
2452  * \warning The allocated memory isn't freed because the old string is used
2453  * by the undo module.
2454  */
2455 void *
QueryInputAndChangeObjectName(int Type,void * Ptr1,void * Ptr2,void * Ptr3)2456 QueryInputAndChangeObjectName (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
2457 {
2458   char *name = NULL;
2459   char msg[513];
2460 
2461   /* if passed an element name, make it an element reference instead */
2462   if (Type == ELEMENTNAME_TYPE)
2463     {
2464       Type = ELEMENT_TYPE;
2465       Ptr2 = Ptr1;
2466       Ptr3 = Ptr1;
2467     }
2468   switch (Type)
2469     {
2470     case LINE_TYPE:
2471       name = gui->prompt_for (_("Linename:"),
2472 			      EMPTY (((LineType *) Ptr2)->Number));
2473       break;
2474 
2475     case VIA_TYPE:
2476       name = gui->prompt_for (_("Vianame:"),
2477 			      EMPTY (((PinType *) Ptr2)->Name));
2478       break;
2479 
2480     case PIN_TYPE:
2481       sprintf (msg, _("%s Pin Name:"), EMPTY (((PinType *) Ptr2)->Number));
2482       name = gui->prompt_for (msg, EMPTY (((PinType *) Ptr2)->Name));
2483       break;
2484 
2485     case PAD_TYPE:
2486       sprintf (msg, _("%s Pad Name:"), EMPTY (((PadType *) Ptr2)->Number));
2487       name = gui->prompt_for (msg, EMPTY (((PadType *) Ptr2)->Name));
2488       break;
2489 
2490     case TEXT_TYPE:
2491       name = gui->prompt_for (_("Enter text:"),
2492 			      EMPTY (((TextType *) Ptr2)->TextString));
2493       break;
2494 
2495     case ELEMENT_TYPE:
2496       name = gui->prompt_for (_("Elementname:"),
2497 			      EMPTY (ELEMENT_NAME
2498 				     (PCB, (ElementType *) Ptr2)));
2499       break;
2500     }
2501   if (name)
2502     {
2503       /* NB: ChangeObjectName takes ownership of the passed memory */
2504       char *old = (char *)ChangeObjectName (Type, Ptr1, Ptr2, Ptr3, name);
2505       if (old != (char *) -1)
2506 	{
2507 	  AddObjectToChangeNameUndoList (Type, Ptr1, Ptr2, Ptr3, old);
2508 	  IncrementUndoSerialNumber ();
2509 	}
2510       Draw ();
2511       return (Ptr3);
2512     }
2513   return (NULL);
2514 }
2515 
2516 /*!
2517  * \brief Changes the maximum size of a layout, adjusts the scrollbars,
2518  * releases the saved pixmap if necessary and adjusts the cursor
2519  * confinement box.
2520  */
2521 void
ChangePCBSize(Coord Width,Coord Height)2522 ChangePCBSize (Coord Width, Coord Height)
2523 {
2524   PCB->MaxWidth = Width;
2525   PCB->MaxHeight = Height;
2526   hid_action ("PCBChanged");
2527 }
2528 
2529 /*!
2530  * \brief Changes the mask size of a pad.
2531  *
2532  * \return TRUE if changed.
2533  */
2534 static void *
ChangePadMaskSize(ElementType * Element,PadType * Pad)2535 ChangePadMaskSize (ElementType *Element, PadType *Pad)
2536 {
2537   Coord new_value = (Absolute) ? Value : Pad->Mask + Value;
2538 
2539   new_value = MAX (new_value, 0);
2540   if (new_value == Pad->Mask && Absolute == 0)
2541     new_value = Pad->Thickness;
2542   if (new_value != Pad->Mask)
2543     {
2544       AddObjectToMaskSizeUndoList (PAD_TYPE, Element, Pad, Pad);
2545       ErasePad (Pad);
2546       r_delete_entry (PCB->Data->pad_tree, &Pad->BoundingBox);
2547       Pad->Mask = new_value;
2548       SetElementBoundingBox (PCB->Data, Element, &PCB->Font);
2549       DrawPad (Pad);
2550       return (Pad);
2551     }
2552   return (NULL);
2553 }
2554 
2555 /*!
2556  * \brief Changes the mask size of a pin.
2557  *
2558  * \return TRUE if changed.
2559  */
2560 static void *
ChangePinMaskSize(ElementType * Element,PinType * Pin)2561 ChangePinMaskSize (ElementType *Element, PinType *Pin)
2562 {
2563   Coord new_value = (Absolute) ? Value : Pin->Mask + Value;
2564 
2565   new_value = MAX (new_value, 0);
2566   if (new_value == Pin->Mask && Absolute == 0)
2567     new_value = Pin->Thickness;
2568   if (new_value != Pin->Mask)
2569     {
2570       AddObjectToMaskSizeUndoList (PIN_TYPE, Element, Pin, Pin);
2571       ErasePin (Pin);
2572       r_delete_entry (PCB->Data->pin_tree, &Pin->BoundingBox);
2573       Pin->Mask = new_value;
2574       SetElementBoundingBox (PCB->Data, Element, &PCB->Font);
2575       DrawPin (Pin);
2576       return (Pin);
2577     }
2578   return (NULL);
2579 }
2580 
2581 /*!
2582  * \brief Changes the mask size of a via.
2583  *
2584  * \return TRUE if changed.
2585  */
2586 static void *
ChangeViaMaskSize(PinType * Via)2587 ChangeViaMaskSize (PinType *Via)
2588 {
2589   Coord new_value;
2590 
2591   new_value = (Absolute) ? Value : Via->Mask + Value;
2592   new_value = MAX (new_value, 0);
2593   if (new_value != Via->Mask)
2594     {
2595       AddObjectToMaskSizeUndoList (VIA_TYPE, Via, Via, Via);
2596       EraseVia (Via);
2597       r_delete_entry (PCB->Data->via_tree, &Via->BoundingBox);
2598       Via->Mask = new_value;
2599       SetPinBoundingBox (Via);
2600       r_insert_entry (PCB->Data->via_tree, &Via->BoundingBox, 0);
2601       DrawVia (Via);
2602       return (Via);
2603     }
2604   return (NULL);
2605 }
2606