pcb 4.1.1
An interactive printed circuit board layout editor.

remove.c

Go to the documentation of this file.
00001 
00036 #ifdef HAVE_CONFIG_H
00037 #include "config.h"
00038 #endif
00039 
00040 #include <setjmp.h>
00041 #include <memory.h>
00042 
00043 #include "global.h"
00044 
00045 #include "data.h"
00046 #include "draw.h"
00047 #include "error.h"
00048 #include "misc.h"
00049 #include "move.h"
00050 #include "mymem.h"
00051 #include "polygon.h"
00052 #include "rats.h"
00053 #include "remove.h"
00054 #include "rtree.h"
00055 #include "search.h"
00056 #include "select.h"
00057 #include "set.h"
00058 #include "undo.h"
00059 
00060 #ifdef HAVE_LIBDMALLOC
00061 #include <dmalloc.h>
00062 #endif
00063 
00064 /* ---------------------------------------------------------------------------
00065  * some local prototypes
00066  */
00067 static void *DestroyVia (PinType *);
00068 static void *DestroyRat (RatType *);
00069 static void *DestroyLine (LayerType *, LineType *);
00070 static void *DestroyArc (LayerType *, ArcType *);
00071 static void *DestroyText (LayerType *, TextType *);
00072 static void *DestroyPolygon (LayerType *, PolygonType *);
00073 static void *DestroyElement (ElementType *);
00074 static void *RemoveVia (PinType *);
00075 static void *RemoveRat (RatType *);
00076 static void *DestroyPolygonPoint (LayerType *, PolygonType *, PointType *);
00077 static void *RemovePolygonContour (LayerType *, PolygonType *, Cardinal);
00078 static void *RemovePolygonPoint (LayerType *, PolygonType *, PointType *);
00079 static void *RemoveLinePoint (LayerType *, LineType *, PointType *);
00080 
00081 /* ---------------------------------------------------------------------------
00082  * some local types
00083  */
00084 static ObjectFunctionType RemoveFunctions = {
00085   RemoveLine,
00086   RemoveText,
00087   RemovePolygon,
00088   RemoveVia,
00089   RemoveElement,
00090   NULL,
00091   NULL,
00092   NULL,
00093   RemoveLinePoint,
00094   RemovePolygonPoint,
00095   RemoveArc,
00096   RemoveRat
00097 };
00098 static ObjectFunctionType DestroyFunctions = {
00099   DestroyLine,
00100   DestroyText,
00101   DestroyPolygon,
00102   DestroyVia,
00103   DestroyElement,
00104   NULL,
00105   NULL,
00106   NULL,
00107   NULL,
00108   DestroyPolygonPoint,
00109   DestroyArc,
00110   DestroyRat
00111 };
00112 static DataType *DestroyTarget;
00113 static bool Bulk = false;
00114 
00118 void
00119 RemovePCB (PCBType *Ptr)
00120 {
00121   ClearUndoList (true);
00122   FreePCBMemory (Ptr);
00123   free (Ptr);
00124 }
00125 
00129 static void *
00130 DestroyVia (PinType *Via)
00131 {
00132   r_delete_entry (DestroyTarget->via_tree, (BoxType *) Via);
00133   free (Via->Name);
00134 
00135   DestroyTarget->Via = g_list_remove (DestroyTarget->Via, Via);
00136   DestroyTarget->ViaN --;
00137 
00138   g_slice_free (PinType, Via);
00139 
00140   return NULL;
00141 }
00142 
00146 static void *
00147 DestroyLine (LayerType *Layer, LineType *Line)
00148 {
00149   r_delete_entry (Layer->line_tree, (BoxType *) Line);
00150   free (Line->Number);
00151 
00152   Layer->Line = g_list_remove (Layer->Line, Line);
00153   Layer->LineN --;
00154 
00155   g_slice_free (LineType, Line);
00156 
00157   return NULL;
00158 }
00159 
00163 static void *
00164 DestroyArc (LayerType *Layer, ArcType *Arc)
00165 {
00166   r_delete_entry (Layer->arc_tree, (BoxType *) Arc);
00167 
00168   Layer->Arc = g_list_remove (Layer->Arc, Arc);
00169   Layer->ArcN --;
00170 
00171   g_slice_free (ArcType, Arc);
00172 
00173   return NULL;
00174 }
00175 
00179 static void *
00180 DestroyPolygon (LayerType *Layer, PolygonType *Polygon)
00181 {
00182   r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
00183   FreePolygonMemory (Polygon);
00184 
00185   Layer->Polygon = g_list_remove (Layer->Polygon, Polygon);
00186   Layer->PolygonN --;
00187 
00188   g_slice_free (PolygonType, Polygon);
00189 
00190   return NULL;
00191 }
00192 
00196 static void *
00197 DestroyPolygonPoint (LayerType *Layer,
00198                      PolygonType *Polygon, PointType *Point)
00199 {
00200   Cardinal point_idx;
00201   Cardinal i;
00202   Cardinal contour;
00203   Cardinal contour_start, contour_end, contour_points;
00204 
00205   point_idx = polygon_point_idx (Polygon, Point);
00206   contour = polygon_point_contour (Polygon, point_idx);
00207   contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1];
00208   contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN :
00209                                                    Polygon->HoleIndex[contour];
00210   contour_points = contour_end - contour_start;
00211 
00212   if (contour_points <= 3)
00213     return RemovePolygonContour (Layer, Polygon, contour);
00214 
00215   r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
00216 
00217   /* remove point from list, keep point order */
00218   for (i = point_idx; i < Polygon->PointN - 1; i++)
00219     Polygon->Points[i] = Polygon->Points[i + 1];
00220   Polygon->PointN--;
00221 
00222   /* Shift down indices of any holes */
00223   for (i = 0; i < Polygon->HoleIndexN; i++)
00224     if (Polygon->HoleIndex[i] > point_idx)
00225       Polygon->HoleIndex[i]--;
00226 
00227   SetPolygonBoundingBox (Polygon);
00228   r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
00229   InitClip (PCB->Data, Layer, Polygon);
00230   return (Polygon);
00231 }
00232 
00236 static void *
00237 DestroyText (LayerType *Layer, TextType *Text)
00238 {
00239   free (Text->TextString);
00240   r_delete_entry (Layer->text_tree, (BoxType *) Text);
00241 
00242   Layer->Text = g_list_remove (Layer->Text, Text);
00243   Layer->TextN --;
00244 
00245   g_slice_free (TextType, Text);
00246 
00247   return NULL;
00248 }
00249 
00250 /* ---------------------------------------------------------------------------
00251  * destroys a element
00252  */
00253 static void *
00254 DestroyElement (ElementType *Element)
00255 {
00256   if (DestroyTarget->element_tree)
00257     r_delete_entry (DestroyTarget->element_tree, (BoxType *) Element);
00258   if (DestroyTarget->pin_tree)
00259     {
00260       PIN_LOOP (Element);
00261       {
00262         r_delete_entry (DestroyTarget->pin_tree, (BoxType *) pin);
00263       }
00264       END_LOOP;
00265     }
00266   if (DestroyTarget->pad_tree)
00267     {
00268       PAD_LOOP (Element);
00269       {
00270         r_delete_entry (DestroyTarget->pad_tree, (BoxType *) pad);
00271       }
00272       END_LOOP;
00273     }
00274   ELEMENTTEXT_LOOP (Element);
00275   {
00276     if (DestroyTarget->name_tree[n])
00277       r_delete_entry (DestroyTarget->name_tree[n], (BoxType *) text);
00278   }
00279   END_LOOP;
00280   FreeElementMemory (Element);
00281 
00282   DestroyTarget->Element = g_list_remove (DestroyTarget->Element, Element);
00283   DestroyTarget->ElementN --;
00284 
00285   g_slice_free (ElementType, Element);
00286 
00287   return NULL;
00288 }
00289 
00293 static void *
00294 DestroyRat (RatType *Rat)
00295 {
00296   if (DestroyTarget->rat_tree)
00297     r_delete_entry (DestroyTarget->rat_tree, &Rat->BoundingBox);
00298 
00299   DestroyTarget->Rat = g_list_remove (DestroyTarget->Rat, Rat);
00300   DestroyTarget->RatN --;
00301 
00302   g_slice_free (RatType, Rat);
00303 
00304   return NULL;
00305 }
00306 
00307 
00311 static void *
00312 RemoveVia (PinType *Via)
00313 {
00314   /* erase from screen and memory */
00315   if (PCB->ViaOn)
00316     {
00317       EraseVia (Via);
00318       if (!Bulk)
00319         Draw ();
00320     }
00321   MoveObjectToRemoveUndoList (VIA_TYPE, Via, Via, Via);
00322   return NULL;
00323 }
00324 
00328 static void *
00329 RemoveRat (RatType *Rat)
00330 {
00331   /* erase from screen and memory */
00332   if (PCB->RatOn)
00333     {
00334       EraseRat (Rat);
00335       if (!Bulk)
00336         Draw ();
00337     }
00338   MoveObjectToRemoveUndoList (RATLINE_TYPE, Rat, Rat, Rat);
00339   return NULL;
00340 }
00341 
00342 struct rlp_info
00343 {
00344   jmp_buf env;
00345   LineType *line;
00346   PointType *point;
00347 };
00348 static int
00349 remove_point (const BoxType * b, void *cl)
00350 {
00351   LineType *line = (LineType *) b;
00352   struct rlp_info *info = (struct rlp_info *) cl;
00353   if (line == info->line)
00354     return 0;
00355   if ((line->Point1.X == info->point->X)
00356       && (line->Point1.Y == info->point->Y))
00357     {
00358       info->line = line;
00359       info->point = &line->Point1;
00360       longjmp (info->env, 1);
00361     }
00362   else
00363     if ((line->Point2.X == info->point->X)
00364         && (line->Point2.Y == info->point->Y))
00365     {
00366       info->line = line;
00367       info->point = &line->Point2;
00368       longjmp (info->env, 1);
00369     }
00370   return 0;
00371 }
00372 
00377 static void *
00378 RemoveLinePoint (LayerType *Layer, LineType *Line, PointType *Point)
00379 {
00380   PointType other;
00381   struct rlp_info info;
00382   if (&Line->Point1 == Point)
00383     other = Line->Point2;
00384   else
00385     other = Line->Point1;
00386   info.line = Line;
00387   info.point = Point;
00388   if (setjmp (info.env) == 0)
00389     {
00390       r_search (Layer->line_tree, (const BoxType *) Point, NULL, remove_point,
00391                 &info);
00392       return RemoveLine (Layer, Line);
00393     }
00394   MoveObject (LINEPOINT_TYPE, Layer, info.line, info.point,
00395               other.X - Point->X, other.Y - Point->Y);
00396   return (RemoveLine (Layer, Line));
00397 }
00398 
00402 void *
00403 RemoveLine (LayerType *Layer, LineType *Line)
00404 {
00405   /* erase from screen */
00406   if (Layer->On)
00407     {
00408       EraseLine (Line);
00409       if (!Bulk)
00410         Draw ();
00411     }
00412   MoveObjectToRemoveUndoList (LINE_TYPE, Layer, Line, Line);
00413   return NULL;
00414 }
00415 
00419 void *
00420 RemoveArc (LayerType *Layer, ArcType *Arc)
00421 {
00422   /* erase from screen */
00423   if (Layer->On)
00424     {
00425       EraseArc (Arc);
00426       if (!Bulk)
00427         Draw ();
00428     }
00429   MoveObjectToRemoveUndoList (ARC_TYPE, Layer, Arc, Arc);
00430   return NULL;
00431 }
00432 
00436 void *
00437 RemoveText (LayerType *Layer, TextType *Text)
00438 {
00439   /* erase from screen */
00440   if (Layer->On)
00441     {
00442       EraseText (Layer, Text);
00443       r_delete_entry (Layer->text_tree, (BoxType *) Text);
00444       if (!Bulk)
00445         Draw ();
00446     }
00447   MoveObjectToRemoveUndoList (TEXT_TYPE, Layer, Text, Text);
00448   return NULL;
00449 }
00450 
00454 void *
00455 RemovePolygon (LayerType *Layer, PolygonType *Polygon)
00456 {
00457   /* erase from screen */
00458   if (Layer->On)
00459     {
00460       ErasePolygon (Polygon);
00461       if (!Bulk)
00462         Draw ();
00463     }
00464   MoveObjectToRemoveUndoList (POLYGON_TYPE, Layer, Polygon, Polygon);
00465   return NULL;
00466 }
00467 
00473 static void *
00474 RemovePolygonContour (LayerType *Layer,
00475                       PolygonType *Polygon,
00476                       Cardinal contour)
00477 {
00478   Cardinal contour_start, contour_end, contour_points;
00479   Cardinal i;
00480 
00481   if (contour == 0)
00482     return RemovePolygon (Layer, Polygon);
00483 
00484   if (Layer->On)
00485     {
00486       ErasePolygon (Polygon);
00487       if (!Bulk)
00488         Draw ();
00489     }
00490 
00491   /* Copy the polygon to the undo list */
00492   AddObjectToRemoveContourUndoList (POLYGON_TYPE, Layer, Polygon);
00493 
00494   contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1];
00495   contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN :
00496                                                    Polygon->HoleIndex[contour];
00497   contour_points = contour_end - contour_start;
00498 
00499   /* remove points from list, keep point order */
00500   for (i = contour_start; i < Polygon->PointN - contour_points; i++)
00501     Polygon->Points[i] = Polygon->Points[i + contour_points];
00502   Polygon->PointN -= contour_points;
00503 
00504   /* remove hole from list and shift down remaining indices */
00505   for (i = contour; i < Polygon->HoleIndexN; i++)
00506     Polygon->HoleIndex[i - 1] = Polygon->HoleIndex[i] - contour_points;
00507   Polygon->HoleIndexN--;
00508 
00509   InitClip (PCB->Data, Layer, Polygon);
00510   /* redraw polygon if necessary */
00511   if (Layer->On)
00512     {
00513       DrawPolygon (Layer, Polygon);
00514       if (!Bulk)
00515         Draw ();
00516     }
00517   return NULL;
00518 }
00519 
00523 static void *
00524 RemovePolygonPoint (LayerType *Layer,
00525                     PolygonType *Polygon, PointType *Point)
00526 {
00527   Cardinal point_idx;
00528   Cardinal i;
00529   Cardinal contour;
00530   Cardinal contour_start, contour_end, contour_points;
00531 
00532   point_idx = polygon_point_idx (Polygon, Point);
00533   contour = polygon_point_contour (Polygon, point_idx);
00534   contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1];
00535   contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN :
00536                                                    Polygon->HoleIndex[contour];
00537   contour_points = contour_end - contour_start;
00538 
00539   if (contour_points <= 3)
00540     return RemovePolygonContour (Layer, Polygon, contour);
00541 
00542   if (Layer->On)
00543     ErasePolygon (Polygon);
00544 
00545   /* insert the polygon-point into the undo list */
00546   AddObjectToRemovePointUndoList (POLYGONPOINT_TYPE, Layer, Polygon, point_idx);
00547   r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
00548 
00549   /* remove point from list, keep point order */
00550   for (i = point_idx; i < Polygon->PointN - 1; i++)
00551     Polygon->Points[i] = Polygon->Points[i + 1];
00552   Polygon->PointN--;
00553 
00554   /* Shift down indices of any holes */
00555   for (i = 0; i < Polygon->HoleIndexN; i++)
00556     if (Polygon->HoleIndex[i] > point_idx)
00557       Polygon->HoleIndex[i]--;
00558 
00559   SetPolygonBoundingBox (Polygon);
00560   r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
00561   RemoveExcessPolygonPoints (Layer, Polygon);
00562   InitClip (PCB->Data, Layer, Polygon);
00563 
00564   /* redraw polygon if necessary */
00565   if (Layer->On)
00566     {
00567       DrawPolygon (Layer, Polygon);
00568       if (!Bulk)
00569         Draw ();
00570     }
00571   return NULL;
00572 }
00573 
00577 void *
00578 RemoveElement (ElementType *Element)
00579 {
00580   /* erase from screen */
00581   if ((PCB->ElementOn || PCB->PinOn) &&
00582       (FRONT (Element) || PCB->InvisibleObjectsOn))
00583     {
00584       EraseElement (Element);
00585       if (!Bulk)
00586         Draw ();
00587     }
00588   MoveObjectToRemoveUndoList (ELEMENT_TYPE, Element, Element, Element);
00589   return NULL;
00590 }
00591 
00597 bool
00598 RemoveSelected (void)
00599 {
00600   Bulk = true;
00601   if (SelectedOperation (&RemoveFunctions, false, ALL_TYPES))
00602     {
00603       IncrementUndoSerialNumber ();
00604       Draw ();
00605       Bulk = false;
00606       return (true);
00607     }
00608   Bulk = false;
00609   return (false);
00610 }
00611 
00612 void
00613 RemoveDegradedVias (void)
00614 {
00615   Bulk = true;
00616   VIA_LOOP (PCB->Data);
00617     {
00618       if (VIA_IS_BURIED (via)
00619           && (via->BuriedFrom == via->BuriedTo))
00620         RemoveVia (via);
00621     }
00622   END_LOOP;
00623   Bulk = false;
00624 }
00625 
00630 void *
00631 RemoveObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
00632 {
00633   void *ptr = ObjectOperation (&RemoveFunctions, Type, Ptr1, Ptr2, Ptr3);
00634   return (ptr);
00635 }
00636 
00642 bool
00643 DeleteRats (bool selected)
00644 {
00645   bool changed = false;
00646   Bulk = true;
00647   RAT_LOOP (PCB->Data);
00648   {
00649     if ((!selected) || TEST_FLAG (SELECTEDFLAG, line))
00650       {
00651         changed = true;
00652         RemoveRat (line);
00653       }
00654   }
00655   END_LOOP;
00656   Bulk = false;
00657   if (changed)
00658     {
00659       Draw ();
00660       IncrementUndoSerialNumber ();
00661     }
00662   return (changed);
00663 }
00664 
00670 void *
00671 DestroyObject (DataType *Target, int Type, void *Ptr1,
00672                void *Ptr2, void *Ptr3)
00673 {
00674   DestroyTarget = Target;
00675   return (ObjectOperation (&DestroyFunctions, Type, Ptr1, Ptr2, Ptr3));
00676 }