6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
30 /* functions used to move pins, elements ...
43 #include "crosshair.h"
57 #ifdef HAVE_LIBDMALLOC
66 /* ---------------------------------------------------------------------------
67 * some local prototypes
69 static void *MoveElementName (ElementTypePtr
);
70 static void *MoveElement (ElementTypePtr
);
71 static void *MoveVia (PinTypePtr
);
72 static void *MoveLine (LayerTypePtr
, LineTypePtr
);
73 static void *MoveArc (LayerTypePtr
, ArcTypePtr
);
74 static void *MoveText (LayerTypePtr
, TextTypePtr
);
75 static void *MovePolygon (LayerTypePtr
, PolygonTypePtr
);
76 static void *MoveLinePoint (LayerTypePtr
, LineTypePtr
, PointTypePtr
);
77 static void *MovePolygonPoint (LayerTypePtr
, PolygonTypePtr
, PointTypePtr
);
78 static void *MoveLineToLayer (LayerTypePtr
, LineTypePtr
);
79 static void *MoveArcToLayer (LayerTypePtr
, ArcTypePtr
);
80 static void *MoveRatToLayer (RatTypePtr
);
81 static void *MoveTextToLayer (LayerTypePtr
, TextTypePtr
);
82 static void *MovePolygonToLayer (LayerTypePtr
, PolygonTypePtr
);
84 /* ---------------------------------------------------------------------------
85 * some local identifiers
87 static LocationType DeltaX
, /* used by local routines as offset */
89 static LayerTypePtr Dest
;
90 static Boolean MoreToCome
;
91 static ObjectFunctionType MoveFunctions
= {
104 }, MoveToLayerFunctions
=
110 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, MoveArcToLayer
, MoveRatToLayer
};
112 /* ---------------------------------------------------------------------------
113 * moves a element by +-X and +-Y
116 MoveElementLowLevel (DataTypePtr Data
, ElementTypePtr Element
,
117 LocationType DX
, LocationType DY
)
120 r_delete_entry (Data
->element_tree
, (BoxType
*) Element
);
121 ELEMENTLINE_LOOP (Element
);
123 MOVE_LINE_LOWLEVEL (line
, DX
, DY
);
130 r_delete_entry (Data
->pin_tree
, (BoxType
*) pin
);
131 RestoreToPolygon (Data
, PIN_TYPE
, Element
, pin
);
133 MOVE_PIN_LOWLEVEL (pin
, DX
, DY
);
136 r_insert_entry (Data
->pin_tree
, (BoxType
*) pin
, 0);
137 ClearFromPolygon (Data
, PIN_TYPE
, Element
, pin
);
145 r_delete_entry (Data
->pad_tree
, (BoxType
*) pad
);
146 RestoreToPolygon (Data
, PAD_TYPE
, Element
, pad
);
148 MOVE_PAD_LOWLEVEL (pad
, DX
, DY
);
151 r_insert_entry (Data
->pad_tree
, (BoxType
*) pad
, 0);
152 ClearFromPolygon (Data
, PAD_TYPE
, Element
, pad
);
158 MOVE_ARC_LOWLEVEL (arc
, DX
, DY
);
161 ELEMENTTEXT_LOOP (Element
);
163 if (Data
&& Data
->name_tree
[n
])
164 r_delete_entry (PCB
->Data
->name_tree
[n
], (BoxType
*) text
);
165 MOVE_TEXT_LOWLEVEL (text
, DX
, DY
);
166 if (Data
&& Data
->name_tree
[n
])
167 r_insert_entry (PCB
->Data
->name_tree
[n
], (BoxType
*) text
, 0);
170 MOVE_BOX_LOWLEVEL (&Element
->BoundingBox
, DX
, DY
);
171 MOVE_BOX_LOWLEVEL (&Element
->VBox
, DX
, DY
);
172 MOVE (Element
->MarkX
, Element
->MarkY
, DX
, DY
);
174 r_insert_entry (Data
->element_tree
, (BoxType
*) Element
, 0);
177 /* ----------------------------------------------------------------------
178 * moves all names of an element to a new position
181 MoveElementName (ElementTypePtr Element
)
183 if (PCB
->ElementOn
&& (FRONT (Element
) || PCB
->InvisibleObjectsOn
))
185 EraseElementName (Element
);
186 ELEMENTTEXT_LOOP (Element
);
188 if (PCB
->Data
->name_tree
[n
])
189 r_delete_entry (PCB
->Data
->name_tree
[n
], (BoxType
*) text
);
190 MOVE_TEXT_LOWLEVEL (text
, DeltaX
, DeltaY
);
191 if (PCB
->Data
->name_tree
[n
])
192 r_insert_entry (PCB
->Data
->name_tree
[n
], (BoxType
*) text
, 0);
195 DrawElementName (Element
, 0);
200 ELEMENTTEXT_LOOP (Element
);
202 if (PCB
->Data
->name_tree
[n
])
203 r_delete_entry (PCB
->Data
->name_tree
[n
], (BoxType
*) text
);
204 MOVE_TEXT_LOWLEVEL (text
, DeltaX
, DeltaY
);
205 if (PCB
->Data
->name_tree
[n
])
206 r_insert_entry (PCB
->Data
->name_tree
[n
], (BoxType
*) text
, 0);
213 /* ---------------------------------------------------------------------------
217 MoveElement (ElementTypePtr Element
)
219 Boolean didDraw
= False
;
221 if (PCB
->ElementOn
&& (FRONT (Element
) || PCB
->InvisibleObjectsOn
))
223 EraseElement (Element
);
224 MoveElementLowLevel (PCB
->Data
, Element
, DeltaX
, DeltaY
);
225 DrawElementName (Element
, 0);
226 DrawElementPackage (Element
, 0);
232 EraseElementPinsAndPads (Element
);
233 MoveElementLowLevel (PCB
->Data
, Element
, DeltaX
, DeltaY
);
237 DrawElementPinsAndPads (Element
, 0);
245 /* ---------------------------------------------------------------------------
249 MoveVia (PinTypePtr Via
)
251 r_delete_entry (PCB
->Data
->via_tree
, (BoxTypePtr
) Via
);
252 RestoreToPolygon (PCB
->Data
, VIA_TYPE
, Via
, Via
);
253 MOVE_VIA_LOWLEVEL (Via
, DeltaX
, DeltaY
);
256 r_insert_entry (PCB
->Data
->via_tree
, (BoxTypePtr
) Via
, 0);
257 ClearFromPolygon (PCB
->Data
, VIA_TYPE
, Via
, Via
);
266 /* ---------------------------------------------------------------------------
270 MoveLine (LayerTypePtr Layer
, LineTypePtr Line
)
274 RestoreToPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
275 r_delete_entry (Layer
->line_tree
, (BoxTypePtr
) Line
);
276 MOVE_LINE_LOWLEVEL (Line
, DeltaX
, DeltaY
);
277 r_insert_entry (Layer
->line_tree
, (BoxTypePtr
) Line
, 0);
278 ClearFromPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
281 DrawLine (Layer
, Line
, 0);
287 /* ---------------------------------------------------------------------------
291 MoveArc (LayerTypePtr Layer
, ArcTypePtr Arc
)
293 RestoreToPolygon (PCB
->Data
, ARC_TYPE
, Layer
, Arc
);
294 r_delete_entry (Layer
->arc_tree
, (BoxTypePtr
) Arc
);
298 MOVE_ARC_LOWLEVEL (Arc
, DeltaX
, DeltaY
);
299 DrawArc (Layer
, Arc
, 0);
304 MOVE_ARC_LOWLEVEL (Arc
, DeltaX
, DeltaY
);
306 r_insert_entry (Layer
->arc_tree
, (BoxTypePtr
) Arc
, 0);
307 ClearFromPolygon (PCB
->Data
, ARC_TYPE
, Layer
, Arc
);
311 /* ---------------------------------------------------------------------------
312 * moves a text object
315 MoveText (LayerTypePtr Layer
, TextTypePtr Text
)
317 RestoreToPolygon (PCB
->Data
, TEXT_TYPE
, Layer
, Text
);
318 r_delete_entry (Layer
->text_tree
, (BoxTypePtr
) Text
);
321 EraseText (Layer
, Text
);
322 MOVE_TEXT_LOWLEVEL (Text
, DeltaX
, DeltaY
);
323 DrawText (Layer
, Text
, 0);
327 MOVE_TEXT_LOWLEVEL (Text
, DeltaX
, DeltaY
);
328 r_insert_entry (Layer
->text_tree
, (BoxTypePtr
) Text
, 0);
329 ClearFromPolygon (PCB
->Data
, TEXT_TYPE
, Layer
, Text
);
333 /* ---------------------------------------------------------------------------
334 * low level routine to move a polygon
337 MovePolygonLowLevel (PolygonTypePtr Polygon
, LocationType DeltaX
,
340 POLYGONPOINT_LOOP (Polygon
);
342 MOVE (point
->X
, point
->Y
, DeltaX
, DeltaY
);
345 MOVE_BOX_LOWLEVEL (&Polygon
->BoundingBox
, DeltaX
, DeltaY
);
348 /* ---------------------------------------------------------------------------
352 MovePolygon (LayerTypePtr Layer
, PolygonTypePtr Polygon
)
356 ErasePolygon (Polygon
);
358 r_delete_entry (Layer
->polygon_tree
, (BoxType
*) Polygon
);
359 MovePolygonLowLevel (Polygon
, DeltaX
, DeltaY
);
360 r_insert_entry (Layer
->polygon_tree
, (BoxType
*) Polygon
, 0);
361 InitClip (PCB
->Data
, Layer
, Polygon
);
364 DrawPolygon (Layer
, Polygon
, 0);
370 /* ---------------------------------------------------------------------------
371 * moves one end of a line
374 MoveLinePoint (LayerTypePtr Layer
, LineTypePtr Line
, PointTypePtr Point
)
380 RestoreToPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
381 r_delete_entry (Layer
->line_tree
, &Line
->BoundingBox
);
382 MOVE (Point
->X
, Point
->Y
, DeltaX
, DeltaY
);
383 SetLineBoundingBox (Line
);
384 r_insert_entry (Layer
->line_tree
, &Line
->BoundingBox
, 0);
385 ClearFromPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
388 DrawLine (Layer
, Line
, 0);
393 else /* must be a rat */
396 EraseRat ((RatTypePtr
) Line
);
397 r_delete_entry (PCB
->Data
->rat_tree
, &Line
->BoundingBox
);
398 MOVE (Point
->X
, Point
->Y
, DeltaX
, DeltaY
);
399 SetLineBoundingBox (Line
);
400 r_insert_entry (PCB
->Data
->rat_tree
, &Line
->BoundingBox
, 0);
403 DrawRat ((RatTypePtr
) Line
, 0);
410 /* ---------------------------------------------------------------------------
411 * moves a polygon-point
414 MovePolygonPoint (LayerTypePtr Layer
, PolygonTypePtr Polygon
,
419 ErasePolygon (Polygon
);
421 r_delete_entry (Layer
->polygon_tree
, (BoxType
*) Polygon
);
422 MOVE (Point
->X
, Point
->Y
, DeltaX
, DeltaY
);
423 SetPolygonBoundingBox (Polygon
);
424 r_insert_entry (Layer
->polygon_tree
, (BoxType
*) Polygon
, 0);
425 RemoveExcessPolygonPoints (Layer
, Polygon
);
426 InitClip (PCB
->Data
, Layer
, Polygon
);
429 DrawPolygon (Layer
, Polygon
, 0);
435 /* ---------------------------------------------------------------------------
436 * moves a line between layers; lowlevel routines
439 MoveLineToLayerLowLevel (LayerTypePtr Source
, LineTypePtr Line
,
440 LayerTypePtr Destination
)
442 LineTypePtr
new = GetLineMemory (Destination
);
444 r_delete_entry (Source
->line_tree
, (BoxTypePtr
) Line
);
445 /* copy the data and remove it from the former layer */
447 *Line
= Source
->Line
[--Source
->LineN
];
448 r_substitute (Source
->line_tree
, (BoxType
*) & Source
->Line
[Source
->LineN
],
450 memset (&Source
->Line
[Source
->LineN
], 0, sizeof (LineType
));
451 if (!Destination
->line_tree
)
452 Destination
->line_tree
= r_create_tree (NULL
, 0, 0);
453 r_insert_entry (Destination
->line_tree
, (BoxTypePtr
) new, 0);
457 /* ---------------------------------------------------------------------------
458 * moves an arc between layers; lowlevel routines
461 MoveArcToLayerLowLevel (LayerTypePtr Source
, ArcTypePtr Arc
,
462 LayerTypePtr Destination
)
464 ArcTypePtr
new = GetArcMemory (Destination
);
466 r_delete_entry (Source
->arc_tree
, (BoxTypePtr
) Arc
);
467 /* copy the data and remove it from the former layer */
469 *Arc
= Source
->Arc
[--Source
->ArcN
];
470 r_substitute (Source
->arc_tree
, (BoxType
*) & Source
->Arc
[Source
->ArcN
],
472 memset (&Source
->Arc
[Source
->ArcN
], 0, sizeof (ArcType
));
473 if (!Destination
->arc_tree
)
474 Destination
->arc_tree
= r_create_tree (NULL
, 0, 0);
475 r_insert_entry (Destination
->arc_tree
, (BoxTypePtr
) new, 0);
480 /* ---------------------------------------------------------------------------
481 * moves an arc between layers
484 MoveArcToLayer (LayerTypePtr Layer
, ArcTypePtr Arc
)
488 if (TEST_FLAG (LOCKFLAG
, Arc
))
490 Message (_("Sorry, the object is locked\n"));
493 if (Dest
== Layer
&& Layer
->On
)
495 DrawArc (Layer
, Arc
, 0);
498 if (((long int) Dest
== -1) || Dest
== Layer
)
500 AddObjectToMoveToLayerUndoList (ARC_TYPE
, Layer
, Arc
, Arc
);
501 RestoreToPolygon (PCB
->Data
, ARC_TYPE
, Layer
, Arc
);
504 new = MoveArcToLayerLowLevel (Layer
, Arc
, Dest
);
505 ClearFromPolygon (PCB
->Data
, ARC_TYPE
, Dest
, Arc
);
507 DrawArc (Dest
, new, 0);
512 /* ---------------------------------------------------------------------------
513 * moves a line between layers
516 MoveRatToLayer (RatTypePtr Rat
)
519 //LocationType X1 = Rat->Point1.X, Y1 = Rat->Point1.Y;
520 //LocationType X1 = Rat->Point1.X, Y1 = Rat->Point1.Y;
522 // if we're on a pin, add a thermal
523 // else make a via and a wire, but 0-length wire not good
526 new = CreateNewLineOnLayer (Dest
, Rat
->Point1
.X
, Rat
->Point1
.Y
,
527 Rat
->Point2
.X
, Rat
->Point2
.Y
,
528 Settings
.LineThickness
, 2 * Settings
.Keepaway
,
530 if (TEST_FLAG (CLEARNEWFLAG
, PCB
))
531 SET_FLAG (CLEARLINEFLAG
, new);
534 AddObjectToCreateUndoList (LINE_TYPE
, Dest
, new, new);
537 MoveObjectToRemoveUndoList (RATLINE_TYPE
, Rat
, Rat
, Rat
);
538 DrawLine (Dest
, new, 0);
543 /* ---------------------------------------------------------------------------
544 * moves a line between layers
554 moveline_callback (const BoxType
* b
, void *cl
)
556 struct via_info
*i
= (struct via_info
*) cl
;
560 CreateNewVia (PCB
->Data
, i
->X
, i
->Y
,
561 Settings
.ViaThickness
, 2 * Settings
.Keepaway
,
562 NOFLAG
, Settings
.ViaDrillingHole
, NULL
,
563 NoFlags ())) != NULL
)
565 AddObjectToCreateUndoList (VIA_TYPE
, via
, via
, via
);
572 MoveLineToLayer (LayerTypePtr Layer
, LineTypePtr Line
)
574 struct via_info info
;
577 void *ptr1
, *ptr2
, *ptr3
;
579 if (TEST_FLAG (LOCKFLAG
, Line
))
581 Message (_("Sorry, the object is locked\n"));
584 if (Dest
== Layer
&& Layer
->On
)
586 DrawLine (Layer
, Line
, 0);
589 if (((long int) Dest
== -1) || Dest
== Layer
)
592 AddObjectToMoveToLayerUndoList (LINE_TYPE
, Layer
, Line
, Line
);
595 RestoreToPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
596 new = MoveLineToLayerLowLevel (Layer
, Line
, Dest
);
598 ClearFromPolygon (PCB
->Data
, LINE_TYPE
, Dest
, new);
600 DrawLine (Dest
, new, 0);
602 if (!PCB
->ViaOn
|| MoreToCome
||
603 GetLayerGroupNumberByPointer (Layer
) ==
604 GetLayerGroupNumberByPointer (Dest
) ||
605 TEST_SILK_LAYER(Layer
) ||
606 TEST_SILK_LAYER(Dest
))
608 /* consider via at Point1 */
609 sb
.X1
= new->Point1
.X
- new->Thickness
/ 2;
610 sb
.X2
= new->Point1
.X
+ new->Thickness
/ 2;
611 sb
.Y1
= new->Point1
.Y
- new->Thickness
/ 2;
612 sb
.Y2
= new->Point1
.Y
+ new->Thickness
/ 2;
613 if ((SearchObjectByLocation (PIN_TYPES
, &ptr1
, &ptr2
, &ptr3
,
614 new->Point1
.X
, new->Point1
.Y
,
615 Settings
.ViaThickness
/ 2) == NO_TYPE
))
617 info
.X
= new->Point1
.X
;
618 info
.Y
= new->Point1
.Y
;
619 if (setjmp (info
.env
) == 0)
620 r_search (Layer
->line_tree
, &sb
, NULL
, moveline_callback
, &info
);
622 /* consider via at Point2 */
623 sb
.X1
= new->Point2
.X
- new->Thickness
/ 2;
624 sb
.X2
= new->Point2
.X
+ new->Thickness
/ 2;
625 sb
.Y1
= new->Point2
.Y
- new->Thickness
/ 2;
626 sb
.Y2
= new->Point2
.Y
+ new->Thickness
/ 2;
627 if ((SearchObjectByLocation (PIN_TYPES
, &ptr1
, &ptr2
, &ptr3
,
628 new->Point2
.X
, new->Point2
.Y
,
629 Settings
.ViaThickness
/ 2) == NO_TYPE
))
631 info
.X
= new->Point2
.X
;
632 info
.Y
= new->Point2
.Y
;
633 if (setjmp (info
.env
) == 0)
634 r_search (Layer
->line_tree
, &sb
, NULL
, moveline_callback
, &info
);
640 /* ---------------------------------------------------------------------------
641 * moves a text object between layers; lowlevel routines
644 MoveTextToLayerLowLevel (LayerTypePtr Source
, TextTypePtr Text
,
645 LayerTypePtr Destination
)
647 TextTypePtr
new = GetTextMemory (Destination
);
649 RestoreToPolygon (PCB
->Data
, TEXT_TYPE
, Source
, Text
);
650 r_delete_entry (Source
->text_tree
, (BoxTypePtr
) Text
);
651 /* copy the data and remove it from the former layer */
653 *Text
= Source
->Text
[--Source
->TextN
];
654 r_substitute (Source
->text_tree
, (BoxType
*) & Source
->Text
[Source
->TextN
],
656 memset (&Source
->Text
[Source
->TextN
], 0, sizeof (TextType
));
657 if (GetLayerGroupNumberByNumber (max_layer
+ SOLDER_LAYER
) ==
658 GetLayerGroupNumberByPointer (Destination
))
659 SET_FLAG (ONSOLDERFLAG
, new);
661 CLEAR_FLAG (ONSOLDERFLAG
, new);
662 /* re-calculate the bounding box (it could be mirrored now) */
663 SetTextBoundingBox (&PCB
->Font
, new);
664 if (!Destination
->text_tree
)
665 Destination
->text_tree
= r_create_tree (NULL
, 0, 0);
666 r_insert_entry (Destination
->text_tree
, (BoxTypePtr
) new, 0);
667 ClearFromPolygon (PCB
->Data
, TEXT_TYPE
, Destination
, new);
671 /* ---------------------------------------------------------------------------
672 * moves a text object between layers
675 MoveTextToLayer (LayerTypePtr Layer
, TextTypePtr Text
)
679 if (TEST_FLAG (LOCKFLAG
, Text
))
681 Message (_("Sorry, the object is locked\n"));
686 AddObjectToMoveToLayerUndoList (TEXT_TYPE
, Layer
, Text
, Text
);
688 EraseText (Layer
, Text
);
689 new = MoveTextToLayerLowLevel (Layer
, Text
, Dest
);
691 DrawText (Dest
, new, 0);
692 if (Layer
->On
|| Dest
->On
)
699 /* ---------------------------------------------------------------------------
700 * moves a polygon between layers; lowlevel routines
703 MovePolygonToLayerLowLevel (LayerTypePtr Source
, PolygonTypePtr Polygon
,
704 LayerTypePtr Destination
)
706 PolygonTypePtr
new = GetPolygonMemory (Destination
);
708 r_delete_entry (Source
->polygon_tree
, (BoxType
*) Polygon
);
709 /* copy the data and remove it from the former layer */
711 *Polygon
= Source
->Polygon
[--Source
->PolygonN
];
712 r_substitute (Source
->polygon_tree
,
713 (BoxType
*) & Source
->Polygon
[Source
->PolygonN
],
714 (BoxType
*) Polygon
);
715 memset (&Source
->Polygon
[Source
->PolygonN
], 0, sizeof (PolygonType
));
716 if (!Destination
->polygon_tree
)
717 Destination
->polygon_tree
= r_create_tree (NULL
, 0, 0);
718 r_insert_entry (Destination
->polygon_tree
, (BoxType
*) new, 0);
726 PolygonTypePtr polygon
;
730 mptl_pin_callback (const BoxType
*b
, void *cl
)
732 struct mptlc
*d
= (struct mptlc
*) cl
;
733 PinTypePtr pin
= (PinTypePtr
) b
;
734 if (!TEST_THERM (d
->snum
, pin
) || !
735 IsPointInPolygon (pin
->X
, pin
->Y
, pin
->Thickness
+ pin
->Clearance
+ 2,
738 if (d
->type
== PIN_TYPE
)
739 AddObjectToFlagUndoList (PIN_TYPE
, pin
->Element
, pin
, pin
);
741 AddObjectToFlagUndoList (VIA_TYPE
, pin
, pin
, pin
);
742 ASSIGN_THERM (d
->dnum
, GET_THERM (d
->snum
, pin
), pin
);
743 CLEAR_THERM (d
->snum
, pin
);
747 /* ---------------------------------------------------------------------------
748 * moves a polygon between layers
751 MovePolygonToLayer (LayerTypePtr Layer
, PolygonTypePtr Polygon
)
756 if (TEST_FLAG (LOCKFLAG
, Polygon
))
758 Message (_("Sorry, the object is locked\n"));
761 if (((long int) Dest
== -1) || (Layer
== Dest
))
763 AddObjectToMoveToLayerUndoList (POLYGON_TYPE
, Layer
, Polygon
, Polygon
);
765 ErasePolygon (Polygon
);
766 /* Move all of the thermals with the polygon */
767 d
.snum
= GetLayerNumber (PCB
->Data
, Layer
);
768 d
.dnum
= GetLayerNumber (PCB
->Data
, Dest
);
771 r_search (PCB
->Data
->pin_tree
, &Polygon
->BoundingBox
, NULL
, mptl_pin_callback
, &d
);
773 r_search (PCB
->Data
->via_tree
, &Polygon
->BoundingBox
, NULL
, mptl_pin_callback
, &d
);
774 new = MovePolygonToLayerLowLevel (Layer
, Polygon
, Dest
);
775 InitClip (PCB
->Data
, Dest
, new);
778 DrawPolygon (Dest
, new, 0);
784 /* ---------------------------------------------------------------------------
785 * moves the object identified by its data pointers and the type
786 * not we don't bump the undo serial number
789 MoveObject (int Type
, void *Ptr1
, void *Ptr2
, void *Ptr3
,
790 LocationType DX
, LocationType DY
)
796 AddObjectToMoveUndoList (Type
, Ptr1
, Ptr2
, Ptr3
, DX
, DY
);
797 result
= ObjectOperation (&MoveFunctions
, Type
, Ptr1
, Ptr2
, Ptr3
);
801 /* ---------------------------------------------------------------------------
802 * moves the object identified by its data pointers and the type
803 * as well as all attached rubberband lines
806 MoveObjectAndRubberband (int Type
, void *Ptr1
, void *Ptr2
, void *Ptr3
,
807 LocationType DX
, LocationType DY
)
809 RubberbandTypePtr ptr
;
815 if (DX
== 0 && DY
== 0)
818 /* move all the lines... and reset the counter */
819 ptr
= Crosshair
.AttachedObject
.Rubberband
;
820 while (Crosshair
.AttachedObject
.RubberbandN
)
822 /* first clear any marks that we made in the line flags */
823 CLEAR_FLAG (RUBBERENDFLAG
, ptr
->Line
);
824 AddObjectToMoveUndoList (LINEPOINT_TYPE
,
825 ptr
->Layer
, ptr
->Line
, ptr
->MovedPoint
, DX
,
827 MoveLinePoint (ptr
->Layer
, ptr
->Line
, ptr
->MovedPoint
);
828 Crosshair
.AttachedObject
.RubberbandN
--;
832 AddObjectToMoveUndoList (Type
, Ptr1
, Ptr2
, Ptr3
, DX
, DY
);
833 ptr2
= ObjectOperation (&MoveFunctions
, Type
, Ptr1
, Ptr2
, Ptr3
);
834 IncrementUndoSerialNumber ();
838 /* ---------------------------------------------------------------------------
839 * moves the object identified by its data pointers and the type
840 * to a new layer without changing it's position
843 MoveObjectToLayer (int Type
, void *Ptr1
, void *Ptr2
, void *Ptr3
,
844 LayerTypePtr Target
, Boolean enmasse
)
848 /* setup global identifiers */
850 MoreToCome
= enmasse
;
851 result
= ObjectOperation (&MoveToLayerFunctions
, Type
, Ptr1
, Ptr2
, Ptr3
);
852 IncrementUndoSerialNumber ();
856 /* ---------------------------------------------------------------------------
857 * moves the selected objects to a new layer without changing their
861 MoveSelectedObjectsToLayer (LayerTypePtr Target
)
865 /* setup global identifiers */
868 changed
= SelectedOperation (&MoveToLayerFunctions
, True
, ALL_TYPES
);
869 /* passing True to above operation causes Undoserial to auto-increment */
873 /* ---------------------------------------------------------------------------
874 * moves the selected layers to a new index in the layer list.
878 move_one_thermal (int old_index
, int new_index
, PinType
*pin
)
881 int oi
=old_index
, ni
=new_index
;
884 t1
= GET_THERM (old_index
, pin
);
887 oi
= MAX_LAYER
-1; /* inserting a layer */
889 ni
= MAX_LAYER
-1; /* deleting a layer */
893 for (i
=oi
; i
<ni
; i
++)
894 ASSIGN_THERM (i
, GET_THERM (i
+1, pin
), pin
);
898 for (i
=oi
; i
>ni
; i
--)
899 ASSIGN_THERM (i
, GET_THERM (i
-1, pin
), pin
);
903 ASSIGN_THERM (new_index
, t1
, pin
);
905 ASSIGN_THERM (ni
, 0, pin
);
909 move_all_thermals (int old_index
, int new_index
)
911 VIA_LOOP (PCB
->Data
);
913 move_one_thermal (old_index
, new_index
, via
);
917 ALLPIN_LOOP (PCB
->Data
);
919 move_one_thermal (old_index
, new_index
, pin
);
926 MoveLayer (int old_index
, int new_index
)
928 int groups
[MAX_LAYER
+ 2], l
, g
;
929 LayerType saved_layer
;
932 AddLayerChangeToUndoList (old_index
, new_index
);
933 IncrementUndoSerialNumber ();
935 if (old_index
< -1 || old_index
>= max_layer
)
937 Message ("Invalid old layer %d for move: must be -1..%d\n",
938 old_index
, max_layer
- 1);
941 if (new_index
< -1 || new_index
> max_layer
|| new_index
>= MAX_LAYER
)
943 Message ("Invalid new layer %d for move: must be -1..%d\n",
944 new_index
, max_layer
);
947 if (old_index
== new_index
)
950 for (g
= 0; g
< MAX_LAYER
; g
++)
951 for (l
= 0; l
< PCB
->LayerGroups
.Number
[g
]; l
++)
952 groups
[PCB
->LayerGroups
.Entries
[g
][l
]] = g
;
957 if (max_layer
== MAX_LAYER
)
959 Message ("No room for new layers\n");
962 /* Create a new layer at new_index. */
963 lp
= &PCB
->Data
->Layer
[new_index
];
964 memmove (&PCB
->Data
->Layer
[new_index
+ 1],
965 &PCB
->Data
->Layer
[new_index
],
966 (max_layer
- new_index
+ 2) * sizeof (LayerType
));
967 memmove (&groups
[new_index
+ 1],
969 (max_layer
- new_index
+ 2) * sizeof (int));
971 memset (lp
, 0, sizeof (LayerType
));
973 lp
->Name
= MyStrdup ("New Layer", "MoveLayer");
974 lp
->Color
= Settings
.LayerColor
[new_index
];
975 lp
->SelectedColor
= Settings
.LayerSelectedColor
[new_index
];
976 for (l
= 0; l
< max_layer
; l
++)
977 if (LayerStack
[l
] >= new_index
)
979 LayerStack
[max_layer
- 1] = new_index
;
981 else if (new_index
== -1)
983 /* Delete the layer at old_index */
984 memmove (&PCB
->Data
->Layer
[old_index
],
985 &PCB
->Data
->Layer
[old_index
+ 1],
986 (max_layer
- old_index
+ 2 - 1) * sizeof (LayerType
));
987 memset (&PCB
->Data
->Layer
[max_layer
+ 1], 0, sizeof (LayerType
));
988 memmove (&groups
[old_index
],
989 &groups
[old_index
+ 1],
990 (max_layer
- old_index
+ 2 - 1) * sizeof (int));
991 for (l
= 0; l
< max_layer
; l
++)
992 if (LayerStack
[l
] == old_index
)
993 memmove (LayerStack
+ l
,
995 (max_layer
- l
- 1) * sizeof (LayerStack
[0]));
997 for (l
= 0; l
< max_layer
; l
++)
998 if (LayerStack
[l
] > old_index
)
1003 /* Move an existing layer */
1004 memcpy (&saved_layer
, &PCB
->Data
->Layer
[old_index
], sizeof (LayerType
));
1005 saved_group
= groups
[old_index
];
1006 if (old_index
< new_index
)
1008 memmove (&PCB
->Data
->Layer
[old_index
],
1009 &PCB
->Data
->Layer
[old_index
+ 1],
1010 (new_index
- old_index
) * sizeof (LayerType
));
1011 memmove (&groups
[old_index
],
1012 &groups
[old_index
+ 1],
1013 (new_index
- old_index
) * sizeof (int));
1017 memmove (&PCB
->Data
->Layer
[new_index
+ 1],
1018 &PCB
->Data
->Layer
[new_index
],
1019 (old_index
- new_index
) * sizeof (LayerType
));
1020 memmove (&groups
[new_index
+ 1],
1022 (old_index
- new_index
) * sizeof (int));
1024 memcpy (&PCB
->Data
->Layer
[new_index
], &saved_layer
, sizeof (LayerType
));
1025 groups
[new_index
] = saved_group
;
1028 move_all_thermals(old_index
, new_index
);
1030 for (g
= 0; g
< MAX_LAYER
; g
++)
1031 PCB
->LayerGroups
.Number
[g
] = 0;
1032 for (l
= 0; l
< max_layer
+ 2; l
++)
1036 i
= PCB
->LayerGroups
.Number
[g
]++;
1037 PCB
->LayerGroups
.Entries
[g
][i
] = l
;
1040 for (g
= 0; g
< MAX_LAYER
; g
++)
1041 if (PCB
->LayerGroups
.Number
[g
] == 0)
1043 memmove (&PCB
->LayerGroups
.Number
[g
],
1044 &PCB
->LayerGroups
.Number
[g
+ 1],
1045 (MAX_LAYER
- g
- 1) * sizeof (PCB
->LayerGroups
.Number
[g
]));
1046 memmove (&PCB
->LayerGroups
.Entries
[g
],
1047 &PCB
->LayerGroups
.Entries
[g
+ 1],
1048 (MAX_LAYER
- g
- 1) * sizeof (PCB
->LayerGroups
.Entries
[g
]));
1051 hid_action ("LayersChanged");
1052 gui
->invalidate_all ();
1056 /* --------------------------------------------------------------------------- */
1058 static const char movelayer_syntax
[] = "MoveLayer(old,new)";
1060 static const char movelayer_help
[] = "Moves/Creates/Deletes Layers";
1062 /* %start-doc actions MoveLayer
1064 Moves a layer, creates a new layer, or deletes a layer.
1069 The is the layer number to act upon. Allowed values are:
1073 Currently selected layer.
1079 An existing layer number.
1084 Specifies where to move the layer to. Allowed values are:
1093 Moves the layer down.
1096 Creates a new layer.
1105 MoveLayerAction (int argc
, char **argv
, int x
, int y
)
1107 int old_index
, new_index
;
1112 Message ("Usage; MoveLayer(old,new)");
1116 if (strcmp (argv
[0], "c") == 0)
1117 old_index
= INDEXOFCURRENT
;
1119 old_index
= atoi (argv
[0]);
1121 if (strcmp (argv
[1], "c") == 0)
1123 new_index
= INDEXOFCURRENT
;
1127 else if (strcmp (argv
[1], "up") == 0)
1129 new_index
= INDEXOFCURRENT
- 1;
1132 new_top
= new_index
;
1134 else if (strcmp (argv
[1], "down") == 0)
1136 new_index
= INDEXOFCURRENT
+ 1;
1137 if (new_index
>= max_layer
)
1139 new_top
= new_index
;
1142 new_index
= atoi (argv
[1]);
1144 if (MoveLayer (old_index
, new_index
))
1147 if (new_index
== -1)
1149 new_top
= old_index
;
1150 if (new_top
>= max_layer
)
1152 new_index
= new_top
;
1154 if (old_index
== -1)
1155 new_top
= new_index
;
1158 ChangeGroupVisibility (new_index
, 1, 1);
1163 HID_Action move_action_list
[] = {
1164 {"MoveLayer", 0, MoveLayerAction
,
1165 movelayer_help
, movelayer_syntax
}
1168 REGISTER_ACTIONS (move_action_list
)