AddElementToBuffer(): Let CopyElementLowLevel() create the element to copy into.
[geda-pcb/pcjc2.git] / src / copy.c
bloba9be335ae43677b57dc114068632b364b2c33eab
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 (FOUNDFLAG, 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 *Dest,
118 ElementType *Src, bool uniqueName, Coord dx,
119 Coord dy, int mask_flags)
121 int i;
122 /* release old memory if necessary */
123 if (Dest)
124 FreeElementMemory (Dest);
126 /* both coordinates and flags are the same */
127 Dest = CreateNewElement (Data, Dest, &PCB->Font,
128 MaskFlags (Src->Flags, mask_flags),
129 DESCRIPTION_NAME (Src), NAMEONPCB_NAME (Src),
130 VALUE_NAME (Src), DESCRIPTION_TEXT (Src).X + dx,
131 DESCRIPTION_TEXT (Src).Y + dy,
132 DESCRIPTION_TEXT (Src).Direction,
133 DESCRIPTION_TEXT (Src).Scale,
134 MaskFlags (DESCRIPTION_TEXT (Src).Flags,
135 mask_flags), uniqueName);
137 /* abort on error */
138 if (!Dest)
139 return (Dest);
141 ELEMENTLINE_LOOP (Src);
143 CreateNewLineInElement (Dest, line->Point1.X + dx,
144 line->Point1.Y + dy, line->Point2.X + dx,
145 line->Point2.Y + dy, line->Thickness);
147 END_LOOP;
148 PIN_LOOP (Src);
150 CreateNewPin (Dest, pin->X + dx, pin->Y + dy, pin->Thickness,
151 pin->Clearance, pin->Mask, pin->DrillingHole,
152 pin->Name, pin->Number, MaskFlags (pin->Flags, mask_flags));
154 END_LOOP;
155 PAD_LOOP (Src);
157 CreateNewPad (Dest, pad->Point1.X + dx, pad->Point1.Y + dy,
158 pad->Point2.X + dx, pad->Point2.Y + dy, pad->Thickness,
159 pad->Clearance, pad->Mask, pad->Name, pad->Number,
160 MaskFlags (pad->Flags, mask_flags));
162 END_LOOP;
163 ARC_LOOP (Src);
165 CreateNewArcInElement (Dest, arc->X + dx, arc->Y + dy, arc->Width,
166 arc->Height, arc->StartAngle, arc->Delta,
167 arc->Thickness);
169 END_LOOP;
171 for (i=0; i<Src->Attributes.Number; i++)
172 CreateNewAttribute (& Dest->Attributes,
173 Src->Attributes.List[i].name,
174 Src->Attributes.List[i].value);
176 Dest->MarkX = Src->MarkX + dx;
177 Dest->MarkY = Src->MarkY + dy;
179 SetElementBoundingBox (Data, Dest, &PCB->Font);
180 return (Dest);
183 /* ---------------------------------------------------------------------------
184 * copies a via
186 static void *
187 CopyVia (PinType *Via)
189 PinType *via;
191 via = CreateNewVia (PCB->Data, Via->X + DeltaX, Via->Y + DeltaY,
192 Via->Thickness, Via->Clearance, Via->Mask,
193 Via->DrillingHole, Via->Name,
194 MaskFlags (Via->Flags, FOUNDFLAG));
195 if (!via)
196 return (via);
197 DrawVia (via);
198 AddObjectToCreateUndoList (VIA_TYPE, via, via, via);
199 return (via);
202 /* ---------------------------------------------------------------------------
203 * copies a line
205 static void *
206 CopyLine (LayerType *Layer, LineType *Line)
208 LineType *line;
210 line = CreateDrawnLineOnLayer (Layer, Line->Point1.X + DeltaX,
211 Line->Point1.Y + DeltaY,
212 Line->Point2.X + DeltaX,
213 Line->Point2.Y + DeltaY, Line->Thickness,
214 Line->Clearance,
215 MaskFlags (Line->Flags, FOUNDFLAG));
216 if (!line)
217 return (line);
218 if (Line->Number)
219 line->Number = strdup (Line->Number);
220 DrawLine (Layer, line);
221 AddObjectToCreateUndoList (LINE_TYPE, Layer, line, line);
222 return (line);
225 /* ---------------------------------------------------------------------------
226 * copies an arc
228 static void *
229 CopyArc (LayerType *Layer, ArcType *Arc)
231 ArcType *arc;
233 arc = CreateNewArcOnLayer (Layer, Arc->X + DeltaX,
234 Arc->Y + DeltaY, Arc->Width, Arc->Height, Arc->StartAngle,
235 Arc->Delta, Arc->Thickness, Arc->Clearance,
236 MaskFlags (Arc->Flags, FOUNDFLAG));
237 if (!arc)
238 return (arc);
239 DrawArc (Layer, arc);
240 AddObjectToCreateUndoList (ARC_TYPE, Layer, arc, arc);
241 return (arc);
244 /* ---------------------------------------------------------------------------
245 * copies a text
247 static void *
248 CopyText (LayerType *Layer, TextType *Text)
250 TextType *text;
252 text = CreateNewText (Layer, &PCB->Font, Text->X + DeltaX,
253 Text->Y + DeltaY, Text->Direction,
254 Text->Scale, Text->TextString,
255 MaskFlags (Text->Flags, FOUNDFLAG));
256 DrawText (Layer, text);
257 AddObjectToCreateUndoList (TEXT_TYPE, Layer, text, text);
258 return (text);
261 /* ---------------------------------------------------------------------------
262 * copies a polygon
264 static void *
265 CopyPolygon (LayerType *Layer, PolygonType *Polygon)
267 PolygonType *polygon;
269 polygon = CreateNewPolygon (Layer, NoFlags ());
270 CopyPolygonLowLevel (polygon, Polygon);
271 MovePolygonLowLevel (polygon, DeltaX, DeltaY);
272 if (!Layer->polygon_tree)
273 Layer->polygon_tree = r_create_tree (NULL, 0, 0);
274 r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0);
275 InitClip (PCB->Data, Layer, polygon);
276 DrawPolygon (Layer, polygon);
277 AddObjectToCreateUndoList (POLYGON_TYPE, Layer, polygon, polygon);
278 return (polygon);
281 /* ---------------------------------------------------------------------------
282 * copies an element onto the PCB. Then does a draw.
284 static void *
285 CopyElement (ElementType *Element)
288 #ifdef DEBUG
289 printf("Entered CopyElement, trying to copy element %s\n",
290 Element->Name[1].TextString);
291 #endif
293 ElementType *element = CopyElementLowLevel (PCB->Data,
294 NULL, Element,
295 TEST_FLAG (UNIQUENAMEFLAG,
296 PCB), DeltaX,
297 DeltaY, FOUNDFLAG);
299 /* this call clears the polygons */
300 AddObjectToCreateUndoList (ELEMENT_TYPE, element, element, element);
301 if (PCB->ElementOn && (FRONT (element) || PCB->InvisibleObjectsOn))
303 DrawElementName (element);
304 DrawElementPackage (element);
306 if (PCB->PinOn)
308 DrawElementPinsAndPads (element);
310 #ifdef DEBUG
311 printf(" ... Leaving CopyElement.\n");
312 #endif
313 return (element);
316 /* ---------------------------------------------------------------------------
317 * pastes the contents of the buffer to the layout. Only visible objects
318 * are handled by the routine.
320 bool
321 CopyPastebufferToLayout (Coord X, Coord Y)
323 Cardinal i;
324 bool changed = false;
326 #ifdef DEBUG
327 printf("Entering CopyPastebufferToLayout.....\n");
328 #endif
330 /* set movement vector */
331 DeltaX = X - PASTEBUFFER->X, DeltaY = Y - PASTEBUFFER->Y;
333 /* paste all layers */
334 for (i = 0; i < max_copper_layer + 2; i++)
336 LayerType *sourcelayer = &PASTEBUFFER->Data->Layer[i];
337 LayerType *destlayer = LAYER_PTR (i);
339 if (destlayer->On)
341 changed = changed ||
342 (sourcelayer->LineN != 0) ||
343 (sourcelayer->ArcN != 0) ||
344 (sourcelayer->PolygonN != 0) || (sourcelayer->TextN != 0);
345 LINE_LOOP (sourcelayer);
347 CopyLine (destlayer, line);
349 END_LOOP;
350 ARC_LOOP (sourcelayer);
352 CopyArc (destlayer, arc);
354 END_LOOP;
355 TEXT_LOOP (sourcelayer);
357 CopyText (destlayer, text);
359 END_LOOP;
360 POLYGON_LOOP (sourcelayer);
362 CopyPolygon (destlayer, polygon);
364 END_LOOP;
368 /* paste elements */
369 if (PCB->PinOn && PCB->ElementOn)
371 ELEMENT_LOOP (PASTEBUFFER->Data);
373 #ifdef DEBUG
374 printf("In CopyPastebufferToLayout, pasting element %s\n",
375 element->Name[1].TextString);
376 #endif
377 if (FRONT (element) || PCB->InvisibleObjectsOn)
379 CopyElement (element);
380 changed = true;
383 END_LOOP;
386 /* finally the vias */
387 if (PCB->ViaOn)
389 changed |= (PASTEBUFFER->Data->ViaN != 0);
390 VIA_LOOP (PASTEBUFFER->Data);
392 CopyVia (via);
394 END_LOOP;
397 if (changed)
399 Draw ();
400 IncrementUndoSerialNumber ();
403 #ifdef DEBUG
404 printf(" .... Leaving CopyPastebufferToLayout.\n");
405 #endif
407 return (changed);
410 /* ---------------------------------------------------------------------------
411 * copies the object identified by its data pointers and the type
412 * the new objects is moved by DX,DY
413 * I assume that the appropriate layer ... is switched on
415 void *
416 CopyObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3,
417 Coord DX, Coord DY)
419 void *ptr;
421 /* setup movement vector */
422 DeltaX = DX;
423 DeltaY = DY;
425 /* the subroutines add the objects to the undo-list */
426 ptr = ObjectOperation (&CopyFunctions, Type, Ptr1, Ptr2, Ptr3);
427 IncrementUndoSerialNumber ();
428 return (ptr);