(no commit message)
[geda-pcb/pcjc2.git] / src / remove.c
blob39af48fc1f87b14bcbe5247b70b99f2cf59e6ef7
1 /*
2 * COPYRIGHT
4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
28 /* functions used to remove vias, pins ...
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
35 #include <setjmp.h>
36 #include <memory.h>
38 #include "global.h"
40 #include "data.h"
41 #include "draw.h"
42 #include "error.h"
43 #include "misc.h"
44 #include "move.h"
45 #include "mymem.h"
46 #include "polygon.h"
47 #include "rats.h"
48 #include "remove.h"
49 #include "rtree.h"
50 #include "search.h"
51 #include "select.h"
52 #include "set.h"
53 #include "undo.h"
55 #ifdef HAVE_LIBDMALLOC
56 #include <dmalloc.h>
57 #endif
59 /* ---------------------------------------------------------------------------
60 * some local prototypes
62 static void *DestroyVia (PinType *);
63 static void *DestroyRat (RatType *);
64 static void *DestroyLine (LayerType *, LineType *);
65 static void *DestroyArc (LayerType *, ArcType *);
66 static void *DestroyText (LayerType *, TextType *);
67 static void *DestroyPolygon (LayerType *, PolygonType *);
68 static void *DestroyElement (ElementType *);
69 static void *RemoveVia (PinType *);
70 static void *RemoveRat (RatType *);
71 static void *DestroyPolygonPoint (LayerType *, PolygonType *, PointType *);
72 static void *RemovePolygonContour (LayerType *, PolygonType *, Cardinal);
73 static void *RemovePolygonPoint (LayerType *, PolygonType *, PointType *);
74 static void *RemoveLinePoint (LayerType *, LineType *, PointType *);
76 /* ---------------------------------------------------------------------------
77 * some local types
79 static ObjectFunctionType RemoveFunctions = {
80 RemoveLine,
81 RemoveText,
82 RemovePolygon,
83 RemoveVia,
84 RemoveElement,
85 NULL,
86 NULL,
87 NULL,
88 RemoveLinePoint,
89 RemovePolygonPoint,
90 RemoveArc,
91 RemoveRat
93 static ObjectFunctionType DestroyFunctions = {
94 DestroyLine,
95 DestroyText,
96 DestroyPolygon,
97 DestroyVia,
98 DestroyElement,
99 NULL,
100 NULL,
101 NULL,
102 NULL,
103 DestroyPolygonPoint,
104 DestroyArc,
105 DestroyRat
107 static DataType *DestroyTarget;
108 static bool Bulk = false;
110 /* ---------------------------------------------------------------------------
111 * remove PCB
113 void
114 RemovePCB (PCBType *Ptr)
116 ClearUndoList (true);
117 FreePCBMemory (Ptr);
118 free (Ptr);
121 /* ---------------------------------------------------------------------------
122 * destroys a via
124 static void *
125 DestroyVia (PinType *Via)
127 r_delete_entry (DestroyTarget->via_tree, (BoxType *) Via);
128 free (Via->Name);
130 DestroyTarget->Via = g_list_remove (DestroyTarget->Via, Via);
131 DestroyTarget->ViaN --;
133 g_slice_free (PinType, Via);
135 return NULL;
138 /* ---------------------------------------------------------------------------
139 * destroys a line from a layer
141 static void *
142 DestroyLine (LayerType *Layer, LineType *Line)
144 r_delete_entry (Layer->line_tree, (BoxType *) Line);
145 free (Line->Number);
147 Layer->Line = g_list_remove (Layer->Line, Line);
148 Layer->LineN --;
150 g_slice_free (LineType, Line);
152 return NULL;
155 /* ---------------------------------------------------------------------------
156 * destroys an arc from a layer
158 static void *
159 DestroyArc (LayerType *Layer, ArcType *Arc)
161 r_delete_entry (Layer->arc_tree, (BoxType *) Arc);
163 Layer->Arc = g_list_remove (Layer->Arc, Arc);
164 Layer->ArcN --;
166 g_slice_free (ArcType, Arc);
168 return NULL;
171 /* ---------------------------------------------------------------------------
172 * destroys a polygon from a layer
174 static void *
175 DestroyPolygon (LayerType *Layer, PolygonType *Polygon)
177 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
178 FreePolygonMemory (Polygon);
180 Layer->Polygon = g_list_remove (Layer->Polygon, Polygon);
181 Layer->PolygonN --;
183 g_slice_free (PolygonType, Polygon);
185 return NULL;
188 /* ---------------------------------------------------------------------------
189 * removes a polygon-point from a polygon and destroys the data
191 static void *
192 DestroyPolygonPoint (LayerType *Layer,
193 PolygonType *Polygon, PointType *Point)
195 Cardinal point_idx;
196 Cardinal i;
197 Cardinal contour;
198 Cardinal contour_start, contour_end, contour_points;
200 point_idx = polygon_point_idx (Polygon, Point);
201 contour = polygon_point_contour (Polygon, point_idx);
202 contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1];
203 contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN :
204 Polygon->HoleIndex[contour];
205 contour_points = contour_end - contour_start;
207 if (contour_points <= 3)
208 return RemovePolygonContour (Layer, Polygon, contour);
210 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
212 /* remove point from list, keep point order */
213 for (i = point_idx; i < Polygon->PointN - 1; i++)
214 Polygon->Points[i] = Polygon->Points[i + 1];
215 Polygon->PointN--;
217 /* Shift down indices of any holes */
218 for (i = 0; i < Polygon->HoleIndexN; i++)
219 if (Polygon->HoleIndex[i] > point_idx)
220 Polygon->HoleIndex[i]--;
222 SetPolygonBoundingBox (Polygon);
223 r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
224 InitClip (PCB->Data, Layer, Polygon);
225 return (Polygon);
228 /* ---------------------------------------------------------------------------
229 * destroys a text from a layer
231 static void *
232 DestroyText (LayerType *Layer, TextType *Text)
234 free (Text->TextString);
235 r_delete_entry (Layer->text_tree, (BoxType *) Text);
237 Layer->Text = g_list_remove (Layer->Text, Text);
238 Layer->TextN --;
240 g_slice_free (TextType, Text);
242 return NULL;
245 /* ---------------------------------------------------------------------------
246 * destroys a element
248 static void *
249 DestroyElement (ElementType *Element)
251 if (DestroyTarget->element_tree)
252 r_delete_entry (DestroyTarget->element_tree, (BoxType *) Element);
253 if (DestroyTarget->pin_tree)
255 PIN_LOOP (Element);
257 r_delete_entry (DestroyTarget->pin_tree, (BoxType *) pin);
259 END_LOOP;
261 if (DestroyTarget->pad_tree)
263 PAD_LOOP (Element);
265 r_delete_entry (DestroyTarget->pad_tree, (BoxType *) pad);
267 END_LOOP;
269 ELEMENTTEXT_LOOP (Element);
271 if (DestroyTarget->name_tree[n])
272 r_delete_entry (DestroyTarget->name_tree[n], (BoxType *) text);
274 END_LOOP;
275 FreeElementMemory (Element);
277 DestroyTarget->Element = g_list_remove (DestroyTarget->Element, Element);
278 DestroyTarget->ElementN --;
280 g_slice_free (ElementType, Element);
282 return NULL;
285 /* ---------------------------------------------------------------------------
286 * destroys a rat
288 static void *
289 DestroyRat (RatType *Rat)
291 if (DestroyTarget->rat_tree)
292 r_delete_entry (DestroyTarget->rat_tree, &Rat->BoundingBox);
294 DestroyTarget->Rat = g_list_remove (DestroyTarget->Rat, Rat);
295 DestroyTarget->RatN --;
297 g_slice_free (RatType, Rat);
299 return NULL;
303 /* ---------------------------------------------------------------------------
304 * removes a via
306 static void *
307 RemoveVia (PinType *Via)
309 /* erase from screen and memory */
310 if (PCB->ViaOn)
312 EraseVia (Via);
313 if (!Bulk)
314 Draw ();
316 MoveObjectToRemoveUndoList (VIA_TYPE, Via, Via, Via);
317 return NULL;
320 /* ---------------------------------------------------------------------------
321 * removes a rat
323 static void *
324 RemoveRat (RatType *Rat)
326 /* erase from screen and memory */
327 if (PCB->RatOn)
329 EraseRat (Rat);
330 if (!Bulk)
331 Draw ();
333 MoveObjectToRemoveUndoList (RATLINE_TYPE, Rat, Rat, Rat);
334 return NULL;
337 struct rlp_info
339 jmp_buf env;
340 LineType *line;
341 PointType *point;
343 static int
344 remove_point (const BoxType * b, void *cl)
346 LineType *line = (LineType *) b;
347 struct rlp_info *info = (struct rlp_info *) cl;
348 if (line == info->line)
349 return 0;
350 if ((line->Point1.X == info->point->X)
351 && (line->Point1.Y == info->point->Y))
353 info->line = line;
354 info->point = &line->Point1;
355 longjmp (info->env, 1);
357 else
358 if ((line->Point2.X == info->point->X)
359 && (line->Point2.Y == info->point->Y))
361 info->line = line;
362 info->point = &line->Point2;
363 longjmp (info->env, 1);
365 return 0;
368 /* ---------------------------------------------------------------------------
369 * removes a line point, or a line if the selected point is the end
371 static void *
372 RemoveLinePoint (LayerType *Layer, LineType *Line, PointType *Point)
374 PointType other;
375 struct rlp_info info;
376 if (&Line->Point1 == Point)
377 other = Line->Point2;
378 else
379 other = Line->Point1;
380 info.line = Line;
381 info.point = Point;
382 if (setjmp (info.env) == 0)
384 r_search (Layer->line_tree, (const BoxType *) Point, NULL, remove_point,
385 &info);
386 return RemoveLine (Layer, Line);
388 MoveObject (LINEPOINT_TYPE, Layer, info.line, info.point,
389 other.X - Point->X, other.Y - Point->Y);
390 return (RemoveLine (Layer, Line));
393 /* ---------------------------------------------------------------------------
394 * removes a line from a layer
396 void *
397 RemoveLine (LayerType *Layer, LineType *Line)
399 /* erase from screen */
400 if (Layer->On)
402 EraseLine (Line);
403 if (!Bulk)
404 Draw ();
406 MoveObjectToRemoveUndoList (LINE_TYPE, Layer, Line, Line);
407 return NULL;
410 /* ---------------------------------------------------------------------------
411 * removes an arc from a layer
413 void *
414 RemoveArc (LayerType *Layer, ArcType *Arc)
416 /* erase from screen */
417 if (Layer->On)
419 EraseArc (Arc);
420 if (!Bulk)
421 Draw ();
423 MoveObjectToRemoveUndoList (ARC_TYPE, Layer, Arc, Arc);
424 return NULL;
427 /* ---------------------------------------------------------------------------
428 * removes a text from a layer
430 void *
431 RemoveText (LayerType *Layer, TextType *Text)
433 /* erase from screen */
434 if (Layer->On)
436 EraseText (Layer, Text);
437 if (!Bulk)
438 Draw ();
440 MoveObjectToRemoveUndoList (TEXT_TYPE, Layer, Text, Text);
441 return NULL;
444 /* ---------------------------------------------------------------------------
445 * removes a polygon from a layer
447 void *
448 RemovePolygon (LayerType *Layer, PolygonType *Polygon)
450 /* erase from screen */
451 if (Layer->On)
453 ErasePolygon (Polygon);
454 if (!Bulk)
455 Draw ();
457 MoveObjectToRemoveUndoList (POLYGON_TYPE, Layer, Polygon, Polygon);
458 return NULL;
461 /* ---------------------------------------------------------------------------
462 * removes a contour from a polygon.
463 * If removing the outer contour, it removes the whole polygon.
465 static void *
466 RemovePolygonContour (LayerType *Layer,
467 PolygonType *Polygon,
468 Cardinal contour)
470 Cardinal contour_start, contour_end, contour_points;
471 Cardinal i;
473 if (contour == 0)
474 return RemovePolygon (Layer, Polygon);
476 if (Layer->On)
478 ErasePolygon (Polygon);
479 if (!Bulk)
480 Draw ();
483 /* Copy the polygon to the undo list */
484 AddObjectToRemoveContourUndoList (POLYGON_TYPE, Layer, Polygon);
486 contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1];
487 contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN :
488 Polygon->HoleIndex[contour];
489 contour_points = contour_end - contour_start;
491 /* remove points from list, keep point order */
492 for (i = contour_start; i < Polygon->PointN - contour_points; i++)
493 Polygon->Points[i] = Polygon->Points[i + contour_points];
494 Polygon->PointN -= contour_points;
496 /* remove hole from list and shift down remaining indices */
497 for (i = contour; i < Polygon->HoleIndexN; i++)
498 Polygon->HoleIndex[i - 1] = Polygon->HoleIndex[i] - contour_points;
499 Polygon->HoleIndexN--;
501 InitClip (PCB->Data, Layer, Polygon);
502 /* redraw polygon if necessary */
503 if (Layer->On)
505 DrawPolygon (Layer, Polygon);
506 if (!Bulk)
507 Draw ();
509 return NULL;
512 /* ---------------------------------------------------------------------------
513 * removes a polygon-point from a polygon
515 static void *
516 RemovePolygonPoint (LayerType *Layer,
517 PolygonType *Polygon, PointType *Point)
519 Cardinal point_idx;
520 Cardinal i;
521 Cardinal contour;
522 Cardinal contour_start, contour_end, contour_points;
524 point_idx = polygon_point_idx (Polygon, Point);
525 contour = polygon_point_contour (Polygon, point_idx);
526 contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1];
527 contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN :
528 Polygon->HoleIndex[contour];
529 contour_points = contour_end - contour_start;
531 if (contour_points <= 3)
532 return RemovePolygonContour (Layer, Polygon, contour);
534 if (Layer->On)
535 ErasePolygon (Polygon);
537 /* insert the polygon-point into the undo list */
538 AddObjectToRemovePointUndoList (POLYGONPOINT_TYPE, Layer, Polygon, point_idx);
539 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
541 /* remove point from list, keep point order */
542 for (i = point_idx; i < Polygon->PointN - 1; i++)
543 Polygon->Points[i] = Polygon->Points[i + 1];
544 Polygon->PointN--;
546 /* Shift down indices of any holes */
547 for (i = 0; i < Polygon->HoleIndexN; i++)
548 if (Polygon->HoleIndex[i] > point_idx)
549 Polygon->HoleIndex[i]--;
551 SetPolygonBoundingBox (Polygon);
552 r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
553 RemoveExcessPolygonPoints (Layer, Polygon);
554 InitClip (PCB->Data, Layer, Polygon);
556 /* redraw polygon if necessary */
557 if (Layer->On)
559 DrawPolygon (Layer, Polygon);
560 if (!Bulk)
561 Draw ();
563 return NULL;
566 /* ---------------------------------------------------------------------------
567 * removes an element
569 void *
570 RemoveElement (ElementType *Element)
572 /* erase from screen */
573 if ((PCB->ElementOn || PCB->PinOn) &&
574 (FRONT (Element) || PCB->InvisibleObjectsOn))
576 EraseElement (Element);
577 if (!Bulk)
578 Draw ();
580 MoveObjectToRemoveUndoList (ELEMENT_TYPE, Element, Element, Element);
581 return NULL;
584 /* ----------------------------------------------------------------------
585 * removes all selected and visible objects
586 * returns true if any objects have been removed
588 bool
589 RemoveSelected (void)
591 Bulk = true;
592 if (SelectedOperation (&RemoveFunctions, false, ALL_TYPES))
594 IncrementUndoSerialNumber ();
595 Draw ();
596 Bulk = false;
597 return (true);
599 Bulk = false;
600 return (false);
603 /* ---------------------------------------------------------------------------
604 * remove object as referred by pointers and type,
605 * allocated memory is passed to the 'remove undo' list
607 void *
608 RemoveObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
610 void *ptr = ObjectOperation (&RemoveFunctions, Type, Ptr1, Ptr2, Ptr3);
611 return (ptr);
614 /* ---------------------------------------------------------------------------
615 * DeleteRats - deletes rat lines only
616 * can delete all rat lines, or only selected one
619 bool
620 DeleteRats (bool selected)
622 bool changed = false;
623 Bulk = true;
624 RAT_LOOP (PCB->Data);
626 if ((!selected) || TEST_FLAG (SELECTEDFLAG, line))
628 changed = true;
629 RemoveRat (line);
632 END_LOOP;
633 Bulk = false;
634 if (changed)
636 Draw ();
637 IncrementUndoSerialNumber ();
639 return (changed);
642 /* ---------------------------------------------------------------------------
643 * remove object as referred by pointers and type
644 * allocated memory is destroyed assumed to already be erased
646 void *
647 DestroyObject (DataType *Target, int Type, void *Ptr1,
648 void *Ptr2, void *Ptr3)
650 DestroyTarget = Target;
651 return (ObjectOperation (&DestroyFunctions, Type, Ptr1, Ptr2, Ptr3));