Fix node_label() function to work with self-intersection
[geda-pcb/gde.git] / src / remove.c
bloba82b478388528b4d156fe29e16fc791ae4b98cfc
1 /* $Id$ */
3 /*
4 * COPYRIGHT
6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
30 /* functions used to remove vias, pins ...
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
37 #include <setjmp.h>
38 #include <memory.h>
40 #include "global.h"
42 #include "data.h"
43 #include "draw.h"
44 #include "error.h"
45 #include "misc.h"
46 #include "move.h"
47 #include "mymem.h"
48 #include "polygon.h"
49 #include "rats.h"
50 #include "remove.h"
51 #include "rtree.h"
52 #include "search.h"
53 #include "select.h"
54 #include "set.h"
55 #include "undo.h"
57 #ifdef HAVE_LIBDMALLOC
58 #include <dmalloc.h>
59 #endif
61 RCSID ("$Id$");
64 /* ---------------------------------------------------------------------------
65 * some local prototypes
67 static void *DestroyVia (PinTypePtr);
68 static void *DestroyRat (RatTypePtr);
69 static void *DestroyLine (LayerTypePtr, LineTypePtr);
70 static void *DestroyArc (LayerTypePtr, ArcTypePtr);
71 static void *DestroyText (LayerTypePtr, TextTypePtr);
72 static void *DestroyPolygon (LayerTypePtr, PolygonTypePtr);
73 static void *DestroyElement (ElementTypePtr);
74 static void *RemoveVia (PinTypePtr);
75 static void *RemoveRat (RatTypePtr);
76 static void *DestroyPolygonPoint (LayerTypePtr, PolygonTypePtr, PointTypePtr);
77 static void *RemovePolygonPoint (LayerTypePtr, PolygonTypePtr, PointTypePtr);
78 static void *RemoveLinePoint (LayerTypePtr, LineTypePtr, PointTypePtr);
80 /* ---------------------------------------------------------------------------
81 * some local types
83 static ObjectFunctionType RemoveFunctions = {
84 RemoveLine,
85 RemoveText,
86 RemovePolygon,
87 RemoveVia,
88 RemoveElement,
89 NULL,
90 NULL,
91 NULL,
92 RemoveLinePoint,
93 RemovePolygonPoint,
94 RemoveArc,
95 RemoveRat
97 static ObjectFunctionType DestroyFunctions = {
98 DestroyLine,
99 DestroyText,
100 DestroyPolygon,
101 DestroyVia,
102 DestroyElement,
103 NULL,
104 NULL,
105 NULL,
106 NULL,
107 DestroyPolygonPoint,
108 DestroyArc,
109 DestroyRat
111 static DataTypePtr DestroyTarget;
112 static Boolean Bulk = False;
114 /* ---------------------------------------------------------------------------
115 * remove PCB
117 void
118 RemovePCB (PCBTypePtr Ptr)
120 ClearUndoList (True);
121 FreePCBMemory (Ptr);
122 SaveFree (Ptr);
125 /* ---------------------------------------------------------------------------
126 * destroys a via
128 static void *
129 DestroyVia (PinTypePtr Via)
131 r_delete_entry (DestroyTarget->via_tree, (BoxTypePtr) Via);
132 MYFREE (Via->Name);
133 if (Via != &DestroyTarget->Via[--DestroyTarget->ViaN])
135 *Via = DestroyTarget->Via[DestroyTarget->ViaN];
136 r_substitute (DestroyTarget->via_tree, (BoxTypePtr)
137 (BoxType *) & DestroyTarget->Via[DestroyTarget->ViaN],
138 (BoxType *) Via);
140 memset (&DestroyTarget->Via[DestroyTarget->ViaN], 0, sizeof (PinType));
141 return (NULL);
144 /* ---------------------------------------------------------------------------
145 * destroys a line from a layer
147 static void *
148 DestroyLine (LayerTypePtr Layer, LineTypePtr Line)
150 r_delete_entry (Layer->line_tree, (BoxTypePtr) Line);
151 MYFREE (Line->Number);
152 if (Line != &Layer->Line[--Layer->LineN])
154 *Line = Layer->Line[Layer->LineN];
155 /* tricky - line pointers are moved around */
156 r_substitute (Layer->line_tree, (BoxType *) & Layer->Line[Layer->LineN],
157 (BoxType *) Line);
159 memset (&Layer->Line[Layer->LineN], 0, sizeof (LineType));
160 return (NULL);
163 /* ---------------------------------------------------------------------------
164 * destroys an arc from a layer
166 static void *
167 DestroyArc (LayerTypePtr Layer, ArcTypePtr Arc)
169 r_delete_entry (Layer->arc_tree, (BoxTypePtr) Arc);
170 if (Arc != &Layer->Arc[--Layer->ArcN])
172 *Arc = Layer->Arc[Layer->ArcN];
173 r_substitute (Layer->arc_tree, (BoxType *) & Layer->Arc[Layer->ArcN],
174 (BoxType *) Arc);
176 memset (&Layer->Arc[Layer->ArcN], 0, sizeof (ArcType));
177 return (NULL);
180 /* ---------------------------------------------------------------------------
181 * destroys a polygon from a layer
183 static void *
184 DestroyPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
186 r_delete_entry (Layer->polygon_tree, (BoxTypePtr) Polygon);
187 FreePolygonMemory (Polygon);
188 if (Polygon != &Layer->Polygon[--Layer->PolygonN])
190 *Polygon = Layer->Polygon[Layer->PolygonN];
191 r_substitute (Layer->polygon_tree,
192 (BoxType *) & Layer->Polygon[Layer->PolygonN],
193 (BoxType *) Polygon);
195 memset (&Layer->Polygon[Layer->PolygonN], 0, sizeof (PolygonType));
196 return (NULL);
199 /* ---------------------------------------------------------------------------
200 * removes a polygon-point from a polygon and destroys the data
202 static void *
203 DestroyPolygonPoint (LayerTypePtr Layer,
204 PolygonTypePtr Polygon, PointTypePtr Point)
206 PointTypePtr ptr;
208 if (Polygon->PointN <= 3)
209 return RemovePolygon (Layer, Polygon);
210 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
211 for (ptr = Point + 1; ptr != &Polygon->Points[Polygon->PointN]; ptr++)
213 *Point = *ptr;
214 Point = ptr;
216 Polygon->PointN--;
217 SetPolygonBoundingBox (Polygon);
218 r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
219 InitClip (PCB->Data, Layer, Polygon);
220 return (Polygon);
223 /* ---------------------------------------------------------------------------
224 * destroys a text from a layer
226 static void *
227 DestroyText (LayerTypePtr Layer, TextTypePtr Text)
229 MYFREE (Text->TextString);
230 r_delete_entry (Layer->text_tree, (BoxTypePtr) Text);
231 if (Text != &Layer->Text[--Layer->TextN])
233 *Text = Layer->Text[Layer->TextN];
234 r_substitute (Layer->text_tree, (BoxType *) & Layer->Text[Layer->TextN],
235 (BoxType *) Text);
237 memset (&Layer->Text[Layer->TextN], 0, sizeof (TextType));
238 return (NULL);
241 /* ---------------------------------------------------------------------------
242 * destroys a element
244 static void *
245 DestroyElement (ElementTypePtr Element)
247 if (DestroyTarget->element_tree)
248 r_delete_entry (DestroyTarget->element_tree, (BoxType *) Element);
249 if (DestroyTarget->pin_tree)
251 PIN_LOOP (Element);
253 r_delete_entry (DestroyTarget->pin_tree, (BoxType *) pin);
255 END_LOOP;
257 if (DestroyTarget->pad_tree)
259 PAD_LOOP (Element);
261 r_delete_entry (DestroyTarget->pad_tree, (BoxType *) pad);
263 END_LOOP;
265 ELEMENTTEXT_LOOP (Element);
267 if (DestroyTarget->name_tree[n])
268 r_delete_entry (DestroyTarget->name_tree[n], (BoxType *) text);
270 END_LOOP;
271 FreeElementMemory (Element);
272 if (Element != &DestroyTarget->Element[--DestroyTarget->ElementN])
274 *Element = DestroyTarget->Element[DestroyTarget->ElementN];
275 /* deal with changed element pointer */
276 r_substitute (DestroyTarget->element_tree,
277 (BoxType *) & DestroyTarget->Element[DestroyTarget->
278 ElementN],
279 (BoxType *) Element);
281 PIN_LOOP (Element);
283 pin->Element = Element;
285 END_LOOP;
286 PAD_LOOP (Element);
288 pad->Element = Element;
290 END_LOOP;
291 ELEMENTTEXT_LOOP (Element);
293 r_substitute (DestroyTarget->name_tree[n],
294 (BoxType *) & DestroyTarget->Element[DestroyTarget->
295 ElementN].Name[n],
296 (BoxType *) text);
297 text->Element = Element;
299 END_LOOP;
300 memset (&DestroyTarget->Element[DestroyTarget->ElementN], 0,
301 sizeof (ElementType));
302 return (NULL);
305 /* ---------------------------------------------------------------------------
306 * destroys a rat
308 static void *
309 DestroyRat (RatTypePtr Rat)
311 if (DestroyTarget->rat_tree)
312 r_delete_entry (DestroyTarget->rat_tree, &Rat->BoundingBox);
313 if (Rat != &DestroyTarget->Rat[--DestroyTarget->RatN])
315 *Rat = DestroyTarget->Rat[DestroyTarget->RatN];
316 r_substitute (DestroyTarget->rat_tree,
317 &DestroyTarget->Rat[DestroyTarget->RatN].BoundingBox,
318 &Rat->BoundingBox);
320 memset (&DestroyTarget->Rat[DestroyTarget->RatN], 0, sizeof (RatType));
321 return (NULL);
325 /* ---------------------------------------------------------------------------
326 * removes a via
328 static void *
329 RemoveVia (PinTypePtr Via)
331 /* erase from screen and memory */
332 if (PCB->ViaOn)
334 EraseVia (Via);
335 if (!Bulk)
336 Draw ();
338 MoveObjectToRemoveUndoList (VIA_TYPE, Via, Via, Via);
339 return (NULL);
342 /* ---------------------------------------------------------------------------
343 * removes a rat
345 static void *
346 RemoveRat (RatTypePtr Rat)
348 /* erase from screen and memory */
349 if (PCB->RatOn)
351 EraseRat (Rat);
352 if (!Bulk)
353 Draw ();
355 MoveObjectToRemoveUndoList (RATLINE_TYPE, Rat, Rat, Rat);
356 return (NULL);
359 struct rlp_info
361 jmp_buf env;
362 LineTypePtr line;
363 PointTypePtr point;
365 static int
366 remove_point (const BoxType * b, void *cl)
368 LineType *line = (LineType *) b;
369 struct rlp_info *info = (struct rlp_info *) cl;
370 if (line == info->line)
371 return 0;
372 if ((line->Point1.X == info->point->X)
373 && (line->Point1.Y == info->point->Y))
375 info->line = line;
376 info->point = &line->Point1;
377 longjmp (info->env, 1);
379 else
380 if ((line->Point2.X == info->point->X)
381 && (line->Point2.Y == info->point->Y))
383 info->line = line;
384 info->point = &line->Point2;
385 longjmp (info->env, 1);
387 return 0;
390 /* ---------------------------------------------------------------------------
391 * removes a line point, or a line if the selected point is the end
393 static void *
394 RemoveLinePoint (LayerTypePtr Layer, LineTypePtr Line, PointTypePtr Point)
396 PointType other;
397 struct rlp_info info;
398 if (&Line->Point1 == Point)
399 other = Line->Point2;
400 else
401 other = Line->Point1;
402 info.line = Line;
403 info.point = Point;
404 if (setjmp (info.env) == 0)
406 r_search (Layer->line_tree, (const BoxType *) Point, NULL, remove_point,
407 &info);
408 return RemoveLine (Layer, Line);
410 MoveObject (LINEPOINT_TYPE, Layer, info.line, info.point,
411 other.X - Point->X, other.Y - Point->Y);
412 return (RemoveLine (Layer, Line));
415 /* ---------------------------------------------------------------------------
416 * removes a line from a layer
418 void *
419 RemoveLine (LayerTypePtr Layer, LineTypePtr Line)
421 /* erase from screen */
422 if (Layer->On)
424 EraseLine (Line);
425 if (!Bulk)
426 Draw ();
428 MoveObjectToRemoveUndoList (LINE_TYPE, Layer, Line, Line);
429 return (NULL);
432 /* ---------------------------------------------------------------------------
433 * removes an arc from a layer
435 void *
436 RemoveArc (LayerTypePtr Layer, ArcTypePtr Arc)
438 /* erase from screen */
439 if (Layer->On)
441 EraseArc (Arc);
442 if (!Bulk)
443 Draw ();
445 MoveObjectToRemoveUndoList (ARC_TYPE, Layer, Arc, Arc);
446 return (NULL);
449 /* ---------------------------------------------------------------------------
450 * removes a text from a layer
452 void *
453 RemoveText (LayerTypePtr Layer, TextTypePtr Text)
455 /* erase from screen */
456 if (Layer->On)
458 EraseText (Layer, Text);
459 if (!Bulk)
460 Draw ();
462 MoveObjectToRemoveUndoList (TEXT_TYPE, Layer, Text, Text);
463 return (NULL);
466 /* ---------------------------------------------------------------------------
467 * removes a polygon from a layer
469 void *
470 RemovePolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
472 /* erase from screen */
473 if (Layer->On)
475 ErasePolygon (Polygon);
476 if (!Bulk)
477 Draw ();
479 MoveObjectToRemoveUndoList (POLYGON_TYPE, Layer, Polygon, Polygon);
480 return (NULL);
483 /* ---------------------------------------------------------------------------
484 * removes a polygon-point from a polygon
486 static void *
487 RemovePolygonPoint (LayerTypePtr Layer,
488 PolygonTypePtr Polygon, PointTypePtr Point)
490 PointTypePtr ptr;
491 Cardinal index = 0;
492 if (Polygon->PointN <= 3)
493 return RemovePolygon (Layer, Polygon);
494 if (Layer->On)
495 ErasePolygon (Polygon);
496 /* insert the polygon-point into the undo list */
497 POLYGONPOINT_LOOP (Polygon);
499 if (point == Point)
501 index = n;
502 break;
505 END_LOOP;
506 AddObjectToRemovePointUndoList (POLYGONPOINT_TYPE, Layer, Polygon, index);
507 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
508 /* remove point from list, keep point order */
509 for (ptr = Point + 1; ptr != &Polygon->Points[Polygon->PointN]; ptr++)
511 *Point = *ptr;
512 Point = ptr;
514 Polygon->PointN--;
515 SetPolygonBoundingBox (Polygon);
516 r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
517 RemoveExcessPolygonPoints (Layer, Polygon);
518 InitClip (PCB->Data, Layer, Polygon);
519 /* redraw polygon if necessary */
520 if (Layer->On)
522 DrawPolygon (Layer, Polygon, 0);
523 if (!Bulk)
524 Draw ();
526 return (NULL);
529 /* ---------------------------------------------------------------------------
530 * removes an element
532 void *
533 RemoveElement (ElementTypePtr Element)
535 /* erase from screen */
536 if ((PCB->ElementOn || PCB->PinOn) &&
537 (FRONT (Element) || PCB->InvisibleObjectsOn))
539 EraseElement (Element);
540 if (!Bulk)
541 Draw ();
543 MoveObjectToRemoveUndoList (ELEMENT_TYPE, Element, Element, Element);
544 return (NULL);
547 /* ----------------------------------------------------------------------
548 * removes all selected and visible objects
549 * returns True if any objects have been removed
551 Boolean
552 RemoveSelected (void)
554 Bulk = True;
555 if (SelectedOperation (&RemoveFunctions, False, ALL_TYPES))
557 IncrementUndoSerialNumber ();
558 Draw ();
559 Bulk = False;
560 return (True);
562 Bulk = False;
563 return (False);
566 /* ---------------------------------------------------------------------------
567 * remove object as referred by pointers and type,
568 * allocated memory is passed to the 'remove undo' list
570 void *
571 RemoveObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
573 void *ptr = ObjectOperation (&RemoveFunctions, Type, Ptr1, Ptr2, Ptr3);
574 return (ptr);
577 /* ---------------------------------------------------------------------------
578 * DeleteRats - deletes rat lines only
579 * can delete all rat lines, or only selected one
582 Boolean
583 DeleteRats (Boolean selected)
585 Boolean changed = False;
586 Bulk = True;
587 RAT_LOOP (PCB->Data);
589 if ((!selected) || TEST_FLAG (SELECTEDFLAG, line))
591 changed = True;
592 RemoveRat (line);
595 END_LOOP;
596 Bulk = False;
597 if (changed)
599 Draw ();
600 IncrementUndoSerialNumber ();
602 return (changed);
605 /* ---------------------------------------------------------------------------
606 * remove object as referred by pointers and type
607 * allocated memory is destroyed assumed to already be erased
609 void *
610 DestroyObject (DataTypePtr Target, int Type, void *Ptr1,
611 void *Ptr2, void *Ptr3)
613 DestroyTarget = Target;
614 return (ObjectOperation (&DestroyFunctions, Type, Ptr1, Ptr2, Ptr3));