Add support for filling / thindrawing raw polygons to the HID interface
[geda-pcb/gde.git] / src / remove.c
blobde88abe61029cb794db0f0e9f4030c2c59161ef3
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 *Via = DestroyTarget->Via[--DestroyTarget->ViaN];
134 r_substitute (DestroyTarget->via_tree, (BoxTypePtr)
135 (BoxType *) & DestroyTarget->Via[DestroyTarget->ViaN],
136 (BoxType *) Via);
137 memset (&DestroyTarget->Via[DestroyTarget->ViaN], 0, sizeof (PinType));
138 return (NULL);
141 /* ---------------------------------------------------------------------------
142 * destroys a line from a layer
144 static void *
145 DestroyLine (LayerTypePtr Layer, LineTypePtr Line)
147 r_delete_entry (Layer->line_tree, (BoxTypePtr) Line);
148 MYFREE (Line->Number);
149 *Line = Layer->Line[--Layer->LineN];
150 /* tricky - line pointers are moved around */
151 r_substitute (Layer->line_tree, (BoxType *) & Layer->Line[Layer->LineN],
152 (BoxType *) Line);
153 memset (&Layer->Line[Layer->LineN], 0, sizeof (LineType));
154 return (NULL);
157 /* ---------------------------------------------------------------------------
158 * destroys an arc from a layer
160 static void *
161 DestroyArc (LayerTypePtr Layer, ArcTypePtr Arc)
163 r_delete_entry (Layer->arc_tree, (BoxTypePtr) Arc);
164 *Arc = Layer->Arc[--Layer->ArcN];
165 r_substitute (Layer->arc_tree, (BoxType *) & Layer->Arc[Layer->ArcN],
166 (BoxType *) Arc);
167 memset (&Layer->Arc[Layer->ArcN], 0, sizeof (ArcType));
168 return (NULL);
171 /* ---------------------------------------------------------------------------
172 * destroys a polygon from a layer
174 static void *
175 DestroyPolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
177 r_delete_entry (Layer->polygon_tree, (BoxTypePtr) Polygon);
178 FreePolygonMemory (Polygon);
179 *Polygon = Layer->Polygon[--Layer->PolygonN];
180 r_substitute (Layer->polygon_tree,
181 (BoxType *) & Layer->Polygon[Layer->PolygonN],
182 (BoxType *) Polygon);
183 memset (&Layer->Polygon[Layer->PolygonN], 0, sizeof (PolygonType));
184 return (NULL);
187 /* ---------------------------------------------------------------------------
188 * removes a polygon-point from a polygon and destroys the data
190 static void *
191 DestroyPolygonPoint (LayerTypePtr Layer,
192 PolygonTypePtr Polygon, PointTypePtr Point)
194 PointTypePtr ptr;
196 if (Polygon->PointN <= 3)
197 return RemovePolygon(Layer, Polygon);
198 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
199 for (ptr = Point + 1; ptr != &Polygon->Points[Polygon->PointN]; ptr++)
201 *Point = *ptr;
202 Point = ptr;
204 Polygon->PointN--;
205 SetPolygonBoundingBox (Polygon);
206 r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
207 InitClip (PCB->Data, Layer, Polygon);
208 return (Polygon);
211 /* ---------------------------------------------------------------------------
212 * destroys a text from a layer
214 static void *
215 DestroyText (LayerTypePtr Layer, TextTypePtr Text)
217 MYFREE (Text->TextString);
218 r_delete_entry (Layer->text_tree, (BoxTypePtr) Text);
219 *Text = Layer->Text[--Layer->TextN];
220 r_substitute (Layer->text_tree, (BoxType *) & Layer->Text[Layer->TextN],
221 (BoxType *) Text);
222 memset (&Layer->Text[Layer->TextN], 0, sizeof (TextType));
223 return (NULL);
226 /* ---------------------------------------------------------------------------
227 * destroys a element
229 static void *
230 DestroyElement (ElementTypePtr Element)
232 if (DestroyTarget->element_tree)
233 r_delete_entry (DestroyTarget->element_tree, (BoxType *) Element);
234 if (DestroyTarget->pin_tree)
236 PIN_LOOP (Element);
238 r_delete_entry (DestroyTarget->pin_tree, (BoxType *) pin);
240 END_LOOP;
242 if (DestroyTarget->pad_tree)
244 PAD_LOOP (Element);
246 r_delete_entry (DestroyTarget->pad_tree, (BoxType *) pad);
248 END_LOOP;
250 ELEMENTTEXT_LOOP (Element);
252 if (DestroyTarget->name_tree[n])
253 r_delete_entry (DestroyTarget->name_tree[n], (BoxType *) text);
255 END_LOOP;
256 FreeElementMemory (Element);
257 *Element = DestroyTarget->Element[--DestroyTarget->ElementN];
258 /* deal with changed element pointer */
259 r_substitute (DestroyTarget->element_tree,
260 (BoxType *) & DestroyTarget->Element[DestroyTarget->ElementN],
261 (BoxType *) Element);
262 PIN_LOOP (Element);
264 pin->Element = Element;
266 END_LOOP;
267 PAD_LOOP (Element);
269 pad->Element = Element;
271 END_LOOP;
272 ELEMENTTEXT_LOOP (Element);
274 r_substitute (DestroyTarget->name_tree[n],
275 (BoxType *) & DestroyTarget->Element[DestroyTarget->
276 ElementN].Name[n],
277 (BoxType *) text);
278 text->Element = Element;
280 END_LOOP;
281 memset (&DestroyTarget->Element[DestroyTarget->ElementN], 0,
282 sizeof (ElementType));
283 return (NULL);
286 /* ---------------------------------------------------------------------------
287 * destroys a rat
289 static void *
290 DestroyRat (RatTypePtr Rat)
292 if (DestroyTarget->rat_tree)
293 r_delete_entry (DestroyTarget->rat_tree, &Rat->BoundingBox);
294 *Rat = DestroyTarget->Rat[--DestroyTarget->RatN];
295 r_substitute (DestroyTarget->rat_tree,
296 &DestroyTarget->Rat[DestroyTarget->RatN].BoundingBox,
297 &Rat->BoundingBox);
298 memset (&DestroyTarget->Rat[DestroyTarget->RatN], 0, sizeof (RatType));
299 return (NULL);
303 /* ---------------------------------------------------------------------------
304 * removes a via
306 static void *
307 RemoveVia (PinTypePtr 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 (RatTypePtr 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 LineTypePtr line;
341 PointTypePtr point;
344 static int
345 remove_point (const BoxType * b, void *cl)
347 LineType *line = (LineType *) b;
348 struct rlp_info *info = (struct rlp_info *) cl;
350 if (line == info->line)
351 return 0;
352 if ((line->Point1.X == info->point->X)
353 && (line->Point1.Y == info->point->Y))
355 info->line = line;
356 info->point = &line->Point1;
357 longjmp (info->env, 1);
359 else if ((line->Point2.X == info->point->X)
360 && (line->Point2.Y == info->point->Y))
362 info->line = line;
363 info->point = &line->Point2;
364 longjmp (info->env, 1);
366 return 0;
369 /* ---------------------------------------------------------------------------
370 * removes a line point, or a line if the selected point is the end
372 static void *
373 RemoveLinePoint (LayerTypePtr Layer, LineTypePtr Line, PointTypePtr Point)
375 PointType other;
376 struct rlp_info info;
378 if (&Line->Point1 == Point)
379 other = Line->Point2;
380 else
381 other = Line->Point1;
382 info.line = Line;
383 info.point = Point;
384 if (setjmp (info.env) == 0)
386 r_search (Layer->line_tree, (const BoxType *) Point, NULL, remove_point,
387 &info);
388 return RemoveLine(Layer, Line);
390 MoveObject (LINEPOINT_TYPE, Layer, info.line, info.point,
391 other.X - Point->X, other.Y - Point->Y);
392 return (RemoveLine (Layer, Line));
395 /* ---------------------------------------------------------------------------
396 * removes a line from a layer
398 void *
399 RemoveLine (LayerTypePtr Layer, LineTypePtr Line)
401 /* erase from screen */
402 if (Layer->On)
404 EraseLine (Line);
405 if (!Bulk)
406 Draw ();
408 MoveObjectToRemoveUndoList (LINE_TYPE, Layer, Line, Line);
409 return (NULL);
412 /* ---------------------------------------------------------------------------
413 * removes an arc from a layer
415 void *
416 RemoveArc (LayerTypePtr Layer, ArcTypePtr Arc)
418 /* erase from screen */
419 if (Layer->On)
421 EraseArc (Arc);
422 if (!Bulk)
423 Draw ();
425 MoveObjectToRemoveUndoList (ARC_TYPE, Layer, Arc, Arc);
426 return (NULL);
429 /* ---------------------------------------------------------------------------
430 * removes a text from a layer
432 void *
433 RemoveText (LayerTypePtr Layer, TextTypePtr Text)
435 /* erase from screen */
436 if (Layer->On)
438 EraseText (Layer, Text);
439 if (!Bulk)
440 Draw ();
442 MoveObjectToRemoveUndoList (TEXT_TYPE, Layer, Text, Text);
443 return (NULL);
446 /* ---------------------------------------------------------------------------
447 * removes a polygon from a layer
449 void *
450 RemovePolygon (LayerTypePtr Layer, PolygonTypePtr Polygon)
452 /* erase from screen */
453 if (Layer->On)
455 ErasePolygon (Polygon);
456 if (!Bulk)
457 Draw ();
459 MoveObjectToRemoveUndoList (POLYGON_TYPE, Layer, Polygon, Polygon);
460 return (NULL);
463 /* ---------------------------------------------------------------------------
464 * removes a polygon-point from a polygon
466 static void *
467 RemovePolygonPoint (LayerTypePtr Layer,
468 PolygonTypePtr Polygon, PointTypePtr Point)
470 PointTypePtr ptr;
471 Cardinal index = 0;
473 if (Polygon->PointN <= 3)
474 return RemovePolygon(Layer, Polygon);
475 if (Layer->On)
476 ErasePolygon (Polygon);
477 /* insert the polygon-point into the undo list */
478 POLYGONPOINT_LOOP (Polygon);
480 if (point == Point)
482 index = n;
483 break;
486 END_LOOP;
488 AddObjectToRemovePointUndoList (POLYGONPOINT_TYPE, Layer, Polygon, index);
489 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon);
491 /* remove point from list, keep point order */
492 for (ptr = Point + 1; ptr != &Polygon->Points[Polygon->PointN]; ptr++)
494 *Point = *ptr;
495 Point = ptr;
497 Polygon->PointN--;
498 SetPolygonBoundingBox (Polygon);
499 r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0);
500 RemoveExcessPolygonPoints (Layer, Polygon);
501 InitClip (PCB->Data, Layer, Polygon);
502 /* redraw polygon if necessary */
503 if (Layer->On)
505 DrawPolygon (Layer, Polygon, 0);
506 if (!Bulk)
507 Draw ();
509 return (NULL);
512 /* ---------------------------------------------------------------------------
513 * removes an element
515 void *
516 RemoveElement (ElementTypePtr Element)
518 /* erase from screen */
519 if ((PCB->ElementOn || PCB->PinOn) &&
520 (FRONT (Element) || PCB->InvisibleObjectsOn))
522 EraseElement (Element);
523 if (!Bulk)
524 Draw ();
526 MoveObjectToRemoveUndoList (ELEMENT_TYPE, Element, Element, Element);
527 return (NULL);
530 /* ----------------------------------------------------------------------
531 * removes all selected and visible objects
532 * returns True if any objects have been removed
534 Boolean
535 RemoveSelected (void)
537 Bulk = True;
538 if (SelectedOperation (&RemoveFunctions, False, ALL_TYPES))
540 IncrementUndoSerialNumber ();
541 Draw ();
542 Bulk = False;
543 return (True);
545 Bulk = False;
546 return (False);
549 /* ---------------------------------------------------------------------------
550 * remove object as referred by pointers and type,
551 * allocated memory is passed to the 'remove undo' list
553 void *
554 RemoveObject (int Type, void *Ptr1, void *Ptr2, void *Ptr3)
556 void *ptr = ObjectOperation (&RemoveFunctions, Type, Ptr1, Ptr2, Ptr3);
557 return (ptr);
560 /* ---------------------------------------------------------------------------
561 * DeleteRats - deletes rat lines only
562 * can delete all rat lines, or only selected one
565 Boolean
566 DeleteRats (Boolean selected)
568 Boolean changed = False;
570 Bulk = True;
571 RAT_LOOP (PCB->Data);
573 if ((!selected) || TEST_FLAG (SELECTEDFLAG, line))
575 changed = True;
576 RemoveRat (line);
579 END_LOOP;
580 Bulk = False;
581 if (changed)
583 Draw ();
584 IncrementUndoSerialNumber ();
586 return (changed);
589 /* ---------------------------------------------------------------------------
590 * remove object as referred by pointers and type
591 * allocated memory is destroyed assumed to already be erased
593 void *
594 DestroyObject (DataTypePtr Target, int Type, void *Ptr1, void *Ptr2,
595 void *Ptr3)
597 DestroyTarget = Target;
598 return (ObjectOperation (&DestroyFunctions, Type, Ptr1, Ptr2, Ptr3));