(no commit message)
[geda-pcb/pcjc2.git] / src / select.c
blob1762c76d4f7a9e6e8325210abd27269ae192c97c
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 /* select routines
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
35 #include "global.h"
37 #include "data.h"
38 #include "draw.h"
39 #include "error.h"
40 #include "search.h"
41 #include "select.h"
42 #include "undo.h"
43 #include "rats.h"
44 #include "misc.h"
45 #include "find.h"
47 #include <sys/types.h>
48 #ifdef HAVE_REGEX_H
49 #include <regex.h>
50 #else
51 #ifdef HAVE_UNISTD_H
52 #include <unistd.h>
53 #endif
54 #endif
56 #ifdef HAVE_LIBDMALLOC
57 #include <dmalloc.h>
58 #endif
60 /* ---------------------------------------------------------------------------
61 * toggles the selection of any kind of object
62 * the different types are defined by search.h
64 bool
65 SelectObject (void)
67 void *ptr1, *ptr2, *ptr3;
68 LayerType *layer;
69 int type;
71 bool changed = true;
73 type = SearchScreen (Crosshair.X, Crosshair.Y, SELECT_TYPES,
74 &ptr1, &ptr2, &ptr3);
75 if (type == NO_TYPE || TEST_FLAG (LOCKFLAG, (PinType *) ptr2))
76 return (false);
77 switch (type)
79 case VIA_TYPE:
80 AddObjectToFlagUndoList (VIA_TYPE, ptr1, ptr1, ptr1);
81 TOGGLE_FLAG (SELECTEDFLAG, (PinType *) ptr1);
82 DrawVia ((PinType *) ptr1);
83 break;
85 case LINE_TYPE:
87 LineType *line = (LineType *) ptr2;
89 layer = (LayerType *) ptr1;
90 AddObjectToFlagUndoList (LINE_TYPE, ptr1, ptr2, ptr2);
91 TOGGLE_FLAG (SELECTEDFLAG, line);
92 DrawLine (layer, line);
93 break;
96 case RATLINE_TYPE:
98 RatType *rat = (RatType *) ptr2;
100 AddObjectToFlagUndoList (RATLINE_TYPE, ptr1, ptr1, ptr1);
101 TOGGLE_FLAG (SELECTEDFLAG, rat);
102 DrawRat (rat);
103 break;
106 case ARC_TYPE:
108 ArcType *arc = (ArcType *) ptr2;
110 layer = (LayerType *) ptr1;
111 AddObjectToFlagUndoList (ARC_TYPE, ptr1, ptr2, ptr2);
112 TOGGLE_FLAG (SELECTEDFLAG, arc);
113 DrawArc (layer, arc);
114 break;
117 case TEXT_TYPE:
119 TextType *text = (TextType *) ptr2;
121 layer = (LayerType *) ptr1;
122 AddObjectToFlagUndoList (TEXT_TYPE, ptr1, ptr2, ptr2);
123 TOGGLE_FLAG (SELECTEDFLAG, text);
124 DrawText (layer, text);
125 break;
128 case POLYGON_TYPE:
130 PolygonType *poly = (PolygonType *) ptr2;
132 layer = (LayerType *) ptr1;
133 AddObjectToFlagUndoList (POLYGON_TYPE, ptr1, ptr2, ptr2);
134 TOGGLE_FLAG (SELECTEDFLAG, poly);
135 DrawPolygon (layer, poly);
136 /* changing memory order no longer effects draw order */
137 break;
140 case PIN_TYPE:
141 AddObjectToFlagUndoList (PIN_TYPE, ptr1, ptr2, ptr2);
142 TOGGLE_FLAG (SELECTEDFLAG, (PinType *) ptr2);
143 DrawPin ((PinType *) ptr2);
144 break;
146 case PAD_TYPE:
147 AddObjectToFlagUndoList (PAD_TYPE, ptr1, ptr2, ptr2);
148 TOGGLE_FLAG (SELECTEDFLAG, (PadType *) ptr2);
149 DrawPad ((PadType *) ptr2);
150 break;
152 case ELEMENTNAME_TYPE:
154 ElementType *element = (ElementType *) ptr1;
156 /* select all names of the element */
157 ELEMENTTEXT_LOOP (element);
159 AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text);
160 TOGGLE_FLAG (SELECTEDFLAG, text);
162 END_LOOP;
163 DrawElementName (element);
164 break;
167 case ELEMENT_TYPE:
169 ElementType *element = (ElementType *) ptr1;
171 /* select all pins and names of the element */
172 PIN_LOOP (element);
174 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
175 TOGGLE_FLAG (SELECTEDFLAG, pin);
177 END_LOOP;
178 PAD_LOOP (element);
180 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
181 TOGGLE_FLAG (SELECTEDFLAG, pad);
183 END_LOOP;
184 ELEMENTTEXT_LOOP (element);
186 AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text);
187 TOGGLE_FLAG (SELECTEDFLAG, text);
189 END_LOOP;
190 AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element);
191 TOGGLE_FLAG (SELECTEDFLAG, element);
192 if (PCB->ElementOn &&
193 ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT ||
194 PCB->InvisibleObjectsOn))
195 if (PCB->ElementOn)
197 DrawElementName (element);
198 DrawElementPackage (element);
200 if (PCB->PinOn)
201 DrawElementPinsAndPads (element);
202 break;
205 Draw ();
206 IncrementUndoSerialNumber ();
207 return (changed);
210 /* ----------------------------------------------------------------------
211 * selects/unselects all visible objects within the passed box
212 * "select" determines if the block is to be selected or unselected
213 * returns true if the state of any object has changed
215 bool
216 SelectBlock (BoxType *Box, bool select)
218 bool changed = false;
220 if (PCB->RatOn || !select)
221 RAT_LOOP (PCB->Data);
223 if (LINE_IN_BOX ((LineType *) line, Box) &&
224 !TEST_FLAG (LOCKFLAG, line) && TEST_FLAG (SELECTEDFLAG, line) != select)
226 AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
227 ASSIGN_FLAG (SELECTEDFLAG, select, line);
228 if (PCB->RatOn)
229 DrawRat (line);
230 changed = true;
233 END_LOOP;
235 /* check layers */
236 LAYER_LOOP(PCB->Data, max_copper_layer + 2);
238 if (layer == & PCB->Data->SILKLAYER)
240 if (! (PCB->ElementOn || !select))
241 continue;
243 else if (layer == & PCB->Data->BACKSILKLAYER)
245 if (! (PCB->InvisibleObjectsOn || !select))
246 continue;
248 else
249 if (! (layer->On || !select))
250 continue;
252 LINE_LOOP (layer);
254 if (LINE_IN_BOX (line, Box)
255 && !TEST_FLAG (LOCKFLAG, line)
256 && TEST_FLAG (SELECTEDFLAG, line) != select)
258 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
259 ASSIGN_FLAG (SELECTEDFLAG, select, line);
260 if (layer->On)
261 DrawLine (layer, line);
262 changed = true;
265 END_LOOP;
266 ARC_LOOP (layer);
268 if (ARC_IN_BOX (arc, Box)
269 && !TEST_FLAG (LOCKFLAG, arc)
270 && TEST_FLAG (SELECTEDFLAG, arc) != select)
272 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
273 ASSIGN_FLAG (SELECTEDFLAG, select, arc);
274 if (layer->On)
275 DrawArc (layer, arc);
276 changed = true;
279 END_LOOP;
280 TEXT_LOOP (layer);
282 if (!select || TEXT_IS_VISIBLE(PCB, layer, text))
284 if (TEXT_IN_BOX (text, Box)
285 && !TEST_FLAG (LOCKFLAG, text)
286 && TEST_FLAG (SELECTEDFLAG, text) != select)
288 AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text);
289 ASSIGN_FLAG (SELECTEDFLAG, select, text);
290 if (TEXT_IS_VISIBLE(PCB, layer, text))
291 DrawText (layer, text);
292 changed = true;
296 END_LOOP;
297 POLYGON_LOOP (layer);
299 if (POLYGON_IN_BOX (polygon, Box)
300 && !TEST_FLAG (LOCKFLAG, polygon)
301 && TEST_FLAG (SELECTEDFLAG, polygon) != select)
303 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
304 ASSIGN_FLAG (SELECTEDFLAG, select, polygon);
305 if (layer->On)
306 DrawPolygon (layer, polygon);
307 changed = true;
310 END_LOOP;
312 END_LOOP;
314 /* elements */
315 ELEMENT_LOOP (PCB->Data);
318 bool gotElement = false;
319 if ((PCB->ElementOn || !select)
320 && !TEST_FLAG (LOCKFLAG, element)
321 && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT
322 || PCB->InvisibleObjectsOn))
324 if (BOX_IN_BOX
325 (&ELEMENT_TEXT (PCB, element).BoundingBox, Box)
326 && !TEST_FLAG (LOCKFLAG, &ELEMENT_TEXT (PCB, element))
327 && TEST_FLAG (SELECTEDFLAG,
328 &ELEMENT_TEXT (PCB, element)) != select)
330 /* select all names of element */
331 ELEMENTTEXT_LOOP (element);
333 AddObjectToFlagUndoList (ELEMENTNAME_TYPE,
334 element, text, text);
335 ASSIGN_FLAG (SELECTEDFLAG, select, text);
337 END_LOOP;
338 if (PCB->ElementOn)
339 DrawElementName (element);
340 changed = true;
342 if ((PCB->PinOn || !select) && ELEMENT_IN_BOX (element, Box))
343 if (TEST_FLAG (SELECTEDFLAG, element) != select)
345 AddObjectToFlagUndoList (ELEMENT_TYPE,
346 element, element, element);
347 ASSIGN_FLAG (SELECTEDFLAG, select, element);
348 PIN_LOOP (element);
350 if (TEST_FLAG (SELECTEDFLAG, pin) != select)
352 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
353 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
354 if (PCB->PinOn)
355 DrawPin (pin);
356 changed = true;
359 END_LOOP;
360 PAD_LOOP (element);
362 if (TEST_FLAG (SELECTEDFLAG, pad) != select)
364 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
365 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
366 if (PCB->PinOn)
367 DrawPad (pad);
368 changed = true;
371 END_LOOP;
372 if (PCB->PinOn)
373 DrawElement (element);
374 changed = true;
375 gotElement = true;
378 if ((PCB->PinOn || !select) && !TEST_FLAG (LOCKFLAG, element) && !gotElement)
380 PIN_LOOP (element);
382 if ((VIA_OR_PIN_IN_BOX (pin, Box)
383 && TEST_FLAG (SELECTEDFLAG, pin) != select))
385 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
386 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
387 if (PCB->PinOn)
388 DrawPin (pin);
389 changed = true;
392 END_LOOP;
393 PAD_LOOP (element);
395 if (PAD_IN_BOX (pad, Box)
396 && TEST_FLAG (SELECTEDFLAG, pad) != select
397 && (TEST_FLAG (ONSOLDERFLAG, pad) == SWAP_IDENT
398 || PCB->InvisibleObjectsOn
399 || !select))
401 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
402 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
403 if (PCB->PinOn)
404 DrawPad (pad);
405 changed = true;
408 END_LOOP;
412 END_LOOP;
413 /* end with vias */
414 if (PCB->ViaOn || !select)
415 VIA_LOOP (PCB->Data);
417 if (VIA_OR_PIN_IN_BOX (via, Box)
418 && !TEST_FLAG (LOCKFLAG, via)
419 && TEST_FLAG (SELECTEDFLAG, via) != select)
421 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
422 ASSIGN_FLAG (SELECTEDFLAG, select, via);
423 if (PCB->ViaOn)
424 DrawVia (via);
425 changed = true;
428 END_LOOP;
429 if (changed)
431 Draw ();
432 IncrementUndoSerialNumber ();
434 return (changed);
437 /* ----------------------------------------------------------------------
438 * performs several operations on the passed object
440 void *
441 ObjectOperation (ObjectFunctionType *F,
442 int Type, void *Ptr1, void *Ptr2, void *Ptr3)
444 switch (Type)
446 case LINE_TYPE:
447 if (F->Line)
448 return (F->Line ((LayerType *) Ptr1, (LineType *) Ptr2));
449 break;
451 case ARC_TYPE:
452 if (F->Arc)
453 return (F->Arc ((LayerType *) Ptr1, (ArcType *) Ptr2));
454 break;
456 case LINEPOINT_TYPE:
457 if (F->LinePoint)
458 return (F->LinePoint ((LayerType *) Ptr1, (LineType *) Ptr2,
459 (PointType *) Ptr3));
460 break;
462 case TEXT_TYPE:
463 if (F->Text)
464 return (F->Text ((LayerType *) Ptr1, (TextType *) Ptr2));
465 break;
467 case POLYGON_TYPE:
468 if (F->Polygon)
469 return (F->Polygon ((LayerType *) Ptr1, (PolygonType *) Ptr2));
470 break;
472 case POLYGONPOINT_TYPE:
473 if (F->Point)
474 return (F->Point ((LayerType *) Ptr1, (PolygonType *) Ptr2,
475 (PointType *) Ptr3));
476 break;
478 case VIA_TYPE:
479 if (F->Via)
480 return (F->Via ((PinType *) Ptr1));
481 break;
483 case ELEMENT_TYPE:
484 if (F->Element)
485 return (F->Element ((ElementType *) Ptr1));
486 break;
488 case PIN_TYPE:
489 if (F->Pin)
490 return (F->Pin ((ElementType *) Ptr1, (PinType *) Ptr2));
491 break;
493 case PAD_TYPE:
494 if (F->Pad)
495 return (F->Pad ((ElementType *) Ptr1, (PadType *) Ptr2));
496 break;
498 case ELEMENTNAME_TYPE:
499 if (F->ElementName)
500 return (F->ElementName ((ElementType *) Ptr1));
501 break;
503 case RATLINE_TYPE:
504 if (F->Rat)
505 return (F->Rat ((RatType *) Ptr1));
506 break;
508 return (NULL);
511 /* ----------------------------------------------------------------------
512 * performs several operations on selected objects which are also visible
513 * The lowlevel procedures are passed together with additional information
514 * resets the selected flag if requested
515 * returns true if anything has changed
517 bool
518 SelectedOperation (ObjectFunctionType *F, bool Reset, int type)
520 bool changed = false;
522 /* check lines */
523 if (type & LINE_TYPE && F->Line)
524 VISIBLELINE_LOOP (PCB->Data);
526 if (TEST_FLAG (SELECTEDFLAG, line))
528 if (Reset)
530 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
531 CLEAR_FLAG (SELECTEDFLAG, line);
533 F->Line (layer, line);
534 changed = true;
537 ENDALL_LOOP;
539 /* check arcs */
540 if (type & ARC_TYPE && F->Arc)
541 VISIBLEARC_LOOP (PCB->Data);
543 if (TEST_FLAG (SELECTEDFLAG, arc))
545 if (Reset)
547 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
548 CLEAR_FLAG (SELECTEDFLAG, arc);
550 F->Arc (layer, arc);
551 changed = true;
554 ENDALL_LOOP;
556 /* check text */
557 if (type & TEXT_TYPE && F->Text)
558 ALLTEXT_LOOP (PCB->Data);
560 if (TEST_FLAG (SELECTEDFLAG, text) && TEXT_IS_VISIBLE (PCB, layer, text))
562 if (Reset)
564 AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text);
565 CLEAR_FLAG (SELECTEDFLAG, text);
567 F->Text (layer, text);
568 changed = true;
571 ENDALL_LOOP;
573 /* check polygons */
574 if (type & POLYGON_TYPE && F->Polygon)
575 VISIBLEPOLYGON_LOOP (PCB->Data);
577 if (TEST_FLAG (SELECTEDFLAG, polygon))
579 if (Reset)
581 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
582 CLEAR_FLAG (SELECTEDFLAG, polygon);
584 F->Polygon (layer, polygon);
585 changed = true;
588 ENDALL_LOOP;
590 /* elements silkscreen */
591 if (type & ELEMENT_TYPE && PCB->ElementOn && F->Element)
592 ELEMENT_LOOP (PCB->Data);
594 if (TEST_FLAG (SELECTEDFLAG, element))
596 if (Reset)
598 AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element);
599 CLEAR_FLAG (SELECTEDFLAG, element);
601 F->Element (element);
602 changed = true;
605 END_LOOP;
606 if (type & ELEMENTNAME_TYPE && PCB->ElementOn && F->ElementName)
607 ELEMENT_LOOP (PCB->Data);
609 if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
611 if (Reset)
613 AddObjectToFlagUndoList (ELEMENTNAME_TYPE,
614 element,
615 &ELEMENT_TEXT (PCB, element),
616 &ELEMENT_TEXT (PCB, element));
617 CLEAR_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element));
619 F->ElementName (element);
620 changed = true;
623 END_LOOP;
625 if (type & PIN_TYPE && PCB->PinOn && F->Pin)
626 ELEMENT_LOOP (PCB->Data);
628 PIN_LOOP (element);
630 if (TEST_FLAG (SELECTEDFLAG, pin))
632 if (Reset)
634 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
635 CLEAR_FLAG (SELECTEDFLAG, pin);
637 F->Pin (element, pin);
638 changed = true;
641 END_LOOP;
643 END_LOOP;
645 if (type & PAD_TYPE && PCB->PinOn && F->Pad)
646 ELEMENT_LOOP (PCB->Data);
648 PAD_LOOP (element);
650 if (TEST_FLAG (SELECTEDFLAG, pad))
652 if (Reset)
654 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
655 CLEAR_FLAG (SELECTEDFLAG, pad);
657 F->Pad (element, pad);
658 changed = true;
661 END_LOOP;
663 END_LOOP;
665 /* process vias */
666 if (type & VIA_TYPE && PCB->ViaOn && F->Via)
667 VIA_LOOP (PCB->Data);
669 if (TEST_FLAG (SELECTEDFLAG, via))
671 if (Reset)
673 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
674 CLEAR_FLAG (SELECTEDFLAG, via);
676 F->Via (via);
677 changed = true;
680 END_LOOP;
681 /* and rat-lines */
682 if (type & RATLINE_TYPE && PCB->RatOn && F->Rat)
683 RAT_LOOP (PCB->Data);
685 if (TEST_FLAG (SELECTEDFLAG, line))
687 if (Reset)
689 AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
690 CLEAR_FLAG (SELECTEDFLAG, line);
692 F->Rat (line);
693 changed = true;
696 END_LOOP;
697 if (Reset && changed)
698 IncrementUndoSerialNumber ();
699 return (changed);
702 /* ----------------------------------------------------------------------
703 * selects/unselects all objects which have (any of) the specified flag(s)
704 * set. (Typically the FOUNDFLAG, assigned during a connection scan).
705 * "select" determines if they are to be selected or unselected
707 * returns true if the state of any object has changed
709 * text objects and elements cannot be selected by this routine
711 bool
712 SelectByFlag (int flag, bool select)
714 bool changed = false;
716 if (PCB->RatOn)
717 RAT_LOOP (PCB->Data);
719 if (TEST_FLAG (flag, line))
721 AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
722 ASSIGN_FLAG (SELECTEDFLAG, select, line);
723 DrawRat (line);
724 changed = true;
727 END_LOOP;
729 VISIBLELINE_LOOP (PCB->Data);
731 if (TEST_FLAG (flag, line) && !TEST_FLAG (LOCKFLAG, line))
733 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
734 ASSIGN_FLAG (SELECTEDFLAG, select, line);
735 DrawLine (layer, line);
736 changed = true;
739 ENDALL_LOOP;
740 VISIBLEARC_LOOP (PCB->Data);
742 if (TEST_FLAG (flag, arc) && !TEST_FLAG (LOCKFLAG, arc))
744 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
745 ASSIGN_FLAG (SELECTEDFLAG, select, arc);
746 DrawArc (layer, arc);
747 changed = true;
750 ENDALL_LOOP;
751 VISIBLEPOLYGON_LOOP (PCB->Data);
753 if (TEST_FLAG (flag, polygon) && !TEST_FLAG (LOCKFLAG, polygon))
755 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
756 ASSIGN_FLAG (SELECTEDFLAG, select, polygon);
757 DrawPolygon (layer, polygon);
758 changed = true;
761 ENDALL_LOOP;
763 if (PCB->PinOn && PCB->ElementOn)
765 ALLPIN_LOOP (PCB->Data);
767 if (!TEST_FLAG (LOCKFLAG, element) && TEST_FLAG (flag, pin))
769 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
770 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
771 DrawPin (pin);
772 changed = true;
775 ENDALL_LOOP;
776 ALLPAD_LOOP (PCB->Data);
778 if (!TEST_FLAG (LOCKFLAG, element) && TEST_FLAG (flag, pad))
780 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
781 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
782 DrawPad (pad);
783 changed = true;
786 ENDALL_LOOP;
789 if (PCB->ViaOn)
790 VIA_LOOP (PCB->Data);
792 if (TEST_FLAG (flag, via) && !TEST_FLAG (LOCKFLAG, via))
794 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
795 ASSIGN_FLAG (SELECTEDFLAG, select, via);
796 DrawVia (via);
797 changed = true;
800 END_LOOP;
801 return (changed);
804 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
805 /* ---------------------------------------------------------------------------
806 * selects objects as defined by Type by name;
807 * it's a case insensitive match
808 * returns true if any object has been selected
811 #if defined (HAVE_REGCOMP)
812 static int
813 regexec_match_all (const regex_t *preg, const char *string)
815 regmatch_t match;
817 if (regexec (preg, string, 1, &match, 0) != 0)
818 return 0;
819 if (match.rm_so != 0)
820 return 0;
821 if (match.rm_eo != strlen(string))
822 return 0;
823 return 1;
825 #endif
827 bool
828 SelectObjectByName (int Type, char *Pattern, bool select)
830 bool changed = false;
832 #if defined(HAVE_REGCOMP)
833 #define REGEXEC(arg) (regexec_match_all(&compiled, (arg)))
835 int result;
836 regex_t compiled;
838 /* compile the regular expression */
839 result = regcomp (&compiled, Pattern, REG_EXTENDED | REG_ICASE);
840 if (result)
842 char errorstring[128];
844 regerror (result, &compiled, errorstring, 128);
845 Message (_("regexp error: %s\n"), errorstring);
846 regfree (&compiled);
847 return (false);
849 #else
850 #define REGEXEC(arg) (re_exec((arg)) == 1)
852 char *compiled;
854 /* compile the regular expression */
855 if ((compiled = re_comp (Pattern)) != NULL)
857 Message (_("re_comp error: %s\n"), compiled);
858 return (false);
860 #endif
862 /* loop over all visible objects with names */
863 if (Type & TEXT_TYPE)
864 ALLTEXT_LOOP (PCB->Data);
866 if (!TEST_FLAG (LOCKFLAG, text)
867 && TEXT_IS_VISIBLE (PCB, layer, text)
868 && text->TextString
869 && REGEXEC (text->TextString)
870 && TEST_FLAG (SELECTEDFLAG, text) != select)
872 AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text);
873 ASSIGN_FLAG (SELECTEDFLAG, select, text);
874 DrawText (layer, text);
875 changed = true;
878 ENDALL_LOOP;
880 if (PCB->ElementOn && (Type & ELEMENT_TYPE))
881 ELEMENT_LOOP (PCB->Data);
883 if (!TEST_FLAG (LOCKFLAG, element)
884 && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT
885 || PCB->InvisibleObjectsOn)
886 && TEST_FLAG (SELECTEDFLAG, element) != select)
888 String name = ELEMENT_NAME (PCB, element);
889 if (name && REGEXEC (name))
891 AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element);
892 ASSIGN_FLAG (SELECTEDFLAG, select, element);
893 PIN_LOOP (element);
895 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
896 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
898 END_LOOP;
899 PAD_LOOP (element);
901 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
902 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
904 END_LOOP;
905 ELEMENTTEXT_LOOP (element);
907 AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text);
908 ASSIGN_FLAG (SELECTEDFLAG, select, text);
910 END_LOOP;
911 DrawElementName (element);
912 DrawElement (element);
913 changed = true;
917 END_LOOP;
918 if (PCB->PinOn && (Type & PIN_TYPE))
919 ALLPIN_LOOP (PCB->Data);
921 if (!TEST_FLAG (LOCKFLAG, element)
922 && pin->Name && REGEXEC (pin->Name)
923 && TEST_FLAG (SELECTEDFLAG, pin) != select)
925 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
926 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
927 DrawPin (pin);
928 changed = true;
931 ENDALL_LOOP;
932 if (PCB->PinOn && (Type & PAD_TYPE))
933 ALLPAD_LOOP (PCB->Data);
935 if (!TEST_FLAG (LOCKFLAG, element)
936 && ((TEST_FLAG (ONSOLDERFLAG, pad) != 0) == SWAP_IDENT
937 || PCB->InvisibleObjectsOn)
938 && TEST_FLAG (SELECTEDFLAG, pad) != select)
939 if (pad->Name && REGEXEC (pad->Name))
941 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
942 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
943 DrawPad (pad);
944 changed = true;
947 ENDALL_LOOP;
948 if (PCB->ViaOn && (Type & VIA_TYPE))
949 VIA_LOOP (PCB->Data);
951 if (!TEST_FLAG (LOCKFLAG, via)
952 && via->Name
953 && REGEXEC (via->Name) && TEST_FLAG (SELECTEDFLAG, via) != select)
955 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
956 ASSIGN_FLAG (SELECTEDFLAG, select, via);
957 DrawVia (via);
958 changed = true;
961 END_LOOP;
962 if (Type & NET_TYPE)
964 InitConnectionLookup ();
965 changed = ClearFlagOnAllObjects (true, FOUNDFLAG) || changed;
967 MENU_LOOP (&PCB->NetlistLib);
969 Cardinal i;
970 LibraryEntryType *entry;
971 ConnectionType conn;
973 /* Name[0] and Name[1] are special purpose, not the actual name*/
974 if (menu->Name && menu->Name[0] != '\0' && menu->Name[1] != '\0' &&
975 REGEXEC (menu->Name + 2))
977 for (i = menu->EntryN, entry = menu->Entry; i; i--, entry++)
978 if (SeekPad (entry, &conn, false))
979 RatFindHook (conn.type, conn.ptr1, conn.ptr2, conn.ptr2,
980 true, FOUNDFLAG, true);
983 END_LOOP;
985 changed = SelectByFlag (FOUNDFLAG, select) || changed;
986 changed = ClearFlagOnAllObjects (false, FOUNDFLAG) || changed;
987 FreeConnectionLookupMemory ();
990 #if defined(HAVE_REGCOMP)
991 #if !defined(sgi)
992 regfree (&compiled);
993 #endif
994 #endif
996 if (changed)
998 IncrementUndoSerialNumber ();
999 Draw ();
1001 return (changed);
1003 #endif /* defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) */