1 /*!
2 * \file src/select.c
3 *
4 * \brief Select routines.
5 *
6 * <hr>
7 *
8 * <h1><b>Copyright.</b></h1>\n
9 *
10 * PCB, interactive printed circuit board design
11 *
12 * Copyright (C) 1994,1995,1996 Thomas Nau
13 *
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.
18 *
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.
23 *
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 *
28 * Contact addresses for paper mail and Email:
29 *
30 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
31 *
32 * Thomas.Nau@rz.uni-ulm.de
33 */
34
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "global.h"
41
42 #include "data.h"
43 #include "draw.h"
44 #include "error.h"
45 #include "flags.h"
46 #include "search.h"
47 #include "select.h"
48 #include "undo.h"
49 #include "rats.h"
50 #include "misc.h"
51 #include "find.h"
52
53 #include <sys/types.h>
54 #ifdef HAVE_REGEX_H
55 #include <regex.h>
56 #else
57 #ifdef HAVE_UNISTD_H
58 #include <unistd.h>
59 #endif
60 #endif
61
62 #ifdef HAVE_LIBDMALLOC
63 #include <dmalloc.h>
64 #endif
65
66 /*!
67 * \brief Toggles the selection of any kind of object.
68 *
69 * The various types are defined in search.h.
70 */
71 bool
SelectObject(void)72 SelectObject (void)
73 {
74 void *ptr1, *ptr2, *ptr3;
75 LayerType *layer;
76 int type;
77
78 bool changed = true;
79
80 type = SearchScreen (Crosshair.X, Crosshair.Y, SELECT_TYPES,
81 &ptr1, &ptr2, &ptr3);
82 if (type == NO_TYPE || TEST_FLAG (LOCKFLAG, (PinType *) ptr2))
83 return (false);
84 switch (type)
85 {
86 case VIA_TYPE:
87 AddObjectToFlagUndoList (VIA_TYPE, ptr1, ptr1, ptr1);
88 TOGGLE_FLAG (SELECTEDFLAG, (PinType *) ptr1);
89 DrawVia ((PinType *) ptr1);
90 break;
91
92 case LINE_TYPE:
93 {
94 LineType *line = (LineType *) ptr2;
95
96 layer = (LayerType *) ptr1;
97 AddObjectToFlagUndoList (LINE_TYPE, ptr1, ptr2, ptr2);
98 TOGGLE_FLAG (SELECTEDFLAG, line);
99 DrawLine (layer, line);
100 break;
101 }
102
103 case RATLINE_TYPE:
104 {
105 RatType *rat = (RatType *) ptr2;
106
107 AddObjectToFlagUndoList (RATLINE_TYPE, ptr1, ptr1, ptr1);
108 TOGGLE_FLAG (SELECTEDFLAG, rat);
109 DrawRat (rat);
110 break;
111 }
112
113 case ARC_TYPE:
114 {
115 ArcType *arc = (ArcType *) ptr2;
116
117 layer = (LayerType *) ptr1;
118 AddObjectToFlagUndoList (ARC_TYPE, ptr1, ptr2, ptr2);
119 TOGGLE_FLAG (SELECTEDFLAG, arc);
120 DrawArc (layer, arc);
121 break;
122 }
123
124 case TEXT_TYPE:
125 {
126 TextType *text = (TextType *) ptr2;
127
128 layer = (LayerType *) ptr1;
129 AddObjectToFlagUndoList (TEXT_TYPE, ptr1, ptr2, ptr2);
130 TOGGLE_FLAG (SELECTEDFLAG, text);
131 DrawText (layer, text);
132 break;
133 }
134
135 case POLYGON_TYPE:
136 {
137 PolygonType *poly = (PolygonType *) ptr2;
138
139 layer = (LayerType *) ptr1;
140 AddObjectToFlagUndoList (POLYGON_TYPE, ptr1, ptr2, ptr2);
141 TOGGLE_FLAG (SELECTEDFLAG, poly);
142 DrawPolygon (layer, poly);
143 /* changing memory order no longer effects draw order */
144 break;
145 }
146
147 case PIN_TYPE:
148 AddObjectToFlagUndoList (PIN_TYPE, ptr1, ptr2, ptr2);
149 TOGGLE_FLAG (SELECTEDFLAG, (PinType *) ptr2);
150 DrawPin ((PinType *) ptr2);
151 break;
152
153 case PAD_TYPE:
154 AddObjectToFlagUndoList (PAD_TYPE, ptr1, ptr2, ptr2);
155 TOGGLE_FLAG (SELECTEDFLAG, (PadType *) ptr2);
156 DrawPad ((PadType *) ptr2);
157 break;
158
159 case ELEMENTNAME_TYPE:
160 {
161 ElementType *element = (ElementType *) ptr1;
162
163 /* select all names of the element */
164 ELEMENTTEXT_LOOP (element);
165 {
166 AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text);
167 TOGGLE_FLAG (SELECTEDFLAG, text);
168 }
169 END_LOOP;
170 DrawElementName (element);
171 break;
172 }
173
174 case ELEMENT_TYPE:
175 {
176 ElementType *element = (ElementType *) ptr1;
177
178 /* select all pins and names of the element */
179 PIN_LOOP (element);
180 {
181 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
182 TOGGLE_FLAG (SELECTEDFLAG, pin);
183 }
184 END_LOOP;
185 PAD_LOOP (element);
186 {
187 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
188 TOGGLE_FLAG (SELECTEDFLAG, pad);
189 }
190 END_LOOP;
191 ELEMENTTEXT_LOOP (element);
192 {
193 AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text);
194 TOGGLE_FLAG (SELECTEDFLAG, text);
195 }
196 END_LOOP;
197 AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element);
198 TOGGLE_FLAG (SELECTEDFLAG, element);
199 if (PCB->ElementOn &&
200 ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT ||
201 PCB->InvisibleObjectsOn))
202 if (PCB->ElementOn)
203 {
204 DrawElementName (element);
205 DrawElementPackage (element);
206 }
207 if (PCB->PinOn)
208 DrawElementPinsAndPads (element);
209 break;
210 }
211 }
212 Draw ();
213 IncrementUndoSerialNumber ();
214 return (changed);
215 }
216
217 /*!
218 * \brief Selects/unselects all visible objects within the passed box.
219 *
220 * "select" determines if the block is to be selected or unselected.
221 *
222 * \return true if the state of any object has changed.
223 */
224 bool
SelectBlock(BoxType * Box,bool select)225 SelectBlock (BoxType *Box, bool select)
226 {
227 bool changed = false;
228
229 if (PCB->RatOn || !select)
230 RAT_LOOP (PCB->Data);
231 {
232 if (LINE_IN_BOX ((LineType *) line, Box) &&
233 !TEST_FLAG (LOCKFLAG, line) && TEST_FLAG (SELECTEDFLAG, line) != select)
234 {
235 AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
236 ASSIGN_FLAG (SELECTEDFLAG, select, line);
237 if (PCB->RatOn)
238 DrawRat (line);
239 changed = true;
240 }
241 }
242 END_LOOP;
243
244 /* check layers */
245 LAYER_LOOP(PCB->Data, max_copper_layer + SILK_LAYER);
246 {
247 if (layer == & PCB->Data->SILKLAYER)
248 {
249 if (! (PCB->ElementOn || !select))
250 continue;
251 }
252 else if (layer == & PCB->Data->BACKSILKLAYER)
253 {
254 if (! (PCB->InvisibleObjectsOn || !select))
255 continue;
256 }
257 else
258 if (! (layer->On || !select))
259 continue;
260
261 LINE_LOOP (layer);
262 {
263 if (LINE_IN_BOX (line, Box)
264 && !TEST_FLAG (LOCKFLAG, line)
265 && TEST_FLAG (SELECTEDFLAG, line) != select)
266 {
267 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
268 ASSIGN_FLAG (SELECTEDFLAG, select, line);
269 if (layer->On)
270 DrawLine (layer, line);
271 changed = true;
272 }
273 }
274 END_LOOP;
275 ARC_LOOP (layer);
276 {
277 if (ARC_IN_BOX (arc, Box)
278 && !TEST_FLAG (LOCKFLAG, arc)
279 && TEST_FLAG (SELECTEDFLAG, arc) != select)
280 {
281 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
282 ASSIGN_FLAG (SELECTEDFLAG, select, arc);
283 if (layer->On)
284 DrawArc (layer, arc);
285 changed = true;
286 }
287 }
288 END_LOOP;
289 TEXT_LOOP (layer);
290 {
291 if (!select || TEXT_IS_VISIBLE(PCB, layer, text))
292 {
293 if (TEXT_IN_BOX (text, Box)
294 && !TEST_FLAG (LOCKFLAG, text)
295 && TEST_FLAG (SELECTEDFLAG, text) != select)
296 {
297 AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text);
298 ASSIGN_FLAG (SELECTEDFLAG, select, text);
299 if (TEXT_IS_VISIBLE(PCB, layer, text))
300 DrawText (layer, text);
301 changed = true;
302 }
303 }
304 }
305 END_LOOP;
306 POLYGON_LOOP (layer);
307 {
308 if (POLYGON_IN_BOX (polygon, Box)
309 && !TEST_FLAG (LOCKFLAG, polygon)
310 && TEST_FLAG (SELECTEDFLAG, polygon) != select)
311 {
312 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
313 ASSIGN_FLAG (SELECTEDFLAG, select, polygon);
314 if (layer->On)
315 DrawPolygon (layer, polygon);
316 changed = true;
317 }
318 }
319 END_LOOP;
320 }
321 END_LOOP;
322
323 /* elements */
324 ELEMENT_LOOP (PCB->Data);
325 {
326 {
327 bool gotElement = false;
328 if ((PCB->ElementOn || !select)
329 && !TEST_FLAG (LOCKFLAG, element)
330 && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT
331 || PCB->InvisibleObjectsOn))
332 {
333 if (BOX_IN_BOX
334 (&ELEMENT_TEXT (PCB, element).BoundingBox, Box)
335 && !TEST_FLAG (LOCKFLAG, &ELEMENT_TEXT (PCB, element))
336 && TEST_FLAG (SELECTEDFLAG,
337 &ELEMENT_TEXT (PCB, element)) != select)
338 {
339 /* select all names of element */
340 ELEMENTTEXT_LOOP (element);
341 {
342 AddObjectToFlagUndoList (ELEMENTNAME_TYPE,
343 element, text, text);
344 ASSIGN_FLAG (SELECTEDFLAG, select, text);
345 }
346 END_LOOP;
347 if (PCB->ElementOn)
348 DrawElementName (element);
349 changed = true;
350 }
351 if ((PCB->PinOn || !select) && ELEMENT_IN_BOX (element, Box))
352 if (TEST_FLAG (SELECTEDFLAG, element) != select)
353 {
354 AddObjectToFlagUndoList (ELEMENT_TYPE,
355 element, element, element);
356 ASSIGN_FLAG (SELECTEDFLAG, select, element);
357 PIN_LOOP (element);
358 {
359 if (TEST_FLAG (SELECTEDFLAG, pin) != select)
360 {
361 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
362 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
363 if (PCB->PinOn)
364 DrawPin (pin);
365 changed = true;
366 }
367 }
368 END_LOOP;
369 PAD_LOOP (element);
370 {
371 if (TEST_FLAG (SELECTEDFLAG, pad) != select)
372 {
373 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
374 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
375 if (PCB->PinOn)
376 DrawPad (pad);
377 changed = true;
378 }
379 }
380 END_LOOP;
381 if (PCB->PinOn)
382 DrawElement (element);
383 changed = true;
384 gotElement = true;
385 }
386 }
387 if ((PCB->PinOn || !select) && !TEST_FLAG (LOCKFLAG, element) && !gotElement)
388 {
389 PIN_LOOP (element);
390 {
391 if ((VIA_OR_PIN_IN_BOX (pin, Box)
392 && TEST_FLAG (SELECTEDFLAG, pin) != select))
393 {
394 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
395 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
396 if (PCB->PinOn)
397 DrawPin (pin);
398 changed = true;
399 }
400 }
401 END_LOOP;
402 PAD_LOOP (element);
403 {
404 if (PAD_IN_BOX (pad, Box)
405 && TEST_FLAG (SELECTEDFLAG, pad) != select
406 && (TEST_FLAG (ONSOLDERFLAG, pad) == SWAP_IDENT
407 || PCB->InvisibleObjectsOn
408 || !select))
409 {
410 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
411 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
412 if (PCB->PinOn)
413 DrawPad (pad);
414 changed = true;
415 }
416 }
417 END_LOOP;
418 }
419 }
420 }
421 END_LOOP;
422 /* end with vias */
423 if (PCB->ViaOn || !select)
424 VIA_LOOP (PCB->Data);
425 {
426 if (VIA_OR_PIN_IN_BOX (via, Box)
427 && !TEST_FLAG (LOCKFLAG, via)
428 && TEST_FLAG (SELECTEDFLAG, via) != select)
429 {
430 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
431 ASSIGN_FLAG (SELECTEDFLAG, select, via);
432 if (PCB->ViaOn)
433 DrawVia (via);
434 changed = true;
435 }
436 }
437 END_LOOP;
438 if (changed)
439 {
440 Draw ();
441 IncrementUndoSerialNumber ();
442 }
443 return (changed);
444 }
445
446 /*!
447 * \brief Performs several operations on the passed object.
448 */
449 void *
ObjectOperation(ObjectFunctionType * F,int Type,void * Ptr1,void * Ptr2,void * Ptr3)450 ObjectOperation (ObjectFunctionType *F,
451 int Type, void *Ptr1, void *Ptr2, void *Ptr3)
452 {
453 switch (Type)
454 {
455 case LINE_TYPE:
456 if (F->Line)
457 return (F->Line ((LayerType *) Ptr1, (LineType *) Ptr2));
458 break;
459
460 case ARC_TYPE:
461 if (F->Arc)
462 return (F->Arc ((LayerType *) Ptr1, (ArcType *) Ptr2));
463 break;
464
465 case LINEPOINT_TYPE:
466 if (F->LinePoint)
467 return (F->LinePoint ((LayerType *) Ptr1, (LineType *) Ptr2,
468 (PointType *) Ptr3));
469 break;
470
471 case TEXT_TYPE:
472 if (F->Text)
473 return (F->Text ((LayerType *) Ptr1, (TextType *) Ptr2));
474 break;
475
476 case POLYGON_TYPE:
477 if (F->Polygon)
478 return (F->Polygon ((LayerType *) Ptr1, (PolygonType *) Ptr2));
479 break;
480
481 case POLYGONPOINT_TYPE:
482 if (F->Point)
483 return (F->Point ((LayerType *) Ptr1, (PolygonType *) Ptr2,
484 (PointType *) Ptr3));
485 break;
486
487 case VIA_TYPE:
488 if (F->Via)
489 return (F->Via ((PinType *) Ptr1));
490 break;
491
492 case ELEMENT_TYPE:
493 if (F->Element)
494 return (F->Element ((ElementType *) Ptr1));
495 break;
496
497 case PIN_TYPE:
498 if (F->Pin)
499 return (F->Pin ((ElementType *) Ptr1, (PinType *) Ptr2));
500 break;
501
502 case PAD_TYPE:
503 if (F->Pad)
504 return (F->Pad ((ElementType *) Ptr1, (PadType *) Ptr2));
505 break;
506
507 case ELEMENTNAME_TYPE:
508 if (F->ElementName)
509 return (F->ElementName ((ElementType *) Ptr1));
510 break;
511
512 case RATLINE_TYPE:
513 if (F->Rat)
514 return (F->Rat ((RatType *) Ptr1));
515 break;
516 }
517 return (NULL);
518 }
519
520 /*!
521 * \brief Performs several operations on selected objects which are also
522 * visible.
523 *
524 * The lowlevel procedures are passed together with additional
525 * information.
526 *
527 * Resets the selected flag if requested.
528 *
529 * \return true if anything has changed.
530 */
531 bool
SelectedOperation(ObjectFunctionType * F,bool Reset,int type)532 SelectedOperation (ObjectFunctionType *F, bool Reset, int type)
533 {
534 bool changed = false;
535
536 /* check lines */
537 if (type & LINE_TYPE && F->Line)
538 VISIBLELINE_LOOP (PCB->Data);
539 {
540 if (TEST_FLAG (SELECTEDFLAG, line))
541 {
542 if (Reset)
543 {
544 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
545 CLEAR_FLAG (SELECTEDFLAG, line);
546 }
547 F->Line (layer, line);
548 changed = true;
549 }
550 }
551 ENDALL_LOOP;
552
553 /* check arcs */
554 if (type & ARC_TYPE && F->Arc)
555 VISIBLEARC_LOOP (PCB->Data);
556 {
557 if (TEST_FLAG (SELECTEDFLAG, arc))
558 {
559 if (Reset)
560 {
561 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
562 CLEAR_FLAG (SELECTEDFLAG, arc);
563 }
564 F->Arc (layer, arc);
565 changed = true;
566 }
567 }
568 ENDALL_LOOP;
569
570 /* check text */
571 if (type & TEXT_TYPE && F->Text)
572 ALLTEXT_LOOP (PCB->Data);
573 {
574 if (TEST_FLAG (SELECTEDFLAG, text) && TEXT_IS_VISIBLE (PCB, layer, text))
575 {
576 if (Reset)
577 {
578 AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text);
579 CLEAR_FLAG (SELECTEDFLAG, text);
580 }
581 F->Text (layer, text);
582 changed = true;
583 }
584 }
585 ENDALL_LOOP;
586
587 /* check polygons */
588 if (type & POLYGON_TYPE && F->Polygon)
589 VISIBLEPOLYGON_LOOP (PCB->Data);
590 {
591 if (TEST_FLAG (SELECTEDFLAG, polygon))
592 {
593 if (Reset)
594 {
595 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
596 CLEAR_FLAG (SELECTEDFLAG, polygon);
597 }
598 F->Polygon (layer, polygon);
599 changed = true;
600 }
601 }
602 ENDALL_LOOP;
603
604 /* elements silkscreen */
605 if (type & ELEMENT_TYPE && PCB->ElementOn && F->Element)
606 ELEMENT_LOOP (PCB->Data);
607 {
608 if (TEST_FLAG (SELECTEDFLAG, element))
609 {
610 if (Reset)
611 {
612 AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element);
613 CLEAR_FLAG (SELECTEDFLAG, element);
614 }
615 F->Element (element);
616 changed = true;
617 }
618 }
619 END_LOOP;
620 if (type & ELEMENTNAME_TYPE && PCB->ElementOn && F->ElementName)
621 ELEMENT_LOOP (PCB->Data);
622 {
623 if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
624 {
625 if (Reset)
626 {
627 AddObjectToFlagUndoList (ELEMENTNAME_TYPE,
628 element,
629 &ELEMENT_TEXT (PCB, element),
630 &ELEMENT_TEXT (PCB, element));
631 CLEAR_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element));
632 }
633 F->ElementName (element);
634 changed = true;
635 }
636 }
637 END_LOOP;
638
639 if (type & PIN_TYPE && PCB->PinOn && F->Pin)
640 ELEMENT_LOOP (PCB->Data);
641 {
642 PIN_LOOP (element);
643 {
644 if (TEST_FLAG (SELECTEDFLAG, pin))
645 {
646 if (Reset)
647 {
648 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
649 CLEAR_FLAG (SELECTEDFLAG, pin);
650 }
651 F->Pin (element, pin);
652 changed = true;
653 }
654 }
655 END_LOOP;
656 }
657 END_LOOP;
658
659 if (type & PAD_TYPE && PCB->PinOn && F->Pad)
660 ELEMENT_LOOP (PCB->Data);
661 {
662 PAD_LOOP (element);
663 {
664 if (TEST_FLAG (SELECTEDFLAG, pad))
665 {
666 if (Reset)
667 {
668 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
669 CLEAR_FLAG (SELECTEDFLAG, pad);
670 }
671 F->Pad (element, pad);
672 changed = true;
673 }
674 }
675 END_LOOP;
676 }
677 END_LOOP;
678
679 /* process vias */
680 if (type & VIA_TYPE && PCB->ViaOn && F->Via)
681 VIA_LOOP (PCB->Data);
682 {
683 if (TEST_FLAG (SELECTEDFLAG, via))
684 {
685 if (Reset)
686 {
687 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
688 CLEAR_FLAG (SELECTEDFLAG, via);
689 }
690 F->Via (via);
691 changed = true;
692 }
693 }
694 END_LOOP;
695 /* and rat-lines */
696 if (type & RATLINE_TYPE && PCB->RatOn && F->Rat)
697 RAT_LOOP (PCB->Data);
698 {
699 if (TEST_FLAG (SELECTEDFLAG, line))
700 {
701 if (Reset)
702 {
703 AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
704 CLEAR_FLAG (SELECTEDFLAG, line);
705 }
706 F->Rat (line);
707 changed = true;
708 }
709 }
710 END_LOOP;
711 if (Reset && changed)
712 IncrementUndoSerialNumber ();
713 return (changed);
714 }
715
716 /*!
717 * \brief Selects/unselects all objects which have (any of) the
718 * specified flag(s) set.
719 *
720 * This is typically the FOUNDFLAG, assigned during a connection scan.
721 *
722 * "select" determines if they are to be selected or unselected.
723 *
724 * \return true if the state of any object has changed.
725 *
726 * \note Text objects and elements cannot be selected by this routine.
727 */
728 bool
SelectByFlag(int flag,bool select)729 SelectByFlag (int flag, bool select)
730 {
731 bool changed = false;
732
733 if (PCB->RatOn)
734 RAT_LOOP (PCB->Data);
735 {
736 if (TEST_FLAG (flag, line))
737 {
738 AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
739 ASSIGN_FLAG (SELECTEDFLAG, select, line);
740 DrawRat (line);
741 changed = true;
742 }
743 }
744 END_LOOP;
745
746 VISIBLELINE_LOOP (PCB->Data);
747 {
748 if (TEST_FLAG (flag, line) && !TEST_FLAG (LOCKFLAG, line))
749 {
750 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
751 ASSIGN_FLAG (SELECTEDFLAG, select, line);
752 DrawLine (layer, line);
753 changed = true;
754 }
755 }
756 ENDALL_LOOP;
757 VISIBLEARC_LOOP (PCB->Data);
758 {
759 if (TEST_FLAG (flag, arc) && !TEST_FLAG (LOCKFLAG, arc))
760 {
761 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
762 ASSIGN_FLAG (SELECTEDFLAG, select, arc);
763 DrawArc (layer, arc);
764 changed = true;
765 }
766 }
767 ENDALL_LOOP;
768 VISIBLEPOLYGON_LOOP (PCB->Data);
769 {
770 if (TEST_FLAG (flag, polygon) && !TEST_FLAG (LOCKFLAG, polygon))
771 {
772 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
773 ASSIGN_FLAG (SELECTEDFLAG, select, polygon);
774 DrawPolygon (layer, polygon);
775 changed = true;
776 }
777 }
778 ENDALL_LOOP;
779
780 if (PCB->PinOn && PCB->ElementOn)
781 {
782 ALLPIN_LOOP (PCB->Data);
783 {
784 if (!TEST_FLAG (LOCKFLAG, element) && TEST_FLAG (flag, pin))
785 {
786 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
787 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
788 DrawPin (pin);
789 changed = true;
790 }
791 }
792 ENDALL_LOOP;
793 ALLPAD_LOOP (PCB->Data);
794 {
795 if (!TEST_FLAG (LOCKFLAG, element) && TEST_FLAG (flag, pad))
796 {
797 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
798 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
799 DrawPad (pad);
800 changed = true;
801 }
802 }
803 ENDALL_LOOP;
804 }
805
806 if (PCB->ViaOn)
807 VIA_LOOP (PCB->Data);
808 {
809 if (TEST_FLAG (flag, via) && !TEST_FLAG (LOCKFLAG, via))
810 {
811 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
812 ASSIGN_FLAG (SELECTEDFLAG, select, via);
813 DrawVia (via);
814 changed = true;
815 }
816 }
817 END_LOOP;
818 return (changed);
819 }
820
821 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
822 /*!
823 * \brief Selects objects as defined by Type by name; it's a case
824 * insensitive match.
825 *
826 * \return true if any object has been selected.
827 */
828 #if defined (HAVE_REGCOMP)
829 static int
regexec_match_all(const regex_t * preg,const char * string)830 regexec_match_all (const regex_t *preg, const char *string)
831 {
832 regmatch_t match;
833
834 if (regexec (preg, string, 1, &match, 0) != 0)
835 return 0;
836 if (match.rm_so != 0)
837 return 0;
838 if (match.rm_eo != strlen(string))
839 return 0;
840 return 1;
841 }
842 #endif
843
844 bool
SelectObjectByName(int Type,char * Pattern,bool select)845 SelectObjectByName (int Type, char *Pattern, bool select)
846 {
847 bool changed = false;
848
849 #if defined(HAVE_REGCOMP)
850 #define REGEXEC(arg) (regexec_match_all(&compiled, (arg)))
851
852 int result;
853 regex_t compiled;
854
855 /* compile the regular expression */
856 result = regcomp (&compiled, Pattern, REG_EXTENDED | REG_ICASE);
857 if (result)
858 {
859 char errorstring[128];
860
861 regerror (result, &compiled, errorstring, 128);
862 Message (_("regexp error: %s\n"), errorstring);
863 regfree (&compiled);
864 return (false);
865 }
866 #else
867 #define REGEXEC(arg) (re_exec((arg)) == 1)
868
869 char *compiled;
870
871 /* compile the regular expression */
872 if ((compiled = re_comp (Pattern)) != NULL)
873 {
874 Message (_("re_comp error: %s\n"), compiled);
875 return (false);
876 }
877 #endif
878
879 /* loop over all visible objects with names */
880 if (Type & TEXT_TYPE)
881 ALLTEXT_LOOP (PCB->Data);
882 {
883 if (!TEST_FLAG (LOCKFLAG, text)
884 && TEXT_IS_VISIBLE (PCB, layer, text)
885 && text->TextString
886 && REGEXEC (text->TextString)
887 && TEST_FLAG (SELECTEDFLAG, text) != select)
888 {
889 AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text);
890 ASSIGN_FLAG (SELECTEDFLAG, select, text);
891 DrawText (layer, text);
892 changed = true;
893 }
894 }
895 ENDALL_LOOP;
896
897 if (PCB->ElementOn && (Type & ELEMENT_TYPE))
898 ELEMENT_LOOP (PCB->Data);
899 {
900 if (!TEST_FLAG (LOCKFLAG, element)
901 && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT
902 || PCB->InvisibleObjectsOn)
903 && TEST_FLAG (SELECTEDFLAG, element) != select)
904 {
905 String name = ELEMENT_NAME (PCB, element);
906 if (name && REGEXEC (name))
907 {
908 AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element);
909 ASSIGN_FLAG (SELECTEDFLAG, select, element);
910 PIN_LOOP (element);
911 {
912 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
913 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
914 }
915 END_LOOP;
916 PAD_LOOP (element);
917 {
918 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
919 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
920 }
921 END_LOOP;
922 ELEMENTTEXT_LOOP (element);
923 {
924 AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text);
925 ASSIGN_FLAG (SELECTEDFLAG, select, text);
926 }
927 END_LOOP;
928 DrawElementName (element);
929 DrawElement (element);
930 changed = true;
931 }
932 }
933 }
934 END_LOOP;
935 if (PCB->PinOn && (Type & PIN_TYPE))
936 ALLPIN_LOOP (PCB->Data);
937 {
938 if (!TEST_FLAG (LOCKFLAG, element)
939 && pin->Name && REGEXEC (pin->Name)
940 && TEST_FLAG (SELECTEDFLAG, pin) != select)
941 {
942 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
943 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
944 DrawPin (pin);
945 changed = true;
946 }
947 }
948 ENDALL_LOOP;
949 if (PCB->PinOn && (Type & PAD_TYPE))
950 ALLPAD_LOOP (PCB->Data);
951 {
952 if (!TEST_FLAG (LOCKFLAG, element)
953 && ((TEST_FLAG (ONSOLDERFLAG, pad) != 0) == SWAP_IDENT
954 || PCB->InvisibleObjectsOn)
955 && TEST_FLAG (SELECTEDFLAG, pad) != select)
956 if (pad->Name && REGEXEC (pad->Name))
957 {
958 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
959 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
960 DrawPad (pad);
961 changed = true;
962 }
963 }
964 ENDALL_LOOP;
965 if (PCB->ViaOn && (Type & VIA_TYPE))
966 VIA_LOOP (PCB->Data);
967 {
968 if (!TEST_FLAG (LOCKFLAG, via)
969 && via->Name
970 && REGEXEC (via->Name) && TEST_FLAG (SELECTEDFLAG, via) != select)
971 {
972 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
973 ASSIGN_FLAG (SELECTEDFLAG, select, via);
974 DrawVia (via);
975 changed = true;
976 }
977 }
978 END_LOOP;
979 if (Type & NET_TYPE)
980 {
981 InitConnectionLookup ();
982 changed = ClearFlagOnAllObjects (FOUNDFLAG, true) || changed;
983
984 MENU_LOOP (&PCB->NetlistLib);
985 {
986 Cardinal i;
987 LibraryEntryType *entry;
988 ConnectionType conn;
989
990 /* Name[0] and Name[1] are special purpose, not the actual name*/
991 if (menu->Name && menu->Name[0] != '\0' && menu->Name[1] != '\0' &&
992 REGEXEC (menu->Name + 2))
993 {
994 for (i = menu->EntryN, entry = menu->Entry; i; i--, entry++)
995 if (SeekPad (entry, &conn, false))
996 RatFindHook (conn.type, conn.ptr1, conn.ptr2, conn.ptr2,
997 true, FOUNDFLAG, true);
998 }
999 }
1000 END_LOOP;
1001
1002 changed = SelectByFlag (FOUNDFLAG, select) || changed;
1003 changed = ClearFlagOnAllObjects (FOUNDFLAG, false) || changed;
1004 FreeConnectionLookupMemory ();
1005 }
1006
1007 #if defined(HAVE_REGCOMP)
1008 #if !defined(sgi)
1009 regfree (&compiled);
1010 #endif
1011 #endif
1012
1013 if (changed)
1014 {
1015 IncrementUndoSerialNumber ();
1016 Draw ();
1017 }
1018 return (changed);
1019 }
1020 #endif /* defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) */
1021
1022 /*!
1023 * \brief Selects all blind/buried vias
1024 *
1025 * \return true if any object has been selected.
1026 */
1027 bool
SelectBuriedVias(bool select)1028 SelectBuriedVias (bool select)
1029 {
1030 bool changed = false;
1031
1032 VIA_LOOP (PCB->Data)
1033 if (TEST_FLAG (LOCKFLAG, via))
1034 continue;
1035 if (VIA_IS_BURIED (via))
1036 {
1037 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
1038 ASSIGN_FLAG (SELECTEDFLAG, select, via);
1039 changed = true;
1040 }
1041 END_LOOP;
1042
1043 return changed;
1044 }
1045