(no commit message)
[geda-pcb/pcjc2.git] / src / copy.c
blobb0cd9c828e8d13dfb6e62d9138914a94fcb697c3
1 /*
2 * COPYRIGHT
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
27 /* functions used to copy pins, elements ...
28 * it's necessary to copy data by calling create... since the base pointer
29 * may change cause of dynamic memory allocation
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include <stdlib.h>
38 #include "global.h"
40 #include "copy.h"
41 #include "create.h"
42 #include "data.h"
43 #include "draw.h"
44 #include "mymem.h"
45 #include "mirror.h"
46 #include "misc.h"
47 #include "move.h"
48 #include "polygon.h"
49 #include "rats.h"
50 #include "rtree.h"
51 #include "select.h"
52 #include "undo.h"
54 #ifdef HAVE_LIBDMALLOC
55 #include <dmalloc.h>
56 #endif
58 /* ---------------------------------------------------------------------------
59 * some local prototypes
61 static void *CopyVia (PinType *);
62 static void *CopyLine (LayerType *, LineType *);
63 static void *CopyArc (LayerType *, ArcType *);
64 static void *CopyText (LayerType *, TextType *);
65 static void *CopyPolygon (LayerType *, PolygonType *);
66 static void *CopyElement (ElementType *);
68 /* ---------------------------------------------------------------------------
69 * some local identifiers
71 static Coord DeltaX, DeltaY; /* movement vector */
72 static ObjectFunctionType CopyFunctions = {
73 CopyLine,
74 CopyText,
75 CopyPolygon,
76 CopyVia,
77 CopyElement,
78 NULL,
79 NULL,
80 NULL,
81 NULL,
82 NULL,
83 CopyArc,
84 NULL
87 /* ---------------------------------------------------------------------------
88 * copies data from one polygon to another
89 * 'Dest' has to exist
91 PolygonType *
92 CopyPolygonLowLevel (PolygonType *Dest, PolygonType *Src)
94 Cardinal hole = 0;
95 Cardinal n;
97 for (n = 0; n < Src->PointN; n++)
99 if (hole < Src->HoleIndexN && n == Src->HoleIndex[hole])
101 CreateNewHoleInPolygon (Dest);
102 hole++;
104 CreateNewPointInPolygon (Dest, Src->Points[n].X, Src->Points[n].Y);
106 SetPolygonBoundingBox (Dest);
107 Dest->Flags = Src->Flags;
108 CLEAR_FLAG (NOCOPY_FLAGS, Dest);
109 return (Dest);
112 /* ---------------------------------------------------------------------------
113 * copies data from one element to another and creates the destination
114 * if necessary
116 ElementType *
117 CopyElementLowLevel (DataType *Data, ElementType *Src,
118 bool uniqueName, Coord dx, Coord dy, int mask_flags)
120 int i;
121 ElementType *Dest;
123 /* both coordinates and flags are the same */
124 Dest = CreateNewElement (Data, &PCB->Font,
125 MaskFlags (Src->Flags, mask_flags),
126 DESCRIPTION_NAME (Src), NAMEONPCB_NAME (Src),
127 VALUE_NAME (Src), DESCRIPTION_TEXT (Src).X + dx,
128 DESCRIPTION_TEXT (Src).Y + dy,
129 DESCRIPTION_TEXT (Src).Direction,
130 DESCRIPTION_TEXT (Src).Scale,
131 MaskFlags (DESCRIPTION_TEXT (Src).Flags,
132 mask_flags), uniqueName);
134 /* abort on error */
135 if (!Dest)
136 return (Dest);
138 ELEMENTLINE_LOOP (Src);
140 CreateNewLineInElement (Dest, line->Point1.X + dx,
141 line->Point1.Y + dy, line->Point2.X + dx,
142 line->Point2.Y + dy, line->Thickness);
144 END_LOOP;
145 PIN_LOOP (Src);
147 CreateNewPin (Dest, pin->X + dx, pin->Y + dy, pin->Thickness,
148 pin->Clearance, pin->Mask, pin->DrillingHole,
149 pin->Name, pin->Number, MaskFlags (pin->Flags, mask_flags));
151 END_LOOP;
152 PAD_LOOP (Src);
154 CreateNewPad (Dest, pad->Point1.X + dx, pad->Point1.Y + dy,
155 pad->Point2.X + dx, pad->Point2.Y + dy, pad->Thickness,
156 pad->Clearance, pad->Mask, pad->Name, pad->Number,
157 MaskFlags (pad->Flags, mask_flags));
159 END_LOOP;
160 ARC_LOOP (Src);
162 CreateNewArcInElement (Dest, arc->X + dx, arc->Y + dy, arc->Width,
163 arc->Height, arc->StartAngle, arc->Delta,
164 arc->Thickness);
166 END_LOOP;
168 for (i=0; i<Src->Attributes.Number; i++)
169 CreateNewAttribute (& Dest->Attributes,
170 Src->Attributes.List[i].name,
171 Src->Attributes.List[i].value);
173 Dest->MarkX = Src->MarkX + dx;
174 Dest->MarkY = Src->MarkY + dy;
176 SetElementBoundingBox (Data, Dest, &PCB->Font);
177 return (Dest);
180 /* ---------------------------------------------------------------------------
181 * copies a via
183 static void *
184 CopyVia (PinType *Via)
186 PinType *via;
188 via = CreateNewVia (PCB->Data, Via->X + DeltaX, Via->Y + DeltaY,
189 Via->Thickness, Via->Clearance, Via->Mask,
190 Via->DrillingHole, Via->Name,
191 MaskFlags (Via->Flags, NOCOPY_FLAGS));
192 if (!via)
193 return (via);
194 DrawVia (via);
195 AddObjectToCreateUndoList (VIA_TYPE, via, via, via);
196 return (via);
199 /* ---------------------------------------------------------------------------
200 * copies a line
202 static void *
203 CopyLine (LayerType *Layer, LineType *Line)
205 LineType *line;
207 line = CreateDrawnLineOnLayer (Layer, Line->Point1.X + DeltaX,
208 Line->Point1.Y + DeltaY,
209 Line->Point2.X + DeltaX,
210 Line->Point2.Y + DeltaY, Line->Thickness,
211 Line->Clearance,
212 MaskFlags (Line->Flags, NOCOPY_FLAGS));
213 if (!line)
214 return (line);
215 if (Line->Number)
216 line->Number = strdup (Line->Number);
217 DrawLine (Layer, line);
218 AddObjectToCreateUndoList (LINE_TYPE, Layer, line, line);
219 return (line);
222 /* ---------------------------------------------------------------------------
223 * copies an arc
225 static void *
226 CopyArc (LayerType *Layer, ArcType *Arc)
228 ArcType *arc;
230 arc = CreateNewArcOnLayer (Layer, Arc->X + DeltaX,
231 Arc->Y + DeltaY, Arc->Width, Arc->Height, Arc->StartAngle,
232 Arc->Delta, Arc->Thickness, Arc->Clearance,
233 MaskFlags (Arc->Flags, NOCOPY_FLAGS));
234 if (!arc)
235 return (arc);
236 DrawArc (Layer, arc);
237 AddObjectToCreateUndoList (ARC_TYPE, Layer, arc, arc);
238 return (arc);
241 /* ---------------------------------------------------------------------------
242 * copies a text
244 static void *
245 CopyText (LayerType *Layer, TextType *Text)
247 TextType *text;
249 text = CreateNewText (Layer, &PCB->Font, Text->X + DeltaX,
250 Text->Y + DeltaY, Text->Direction,
251 Text->Scale, Text->TextString,
252 MaskFlags (Text->Flags, NOCOPY_FLAGS));
253 DrawText (Layer, text);
254 AddObjectToCreateUndoList (TEXT_TYPE, Layer, text, text);
255 return (text);
258 /* ---------------------------------------------------------------------------
259 * copies a polygon
261 static void *
262 CopyPolygon (LayerType *Layer, PolygonType *Polygon)
264 PolygonType *polygon;
266 polygon = CreateNewPolygon (Layer, NoFlags ());
267 CopyPolygonLowLevel (polygon, Polygon);
268 MovePolygonLowLevel (polygon, DeltaX, DeltaY);
269 if (!Layer->polygon_tree)
270 Layer->polygon_tree = r_create_tree (NULL, 0, 0);
271 r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0);
272 InitClip (PCB->Data, Layer, polygon);
273 DrawPolygon (Layer, polygon);
274 AddObjectToCreateUndoList (POLYGON_TYPE, Layer, polygon, polygon);
275 return (polygon);
278 /* ---------------------------------------------------------------------------
279 * copies an element onto the PCB. Then does a draw.
281 static void *
282 CopyElement (ElementType *Element)
285 #ifdef DEBUG
286 printf("Entered CopyElement, trying to copy element %s\n",
287 Element->Name[1].TextString);
288 #endif
290 ElementType *element = CopyElementLowLevel (PCB->Data, Element,
291 TEST_FLAG (UNIQUENAMEFLAG, PCB),
292 DeltaX, DeltaY, NOCOPY_FLAGS);
294 /* this call clears the polygons */
295 AddObjectToCreateUndoList (ELEMENT_TYPE, element, element, element);
296 if (PCB->ElementOn && (FRONT (element) || PCB->InvisibleObjectsOn))
298 DrawElementName (element);
299 DrawElementPackage (element);
301 if (PCB->PinOn)
303 DrawElementPinsAndPads (element);
305 #ifdef DEBUG
306 printf(" ... Leaving CopyElement.\n");
307 #endif
308 return (element);
311 /* ---------------------------------------------------------------------------
312 * pastes the contents of the buffer to the layout. Only visible objects
313 * are handled by the routine.
315 bool
316 CopyPastebufferToLayout (Coord X, Coord Y)
318 Cardinal i;
319 bool changed = false;
321 #ifdef DEBUG
322 printf("Entering CopyPastebufferToLayout.....\n");
323 #endif
325 /* set movement vector */
326 DeltaX = X - PASTEBUFFER->X, DeltaY = Y - PASTEBUFFER->Y;
328 /* paste all layers */
329 for (i = 0; i < max_copper_layer + 2; i++)
331 LayerType *sourcelayer = &PASTEBUFFER->Data->Layer[i];
332 LayerType *destlayer = LAYER_PTR (i);
334 if (destlayer->On)
336 changed = changed ||
337 (sourcelayer->LineN != 0) ||
338 (sourcelayer->ArcN != 0) ||
339 (sourcelayer->PolygonN != 0) || (sourcelayer->TextN != 0);
340 LINE_LOOP (sourcelayer);
342 CopyLine (destlayer, line);
344 END_LOOP;
345 ARC_LOOP (sourcelayer);
347 CopyArc (destlayer, arc);
349 END_LOOP;
350 TEXT_LOOP (sourcelayer);
352 CopyText (destlayer, text);
354 END_LOOP;
355 POLYGON_LOOP (sourcelayer);
357 CopyPolygon (destlayer, polygon);
359 END_LOOP;
363 /* paste elements */
364 if (PCB->PinOn && PCB->ElementOn)
366 ELEMENT_LOOP (PASTEBUFFER->Data);
368 #ifdef DEBUG
369 printf("In CopyPastebufferToLayout, pasting element %s\n",
370 element->Name[1].TextString);
371 #endif
372 if (FRONT (element) || PCB->InvisibleObjectsOn)
374 CopyElement (element);
375 changed = true;
378 END_LOOP;
381 /* finally the vias */
382 if (PCB->ViaOn)
384 changed |= (PASTEBUFFER->Data->ViaN != 0);
385 VIA_LOOP (PASTEBUFFER->Data);
387 CopyVia (via);
389 END_LOOP;
392 if (changed)
394 Draw ();
395 IncrementUndoSerialNumber ();
398 #ifdef DEBUG
399 printf(" .... Leaving CopyPastebufferToLayout.\n");
400 #endif
402 return (changed);
405 /* ---------------------------------------------------------------------------
406 * copies the object identified by its data pointers and the type
407 * the new objects is moved by DX,DY
408 * I assume that the appropriate layer ... is switched on
410 void *
411 CopyObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3,
412 Coord DX, Coord DY)
414 void *ptr;
416 /* setup movement vector */
417 DeltaX = DX;
418 DeltaY = DY;
420 /* the subroutines add the objects to the undo-list */
421 ptr = ObjectOperation (&CopyFunctions, Type, Ptr1, Ptr2, Ptr3);
422 IncrementUndoSerialNumber ();
423 return (ptr);