4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
28 /* functions used to move pins, elements ...
41 #include "crosshair.h"
55 #ifdef HAVE_LIBDMALLOC
59 /* ---------------------------------------------------------------------------
60 * some local prototypes
62 static void *MoveElementName (ElementType
*);
63 static void *MoveElement (ElementType
*);
64 static void *MoveVia (PinType
*);
65 static void *MoveLine (LayerType
*, LineType
*);
66 static void *MoveArc (LayerType
*, ArcType
*);
67 static void *MoveText (LayerType
*, TextType
*);
68 static void *MovePolygon (LayerType
*, PolygonType
*);
69 static void *MoveLinePoint (LayerType
*, LineType
*, PointType
*);
70 static void *MovePolygonPoint (LayerType
*, PolygonType
*, PointType
*);
71 static void *MoveLineToLayer (LayerType
*, LineType
*);
72 static void *MoveArcToLayer (LayerType
*, ArcType
*);
73 static void *MoveRatToLayer (RatType
*);
74 static void *MoveTextToLayer (LayerType
*, TextType
*);
75 static void *MovePolygonToLayer (LayerType
*, PolygonType
*);
77 /* ---------------------------------------------------------------------------
78 * some local identifiers
80 static Coord DeltaX
, DeltaY
; /* used by local routines as offset */
81 static LayerType
*Dest
;
82 static bool MoreToCome
;
83 static ObjectFunctionType MoveFunctions
= {
96 }, MoveToLayerFunctions
=
102 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, MoveArcToLayer
, MoveRatToLayer
};
104 /* ---------------------------------------------------------------------------
105 * moves a element by +-X and +-Y
108 MoveElementLowLevel (DataType
*Data
, ElementType
*Element
,
112 r_delete_entry (Data
->element_tree
, (BoxType
*)Element
);
113 ELEMENTLINE_LOOP (Element
);
115 MOVE_LINE_LOWLEVEL (line
, DX
, DY
);
122 r_delete_entry (Data
->pin_tree
, (BoxType
*)pin
);
123 RestoreToPolygon (Data
, PIN_TYPE
, Element
, pin
);
125 MOVE_PIN_LOWLEVEL (pin
, DX
, DY
);
128 r_insert_entry (Data
->pin_tree
, (BoxType
*)pin
, 0);
129 ClearFromPolygon (Data
, PIN_TYPE
, Element
, pin
);
137 r_delete_entry (Data
->pad_tree
, (BoxType
*)pad
);
138 RestoreToPolygon (Data
, PAD_TYPE
, Element
, pad
);
140 MOVE_PAD_LOWLEVEL (pad
, DX
, DY
);
143 r_insert_entry (Data
->pad_tree
, (BoxType
*)pad
, 0);
144 ClearFromPolygon (Data
, PAD_TYPE
, Element
, pad
);
150 MOVE_ARC_LOWLEVEL (arc
, DX
, DY
);
153 ELEMENTTEXT_LOOP (Element
);
155 if (Data
&& Data
->name_tree
[n
])
156 r_delete_entry (PCB
->Data
->name_tree
[n
], (BoxType
*)text
);
157 MOVE_TEXT_LOWLEVEL (text
, DX
, DY
);
158 if (Data
&& Data
->name_tree
[n
])
159 r_insert_entry (PCB
->Data
->name_tree
[n
], (BoxType
*)text
, 0);
162 MOVE_BOX_LOWLEVEL (&Element
->BoundingBox
, DX
, DY
);
163 MOVE_BOX_LOWLEVEL (&Element
->VBox
, DX
, DY
);
164 MOVE (Element
->MarkX
, Element
->MarkY
, DX
, DY
);
166 r_insert_entry (Data
->element_tree
, (BoxType
*)Element
, 0);
169 /* ----------------------------------------------------------------------
170 * moves all names of an element to a new position
173 MoveElementName (ElementType
*Element
)
175 if (PCB
->ElementOn
&& (FRONT (Element
) || PCB
->InvisibleObjectsOn
))
177 EraseElementName (Element
);
178 ELEMENTTEXT_LOOP (Element
);
180 if (PCB
->Data
->name_tree
[n
])
181 r_delete_entry (PCB
->Data
->name_tree
[n
], (BoxType
*)text
);
182 MOVE_TEXT_LOWLEVEL (text
, DeltaX
, DeltaY
);
183 if (PCB
->Data
->name_tree
[n
])
184 r_insert_entry (PCB
->Data
->name_tree
[n
], (BoxType
*)text
, 0);
187 DrawElementName (Element
);
192 ELEMENTTEXT_LOOP (Element
);
194 if (PCB
->Data
->name_tree
[n
])
195 r_delete_entry (PCB
->Data
->name_tree
[n
], (BoxType
*)text
);
196 MOVE_TEXT_LOWLEVEL (text
, DeltaX
, DeltaY
);
197 if (PCB
->Data
->name_tree
[n
])
198 r_insert_entry (PCB
->Data
->name_tree
[n
], (BoxType
*)text
, 0);
205 /* ---------------------------------------------------------------------------
209 MoveElement (ElementType
*Element
)
211 bool didDraw
= false;
213 if (PCB
->ElementOn
&& (FRONT (Element
) || PCB
->InvisibleObjectsOn
))
215 EraseElement (Element
);
216 MoveElementLowLevel (PCB
->Data
, Element
, DeltaX
, DeltaY
);
217 DrawElementName (Element
);
218 DrawElementPackage (Element
);
224 EraseElementPinsAndPads (Element
);
225 MoveElementLowLevel (PCB
->Data
, Element
, DeltaX
, DeltaY
);
229 DrawElementPinsAndPads (Element
);
237 /* ---------------------------------------------------------------------------
241 MoveVia (PinType
*Via
)
243 r_delete_entry (PCB
->Data
->via_tree
, (BoxType
*)Via
);
244 RestoreToPolygon (PCB
->Data
, VIA_TYPE
, Via
, Via
);
245 MOVE_VIA_LOWLEVEL (Via
, DeltaX
, DeltaY
);
248 r_insert_entry (PCB
->Data
->via_tree
, (BoxType
*)Via
, 0);
249 ClearFromPolygon (PCB
->Data
, VIA_TYPE
, Via
, Via
);
258 /* ---------------------------------------------------------------------------
262 MoveLine (LayerType
*Layer
, LineType
*Line
)
266 RestoreToPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
267 r_delete_entry (Layer
->line_tree
, (BoxType
*)Line
);
268 MOVE_LINE_LOWLEVEL (Line
, DeltaX
, DeltaY
);
269 r_insert_entry (Layer
->line_tree
, (BoxType
*)Line
, 0);
270 ClearFromPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
273 DrawLine (Layer
, Line
);
279 /* ---------------------------------------------------------------------------
283 MoveArc (LayerType
*Layer
, ArcType
*Arc
)
285 RestoreToPolygon (PCB
->Data
, ARC_TYPE
, Layer
, Arc
);
286 r_delete_entry (Layer
->arc_tree
, (BoxType
*)Arc
);
290 MOVE_ARC_LOWLEVEL (Arc
, DeltaX
, DeltaY
);
291 DrawArc (Layer
, Arc
);
296 MOVE_ARC_LOWLEVEL (Arc
, DeltaX
, DeltaY
);
298 r_insert_entry (Layer
->arc_tree
, (BoxType
*)Arc
, 0);
299 ClearFromPolygon (PCB
->Data
, ARC_TYPE
, Layer
, Arc
);
303 /* ---------------------------------------------------------------------------
304 * moves a text object
307 MoveText (LayerType
*Layer
, TextType
*Text
)
309 RestoreToPolygon (PCB
->Data
, TEXT_TYPE
, Layer
, Text
);
310 r_delete_entry (Layer
->text_tree
, (BoxType
*)Text
);
313 EraseText (Layer
, Text
);
314 MOVE_TEXT_LOWLEVEL (Text
, DeltaX
, DeltaY
);
315 DrawText (Layer
, Text
);
319 MOVE_TEXT_LOWLEVEL (Text
, DeltaX
, DeltaY
);
320 r_insert_entry (Layer
->text_tree
, (BoxType
*)Text
, 0);
321 ClearFromPolygon (PCB
->Data
, TEXT_TYPE
, Layer
, Text
);
325 /* ---------------------------------------------------------------------------
326 * low level routine to move a polygon
329 MovePolygonLowLevel (PolygonType
*Polygon
, Coord DeltaX
, Coord DeltaY
)
331 POLYGONPOINT_LOOP (Polygon
);
333 MOVE (point
->X
, point
->Y
, DeltaX
, DeltaY
);
336 MOVE_BOX_LOWLEVEL (&Polygon
->BoundingBox
, DeltaX
, DeltaY
);
339 /* ---------------------------------------------------------------------------
343 MovePolygon (LayerType
*Layer
, PolygonType
*Polygon
)
347 ErasePolygon (Polygon
);
349 r_delete_entry (Layer
->polygon_tree
, (BoxType
*)Polygon
);
350 MovePolygonLowLevel (Polygon
, DeltaX
, DeltaY
);
351 r_insert_entry (Layer
->polygon_tree
, (BoxType
*)Polygon
, 0);
352 InitClip (PCB
->Data
, Layer
, Polygon
);
355 DrawPolygon (Layer
, Polygon
);
361 /* ---------------------------------------------------------------------------
362 * moves one end of a line
365 MoveLinePoint (LayerType
*Layer
, LineType
*Line
, PointType
*Point
)
371 RestoreToPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
372 r_delete_entry (Layer
->line_tree
, &Line
->BoundingBox
);
373 MOVE (Point
->X
, Point
->Y
, DeltaX
, DeltaY
);
374 SetLineBoundingBox (Line
);
375 r_insert_entry (Layer
->line_tree
, &Line
->BoundingBox
, 0);
376 ClearFromPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
379 DrawLine (Layer
, Line
);
384 else /* must be a rat */
387 EraseRat ((RatType
*) Line
);
388 r_delete_entry (PCB
->Data
->rat_tree
, &Line
->BoundingBox
);
389 MOVE (Point
->X
, Point
->Y
, DeltaX
, DeltaY
);
390 SetLineBoundingBox (Line
);
391 r_insert_entry (PCB
->Data
->rat_tree
, &Line
->BoundingBox
, 0);
394 DrawRat ((RatType
*) Line
);
401 /* ---------------------------------------------------------------------------
402 * moves a polygon-point
405 MovePolygonPoint (LayerType
*Layer
, PolygonType
*Polygon
,
410 ErasePolygon (Polygon
);
412 r_delete_entry (Layer
->polygon_tree
, (BoxType
*)Polygon
);
413 MOVE (Point
->X
, Point
->Y
, DeltaX
, DeltaY
);
414 SetPolygonBoundingBox (Polygon
);
415 r_insert_entry (Layer
->polygon_tree
, (BoxType
*)Polygon
, 0);
416 RemoveExcessPolygonPoints (Layer
, Polygon
);
417 InitClip (PCB
->Data
, Layer
, Polygon
);
420 DrawPolygon (Layer
, Polygon
);
426 /* ---------------------------------------------------------------------------
427 * moves a line between layers; lowlevel routines
430 MoveLineToLayerLowLevel (LayerType
*Source
, LineType
*line
,
431 LayerType
*Destination
)
433 r_delete_entry (Source
->line_tree
, (BoxType
*)line
);
435 Source
->Line
= g_list_remove (Source
->Line
, line
);
437 Destination
->Line
= g_list_append (Destination
->Line
, line
);
438 Destination
->LineN
++;
440 if (!Destination
->line_tree
)
441 Destination
->line_tree
= r_create_tree (NULL
, 0, 0);
442 r_insert_entry (Destination
->line_tree
, (BoxType
*)line
, 0);
446 /* ---------------------------------------------------------------------------
447 * moves an arc between layers; lowlevel routines
450 MoveArcToLayerLowLevel (LayerType
*Source
, ArcType
*arc
,
451 LayerType
*Destination
)
453 r_delete_entry (Source
->arc_tree
, (BoxType
*)arc
);
455 Source
->Arc
= g_list_remove (Source
->Arc
, arc
);
457 Destination
->Arc
= g_list_append (Destination
->Arc
, arc
);
458 Destination
->ArcN
++;
460 if (!Destination
->arc_tree
)
461 Destination
->arc_tree
= r_create_tree (NULL
, 0, 0);
462 r_insert_entry (Destination
->arc_tree
, (BoxType
*)arc
, 0);
467 /* ---------------------------------------------------------------------------
468 * moves an arc between layers
471 MoveArcToLayer (LayerType
*Layer
, ArcType
*Arc
)
475 if (TEST_FLAG (LOCKFLAG
, Arc
))
477 Message (_("Sorry, the object is locked\n"));
480 if (Dest
== Layer
&& Layer
->On
)
482 DrawArc (Layer
, Arc
);
485 if (((long int) Dest
== -1) || Dest
== Layer
)
487 AddObjectToMoveToLayerUndoList (ARC_TYPE
, Layer
, Arc
, Arc
);
488 RestoreToPolygon (PCB
->Data
, ARC_TYPE
, Layer
, Arc
);
491 newone
= (ArcType
*)MoveArcToLayerLowLevel (Layer
, Arc
, Dest
);
492 ClearFromPolygon (PCB
->Data
, ARC_TYPE
, Dest
, Arc
);
494 DrawArc (Dest
, newone
);
499 /* ---------------------------------------------------------------------------
500 * moves a line between layers
503 MoveRatToLayer (RatType
*Rat
)
506 //Coord X1 = Rat->Point1.X, Y1 = Rat->Point1.Y;
507 //Coord X1 = Rat->Point1.X, Y1 = Rat->Point1.Y;
509 // if we're on a pin, add a thermal
510 // else make a via and a wire, but 0-length wire not good
513 newone
= CreateNewLineOnLayer (Dest
, Rat
->Point1
.X
, Rat
->Point1
.Y
,
514 Rat
->Point2
.X
, Rat
->Point2
.Y
,
515 Settings
.LineThickness
, 2 * Settings
.Keepaway
,
517 if (TEST_FLAG (CLEARNEWFLAG
, PCB
))
518 SET_FLAG (CLEARLINEFLAG
, newone
);
521 AddObjectToCreateUndoList (LINE_TYPE
, Dest
, newone
, newone
);
524 MoveObjectToRemoveUndoList (RATLINE_TYPE
, Rat
, Rat
, Rat
);
525 DrawLine (Dest
, newone
);
530 /* ---------------------------------------------------------------------------
531 * moves a line between layers
541 moveline_callback (const BoxType
* b
, void *cl
)
543 struct via_info
*i
= (struct via_info
*) cl
;
547 CreateNewVia (PCB
->Data
, i
->X
, i
->Y
,
548 Settings
.ViaThickness
, 2 * Settings
.Keepaway
,
549 NOFLAG
, Settings
.ViaDrillingHole
, NULL
,
550 NoFlags ())) != NULL
)
552 AddObjectToCreateUndoList (VIA_TYPE
, via
, via
, via
);
559 MoveLineToLayer (LayerType
*Layer
, LineType
*Line
)
561 struct via_info info
;
564 void *ptr1
, *ptr2
, *ptr3
;
566 if (TEST_FLAG (LOCKFLAG
, Line
))
568 Message (_("Sorry, the object is locked\n"));
571 if (Dest
== Layer
&& Layer
->On
)
573 DrawLine (Layer
, Line
);
576 if (((long int) Dest
== -1) || Dest
== Layer
)
579 AddObjectToMoveToLayerUndoList (LINE_TYPE
, Layer
, Line
, Line
);
582 RestoreToPolygon (PCB
->Data
, LINE_TYPE
, Layer
, Line
);
583 newone
= (LineType
*)MoveLineToLayerLowLevel (Layer
, Line
, Dest
);
585 ClearFromPolygon (PCB
->Data
, LINE_TYPE
, Dest
, newone
);
587 DrawLine (Dest
, newone
);
589 if (!PCB
->ViaOn
|| MoreToCome
||
590 GetLayerGroupNumberByPointer (Layer
) ==
591 GetLayerGroupNumberByPointer (Dest
) ||
592 TEST_SILK_LAYER(Layer
) ||
593 TEST_SILK_LAYER(Dest
))
595 /* consider via at Point1 */
596 sb
.X1
= newone
->Point1
.X
- newone
->Thickness
/ 2;
597 sb
.X2
= newone
->Point1
.X
+ newone
->Thickness
/ 2;
598 sb
.Y1
= newone
->Point1
.Y
- newone
->Thickness
/ 2;
599 sb
.Y2
= newone
->Point1
.Y
+ newone
->Thickness
/ 2;
600 if ((SearchObjectByLocation (PIN_TYPES
, &ptr1
, &ptr2
, &ptr3
,
601 newone
->Point1
.X
, newone
->Point1
.Y
,
602 Settings
.ViaThickness
/ 2) == NO_TYPE
))
604 info
.X
= newone
->Point1
.X
;
605 info
.Y
= newone
->Point1
.Y
;
606 if (setjmp (info
.env
) == 0)
607 r_search (Layer
->line_tree
, &sb
, NULL
, moveline_callback
, &info
);
609 /* consider via at Point2 */
610 sb
.X1
= newone
->Point2
.X
- newone
->Thickness
/ 2;
611 sb
.X2
= newone
->Point2
.X
+ newone
->Thickness
/ 2;
612 sb
.Y1
= newone
->Point2
.Y
- newone
->Thickness
/ 2;
613 sb
.Y2
= newone
->Point2
.Y
+ newone
->Thickness
/ 2;
614 if ((SearchObjectByLocation (PIN_TYPES
, &ptr1
, &ptr2
, &ptr3
,
615 newone
->Point2
.X
, newone
->Point2
.Y
,
616 Settings
.ViaThickness
/ 2) == NO_TYPE
))
618 info
.X
= newone
->Point2
.X
;
619 info
.Y
= newone
->Point2
.Y
;
620 if (setjmp (info
.env
) == 0)
621 r_search (Layer
->line_tree
, &sb
, NULL
, moveline_callback
, &info
);
627 /* ---------------------------------------------------------------------------
628 * moves a text object between layers; lowlevel routines
631 MoveTextToLayerLowLevel (LayerType
*Source
, TextType
*text
,
632 LayerType
*Destination
)
634 RestoreToPolygon (PCB
->Data
, TEXT_TYPE
, Source
, text
);
635 r_delete_entry (Source
->text_tree
, (BoxType
*)text
);
637 Source
->Text
= g_list_remove (Source
->Text
, text
);
639 Destination
->Text
= g_list_append (Destination
->Text
, text
);
640 Destination
->TextN
++;
642 if (GetLayerGroupNumberByNumber (solder_silk_layer
) ==
643 GetLayerGroupNumberByPointer (Destination
))
644 SET_FLAG (ONSOLDERFLAG
, text
);
646 CLEAR_FLAG (ONSOLDERFLAG
, text
);
648 /* re-calculate the bounding box (it could be mirrored now) */
649 SetTextBoundingBox (&PCB
->Font
, text
);
650 if (!Destination
->text_tree
)
651 Destination
->text_tree
= r_create_tree (NULL
, 0, 0);
652 r_insert_entry (Destination
->text_tree
, (BoxType
*)text
, 0);
653 ClearFromPolygon (PCB
->Data
, TEXT_TYPE
, Destination
, text
);
658 /* ---------------------------------------------------------------------------
659 * moves a text object between layers
662 MoveTextToLayer (LayerType
*layer
, TextType
*text
)
664 if (TEST_FLAG (LOCKFLAG
, text
))
666 Message (_("Sorry, the object is locked\n"));
671 AddObjectToMoveToLayerUndoList (TEXT_TYPE
, layer
, text
, text
);
673 EraseText (layer
, text
);
674 text
= MoveTextToLayerLowLevel (layer
, text
, Dest
);
676 DrawText (Dest
, text
);
677 if (layer
->On
|| Dest
->On
)
683 /* ---------------------------------------------------------------------------
684 * moves a polygon between layers; lowlevel routines
687 MovePolygonToLayerLowLevel (LayerType
*Source
, PolygonType
*polygon
,
688 LayerType
*Destination
)
690 r_delete_entry (Source
->polygon_tree
, (BoxType
*)polygon
);
692 Source
->Polygon
= g_list_remove (Source
->Polygon
, polygon
);
694 Destination
->Polygon
= g_list_append (Destination
->Polygon
, polygon
);
695 Destination
->PolygonN
++;
697 if (!Destination
->polygon_tree
)
698 Destination
->polygon_tree
= r_create_tree (NULL
, 0, 0);
699 r_insert_entry (Destination
->polygon_tree
, (BoxType
*)polygon
, 0);
708 PolygonType
*polygon
;
712 mptl_pin_callback (const BoxType
*b
, void *cl
)
714 struct mptlc
*d
= (struct mptlc
*) cl
;
715 PinType
*pin
= (PinType
*) b
;
716 if (!TEST_THERM (d
->snum
, pin
) || !
717 IsPointInPolygon (pin
->X
, pin
->Y
, pin
->Thickness
+ pin
->Clearance
+ 2,
720 if (d
->type
== PIN_TYPE
)
721 AddObjectToFlagUndoList (PIN_TYPE
, pin
->Element
, pin
, pin
);
723 AddObjectToFlagUndoList (VIA_TYPE
, pin
, pin
, pin
);
724 ASSIGN_THERM (d
->dnum
, GET_THERM (d
->snum
, pin
), pin
);
725 CLEAR_THERM (d
->snum
, pin
);
729 /* ---------------------------------------------------------------------------
730 * moves a polygon between layers
733 MovePolygonToLayer (LayerType
*Layer
, PolygonType
*Polygon
)
738 if (TEST_FLAG (LOCKFLAG
, Polygon
))
740 Message (_("Sorry, the object is locked\n"));
743 if (((long int) Dest
== -1) || (Layer
== Dest
))
745 AddObjectToMoveToLayerUndoList (POLYGON_TYPE
, Layer
, Polygon
, Polygon
);
747 ErasePolygon (Polygon
);
748 /* Move all of the thermals with the polygon */
749 d
.snum
= GetLayerNumber (PCB
->Data
, Layer
);
750 d
.dnum
= GetLayerNumber (PCB
->Data
, Dest
);
753 r_search (PCB
->Data
->pin_tree
, &Polygon
->BoundingBox
, NULL
, mptl_pin_callback
, &d
);
755 r_search (PCB
->Data
->via_tree
, &Polygon
->BoundingBox
, NULL
, mptl_pin_callback
, &d
);
756 newone
= (struct polygon_st
*)MovePolygonToLayerLowLevel (Layer
, Polygon
, Dest
);
757 InitClip (PCB
->Data
, Dest
, newone
);
760 DrawPolygon (Dest
, newone
);
766 /* ---------------------------------------------------------------------------
767 * moves the object identified by its data pointers and the type
768 * not we don't bump the undo serial number
771 MoveObject (int Type
, void *Ptr1
, void *Ptr2
, void *Ptr3
, Coord DX
, Coord DY
)
777 AddObjectToMoveUndoList (Type
, Ptr1
, Ptr2
, Ptr3
, DX
, DY
);
778 result
= ObjectOperation (&MoveFunctions
, Type
, Ptr1
, Ptr2
, Ptr3
);
782 /* ---------------------------------------------------------------------------
783 * moves the object identified by its data pointers and the type
784 * as well as all attached rubberband lines
787 MoveObjectAndRubberband (int Type
, void *Ptr1
, void *Ptr2
, void *Ptr3
,
797 /* move all the lines... and reset the counter */
798 ptr
= Crosshair
.AttachedObject
.Rubberband
;
799 while (Crosshair
.AttachedObject
.RubberbandN
)
801 /* first clear any marks that we made in the line flags */
802 CLEAR_FLAG (RUBBERENDFLAG
, ptr
->Line
);
803 /* only update undo list if an actual movement happened */
804 if (DX
!= 0 || DY
!= 0)
806 AddObjectToMoveUndoList (LINEPOINT_TYPE
,
807 ptr
->Layer
, ptr
->Line
,
808 ptr
->MovedPoint
, DX
, DY
);
809 MoveLinePoint (ptr
->Layer
, ptr
->Line
, ptr
->MovedPoint
);
811 Crosshair
.AttachedObject
.RubberbandN
--;
815 if (DX
== 0 && DY
== 0)
818 AddObjectToMoveUndoList (Type
, Ptr1
, Ptr2
, Ptr3
, DX
, DY
);
819 ptr2
= ObjectOperation (&MoveFunctions
, Type
, Ptr1
, Ptr2
, Ptr3
);
820 IncrementUndoSerialNumber ();
824 /* ---------------------------------------------------------------------------
825 * moves the object identified by its data pointers and the type
826 * to a new layer without changing it's position
829 MoveObjectToLayer (int Type
, void *Ptr1
, void *Ptr2
, void *Ptr3
,
830 LayerType
*Target
, bool enmasse
)
834 /* setup global identifiers */
836 MoreToCome
= enmasse
;
837 result
= ObjectOperation (&MoveToLayerFunctions
, Type
, Ptr1
, Ptr2
, Ptr3
);
838 IncrementUndoSerialNumber ();
842 /* ---------------------------------------------------------------------------
843 * moves the selected objects to a new layer without changing their
847 MoveSelectedObjectsToLayer (LayerType
*Target
)
851 /* setup global identifiers */
854 changed
= SelectedOperation (&MoveToLayerFunctions
, true, ALL_TYPES
);
855 /* passing true to above operation causes Undoserial to auto-increment */
859 /* ---------------------------------------------------------------------------
860 * moves the selected layers to a new index in the layer list.
864 move_one_thermal (int old_index
, int new_index
, PinType
*pin
)
867 int oi
=old_index
, ni
=new_index
;
870 t1
= GET_THERM (old_index
, pin
);
873 oi
= MAX_LAYER
-1; /* inserting a layer */
875 ni
= MAX_LAYER
-1; /* deleting a layer */
879 for (i
=oi
; i
<ni
; i
++)
880 ASSIGN_THERM (i
, GET_THERM (i
+1, pin
), pin
);
884 for (i
=oi
; i
>ni
; i
--)
885 ASSIGN_THERM (i
, GET_THERM (i
-1, pin
), pin
);
889 ASSIGN_THERM (new_index
, t1
, pin
);
891 ASSIGN_THERM (ni
, 0, pin
);
895 move_all_thermals (int old_index
, int new_index
)
897 VIA_LOOP (PCB
->Data
);
899 move_one_thermal (old_index
, new_index
, via
);
903 ALLPIN_LOOP (PCB
->Data
);
905 move_one_thermal (old_index
, new_index
, pin
);
911 LastLayerInComponentGroup (int layer
)
913 int cgroup
= GetLayerGroupNumberByNumber(max_group
+ COMPONENT_LAYER
);
914 int lgroup
= GetLayerGroupNumberByNumber(layer
);
916 && PCB
->LayerGroups
.Number
[lgroup
] == 2)
922 LastLayerInSolderGroup (int layer
)
924 int sgroup
= GetLayerGroupNumberByNumber(max_group
+ SOLDER_LAYER
);
925 int lgroup
= GetLayerGroupNumberByNumber(layer
);
927 && PCB
->LayerGroups
.Number
[lgroup
] == 2)
933 MoveLayer (int old_index
, int new_index
)
935 int group_of_layer
[MAX_LAYER
+ 2], l
, g
, i
;
936 LayerType saved_layer
;
939 AddLayerChangeToUndoList (old_index
, new_index
);
940 IncrementUndoSerialNumber ();
942 if (old_index
< -1 || old_index
>= max_copper_layer
)
944 Message ("Invalid old layer %d for move: must be -1..%d\n",
945 old_index
, max_copper_layer
- 1);
948 if (new_index
< -1 || new_index
> max_copper_layer
|| new_index
>= MAX_LAYER
)
950 Message ("Invalid new layer %d for move: must be -1..%d\n",
951 new_index
, max_copper_layer
);
954 if (old_index
== new_index
)
958 && LastLayerInComponentGroup (old_index
))
960 gui
->confirm_dialog ("You can't delete the last top-side layer\n", "Ok", NULL
);
965 && LastLayerInSolderGroup (old_index
))
967 gui
->confirm_dialog ("You can't delete the last bottom-side layer\n", "Ok", NULL
);
971 for (l
= 0; l
< MAX_LAYER
+2; l
++)
972 group_of_layer
[l
] = -1;
974 for (g
= 0; g
< MAX_LAYER
; g
++)
975 for (i
= 0; i
< PCB
->LayerGroups
.Number
[g
]; i
++)
976 group_of_layer
[PCB
->LayerGroups
.Entries
[g
][i
]] = g
;
981 if (max_copper_layer
== MAX_LAYER
)
983 Message ("No room for new layers\n");
986 /* Create a new layer at new_index. */
987 lp
= &PCB
->Data
->Layer
[new_index
];
988 memmove (&PCB
->Data
->Layer
[new_index
+ 1],
989 &PCB
->Data
->Layer
[new_index
],
990 (max_copper_layer
+ 2 - new_index
) * sizeof (LayerType
));
991 memmove (&group_of_layer
[new_index
+ 1],
992 &group_of_layer
[new_index
],
993 (max_copper_layer
+ 2 - new_index
) * sizeof (int));
995 memset (lp
, 0, sizeof (LayerType
));
997 lp
->Name
= strdup ("New Layer");
998 lp
->Color
= Settings
.LayerColor
[new_index
];
999 lp
->SelectedColor
= Settings
.LayerSelectedColor
[new_index
];
1000 for (l
= 0; l
< max_copper_layer
; l
++)
1001 if (LayerStack
[l
] >= new_index
)
1003 LayerStack
[max_copper_layer
- 1] = new_index
;
1005 else if (new_index
== -1)
1007 /* Delete the layer at old_index */
1008 memmove (&PCB
->Data
->Layer
[old_index
],
1009 &PCB
->Data
->Layer
[old_index
+ 1],
1010 (max_copper_layer
+ 2 - old_index
- 1) * sizeof (LayerType
));
1011 memset (&PCB
->Data
->Layer
[max_copper_layer
+ 2 - 1], 0, sizeof (LayerType
));
1012 memmove (&group_of_layer
[old_index
],
1013 &group_of_layer
[old_index
+ 1],
1014 (max_copper_layer
+ 2 - old_index
- 1) * sizeof (int));
1015 for (l
= 0; l
< max_copper_layer
; l
++)
1016 if (LayerStack
[l
] == old_index
)
1017 memmove (LayerStack
+ l
,
1019 (max_copper_layer
- l
- 1) * sizeof (LayerStack
[0]));
1021 for (l
= 0; l
< max_copper_layer
; l
++)
1022 if (LayerStack
[l
] > old_index
)
1027 /* Move an existing layer */
1028 memcpy (&saved_layer
, &PCB
->Data
->Layer
[old_index
], sizeof (LayerType
));
1029 saved_group
= group_of_layer
[old_index
];
1030 if (old_index
< new_index
)
1032 memmove (&PCB
->Data
->Layer
[old_index
],
1033 &PCB
->Data
->Layer
[old_index
+ 1],
1034 (new_index
- old_index
) * sizeof (LayerType
));
1035 memmove (&group_of_layer
[old_index
],
1036 &group_of_layer
[old_index
+ 1],
1037 (new_index
- old_index
) * sizeof (int));
1041 memmove (&PCB
->Data
->Layer
[new_index
+ 1],
1042 &PCB
->Data
->Layer
[new_index
],
1043 (old_index
- new_index
) * sizeof (LayerType
));
1044 memmove (&group_of_layer
[new_index
+ 1],
1045 &group_of_layer
[new_index
],
1046 (old_index
- new_index
) * sizeof (int));
1048 memcpy (&PCB
->Data
->Layer
[new_index
], &saved_layer
, sizeof (LayerType
));
1049 group_of_layer
[new_index
] = saved_group
;
1052 move_all_thermals(old_index
, new_index
);
1054 for (g
= 0; g
< MAX_LAYER
; g
++)
1055 PCB
->LayerGroups
.Number
[g
] = 0;
1056 for (l
= 0; l
< max_copper_layer
+ 2; l
++)
1058 g
= group_of_layer
[l
];
1060 /* XXX: Should this ever happen? */
1064 i
= PCB
->LayerGroups
.Number
[g
]++;
1065 PCB
->LayerGroups
.Entries
[g
][i
] = l
;
1068 for (g
= 1; g
< MAX_LAYER
; g
++)
1069 if (PCB
->LayerGroups
.Number
[g
- 1] == 0)
1071 memmove (&PCB
->LayerGroups
.Number
[g
- 1],
1072 &PCB
->LayerGroups
.Number
[g
],
1073 (MAX_LAYER
- g
) * sizeof (PCB
->LayerGroups
.Number
[g
]));
1074 memmove (&PCB
->LayerGroups
.Entries
[g
- 1],
1075 &PCB
->LayerGroups
.Entries
[g
],
1076 (MAX_LAYER
- g
) * sizeof (PCB
->LayerGroups
.Entries
[g
]));
1079 hid_action ("LayersChanged");
1080 gui
->invalidate_all ();
1084 /* --------------------------------------------------------------------------- */
1086 static const char movelayer_syntax
[] = "MoveLayer(old,new)";
1088 static const char movelayer_help
[] = "Moves/Creates/Deletes Layers.";
1090 /* %start-doc actions MoveLayer
1092 Moves a layer, creates a new layer, or deletes a layer.
1097 The is the layer number to act upon. Allowed values are:
1101 Currently selected layer.
1107 An existing layer number.
1112 Specifies where to move the layer to. Allowed values are:
1121 Moves the layer down.
1124 Creates a new layer.
1133 MoveLayerAction (int argc
, char **argv
, Coord x
, Coord y
)
1135 int old_index
, new_index
;
1140 Message ("Usage; MoveLayer(old,new)");
1144 if (strcmp (argv
[0], "c") == 0)
1145 old_index
= INDEXOFCURRENT
;
1147 old_index
= atoi (argv
[0]);
1149 if (strcmp (argv
[1], "c") == 0)
1151 new_index
= INDEXOFCURRENT
;
1155 else if (strcmp (argv
[1], "up") == 0)
1157 new_index
= INDEXOFCURRENT
- 1;
1160 new_top
= new_index
;
1162 else if (strcmp (argv
[1], "down") == 0)
1164 new_index
= INDEXOFCURRENT
+ 1;
1165 if (new_index
>= max_copper_layer
)
1167 new_top
= new_index
;
1170 new_index
= atoi (argv
[1]);
1172 if (MoveLayer (old_index
, new_index
))
1175 if (new_index
== -1)
1177 new_top
= old_index
;
1178 if (new_top
>= max_copper_layer
)
1180 new_index
= new_top
;
1182 if (old_index
== -1)
1183 new_top
= new_index
;
1186 ChangeGroupVisibility (new_index
, 1, 1);
1191 HID_Action move_action_list
[] = {
1192 {"MoveLayer", 0, MoveLayerAction
,
1193 movelayer_help
, movelayer_syntax
}
1196 REGISTER_ACTIONS (move_action_list
)