src/undo.c: Converted plain comments into doxygen comments.
[geda-pcb/pcjc2.git] / src / remove.c
blob3ca519738c19ae800c60540de36f239b9195bfce
1 /*!
2 * \file src/remove.c
4 * \brief Functions used to remove vias, pins ...
6 * <hr>
8 * <h1><b>Copyright.</b></h1>\n
10 * PCB, interactive printed circuit board design.
12 * Copyright (C) 1994,1995,1996 Thomas Nau
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 * Contact addresses for paper mail and Email:
30 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
32 * Thomas.Nau@rz.uni-ulm.de
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
40 #include <setjmp.h>
41 #include <memory.h>
43 #include "global.h"
45 #include "data.h"
46 #include "draw.h"
47 #include "error.h"
48 #include "misc.h"
49 #include "move.h"
50 #include "mymem.h"
51 #include "polygon.h"
52 #include "rats.h"
53 #include "remove.h"
54 #include "rtree.h"
55 #include "search.h"
56 #include "select.h"
57 #include "set.h"
58 #include "undo.h"
60 #ifdef HAVE_LIBDMALLOC
61 #include <dmalloc.h>
62 #endif
64 /* ---------------------------------------------------------------------------
65 * some local prototypes
67 static void *DestroyVia (PinType *);
68 static void *DestroyRat (RatType *);
69 static void *DestroyLine (LayerType *, LineType *);
70 static void *DestroyArc (LayerType *, ArcType *);
71 static void *DestroyText (LayerType *, TextType *);
72 static void *DestroyPolygon (LayerType *, PolygonType *);
73 static void *DestroyElement (ElementType *);
74 static void *RemoveVia (PinType *);
75 static void *RemoveRat (RatType *);
76 static void *DestroyPolygonPoint (LayerType *, PolygonType *, PointType *);
77 static void *RemovePolygonContour (LayerType *, PolygonType *, Cardinal);
78 static void *RemovePolygonPoint (LayerType *, PolygonType *, PointType *);
79 static void *RemoveLinePoint (LayerType *, LineType *, PointType *);
81 /* ---------------------------------------------------------------------------
82 * some local types
84 static ObjectFunctionType RemoveFunctions = {
85 RemoveLine,
86 RemoveText,
87 RemovePolygon,
88 RemoveVia,
89 RemoveElement,
90 NULL,
91 NULL,
92 NULL,
93 RemoveLinePoint,
94 RemovePolygonPoint,
95 RemoveArc,
96 RemoveRat
98 static ObjectFunctionType DestroyFunctions = {
99 DestroyLine,
100 DestroyText,
101 DestroyPolygon,
102 DestroyVia,
103 DestroyElement,
104 NULL,
105 NULL,
106 NULL,
107 NULL,
108 DestroyPolygonPoint,
109 DestroyArc,
110 DestroyRat
112 static DataType *DestroyTarget;
113 static bool Bulk = false;
116 * \brief Remove PCB.
118 void
119 RemovePCB (PCBType *Ptr)
121 ClearUndoList (true);
122 FreePCBMemory (Ptr);
123 free (Ptr);
127 * \brief Destroys a via.
129 static void *
130 DestroyVia (PinType *Via)
132 r_delete_entry (DestroyTarget->via_tree, (BoxType *) Via);
133 free (Via->Name);
135 DestroyTarget->Via = g_list_remove (DestroyTarget->Via, Via);
136 DestroyTarget->ViaN --;
138 g_slice_free (PinType, Via);
140 return NULL;
144 * \brief Destroys a line from a layer.
146 static void *
147 DestroyLine (LayerType *Layer, LineType *Line)
149 r_delete_entry (Layer->line_tree, (BoxType *) Line);
150 free (Line->Number);
152 Layer->Line = g_list_remove (Layer->Line, Line);
153 Layer->LineN --;
155 g_slice_free (LineType, Line);
157 return NULL;
161 * \brief Destroys an arc from a layer.
163 static void *
164 DestroyArc (LayerType *Layer, ArcType *Arc)
166 r_delete_entry (Layer->arc_tree, (BoxType *) Arc);
168 Layer->Arc = g_list_remove (Layer->Arc, Arc);
169 Layer->ArcN --;
171 g_slice_free (ArcType, Arc);
173 return NULL;
177 * \brief Destroys a polygon from a layer.
179 static void *
180 DestroyPolygon (LayerType *Layer, PolygonType *Polygon)
182 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
183 FreePolygonMemory (Polygon);
185 Layer->Polygon = g_list_remove (Layer->Polygon, Polygon);
186 Layer->PolygonN --;
188 g_slice_free (PolygonType, Polygon);
190 return NULL;
194 * \brief Removes a polygon-point from a polygon and destroys the data.
196 static void *
197 DestroyPolygonPoint (LayerType *Layer,
198 PolygonType *Polygon, PointType *Point)
200 Cardinal point_idx;
201 Cardinal i;
202 Cardinal contour;
203 Cardinal contour_start, contour_end, contour_points;
205 point_idx = polygon_point_idx (Polygon, Point);
206 contour = polygon_point_contour (Polygon, point_idx);
207 contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1];
208 contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN :
209 Polygon->HoleIndex[contour];
210 contour_points = contour_end - contour_start;
212 if (contour_points <= 3)
213 return RemovePolygonContour (Layer, Polygon, contour);
215 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
217 /* remove point from list, keep point order */
218 for (i = point_idx; i < Polygon->PointN - 1; i++)
219 Polygon->Points[i] = Polygon->Points[i + 1];
220 Polygon->PointN--;
222 /* Shift down indices of any holes */
223 for (i = 0; i < Polygon->HoleIndexN; i++)
224 if (Polygon->HoleIndex[i] > point_idx)
225 Polygon->HoleIndex[i]--;
227 SetPolygonBoundingBox (Polygon);
228 r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
229 InitClip (PCB->Data, Layer, Polygon);
230 return (Polygon);
234 * \brief Destroys a text from a layer.
236 static void *
237 DestroyText (LayerType *Layer, TextType *Text)
239 free (Text->TextString);
240 r_delete_entry (Layer->text_tree, (BoxType *) Text);
242 Layer->Text = g_list_remove (Layer->Text, Text);
243 Layer->TextN --;
245 g_slice_free (TextType, Text);
247 return NULL;
250 /* ---------------------------------------------------------------------------
251 * destroys a element
253 static void *
254 DestroyElement (ElementType *Element)
256 if (DestroyTarget->element_tree)
257 r_delete_entry (DestroyTarget->element_tree, (BoxType *) Element);
258 if (DestroyTarget->pin_tree)
260 PIN_LOOP (Element);
262 r_delete_entry (DestroyTarget->pin_tree, (BoxType *) pin);
264 END_LOOP;
266 if (DestroyTarget->pad_tree)
268 PAD_LOOP (Element);
270 r_delete_entry (DestroyTarget->pad_tree, (BoxType *) pad);
272 END_LOOP;
274 ELEMENTTEXT_LOOP (Element);
276 if (DestroyTarget->name_tree[n])
277 r_delete_entry (DestroyTarget->name_tree[n], (BoxType *) text);
279 END_LOOP;
280 FreeElementMemory (Element);
282 DestroyTarget->Element = g_list_remove (DestroyTarget->Element, Element);
283 DestroyTarget->ElementN --;
285 g_slice_free (ElementType, Element);
287 return NULL;
291 * \brief Destroys a rat.
293 static void *
294 DestroyRat (RatType *Rat)
296 if (DestroyTarget->rat_tree)
297 r_delete_entry (DestroyTarget->rat_tree, &Rat->BoundingBox);
299 DestroyTarget->Rat = g_list_remove (DestroyTarget->Rat, Rat);
300 DestroyTarget->RatN --;
302 g_slice_free (RatType, Rat);
304 return NULL;
309 * \brief Removes a via.
311 static void *
312 RemoveVia (PinType *Via)
314 /* erase from screen and memory */
315 if (PCB->ViaOn)
317 EraseVia (Via);
318 if (!Bulk)
319 Draw ();
321 MoveObjectToRemoveUndoList (VIA_TYPE, Via, Via, Via);
322 return NULL;
326 * \brief Removes a rat.
328 static void *
329 RemoveRat (RatType *Rat)
331 /* erase from screen and memory */
332 if (PCB->RatOn)
334 EraseRat (Rat);
335 if (!Bulk)
336 Draw ();
338 MoveObjectToRemoveUndoList (RATLINE_TYPE, Rat, Rat, Rat);
339 return NULL;
342 struct rlp_info
344 jmp_buf env;
345 LineType *line;
346 PointType *point;
348 static int
349 remove_point (const BoxType * b, void *cl)
351 LineType *line = (LineType *) b;
352 struct rlp_info *info = (struct rlp_info *) cl;
353 if (line == info->line)
354 return 0;
355 if ((line->Point1.X == info->point->X)
356 && (line->Point1.Y == info->point->Y))
358 info->line = line;
359 info->point = &line->Point1;
360 longjmp (info->env, 1);
362 else
363 if ((line->Point2.X == info->point->X)
364 && (line->Point2.Y == info->point->Y))
366 info->line = line;
367 info->point = &line->Point2;
368 longjmp (info->env, 1);
370 return 0;
374 * \brief Removes a line point, or a line if the selected point is the
375 * end.
377 static void *
378 RemoveLinePoint (LayerType *Layer, LineType *Line, PointType *Point)
380 PointType other;
381 struct rlp_info info;
382 if (&Line->Point1 == Point)
383 other = Line->Point2;
384 else
385 other = Line->Point1;
386 info.line = Line;
387 info.point = Point;
388 if (setjmp (info.env) == 0)
390 r_search (Layer->line_tree, (const BoxType *) Point, NULL, remove_point,
391 &info);
392 return RemoveLine (Layer, Line);
394 MoveObject (LINEPOINT_TYPE, Layer, info.line, info.point,
395 other.X - Point->X, other.Y - Point->Y);
396 return (RemoveLine (Layer, Line));
400 * \brief Removes a line from a layer.
402 void *
403 RemoveLine (LayerType *Layer, LineType *Line)
405 /* erase from screen */
406 if (Layer->On)
408 EraseLine (Line);
409 if (!Bulk)
410 Draw ();
412 MoveObjectToRemoveUndoList (LINE_TYPE, Layer, Line, Line);
413 return NULL;
417 * \brief Removes an arc from a layer.
419 void *
420 RemoveArc (LayerType *Layer, ArcType *Arc)
422 /* erase from screen */
423 if (Layer->On)
425 EraseArc (Arc);
426 if (!Bulk)
427 Draw ();
429 MoveObjectToRemoveUndoList (ARC_TYPE, Layer, Arc, Arc);
430 return NULL;
434 * \brief Removes a text from a layer.
436 void *
437 RemoveText (LayerType *Layer, TextType *Text)
439 /* erase from screen */
440 if (Layer->On)
442 EraseText (Layer, Text);
443 r_delete_entry (Layer->text_tree, (BoxType *) Text);
444 if (!Bulk)
445 Draw ();
447 MoveObjectToRemoveUndoList (TEXT_TYPE, Layer, Text, Text);
448 return NULL;
452 * \brief Removes a polygon from a layer.
454 void *
455 RemovePolygon (LayerType *Layer, PolygonType *Polygon)
457 /* erase from screen */
458 if (Layer->On)
460 ErasePolygon (Polygon);
461 if (!Bulk)
462 Draw ();
464 MoveObjectToRemoveUndoList (POLYGON_TYPE, Layer, Polygon, Polygon);
465 return NULL;
469 * \brief Removes a contour from a polygon.
471 * If removing the outer contour, it removes the whole polygon.
473 static void *
474 RemovePolygonContour (LayerType *Layer,
475 PolygonType *Polygon,
476 Cardinal contour)
478 Cardinal contour_start, contour_end, contour_points;
479 Cardinal i;
481 if (contour == 0)
482 return RemovePolygon (Layer, Polygon);
484 if (Layer->On)
486 ErasePolygon (Polygon);
487 if (!Bulk)
488 Draw ();
491 /* Copy the polygon to the undo list */
492 AddObjectToRemoveContourUndoList (POLYGON_TYPE, Layer, Polygon);
494 contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1];
495 contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN :
496 Polygon->HoleIndex[contour];
497 contour_points = contour_end - contour_start;
499 /* remove points from list, keep point order */
500 for (i = contour_start; i < Polygon->PointN - contour_points; i++)
501 Polygon->Points[i] = Polygon->Points[i + contour_points];
502 Polygon->PointN -= contour_points;
504 /* remove hole from list and shift down remaining indices */
505 for (i = contour; i < Polygon->HoleIndexN; i++)
506 Polygon->HoleIndex[i - 1] = Polygon->HoleIndex[i] - contour_points;
507 Polygon->HoleIndexN--;
509 InitClip (PCB->Data, Layer, Polygon);
510 /* redraw polygon if necessary */
511 if (Layer->On)
513 DrawPolygon (Layer, Polygon);
514 if (!Bulk)
515 Draw ();
517 return NULL;
521 * \brief Removes a polygon-point from a polygon.
523 static void *
524 RemovePolygonPoint (LayerType *Layer,
525 PolygonType *Polygon, PointType *Point)
527 Cardinal point_idx;
528 Cardinal i;
529 Cardinal contour;
530 Cardinal contour_start, contour_end, contour_points;
532 point_idx = polygon_point_idx (Polygon, Point);
533 contour = polygon_point_contour (Polygon, point_idx);
534 contour_start = (contour == 0) ? 0 : Polygon->HoleIndex[contour - 1];
535 contour_end = (contour == Polygon->HoleIndexN) ? Polygon->PointN :
536 Polygon->HoleIndex[contour];
537 contour_points = contour_end - contour_start;
539 if (contour_points <= 3)
540 return RemovePolygonContour (Layer, Polygon, contour);
542 if (Layer->On)
543 ErasePolygon (Polygon);
545 /* insert the polygon-point into the undo list */
546 AddObjectToRemovePointUndoList (POLYGONPOINT_TYPE, Layer, Polygon, point_idx);
547 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
549 /* remove point from list, keep point order */
550 for (i = point_idx; i < Polygon->PointN - 1; i++)
551 Polygon->Points[i] = Polygon->Points[i + 1];
552 Polygon->PointN--;
554 /* Shift down indices of any holes */
555 for (i = 0; i < Polygon->HoleIndexN; i++)
556 if (Polygon->HoleIndex[i] > point_idx)
557 Polygon->HoleIndex[i]--;
559 SetPolygonBoundingBox (Polygon);
560 r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
561 RemoveExcessPolygonPoints (Layer, Polygon);
562 InitClip (PCB->Data, Layer, Polygon);
564 /* redraw polygon if necessary */
565 if (Layer->On)
567 DrawPolygon (Layer, Polygon);
568 if (!Bulk)
569 Draw ();
571 return NULL;
575 * \brief Removes an element.
577 void *
578 RemoveElement (ElementType *Element)
580 /* erase from screen */
581 if ((PCB->ElementOn || PCB->PinOn) &&
582 (FRONT (Element) || PCB->InvisibleObjectsOn))
584 EraseElement (Element);
585 if (!Bulk)
586 Draw ();
588 MoveObjectToRemoveUndoList (ELEMENT_TYPE, Element, Element, Element);
589 return NULL;
593 * \brief Removes all selected and visible objects.
595 * \return true if any objects have been removed.
597 bool
598 RemoveSelected (void)
600 Bulk = true;
601 if (SelectedOperation (&RemoveFunctions, false, ALL_TYPES))
603 IncrementUndoSerialNumber ();
604 Draw ();
605 Bulk = false;
606 return (true);
608 Bulk = false;
609 return (false);
613 * \brief Remove object as referred by pointers and type,
614 * allocated memory is passed to the 'remove undo' list.
616 void *
617 RemoveObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
619 void *ptr = ObjectOperation (&RemoveFunctions, Type, Ptr1, Ptr2, Ptr3);
620 return (ptr);
624 * \brief Deletes rat lines only.
626 * Can delete all rat lines, or only selected one.
628 bool
629 DeleteRats (bool selected)
631 bool changed = false;
632 Bulk = true;
633 RAT_LOOP (PCB->Data);
635 if ((!selected) || TEST_FLAG (SELECTEDFLAG, line))
637 changed = true;
638 RemoveRat (line);
641 END_LOOP;
642 Bulk = false;
643 if (changed)
645 Draw ();
646 IncrementUndoSerialNumber ();
648 return (changed);
652 * \brief Remove object as referred by pointers and type.
654 * Allocated memory is destroyed assumed to already be erased.
656 void *
657 DestroyObject (DataType *Target, int Type, void *Ptr1,
658 void *Ptr2, void *Ptr3)
660 DestroyTarget = Target;
661 return (ObjectOperation (&DestroyFunctions, Type, Ptr1, Ptr2, Ptr3));