pcb 4.1.1
An interactive printed circuit board layout editor.

copy.c

Go to the documentation of this file.
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 }