Shiny 3D eye-candy
[geda-pcb/pcjc2.git] / src / select.c
blobf130b07b35775aeaec852c18338cf8b021bc54ba
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 + EXTRA_LAYERS);
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 if (layer == & PCB->Data->SOLDERMASKLAYER)
250 if (! (TEST_FLAG (SHOWMASKFLAG, PCB) || !select))
251 continue;
253 if (layer == & PCB->Data->BACKSOLDERMASKLAYER)
255 if (! ((PCB->InvisibleObjectsOn && TEST_FLAG (SHOWMASKFLAG, PCB)) || !select))
256 continue;
258 else
259 if (! (layer->On || !select))
260 continue;
262 LINE_LOOP (layer);
264 if (LINE_IN_BOX (line, Box)
265 && !TEST_FLAG (LOCKFLAG, line)
266 && TEST_FLAG (SELECTEDFLAG, line) != select)
268 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
269 ASSIGN_FLAG (SELECTEDFLAG, select, line);
270 if (layer->On)
271 DrawLine (layer, line);
272 changed = true;
275 END_LOOP;
276 ARC_LOOP (layer);
278 if (ARC_IN_BOX (arc, Box)
279 && !TEST_FLAG (LOCKFLAG, arc)
280 && TEST_FLAG (SELECTEDFLAG, arc) != select)
282 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
283 ASSIGN_FLAG (SELECTEDFLAG, select, arc);
284 if (layer->On)
285 DrawArc (layer, arc);
286 changed = true;
289 END_LOOP;
290 TEXT_LOOP (layer);
292 if (!select || TEXT_IS_VISIBLE(PCB, layer, text))
294 if (TEXT_IN_BOX (text, Box)
295 && !TEST_FLAG (LOCKFLAG, text)
296 && TEST_FLAG (SELECTEDFLAG, text) != select)
298 AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text);
299 ASSIGN_FLAG (SELECTEDFLAG, select, text);
300 if (TEXT_IS_VISIBLE(PCB, layer, text))
301 DrawText (layer, text);
302 changed = true;
306 END_LOOP;
307 POLYGON_LOOP (layer);
309 if (POLYGON_IN_BOX (polygon, Box)
310 && !TEST_FLAG (LOCKFLAG, polygon)
311 && TEST_FLAG (SELECTEDFLAG, polygon) != select)
313 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
314 ASSIGN_FLAG (SELECTEDFLAG, select, polygon);
315 if (layer->On)
316 DrawPolygon (layer, polygon);
317 changed = true;
320 END_LOOP;
322 END_LOOP;
324 /* elements */
325 ELEMENT_LOOP (PCB->Data);
328 bool gotElement = false;
329 if ((PCB->ElementOn || !select)
330 && !TEST_FLAG (LOCKFLAG, element)
331 && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT
332 || PCB->InvisibleObjectsOn))
334 if (BOX_IN_BOX
335 (&ELEMENT_TEXT (PCB, element).BoundingBox, Box)
336 && !TEST_FLAG (LOCKFLAG, &ELEMENT_TEXT (PCB, element))
337 && TEST_FLAG (SELECTEDFLAG,
338 &ELEMENT_TEXT (PCB, element)) != select)
340 /* select all names of element */
341 ELEMENTTEXT_LOOP (element);
343 AddObjectToFlagUndoList (ELEMENTNAME_TYPE,
344 element, text, text);
345 ASSIGN_FLAG (SELECTEDFLAG, select, text);
347 END_LOOP;
348 if (PCB->ElementOn)
349 DrawElementName (element);
350 changed = true;
352 if ((PCB->PinOn || !select) && ELEMENT_IN_BOX (element, Box))
353 if (TEST_FLAG (SELECTEDFLAG, element) != select)
355 AddObjectToFlagUndoList (ELEMENT_TYPE,
356 element, element, element);
357 ASSIGN_FLAG (SELECTEDFLAG, select, element);
358 PIN_LOOP (element);
360 if (TEST_FLAG (SELECTEDFLAG, pin) != select)
362 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
363 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
364 if (PCB->PinOn)
365 DrawPin (pin);
366 changed = true;
369 END_LOOP;
370 PAD_LOOP (element);
372 if (TEST_FLAG (SELECTEDFLAG, pad) != select)
374 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
375 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
376 if (PCB->PinOn)
377 DrawPad (pad);
378 changed = true;
381 END_LOOP;
382 if (PCB->PinOn)
383 DrawElement (element);
384 changed = true;
385 gotElement = true;
388 if ((PCB->PinOn || !select) && !TEST_FLAG (LOCKFLAG, element) && !gotElement)
390 PIN_LOOP (element);
392 if ((VIA_OR_PIN_IN_BOX (pin, Box)
393 && TEST_FLAG (SELECTEDFLAG, pin) != select))
395 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
396 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
397 if (PCB->PinOn)
398 DrawPin (pin);
399 changed = true;
402 END_LOOP;
403 PAD_LOOP (element);
405 if (PAD_IN_BOX (pad, Box)
406 && TEST_FLAG (SELECTEDFLAG, pad) != select
407 && (TEST_FLAG (ONSOLDERFLAG, pad) == SWAP_IDENT
408 || PCB->InvisibleObjectsOn
409 || !select))
411 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
412 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
413 if (PCB->PinOn)
414 DrawPad (pad);
415 changed = true;
418 END_LOOP;
422 END_LOOP;
423 /* end with vias */
424 if (PCB->ViaOn || !select)
425 VIA_LOOP (PCB->Data);
427 if (VIA_OR_PIN_IN_BOX (via, Box)
428 && !TEST_FLAG (LOCKFLAG, via)
429 && TEST_FLAG (SELECTEDFLAG, via) != select)
431 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
432 ASSIGN_FLAG (SELECTEDFLAG, select, via);
433 if (PCB->ViaOn)
434 DrawVia (via);
435 changed = true;
438 END_LOOP;
439 if (changed)
441 Draw ();
442 IncrementUndoSerialNumber ();
444 return (changed);
447 /* ----------------------------------------------------------------------
448 * performs several operations on the passed object
450 void *
451 ObjectOperation (ObjectFunctionType *F,
452 int Type, void *Ptr1, void *Ptr2, void *Ptr3)
454 switch (Type)
456 case LINE_TYPE:
457 if (F->Line)
458 return (F->Line ((LayerType *) Ptr1, (LineType *) Ptr2));
459 break;
461 case ARC_TYPE:
462 if (F->Arc)
463 return (F->Arc ((LayerType *) Ptr1, (ArcType *) Ptr2));
464 break;
466 case LINEPOINT_TYPE:
467 if (F->LinePoint)
468 return (F->LinePoint ((LayerType *) Ptr1, (LineType *) Ptr2,
469 (PointType *) Ptr3));
470 break;
472 case TEXT_TYPE:
473 if (F->Text)
474 return (F->Text ((LayerType *) Ptr1, (TextType *) Ptr2));
475 break;
477 case POLYGON_TYPE:
478 if (F->Polygon)
479 return (F->Polygon ((LayerType *) Ptr1, (PolygonType *) Ptr2));
480 break;
482 case POLYGONPOINT_TYPE:
483 if (F->Point)
484 return (F->Point ((LayerType *) Ptr1, (PolygonType *) Ptr2,
485 (PointType *) Ptr3));
486 break;
488 case VIA_TYPE:
489 if (F->Via)
490 return (F->Via ((PinType *) Ptr1));
491 break;
493 case ELEMENT_TYPE:
494 if (F->Element)
495 return (F->Element ((ElementType *) Ptr1));
496 break;
498 case PIN_TYPE:
499 if (F->Pin)
500 return (F->Pin ((ElementType *) Ptr1, (PinType *) Ptr2));
501 break;
503 case PAD_TYPE:
504 if (F->Pad)
505 return (F->Pad ((ElementType *) Ptr1, (PadType *) Ptr2));
506 break;
508 case ELEMENTNAME_TYPE:
509 if (F->ElementName)
510 return (F->ElementName ((ElementType *) Ptr1));
511 break;
513 case RATLINE_TYPE:
514 if (F->Rat)
515 return (F->Rat ((RatType *) Ptr1));
516 break;
518 return (NULL);
521 /* ----------------------------------------------------------------------
522 * performs several operations on selected objects which are also visible
523 * The lowlevel procedures are passed together with additional information
524 * resets the selected flag if requested
525 * returns true if anything has changed
527 bool
528 SelectedOperation (ObjectFunctionType *F, bool Reset, int type)
530 bool changed = false;
532 /* check lines */
533 if (type & LINE_TYPE && F->Line)
534 VISIBLELINE_LOOP (PCB->Data);
536 if (TEST_FLAG (SELECTEDFLAG, line))
538 if (Reset)
540 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
541 CLEAR_FLAG (SELECTEDFLAG, line);
543 F->Line (layer, line);
544 changed = true;
547 ENDALL_LOOP;
549 /* check arcs */
550 if (type & ARC_TYPE && F->Arc)
551 VISIBLEARC_LOOP (PCB->Data);
553 if (TEST_FLAG (SELECTEDFLAG, arc))
555 if (Reset)
557 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
558 CLEAR_FLAG (SELECTEDFLAG, arc);
560 F->Arc (layer, arc);
561 changed = true;
564 ENDALL_LOOP;
566 /* check text */
567 if (type & TEXT_TYPE && F->Text)
568 ALLTEXT_LOOP (PCB->Data);
570 if (TEST_FLAG (SELECTEDFLAG, text) && TEXT_IS_VISIBLE (PCB, layer, text))
572 if (Reset)
574 AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text);
575 CLEAR_FLAG (SELECTEDFLAG, text);
577 F->Text (layer, text);
578 changed = true;
581 ENDALL_LOOP;
583 /* check polygons */
584 if (type & POLYGON_TYPE && F->Polygon)
585 VISIBLEPOLYGON_LOOP (PCB->Data);
587 if (TEST_FLAG (SELECTEDFLAG, polygon))
589 if (Reset)
591 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
592 CLEAR_FLAG (SELECTEDFLAG, polygon);
594 F->Polygon (layer, polygon);
595 changed = true;
598 ENDALL_LOOP;
600 /* elements silkscreen */
601 if (type & ELEMENT_TYPE && PCB->ElementOn && F->Element)
602 ELEMENT_LOOP (PCB->Data);
604 if (TEST_FLAG (SELECTEDFLAG, element))
606 if (Reset)
608 AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element);
609 CLEAR_FLAG (SELECTEDFLAG, element);
611 F->Element (element);
612 changed = true;
615 END_LOOP;
616 if (type & ELEMENTNAME_TYPE && PCB->ElementOn && F->ElementName)
617 ELEMENT_LOOP (PCB->Data);
619 if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element)))
621 if (Reset)
623 AddObjectToFlagUndoList (ELEMENTNAME_TYPE,
624 element,
625 &ELEMENT_TEXT (PCB, element),
626 &ELEMENT_TEXT (PCB, element));
627 CLEAR_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, element));
629 F->ElementName (element);
630 changed = true;
633 END_LOOP;
635 if (type & PIN_TYPE && PCB->PinOn && F->Pin)
636 ELEMENT_LOOP (PCB->Data);
638 PIN_LOOP (element);
640 if (TEST_FLAG (SELECTEDFLAG, pin))
642 if (Reset)
644 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
645 CLEAR_FLAG (SELECTEDFLAG, pin);
647 F->Pin (element, pin);
648 changed = true;
651 END_LOOP;
653 END_LOOP;
655 if (type & PAD_TYPE && PCB->PinOn && F->Pad)
656 ELEMENT_LOOP (PCB->Data);
658 PAD_LOOP (element);
660 if (TEST_FLAG (SELECTEDFLAG, pad))
662 if (Reset)
664 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
665 CLEAR_FLAG (SELECTEDFLAG, pad);
667 F->Pad (element, pad);
668 changed = true;
671 END_LOOP;
673 END_LOOP;
675 /* process vias */
676 if (type & VIA_TYPE && PCB->ViaOn && F->Via)
677 VIA_LOOP (PCB->Data);
679 if (TEST_FLAG (SELECTEDFLAG, via))
681 if (Reset)
683 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
684 CLEAR_FLAG (SELECTEDFLAG, via);
686 F->Via (via);
687 changed = true;
690 END_LOOP;
691 /* and rat-lines */
692 if (type & RATLINE_TYPE && PCB->RatOn && F->Rat)
693 RAT_LOOP (PCB->Data);
695 if (TEST_FLAG (SELECTEDFLAG, line))
697 if (Reset)
699 AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
700 CLEAR_FLAG (SELECTEDFLAG, line);
702 F->Rat (line);
703 changed = true;
706 END_LOOP;
707 if (Reset && changed)
708 IncrementUndoSerialNumber ();
709 return (changed);
712 /* ----------------------------------------------------------------------
713 * selects/unselects all objects which have (any of) the specified flag(s)
714 * set. (Typically the FOUNDFLAG, assigned during a connection scan).
715 * "select" determines if they are to be selected or unselected
717 * returns true if the state of any object has changed
719 * text objects and elements cannot be selected by this routine
721 bool
722 SelectByFlag (int flag, bool select)
724 bool changed = false;
726 if (PCB->RatOn)
727 RAT_LOOP (PCB->Data);
729 if (TEST_FLAG (flag, line))
731 AddObjectToFlagUndoList (RATLINE_TYPE, line, line, line);
732 ASSIGN_FLAG (SELECTEDFLAG, select, line);
733 DrawRat (line);
734 changed = true;
737 END_LOOP;
739 VISIBLELINE_LOOP (PCB->Data);
741 if (TEST_FLAG (flag, line) && !TEST_FLAG (LOCKFLAG, line))
743 AddObjectToFlagUndoList (LINE_TYPE, layer, line, line);
744 ASSIGN_FLAG (SELECTEDFLAG, select, line);
745 DrawLine (layer, line);
746 changed = true;
749 ENDALL_LOOP;
750 VISIBLEARC_LOOP (PCB->Data);
752 if (TEST_FLAG (flag, arc) && !TEST_FLAG (LOCKFLAG, arc))
754 AddObjectToFlagUndoList (ARC_TYPE, layer, arc, arc);
755 ASSIGN_FLAG (SELECTEDFLAG, select, arc);
756 DrawArc (layer, arc);
757 changed = true;
760 ENDALL_LOOP;
761 VISIBLEPOLYGON_LOOP (PCB->Data);
763 if (TEST_FLAG (flag, polygon) && !TEST_FLAG (LOCKFLAG, polygon))
765 AddObjectToFlagUndoList (POLYGON_TYPE, layer, polygon, polygon);
766 ASSIGN_FLAG (SELECTEDFLAG, select, polygon);
767 DrawPolygon (layer, polygon);
768 changed = true;
771 ENDALL_LOOP;
773 if (PCB->PinOn && PCB->ElementOn)
775 ALLPIN_LOOP (PCB->Data);
777 if (!TEST_FLAG (LOCKFLAG, element) && TEST_FLAG (flag, pin))
779 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
780 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
781 DrawPin (pin);
782 changed = true;
785 ENDALL_LOOP;
786 ALLPAD_LOOP (PCB->Data);
788 if (!TEST_FLAG (LOCKFLAG, element) && TEST_FLAG (flag, pad))
790 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
791 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
792 DrawPad (pad);
793 changed = true;
796 ENDALL_LOOP;
799 if (PCB->ViaOn)
800 VIA_LOOP (PCB->Data);
802 if (TEST_FLAG (flag, via) && !TEST_FLAG (LOCKFLAG, via))
804 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
805 ASSIGN_FLAG (SELECTEDFLAG, select, via);
806 DrawVia (via);
807 changed = true;
810 END_LOOP;
811 return (changed);
814 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
815 /* ---------------------------------------------------------------------------
816 * selects objects as defined by Type by name;
817 * it's a case insensitive match
818 * returns true if any object has been selected
821 #if defined (HAVE_REGCOMP)
822 static int
823 regexec_match_all (const regex_t *preg, const char *string)
825 regmatch_t match;
827 if (regexec (preg, string, 1, &match, 0) != 0)
828 return 0;
829 if (match.rm_so != 0)
830 return 0;
831 if (match.rm_eo != strlen(string))
832 return 0;
833 return 1;
835 #endif
837 bool
838 SelectObjectByName (int Type, char *Pattern, bool select)
840 bool changed = false;
842 #if defined(HAVE_REGCOMP)
843 #define REGEXEC(arg) (regexec_match_all(&compiled, (arg)))
845 int result;
846 regex_t compiled;
848 /* compile the regular expression */
849 result = regcomp (&compiled, Pattern, REG_EXTENDED | REG_ICASE);
850 if (result)
852 char errorstring[128];
854 regerror (result, &compiled, errorstring, 128);
855 Message (_("regexp error: %s\n"), errorstring);
856 regfree (&compiled);
857 return (false);
859 #else
860 #define REGEXEC(arg) (re_exec((arg)) == 1)
862 char *compiled;
864 /* compile the regular expression */
865 if ((compiled = re_comp (Pattern)) != NULL)
867 Message (_("re_comp error: %s\n"), compiled);
868 return (false);
870 #endif
872 /* loop over all visible objects with names */
873 if (Type & TEXT_TYPE)
874 ALLTEXT_LOOP (PCB->Data);
876 if (!TEST_FLAG (LOCKFLAG, text)
877 && TEXT_IS_VISIBLE (PCB, layer, text)
878 && text->TextString
879 && REGEXEC (text->TextString)
880 && TEST_FLAG (SELECTEDFLAG, text) != select)
882 AddObjectToFlagUndoList (TEXT_TYPE, layer, text, text);
883 ASSIGN_FLAG (SELECTEDFLAG, select, text);
884 DrawText (layer, text);
885 changed = true;
888 ENDALL_LOOP;
890 if (PCB->ElementOn && (Type & ELEMENT_TYPE))
891 ELEMENT_LOOP (PCB->Data);
893 if (!TEST_FLAG (LOCKFLAG, element)
894 && ((TEST_FLAG (ONSOLDERFLAG, element) != 0) == SWAP_IDENT
895 || PCB->InvisibleObjectsOn)
896 && TEST_FLAG (SELECTEDFLAG, element) != select)
898 String name = ELEMENT_NAME (PCB, element);
899 if (name && REGEXEC (name))
901 AddObjectToFlagUndoList (ELEMENT_TYPE, element, element, element);
902 ASSIGN_FLAG (SELECTEDFLAG, select, element);
903 PIN_LOOP (element);
905 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
906 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
908 END_LOOP;
909 PAD_LOOP (element);
911 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
912 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
914 END_LOOP;
915 ELEMENTTEXT_LOOP (element);
917 AddObjectToFlagUndoList (ELEMENTNAME_TYPE, element, text, text);
918 ASSIGN_FLAG (SELECTEDFLAG, select, text);
920 END_LOOP;
921 DrawElementName (element);
922 DrawElement (element);
923 changed = true;
927 END_LOOP;
928 if (PCB->PinOn && (Type & PIN_TYPE))
929 ALLPIN_LOOP (PCB->Data);
931 if (!TEST_FLAG (LOCKFLAG, element)
932 && pin->Name && REGEXEC (pin->Name)
933 && TEST_FLAG (SELECTEDFLAG, pin) != select)
935 AddObjectToFlagUndoList (PIN_TYPE, element, pin, pin);
936 ASSIGN_FLAG (SELECTEDFLAG, select, pin);
937 DrawPin (pin);
938 changed = true;
941 ENDALL_LOOP;
942 if (PCB->PinOn && (Type & PAD_TYPE))
943 ALLPAD_LOOP (PCB->Data);
945 if (!TEST_FLAG (LOCKFLAG, element)
946 && ((TEST_FLAG (ONSOLDERFLAG, pad) != 0) == SWAP_IDENT
947 || PCB->InvisibleObjectsOn)
948 && TEST_FLAG (SELECTEDFLAG, pad) != select)
949 if (pad->Name && REGEXEC (pad->Name))
951 AddObjectToFlagUndoList (PAD_TYPE, element, pad, pad);
952 ASSIGN_FLAG (SELECTEDFLAG, select, pad);
953 DrawPad (pad);
954 changed = true;
957 ENDALL_LOOP;
958 if (PCB->ViaOn && (Type & VIA_TYPE))
959 VIA_LOOP (PCB->Data);
961 if (!TEST_FLAG (LOCKFLAG, via)
962 && via->Name
963 && REGEXEC (via->Name) && TEST_FLAG (SELECTEDFLAG, via) != select)
965 AddObjectToFlagUndoList (VIA_TYPE, via, via, via);
966 ASSIGN_FLAG (SELECTEDFLAG, select, via);
967 DrawVia (via);
968 changed = true;
971 END_LOOP;
972 if (Type & NET_TYPE)
974 InitConnectionLookup ();
975 changed = ClearFlagOnAllObjects (true, FOUNDFLAG) || changed;
977 MENU_LOOP (&PCB->NetlistLib);
979 Cardinal i;
980 LibraryEntryType *entry;
981 ConnectionType conn;
983 /* Name[0] and Name[1] are special purpose, not the actual name*/
984 if (menu->Name && menu->Name[0] != '\0' && menu->Name[1] != '\0' &&
985 REGEXEC (menu->Name + 2))
987 for (i = menu->EntryN, entry = menu->Entry; i; i--, entry++)
988 if (SeekPad (entry, &conn, false))
989 RatFindHook (conn.type, conn.ptr1, conn.ptr2, conn.ptr2,
990 true, FOUNDFLAG, true);
993 END_LOOP;
995 changed = SelectByFlag (FOUNDFLAG, select) || changed;
996 changed = ClearFlagOnAllObjects (false, FOUNDFLAG) || changed;
997 FreeConnectionLookupMemory ();
1000 #if defined(HAVE_REGCOMP)
1001 #if !defined(sgi)
1002 regfree (&compiled);
1003 #endif
1004 #endif
1006 if (changed)
1008 IncrementUndoSerialNumber ();
1009 Draw ();
1011 return (changed);
1013 #endif /* defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) */