Repopulate route style selector on PCBChanged action
[geda-pcb/whiteaudio.git] / src / copy.c
blob29ac62f54f967814bd475caf4f177158eb3af11b
1 /* $Id$ */
3 /*
4 * COPYRIGHT
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
29 /* functions used to copy pins, elements ...
30 * it's necessary to copy data by calling create... since the base pointer
31 * may change cause of dynamic memory allocation
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
38 #include <stdlib.h>
40 #include "global.h"
42 #include "copy.h"
43 #include "create.h"
44 #include "data.h"
45 #include "draw.h"
46 #include "mymem.h"
47 #include "mirror.h"
48 #include "misc.h"
49 #include "move.h"
50 #include "polygon.h"
51 #include "rats.h"
52 #include "rtree.h"
53 #include "select.h"
54 #include "undo.h"
56 #ifdef HAVE_LIBDMALLOC
57 #include <dmalloc.h>
58 #endif
60 RCSID ("$Id$");
62 /* ---------------------------------------------------------------------------
63 * some local prototypes
65 static void *CopyVia (PinTypePtr);
66 static void *CopyLine (LayerTypePtr, LineTypePtr);
67 static void *CopyArc (LayerTypePtr, ArcTypePtr);
68 static void *CopyText (LayerTypePtr, TextTypePtr);
69 static void *CopyPolygon (LayerTypePtr, PolygonTypePtr);
70 static void *CopyElement (ElementTypePtr);
72 /* ---------------------------------------------------------------------------
73 * some local identifiers
75 static Coord DeltaX, DeltaY; /* movement vector */
76 static ObjectFunctionType CopyFunctions = {
77 CopyLine,
78 CopyText,
79 CopyPolygon,
80 CopyVia,
81 CopyElement,
82 NULL,
83 NULL,
84 NULL,
85 NULL,
86 NULL,
87 CopyArc,
88 NULL
91 /* ---------------------------------------------------------------------------
92 * copies data from one polygon to another
93 * 'Dest' has to exist
95 PolygonTypePtr
96 CopyPolygonLowLevel (PolygonTypePtr Dest, PolygonTypePtr Src)
98 Cardinal hole = 0;
99 Cardinal n;
101 for (n = 0; n < Src->PointN; n++)
103 if (hole < Src->HoleIndexN && n == Src->HoleIndex[hole])
105 CreateNewHoleInPolygon (Dest);
106 hole++;
108 CreateNewPointInPolygon (Dest, Src->Points[n].X, Src->Points[n].Y);
110 SetPolygonBoundingBox (Dest);
111 Dest->Flags = Src->Flags;
112 CLEAR_FLAG (FOUNDFLAG, Dest);
113 return (Dest);
116 /* ---------------------------------------------------------------------------
117 * copies data from one element to another and creates the destination
118 * if necessary
120 ElementTypePtr
121 CopyElementLowLevel (DataTypePtr Data, ElementTypePtr Dest,
122 ElementTypePtr Src, bool uniqueName, Coord dx,
123 Coord dy)
125 int i;
126 /* release old memory if necessary */
127 if (Dest)
128 FreeElementMemory (Dest);
130 /* both coordinates and flags are the same */
131 Dest = CreateNewElement (Data, Dest, &PCB->Font,
132 MaskFlags (Src->Flags, FOUNDFLAG),
133 DESCRIPTION_NAME (Src), NAMEONPCB_NAME (Src),
134 VALUE_NAME (Src), DESCRIPTION_TEXT (Src).X + dx,
135 DESCRIPTION_TEXT (Src).Y + dy,
136 DESCRIPTION_TEXT (Src).Direction,
137 DESCRIPTION_TEXT (Src).Scale,
138 MaskFlags (DESCRIPTION_TEXT (Src).Flags,
139 FOUNDFLAG), uniqueName);
141 /* abort on error */
142 if (!Dest)
143 return (Dest);
145 ELEMENTLINE_LOOP (Src);
147 CreateNewLineInElement (Dest, line->Point1.X + dx,
148 line->Point1.Y + dy, line->Point2.X + dx,
149 line->Point2.Y + dy, line->Thickness);
151 END_LOOP;
152 PIN_LOOP (Src);
154 CreateNewPin (Dest, pin->X + dx, pin->Y + dy, pin->Thickness,
155 pin->Clearance, pin->Mask, pin->DrillingHole,
156 pin->Name, pin->Number, MaskFlags (pin->Flags, FOUNDFLAG));
158 END_LOOP;
159 PAD_LOOP (Src);
161 CreateNewPad (Dest, pad->Point1.X + dx, pad->Point1.Y + dy,
162 pad->Point2.X + dx, pad->Point2.Y + dy, pad->Thickness,
163 pad->Clearance, pad->Mask, pad->Name, pad->Number,
164 MaskFlags (pad->Flags, FOUNDFLAG));
166 END_LOOP;
167 ARC_LOOP (Src);
169 CreateNewArcInElement (Dest, arc->X + dx, arc->Y + dy, arc->Width,
170 arc->Height, arc->StartAngle, arc->Delta,
171 arc->Thickness);
173 END_LOOP;
175 for (i=0; i<Src->Attributes.Number; i++)
176 CreateNewAttribute (& Dest->Attributes,
177 Src->Attributes.List[i].name,
178 Src->Attributes.List[i].value);
180 Dest->MarkX = Src->MarkX + dx;
181 Dest->MarkY = Src->MarkY + dy;
183 SetElementBoundingBox (Data, Dest, &PCB->Font);
184 return (Dest);
187 /* ---------------------------------------------------------------------------
188 * copies a via
190 static void *
191 CopyVia (PinTypePtr Via)
193 PinTypePtr via;
195 via = CreateNewVia (PCB->Data, Via->X + DeltaX, Via->Y + DeltaY,
196 Via->Thickness, Via->Clearance, Via->Mask,
197 Via->DrillingHole, Via->Name,
198 MaskFlags (Via->Flags, FOUNDFLAG));
199 if (!via)
200 return (via);
201 DrawVia (via);
202 AddObjectToCreateUndoList (VIA_TYPE, via, via, via);
203 return (via);
206 /* ---------------------------------------------------------------------------
207 * copies a line
209 static void *
210 CopyLine (LayerTypePtr Layer, LineTypePtr Line)
212 LineTypePtr line;
214 line = CreateDrawnLineOnLayer (Layer, Line->Point1.X + DeltaX,
215 Line->Point1.Y + DeltaY,
216 Line->Point2.X + DeltaX,
217 Line->Point2.Y + DeltaY, Line->Thickness,
218 Line->Clearance,
219 MaskFlags (Line->Flags, FOUNDFLAG));
220 if (!line)
221 return (line);
222 if (Line->Number)
223 line->Number = strdup (Line->Number);
224 DrawLine (Layer, line);
225 AddObjectToCreateUndoList (LINE_TYPE, Layer, line, line);
226 return (line);
229 /* ---------------------------------------------------------------------------
230 * copies an arc
232 static void *
233 CopyArc (LayerTypePtr Layer, ArcTypePtr Arc)
235 ArcTypePtr arc;
237 arc = CreateNewArcOnLayer (Layer, Arc->X + DeltaX,
238 Arc->Y + DeltaY, Arc->Width, Arc->Height, Arc->StartAngle,
239 Arc->Delta, Arc->Thickness, Arc->Clearance,
240 MaskFlags (Arc->Flags, FOUNDFLAG));
241 if (!arc)
242 return (arc);
243 DrawArc (Layer, arc);
244 AddObjectToCreateUndoList (ARC_TYPE, Layer, arc, arc);
245 return (arc);
248 /* ---------------------------------------------------------------------------
249 * copies a text
251 static void *
252 CopyText (LayerTypePtr Layer, TextTypePtr Text)
254 TextTypePtr text;
256 text = CreateNewText (Layer, &PCB->Font, Text->X + DeltaX,
257 Text->Y + DeltaY, Text->Direction,
258 Text->Scale, Text->TextString,
259 MaskFlags (Text->Flags, FOUNDFLAG));
260 DrawText (Layer, text);
261 AddObjectToCreateUndoList (TEXT_TYPE, Layer, text, text);
262 return (text);
265 /* ---------------------------------------------------------------------------
266 * copies a polygon
268 static void *
269 CopyPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
271 PolygonTypePtr polygon;
273 polygon = CreateNewPolygon (Layer, NoFlags ());
274 CopyPolygonLowLevel (polygon, Polygon);
275 MovePolygonLowLevel (polygon, DeltaX, DeltaY);
276 if (!Layer->polygon_tree)
277 Layer->polygon_tree = r_create_tree (NULL, 0, 0);
278 r_insert_entry (Layer->polygon_tree, (BoxTypePtr) polygon, 0);
279 InitClip (PCB->Data, Layer, polygon);
280 DrawPolygon (Layer, polygon);
281 AddObjectToCreateUndoList (POLYGON_TYPE, Layer, polygon, polygon);
282 return (polygon);
285 /* ---------------------------------------------------------------------------
286 * copies an element onto the PCB. Then does a draw.
288 static void *
289 CopyElement (ElementTypePtr Element)
292 #ifdef DEBUG
293 printf("Entered CopyElement, trying to copy element %s\n",
294 Element->Name[1].TextString);
295 #endif
297 ElementTypePtr element = CopyElementLowLevel (PCB->Data,
298 NULL, Element,
299 TEST_FLAG (UNIQUENAMEFLAG,
300 PCB), DeltaX,
301 DeltaY);
303 /* this call clears the polygons */
304 AddObjectToCreateUndoList (ELEMENT_TYPE, element, element, element);
305 if (PCB->ElementOn && (FRONT (element) || PCB->InvisibleObjectsOn))
307 DrawElementName (element);
308 DrawElementPackage (element);
310 if (PCB->PinOn)
312 DrawElementPinsAndPads (element);
314 #ifdef DEBUG
315 printf(" ... Leaving CopyElement.\n");
316 #endif
317 return (element);
320 /* ---------------------------------------------------------------------------
321 * pastes the contents of the buffer to the layout. Only visible objects
322 * are handled by the routine.
324 bool
325 CopyPastebufferToLayout (Coord X, Coord Y)
327 Cardinal i;
328 bool changed = false;
330 #ifdef DEBUG
331 printf("Entering CopyPastebufferToLayout.....\n");
332 #endif
334 /* set movement vector */
335 DeltaX = X - PASTEBUFFER->X, DeltaY = Y - PASTEBUFFER->Y;
337 /* paste all layers */
338 for (i = 0; i < max_copper_layer + 2; i++)
340 LayerTypePtr sourcelayer = &PASTEBUFFER->Data->Layer[i],
341 destlayer = LAYER_PTR (i);
343 if (destlayer->On)
345 changed = changed ||
346 (sourcelayer->LineN != 0) ||
347 (sourcelayer->ArcN != 0) ||
348 (sourcelayer->PolygonN != 0) || (sourcelayer->TextN != 0);
349 LINE_LOOP (sourcelayer);
351 CopyLine (destlayer, line);
353 END_LOOP;
354 ARC_LOOP (sourcelayer);
356 CopyArc (destlayer, arc);
358 END_LOOP;
359 TEXT_LOOP (sourcelayer);
361 CopyText (destlayer, text);
363 END_LOOP;
364 POLYGON_LOOP (sourcelayer);
366 CopyPolygon (destlayer, polygon);
368 END_LOOP;
372 /* paste elements */
373 if (PCB->PinOn && PCB->ElementOn)
375 ELEMENT_LOOP (PASTEBUFFER->Data);
377 #ifdef DEBUG
378 printf("In CopyPastebufferToLayout, pasting element %s\n",
379 element->Name[1].TextString);
380 #endif
381 if (FRONT (element) || PCB->InvisibleObjectsOn)
383 CopyElement (element);
384 changed = true;
387 END_LOOP;
390 /* finally the vias */
391 if (PCB->ViaOn)
393 changed |= (PASTEBUFFER->Data->ViaN != 0);
394 VIA_LOOP (PASTEBUFFER->Data);
396 CopyVia (via);
398 END_LOOP;
401 if (changed)
403 Draw ();
404 IncrementUndoSerialNumber ();
407 #ifdef DEBUG
408 printf(" .... Leaving CopyPastebufferToLayout.\n");
409 #endif
411 return (changed);
414 /* ---------------------------------------------------------------------------
415 * copies the object identified by its data pointers and the type
416 * the new objects is moved by DX,DY
417 * I assume that the appropriate layer ... is switched on
419 void *
420 CopyObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3,
421 Coord DX, Coord DY)
423 void *ptr;
425 /* setup movement vector */
426 DeltaX = DX;
427 DeltaY = DY;
429 /* the subroutines add the objects to the undo-list */
430 ptr = ObjectOperation (&CopyFunctions, Type, Ptr1, Ptr2, Ptr3);
431 IncrementUndoSerialNumber ();
432 return (ptr);