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 <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 }