pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00036 #ifdef HAVE_CONFIG_H 00037 #include "config.h" 00038 #endif 00039 00040 #include <stdlib.h> 00041 00042 #include "global.h" 00043 00044 #include "copy.h" 00045 #include "create.h" 00046 #include "data.h" 00047 #include "draw.h" 00048 #include "mymem.h" 00049 #include "mirror.h" 00050 #include "misc.h" 00051 #include "move.h" 00052 #include "polygon.h" 00053 #include "rats.h" 00054 #include "rtree.h" 00055 #include "select.h" 00056 #include "undo.h" 00057 00058 #ifdef HAVE_LIBDMALLOC 00059 #include <dmalloc.h> 00060 #endif 00061 00062 /* --------------------------------------------------------------------------- 00063 * some local prototypes 00064 */ 00065 static void *CopyVia (PinType *); 00066 static void *CopyLine (LayerType *, LineType *); 00067 static void *CopyArc (LayerType *, ArcType *); 00068 static void *CopyText (LayerType *, TextType *); 00069 static void *CopyPolygon (LayerType *, PolygonType *); 00070 static void *CopyElement (ElementType *); 00071 00072 /* --------------------------------------------------------------------------- 00073 * some local identifiers 00074 */ 00075 static Coord DeltaX, DeltaY; /* movement vector */ 00076 static ObjectFunctionType CopyFunctions = { 00077 CopyLine, 00078 CopyText, 00079 CopyPolygon, 00080 CopyVia, 00081 CopyElement, 00082 NULL, 00083 NULL, 00084 NULL, 00085 NULL, 00086 NULL, 00087 CopyArc, 00088 NULL 00089 }; 00090 00096 PolygonType * 00097 CopyPolygonLowLevel (PolygonType *Dest, PolygonType *Src) 00098 { 00099 Cardinal hole = 0; 00100 Cardinal n; 00101 00102 for (n = 0; n < Src->PointN; n++) 00103 { 00104 if (hole < Src->HoleIndexN && n == Src->HoleIndex[hole]) 00105 { 00106 CreateNewHoleInPolygon (Dest); 00107 hole++; 00108 } 00109 CreateNewPointInPolygon (Dest, Src->Points[n].X, Src->Points[n].Y); 00110 } 00111 SetPolygonBoundingBox (Dest); 00112 Dest->Flags = Src->Flags; 00113 CLEAR_FLAG (NOCOPY_FLAGS, Dest); 00114 return (Dest); 00115 } 00116 00121 ElementType * 00122 CopyElementLowLevel (DataType *Data, ElementType *Src, 00123 bool uniqueName, Coord dx, Coord dy, int mask_flags) 00124 { 00125 int i; 00126 ElementType *Dest; 00127 00128 /* both coordinates and flags are the same */ 00129 Dest = CreateNewElement (Data, &PCB->Font, 00130 MaskFlags (Src->Flags, mask_flags), 00131 DESCRIPTION_NAME (Src), NAMEONPCB_NAME (Src), 00132 VALUE_NAME (Src), DESCRIPTION_TEXT (Src).X + dx, 00133 DESCRIPTION_TEXT (Src).Y + dy, 00134 DESCRIPTION_TEXT (Src).Direction, 00135 DESCRIPTION_TEXT (Src).Scale, 00136 MaskFlags (DESCRIPTION_TEXT (Src).Flags, 00137 mask_flags), uniqueName); 00138 00139 /* abort on error */ 00140 if (!Dest) 00141 return (Dest); 00142 00143 ELEMENTLINE_LOOP (Src); 00144 { 00145 CreateNewLineInElement (Dest, line->Point1.X + dx, 00146 line->Point1.Y + dy, line->Point2.X + dx, 00147 line->Point2.Y + dy, line->Thickness); 00148 } 00149 END_LOOP; 00150 PIN_LOOP (Src); 00151 { 00152 CreateNewPin (Dest, pin->X + dx, pin->Y + dy, pin->Thickness, 00153 pin->Clearance, pin->Mask, pin->DrillingHole, 00154 pin->Name, pin->Number, MaskFlags (pin->Flags, mask_flags)); 00155 } 00156 END_LOOP; 00157 PAD_LOOP (Src); 00158 { 00159 CreateNewPad (Dest, pad->Point1.X + dx, pad->Point1.Y + dy, 00160 pad->Point2.X + dx, pad->Point2.Y + dy, pad->Thickness, 00161 pad->Clearance, pad->Mask, pad->Name, pad->Number, 00162 MaskFlags (pad->Flags, mask_flags)); 00163 } 00164 END_LOOP; 00165 ARC_LOOP (Src); 00166 { 00167 CreateNewArcInElement (Dest, arc->X + dx, arc->Y + dy, arc->Width, 00168 arc->Height, arc->StartAngle, arc->Delta, 00169 arc->Thickness); 00170 } 00171 END_LOOP; 00172 00173 for (i=0; i<Src->Attributes.Number; i++) 00174 CreateNewAttribute (& Dest->Attributes, 00175 Src->Attributes.List[i].name, 00176 Src->Attributes.List[i].value); 00177 00178 Dest->MarkX = Src->MarkX + dx; 00179 Dest->MarkY = Src->MarkY + dy; 00180 00181 SetElementBoundingBox (Data, Dest, &PCB->Font); 00182 return (Dest); 00183 } 00184 00188 static void * 00189 CopyVia (PinType *Via) 00190 { 00191 PinType *via; 00192 00193 via = CreateNewViaEx (PCB->Data, Via->X + DeltaX, Via->Y + DeltaY, 00194 Via->Thickness, Via->Clearance, Via->Mask, 00195 Via->DrillingHole, Via->Name, 00196 MaskFlags (Via->Flags, NOCOPY_FLAGS), Via->BuriedFrom, Via->BuriedTo); 00197 if (!via) 00198 return (via); 00199 DrawVia (via); 00200 AddObjectToCreateUndoList (VIA_TYPE, via, via, via); 00201 return (via); 00202 } 00203 00207 static void * 00208 CopyLine (LayerType *Layer, LineType *Line) 00209 { 00210 LineType *line; 00211 00212 line = CreateDrawnLineOnLayer (Layer, Line->Point1.X + DeltaX, 00213 Line->Point1.Y + DeltaY, 00214 Line->Point2.X + DeltaX, 00215 Line->Point2.Y + DeltaY, Line->Thickness, 00216 Line->Clearance, 00217 MaskFlags (Line->Flags, NOCOPY_FLAGS)); 00218 if (!line) 00219 return (line); 00220 if (Line->Number) 00221 line->Number = strdup (Line->Number); 00222 DrawLine (Layer, line); 00223 AddObjectToCreateUndoList (LINE_TYPE, Layer, line, line); 00224 return (line); 00225 } 00226 00230 static void * 00231 CopyArc (LayerType *Layer, ArcType *Arc) 00232 { 00233 ArcType *arc; 00234 00235 arc = CreateNewArcOnLayer (Layer, Arc->X + DeltaX, 00236 Arc->Y + DeltaY, Arc->Width, Arc->Height, Arc->StartAngle, 00237 Arc->Delta, Arc->Thickness, Arc->Clearance, 00238 MaskFlags (Arc->Flags, NOCOPY_FLAGS)); 00239 if (!arc) 00240 return (arc); 00241 DrawArc (Layer, arc); 00242 AddObjectToCreateUndoList (ARC_TYPE, Layer, arc, arc); 00243 return (arc); 00244 } 00245 00249 static void * 00250 CopyText (LayerType *Layer, TextType *Text) 00251 { 00252 TextType *text; 00253 00254 text = CreateNewText (Layer, &PCB->Font, Text->X + DeltaX, 00255 Text->Y + DeltaY, Text->Direction, 00256 Text->Scale, Text->TextString, 00257 MaskFlags (Text->Flags, NOCOPY_FLAGS)); 00258 DrawText (Layer, text); 00259 AddObjectToCreateUndoList (TEXT_TYPE, Layer, text, text); 00260 return (text); 00261 } 00262 00266 static void * 00267 CopyPolygon (LayerType *Layer, PolygonType *Polygon) 00268 { 00269 PolygonType *polygon; 00270 00271 polygon = CreateNewPolygon (Layer, NoFlags ()); 00272 CopyPolygonLowLevel (polygon, Polygon); 00273 MovePolygonLowLevel (polygon, DeltaX, DeltaY); 00274 if (!Layer->polygon_tree) 00275 Layer->polygon_tree = r_create_tree (NULL, 0, 0); 00276 r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0); 00277 InitClip (PCB->Data, Layer, polygon); 00278 DrawPolygon (Layer, polygon); 00279 AddObjectToCreateUndoList (POLYGON_TYPE, Layer, polygon, polygon); 00280 return (polygon); 00281 } 00282 00286 static void * 00287 CopyElement (ElementType *Element) 00288 { 00289 ElementType *element; 00290 00291 #ifdef DEBUG 00292 printf("Entered CopyElement, trying to copy element %s\n", 00293 Element->Name[1].TextString); 00294 #endif 00295 00296 element = CopyElementLowLevel (PCB->Data, Element, 00297 TEST_FLAG (UNIQUENAMEFLAG, PCB), 00298 DeltaX, DeltaY, NOCOPY_FLAGS); 00299 /* this call clears the polygons */ 00300 AddObjectToCreateUndoList (ELEMENT_TYPE, element, element, element); 00301 if (PCB->ElementOn && (FRONT (element) || PCB->InvisibleObjectsOn)) 00302 { 00303 DrawElementName (element); 00304 DrawElementPackage (element); 00305 } 00306 if (PCB->PinOn) 00307 { 00308 DrawElementPinsAndPads (element); 00309 } 00310 #ifdef DEBUG 00311 printf(" ... Leaving CopyElement.\n"); 00312 #endif 00313 return (element); 00314 } 00315 00321 bool 00322 CopyPastebufferToLayout (Coord X, Coord Y) 00323 { 00324 Cardinal i; 00325 bool changed = false; 00326 00327 #ifdef DEBUG 00328 printf("Entering CopyPastebufferToLayout.....\n"); 00329 #endif 00330 00331 /* set movement vector */ 00332 DeltaX = X - PASTEBUFFER->X, DeltaY = Y - PASTEBUFFER->Y; 00333 00334 /* paste all layers */ 00335 for (i = 0; i < max_copper_layer + SILK_LAYER; i++) 00336 { 00337 LayerType *sourcelayer = &PASTEBUFFER->Data->Layer[i]; 00338 LayerType *destlayer = LAYER_PTR (i); 00339 00340 if (destlayer->On) 00341 { 00342 changed = changed || 00343 (sourcelayer->LineN != 0) || 00344 (sourcelayer->ArcN != 0) || 00345 (sourcelayer->PolygonN != 0) || (sourcelayer->TextN != 0); 00346 LINE_LOOP (sourcelayer); 00347 { 00348 CopyLine (destlayer, line); 00349 } 00350 END_LOOP; 00351 ARC_LOOP (sourcelayer); 00352 { 00353 CopyArc (destlayer, arc); 00354 } 00355 END_LOOP; 00356 TEXT_LOOP (sourcelayer); 00357 { 00358 CopyText (destlayer, text); 00359 } 00360 END_LOOP; 00361 POLYGON_LOOP (sourcelayer); 00362 { 00363 CopyPolygon (destlayer, polygon); 00364 } 00365 END_LOOP; 00366 } 00367 } 00368 00369 /* paste elements */ 00370 if (PCB->PinOn && PCB->ElementOn) 00371 { 00372 ELEMENT_LOOP (PASTEBUFFER->Data); 00373 { 00374 #ifdef DEBUG 00375 printf("In CopyPastebufferToLayout, pasting element %s\n", 00376 element->Name[1].TextString); 00377 #endif 00378 if (FRONT (element) || PCB->InvisibleObjectsOn) 00379 { 00380 CopyElement (element); 00381 changed = true; 00382 } 00383 } 00384 END_LOOP; 00385 } 00386 00387 /* finally the vias */ 00388 if (PCB->ViaOn) 00389 { 00390 changed |= (PASTEBUFFER->Data->ViaN != 0); 00391 VIA_LOOP (PASTEBUFFER->Data); 00392 { 00393 CopyVia (via); 00394 } 00395 END_LOOP; 00396 } 00397 00398 if (changed) 00399 { 00400 Draw (); 00401 IncrementUndoSerialNumber (); 00402 } 00403 00404 #ifdef DEBUG 00405 printf(" .... Leaving CopyPastebufferToLayout.\n"); 00406 #endif 00407 00408 return (changed); 00409 } 00410 00417 void * 00418 CopyObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3, 00419 Coord DX, Coord DY) 00420 { 00421 void *ptr; 00422 00423 /* setup movement vector */ 00424 DeltaX = DX; 00425 DeltaY = DY; 00426 00427 /* the subroutines add the objects to the undo-list */ 00428 ptr = ObjectOperation (&CopyFunctions, Type, Ptr1, Ptr2, Ptr3); 00429 IncrementUndoSerialNumber (); 00430 return (ptr); 00431 }