4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996,1997,1998,1999 Thomas Nau
7 * This module, report.c, was written and is Copyright (C) 1997 harry eaton
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
37 #include "crosshair.h"
51 #include "pcb-printf.h"
60 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
64 #ifdef HAVE_LIBDMALLOC
68 #define USER_UNITMASK (Settings.grid_unit->allow)
71 ReportDrills (int argc
, char **argv
, Coord x
, Coord y
)
73 DrillInfoType
*AllDrills
;
75 char *stringlist
, *thestring
;
79 AllDrills
= GetDrillInfo (PCB
->Data
);
81 for (n
= 0; n
< AllDrills
->DrillN
; n
++)
83 total_drills
+= AllDrills
->Drill
[n
].PinCount
;
84 total_drills
+= AllDrills
->Drill
[n
].ViaCount
;
87 size_left
= 512L + AllDrills
->DrillN
* 64L;
88 stringlist
= (char *)malloc (size_left
);
90 /* Use tabs for formatting since can't count on a fixed font anymore.
91 | And even that probably isn't going to work in all cases.
94 _("There are %d different drill sizes used in this layout, %d holes total\n\n"
95 "Drill Diam. (%s)\t# of Pins\t# of Vias\t# of Elements\t# Unplated\n"),
96 AllDrills
->DrillN
, total_drills
, Settings
.grid_unit
->suffix
);
98 thestring
= stringlist
;
99 while (size_left
> 0 && *thestring
!= '\0')
105 for (n
= 0; n
< AllDrills
->DrillN
; n
++)
107 pcb_snprintf (thestring
, size_left
,
108 "%10m*\t\t%d\t\t%d\t\t%d\t\t%d\n",
109 Settings
.grid_unit
->suffix
,
110 AllDrills
->Drill
[n
].DrillSize
,
111 AllDrills
->Drill
[n
].PinCount
, AllDrills
->Drill
[n
].ViaCount
,
112 AllDrills
->Drill
[n
].ElementN
,
113 AllDrills
->Drill
[n
].UnplatedCount
);
114 while (size_left
> 0 && *thestring
!= '\0')
120 FreeDrillInfo (AllDrills
);
121 /* create dialog box */
122 gui
->report_dialog (_("Drill Report"), stringlist
);
129 static const char reportdialog_syntax
[] = N_("ReportDialog()");
131 static const char reportdialog_help
[] =
132 N_("Report on the object under the crosshair");
134 /* %start-doc actions ReportDialog
136 This is a shortcut for @code{Report(Object)}.
141 ReportDialog (int argc
, char **argv
, Coord x
, Coord y
)
143 void *ptr1
, *ptr2
, *ptr3
;
147 type
= SearchScreen (x
, y
, REPORT_TYPES
, &ptr1
, &ptr2
, &ptr3
);
150 SearchScreen (x
, y
, REPORT_TYPES
| LOCKED_TYPE
, &ptr1
, &ptr2
, &ptr3
);
158 if (gui
->shift_is_pressed ())
160 __r_dump_tree (PCB
->Data
->via_tree
->root
, 0);
164 via
= (PinType
*) ptr2
;
165 if (TEST_FLAG (HOLEFLAG
, via
))
166 pcb_snprintf (report
, sizeof (report
), _("%m+VIA ID# %ld; Flags:%s\n"
168 "It is a pure hole of diameter %$mS.\n"
170 "%s"), USER_UNITMASK
, via
->ID
, flags_to_string (via
->Flags
, VIA_TYPE
),
171 via
->X
, via
->Y
, via
->DrillingHole
, EMPTY (via
->Name
),
172 TEST_FLAG (LOCKFLAG
, via
) ? _("It is LOCKED.\n") : "");
174 pcb_snprintf (report
, sizeof (report
), _("%m+VIA ID# %ld; Flags:%s\n"
176 "Copper width = %$mS. Drill width = %$mS.\n"
177 "Clearance width in polygons = %$mS.\n"
179 "Solder mask hole = %$mS (gap = %$mS).\n"
181 "%s"), USER_UNITMASK
, via
->ID
, flags_to_string (via
->Flags
, VIA_TYPE
),
186 (via
->Thickness
- via
->DrillingHole
) / 2,
188 (via
->Mask
- via
->Thickness
) / 2,
189 EMPTY (via
->Name
), TEST_FLAG (LOCKFLAG
, via
) ?
190 _("It is LOCKED.\n") : "");
196 ElementType
*element
;
198 if (gui
->shift_is_pressed ())
200 __r_dump_tree (PCB
->Data
->pin_tree
->root
, 0);
204 Pin
= (PinType
*) ptr2
;
205 element
= (ElementType
*) ptr1
;
213 if (TEST_FLAG (HOLEFLAG
, Pin
))
214 pcb_snprintf (report
, sizeof (report
), _("%m+PIN ID# %ld; Flags:%s\n"
216 "It is a mounting hole. Drill width = %$mS.\n"
217 "It is owned by element %$mS.\n"
218 "%s"), USER_UNITMASK
, Pin
->ID
, flags_to_string (Pin
->Flags
, PIN_TYPE
),
219 Pin
->X
, Pin
->Y
, Pin
->DrillingHole
,
220 EMPTY (element
->Name
[1].TextString
),
221 TEST_FLAG (LOCKFLAG
, Pin
) ? _("It is LOCKED.\n") : "");
223 pcb_snprintf (report
, sizeof (report
),
224 _("%m+PIN ID# %ld; Flags:%s\n" "(X,Y) = %$mD.\n"
225 "Copper width = %$mS. Drill width = %$mS.\n"
226 "Clearance width to Polygon = %$mS.\n"
228 "Solder mask hole = %$mS (gap = %$mS).\n"
230 "It is owned by element %s\n as pin number %s.\n"
231 "%s"), USER_UNITMASK
,
232 Pin
->ID
, flags_to_string (Pin
->Flags
, PIN_TYPE
),
233 Pin
->X
, Pin
->Y
, Pin
->Thickness
,
236 (Pin
->Thickness
- Pin
->DrillingHole
) / 2,
238 (Pin
->Mask
- Pin
->Thickness
) / 2,
240 EMPTY (element
->Name
[1].TextString
), EMPTY (Pin
->Number
),
241 TEST_FLAG (LOCKFLAG
, Pin
) ? _("It is LOCKED.\n") : "");
248 if (gui
->shift_is_pressed ())
250 LayerType
*layer
= (LayerType
*) ptr1
;
251 __r_dump_tree (layer
->line_tree
->root
, 0);
255 line
= (LineType
*) ptr2
;
256 pcb_snprintf (report
, sizeof (report
), _("%m+LINE ID# %ld; Flags:%s\n"
257 "FirstPoint(X,Y) = %$mD, ID = %ld.\n"
258 "SecondPoint(X,Y) = %$mD, ID = %ld.\n"
259 "Width = %$mS.\nClearance width in polygons = %$mS.\n"
260 "It is on layer %d\n"
261 "and has name \"%s\".\n"
262 "%s"), USER_UNITMASK
,
263 line
->ID
, flags_to_string (line
->Flags
, LINE_TYPE
),
264 line
->Point1
.X
, line
->Point1
.Y
, line
->Point1
.ID
,
265 line
->Point2
.X
, line
->Point2
.Y
, line
->Point2
.ID
,
266 line
->Thickness
, line
->Clearance
/ 2,
267 GetLayerNumber (PCB
->Data
, (LayerType
*) ptr1
),
268 UNKNOWN (line
->Number
),
269 TEST_FLAG (LOCKFLAG
, line
) ? _("It is LOCKED.\n") : "");
276 if (gui
->shift_is_pressed ())
278 __r_dump_tree (PCB
->Data
->rat_tree
->root
, 0);
282 line
= (RatType
*) ptr2
;
283 pcb_snprintf (report
, sizeof (report
), _("%m+RAT-LINE ID# %ld; Flags:%s\n"
284 "FirstPoint(X,Y) = %$mD; ID = %ld; "
285 "connects to layer group %d.\n"
286 "SecondPoint(X,Y) = %$mD; ID = %ld; "
287 "connects to layer group %d.\n"),
288 USER_UNITMASK
, line
->ID
, flags_to_string (line
->Flags
, LINE_TYPE
),
289 line
->Point1
.X
, line
->Point1
.Y
,
290 line
->Point1
.ID
, line
->group1
,
291 line
->Point2
.X
, line
->Point2
.Y
,
292 line
->Point2
.ID
, line
->group2
);
300 if (gui
->shift_is_pressed ())
302 LayerType
*layer
= (LayerType
*) ptr1
;
303 __r_dump_tree (layer
->arc_tree
->root
, 0);
307 Arc
= (ArcType
*) ptr2
;
308 box
= GetArcEnds (Arc
);
310 pcb_snprintf (report
, sizeof (report
), _("%m+ARC ID# %ld; Flags:%s\n"
311 "CenterPoint(X,Y) = %$mD.\n"
312 "Radius = %$mS, Thickness = %$mS.\n"
313 "Clearance width in polygons = %$mS.\n"
314 "StartAngle = %ma degrees, DeltaAngle = %ma degrees.\n"
315 "Bounding Box is %$mD, %$mD.\n"
316 "That makes the end points at %$mD and %$mD.\n"
317 "It is on layer %d.\n"
318 "%s"), USER_UNITMASK
, Arc
->ID
, flags_to_string (Arc
->Flags
, ARC_TYPE
),
320 Arc
->Width
, Arc
->Thickness
,
321 Arc
->Clearance
/ 2, Arc
->StartAngle
, Arc
->Delta
,
322 Arc
->BoundingBox
.X1
, Arc
->BoundingBox
.Y1
,
323 Arc
->BoundingBox
.X2
, Arc
->BoundingBox
.Y2
,
326 GetLayerNumber (PCB
->Data
, (LayerType
*) ptr1
),
327 TEST_FLAG (LOCKFLAG
, Arc
) ? _("It is LOCKED.\n") : "");
332 PolygonType
*Polygon
;
334 if (gui
->shift_is_pressed ())
336 LayerType
*layer
= (LayerType
*) ptr1
;
337 __r_dump_tree (layer
->polygon_tree
->root
, 0);
341 Polygon
= (PolygonType
*) ptr2
;
343 pcb_snprintf (report
, sizeof (report
), _("%m+POLYGON ID# %ld; Flags:%s\n"
344 "Its bounding box is %$mD %$mD.\n"
345 "It has %d points and could store %d more\n"
346 " without using more memory.\n"
347 "It has %d holes and resides on layer %d.\n"
348 "%s"), USER_UNITMASK
, Polygon
->ID
,
349 flags_to_string (Polygon
->Flags
, POLYGON_TYPE
),
350 Polygon
->BoundingBox
.X1
, Polygon
->BoundingBox
.Y1
,
351 Polygon
->BoundingBox
.X2
, Polygon
->BoundingBox
.Y2
,
352 Polygon
->PointN
, Polygon
->PointMax
- Polygon
->PointN
,
354 GetLayerNumber (PCB
->Data
, (LayerType
*) ptr1
),
355 TEST_FLAG (LOCKFLAG
, Polygon
) ? _("It is LOCKED.\n") : "");
362 ElementType
*element
;
364 if (gui
->shift_is_pressed ())
366 __r_dump_tree (PCB
->Data
->pad_tree
->root
, 0);
370 Pad
= (PadType
*) ptr2
;
371 element
= (ElementType
*) ptr1
;
381 len
= Distance (Pad
->Point1
.X
, Pad
->Point1
.Y
, Pad
->Point2
.X
, Pad
->Point2
.Y
);
382 pcb_snprintf (report
, sizeof (report
), _("%m+PAD ID# %ld; Flags:%s\n"
383 "FirstPoint(X,Y) = %$mD; ID = %ld.\n"
384 "SecondPoint(X,Y) = %$mD; ID = %ld.\n"
385 "Width = %$mS. Length = %$mS.\n"
386 "Clearance width in polygons = %$mS.\n"
387 "Solder mask = %$mS x %$mS (gap = %$mS).\n"
389 "It is owned by SMD element %s\n"
390 " as pin number %s and is on the %s\n"
391 "side of the board.\n"
392 "%s"), USER_UNITMASK
, Pad
->ID
,
393 flags_to_string (Pad
->Flags
, PAD_TYPE
),
394 Pad
->Point1
.X
, Pad
->Point1
.Y
, Pad
->Point1
.ID
,
395 Pad
->Point2
.X
, Pad
->Point2
.Y
, Pad
->Point2
.ID
,
396 Pad
->Thickness
, len
+ Pad
->Thickness
,
398 Pad
->Mask
, len
+ Pad
->Mask
,
399 (Pad
->Mask
- Pad
->Thickness
) / 2,
401 EMPTY (element
->Name
[1].TextString
),
403 TEST_FLAG (ONSOLDERFLAG
,
404 Pad
) ? _("solder (bottom)") : _("component"),
405 TEST_FLAG (LOCKFLAG
, Pad
) ? _("It is LOCKED.\n") : "");
410 ElementType
*element
;
412 if (gui
->shift_is_pressed ())
414 __r_dump_tree (PCB
->Data
->element_tree
->root
, 0);
418 element
= (ElementType
*) ptr2
;
419 pcb_snprintf (report
, sizeof (report
), _("%m+ELEMENT ID# %ld; Flags:%s\n"
420 "BoundingBox %$mD %$mD.\n"
421 "Descriptive Name \"%s\".\n"
422 "Name on board \"%s\".\n"
423 "Part number name \"%s\".\n"
424 "It is %$mS tall and is located at (X,Y) = %$mD %s.\n"
425 "Mark located at point (X,Y) = %$mD.\n"
426 "It is on the %s side of the board.\n"
427 "%s"), USER_UNITMASK
,
428 element
->ID
, flags_to_string (element
->Flags
, ELEMENT_TYPE
),
429 element
->BoundingBox
.X1
, element
->BoundingBox
.Y1
,
430 element
->BoundingBox
.X2
, element
->BoundingBox
.Y2
,
431 EMPTY (element
->Name
[0].TextString
),
432 EMPTY (element
->Name
[1].TextString
),
433 EMPTY (element
->Name
[2].TextString
),
434 SCALE_TEXT (FONT_CAPHEIGHT
, element
->Name
[1].Scale
),
435 element
->Name
[1].X
, element
->Name
[1].Y
,
436 TEST_FLAG (HIDENAMEFLAG
, element
) ? _(",\n but it's hidden") : "",
437 element
->MarkX
, element
->MarkY
,
438 TEST_FLAG (ONSOLDERFLAG
, element
) ? _("solder (bottom)") : _("component"),
439 TEST_FLAG (LOCKFLAG
, element
) ? _("It is LOCKED.\n") : "");
444 if (gui
->shift_is_pressed ())
446 LayerType
*layer
= (LayerType
*) ptr1
;
447 __r_dump_tree (layer
->text_tree
->root
, 0);
451 case ELEMENTNAME_TYPE
:
456 if (gui
->shift_is_pressed ())
458 __r_dump_tree (PCB
->Data
->name_tree
[NAME_INDEX (PCB
)]->root
, 0);
462 text
= (TextType
*) ptr2
;
464 if (type
== TEXT_TYPE
)
465 sprintf (laynum
, _("It is on layer %d."),
466 GetLayerNumber (PCB
->Data
, (LayerType
*) ptr1
));
467 pcb_snprintf (report
, sizeof (report
), _("%m+TEXT ID# %ld; Flags:%s\n"
468 "Located at (X,Y) = %$mD.\n"
469 "Characters are %$mS tall.\n"
472 "The bounding box is %$mD %$mD.\n"
474 "%s"), USER_UNITMASK
, text
->ID
, flags_to_string (text
->Flags
, TEXT_TYPE
),
475 text
->X
, text
->Y
, SCALE_TEXT (FONT_CAPHEIGHT
, text
->Scale
),
476 text
->TextString
, text
->Direction
,
477 text
->BoundingBox
.X1
, text
->BoundingBox
.Y1
,
478 text
->BoundingBox
.X2
, text
->BoundingBox
.Y2
,
479 (type
== TEXT_TYPE
) ? laynum
: _("It is an element name."),
480 TEST_FLAG (LOCKFLAG
, text
) ? _("It is LOCKED.\n") : "");
484 case POLYGONPOINT_TYPE
:
486 PointType
*point
= (PointType
*) ptr2
;
487 pcb_snprintf (report
, sizeof (report
), _("%m+POINT ID# %ld.\n"
488 "Located at (X,Y) = %$mD.\n"
489 "It belongs to a %s on layer %d.\n"), USER_UNITMASK
, point
->ID
,
491 (type
== LINEPOINT_TYPE
) ?
492 C_("report", "line") : C_("report", "polygon"),
493 GetLayerNumber (PCB
->Data
, (LayerType
*) ptr1
));
501 sprintf (report
, _("Unknown\n"));
505 if (report
[0] == '\0')
507 Message (_("Nothing found to report on\n"));
510 /* create dialog box */
511 gui
->report_dialog (_("Report"), report
);
517 ReportFoundPins (int argc
, char **argv
, Coord x
, Coord y
)
519 static DynamicStringType list
;
523 DSClearString (&list
);
524 DSAddString (&list
, _("The following pins/pads are FOUND:\n"));
525 ELEMENT_LOOP (PCB
->Data
);
529 if (TEST_FLAG (FOUNDFLAG
, pin
))
531 sprintf (temp
, _("%s-%s,%c"),
532 NAMEONPCB_NAME (element
),
534 ((col
++ % (COLUMNS
+ 1)) == COLUMNS
) ? '\n' : ' ');
535 DSAddString (&list
, temp
);
541 if (TEST_FLAG (FOUNDFLAG
, pad
))
543 sprintf (temp
, _("%s-%s,%c"),
544 NAMEONPCB_NAME (element
), pad
->Number
,
545 ((col
++ % (COLUMNS
+ 1)) == COLUMNS
) ? '\n' : ' ');
546 DSAddString (&list
, temp
);
553 gui
->report_dialog (_("Report"), list
.Data
);
557 /* Assumes that we start with a blank connection state,
558 * e.g. ClearFlagOnAllObjects() has been run.
559 * Does not add its own changes to the undo system
562 XYtoNetLength (Coord x
, Coord y
, int *found
)
569 /* NB: The third argument here, 'false' ensures LookupConnection
570 * does not add its changes to the undo system.
572 LookupConnection (x
, y
, false, PCB
->Grid
, FOUNDFLAG
, true);
574 ALLLINE_LOOP (PCB
->Data
);
576 if (TEST_FLAG (FOUNDFLAG
, line
))
579 dx
= line
->Point1
.X
- line
->Point2
.X
;
580 dy
= line
->Point1
.Y
- line
->Point2
.Y
;
581 length
+= hypot (dx
, dy
);
587 ALLARC_LOOP (PCB
->Data
);
589 if (TEST_FLAG (FOUNDFLAG
, arc
))
592 /* FIXME: we assume width==height here */
593 l
= M_PI
* 2*arc
->Width
* abs(arc
->Delta
)/360.0;
604 ReportAllNetLengths (int argc
, char **argv
, Coord x
, Coord y
)
609 /* Reset all connection flags and save an undo-state to get back
610 * to the state the board was in when we started this function.
612 * After this, we don't add any changes to the undo system, but
613 * ensure we get back to a point where we can Undo() our changes
614 * by resetting the connections with ClearFlagOnAllObjects() before
615 * calling Undo() at the end of the procedure.
617 ClearFlagOnAllObjects (true, FOUNDFLAG
);
618 IncrementUndoSerialNumber ();
620 for (ni
= 0; ni
< PCB
->NetlistLib
.MenuN
; ni
++)
622 char *netname
= PCB
->NetlistLib
.Menu
[ni
].Name
+ 2;
623 char *ename
= PCB
->NetlistLib
.Menu
[ni
].Entry
[0].ListEntry
;
627 ename
= strdup (ename
);
628 pname
= strchr (ename
, '-');
636 ELEMENT_LOOP (PCB
->Data
);
638 char *es
= element
->Name
[NAMEONPCB_INDEX
].TextString
;
639 if (es
&& strcmp (es
, ename
) == 0)
643 if (strcmp (pin
->Number
, pname
) == 0)
654 if (strcmp (pad
->Number
, pname
) == 0)
656 x
= (pad
->Point1
.X
+ pad
->Point2
.X
) / 2;
657 y
= (pad
->Point1
.Y
+ pad
->Point2
.Y
) / 2;
670 const char *units_name
= argv
[0];
674 units_name
= Settings
.grid_unit
->suffix
;
676 length
= XYtoNetLength (x
, y
, &found
);
678 /* Reset connectors for the next lookup */
679 ClearFlagOnAllObjects (false, FOUNDFLAG
);
681 pcb_snprintf(buf
, sizeof (buf
), _("%$m*"), units_name
, length
);
682 gui
->log(_("Net %s length %s\n"), netname
, buf
);
686 ClearFlagOnAllObjects (false, FOUNDFLAG
);
692 ReportNetLength (int argc
, char **argv
, Coord x
, Coord y
)
698 gui
->get_coords (_("Click on a connection"), &x
, &y
);
700 /* Reset all connection flags and save an undo-state to get back
701 * to the state the board was in when we started this function.
703 * After this, we don't add any changes to the undo system, but
704 * ensure we get back to a point where we can Undo() our changes
705 * by resetting the connections with ClearFlagOnAllObjects() before
706 * calling Undo() at the end of the procedure.
708 ClearFlagOnAllObjects (true, FOUNDFLAG
);
709 IncrementUndoSerialNumber ();
711 length
= XYtoNetLength (x
, y
, &found
);
715 ClearFlagOnAllObjects (false, FOUNDFLAG
);
717 gui
->log (_("No net under cursor.\n"));
721 ELEMENT_LOOP (PCB
->Data
);
725 if (TEST_FLAG (FOUNDFLAG
, pin
))
728 char *ename
= element
->Name
[NAMEONPCB_INDEX
].TextString
;
729 char *pname
= pin
->Number
;
734 n
= Concat (ename
, _("-"), pname
, NULL
);
735 for (ni
= 0; ni
< PCB
->NetlistLib
.MenuN
; ni
++)
736 for (nei
= 0; nei
< PCB
->NetlistLib
.Menu
[ni
].EntryN
; nei
++)
738 if (strcmp (PCB
->NetlistLib
.Menu
[ni
].Entry
[nei
].ListEntry
, n
) == 0)
740 netname
= PCB
->NetlistLib
.Menu
[ni
].Name
+ 2;
741 goto got_net_name
; /* four for loops deep */
750 if (TEST_FLAG (FOUNDFLAG
, pad
))
753 char *ename
= element
->Name
[NAMEONPCB_INDEX
].TextString
;
754 char *pname
= pad
->Number
;
759 n
= Concat (ename
, _("-"), pname
, NULL
);
760 for (ni
= 0; ni
< PCB
->NetlistLib
.MenuN
; ni
++)
761 for (nei
= 0; nei
< PCB
->NetlistLib
.Menu
[ni
].EntryN
; nei
++)
763 if (strcmp (PCB
->NetlistLib
.Menu
[ni
].Entry
[nei
].ListEntry
, n
) == 0)
765 netname
= PCB
->NetlistLib
.Menu
[ni
].Name
+ 2;
766 goto got_net_name
; /* four for loops deep */
777 ClearFlagOnAllObjects (false, FOUNDFLAG
);
782 pcb_snprintf(buf
, sizeof (buf
), _("%$m*"), Settings
.grid_unit
->suffix
, length
);
784 gui
->log (_("Net \"%s\" length: %s\n"), netname
, buf
);
786 gui
->log (_("Net length: %s\n"), buf
);
793 ReportNetLengthByName (char *tofind
, int x
, int y
)
800 LibraryMenuType
*net
;
806 #if defined(HAVE_REGCOMP)
810 #if defined(HAVE_RE_COMP)
822 for (i
= 0; i
< PCB
->NetlistLib
.MenuN
; i
++)
824 net
= PCB
->NetlistLib
.Menu
+ i
;
825 if (strcasecmp (tofind
, net
->Name
+ 2) == 0)
830 #if defined(HAVE_REGCOMP)
832 regcomp (&elt_pattern
, tofind
,
833 REG_EXTENDED
| REG_ICASE
| REG_NOSUB
);
836 char errorstring
[128];
838 regerror (result
, &elt_pattern
, errorstring
, 128);
839 Message (_("regexp error: %s\n"), errorstring
);
840 regfree (&elt_pattern
);
844 #if defined(HAVE_RE_COMP)
845 if ((elt_pattern
= re_comp (tofind
)) != NULL
)
847 Message (_("re_comp error: %s\n"), elt_pattern
);
854 for (i
= 0; i
< PCB
->NetlistLib
.MenuN
; i
++)
856 net
= PCB
->NetlistLib
.Menu
+ i
;
861 #if defined(HAVE_REGCOMP)
862 if (regexec (&elt_pattern
, net
->Name
+ 2, 1, &match
, 0) != 0)
865 #if defined(HAVE_RE_COMP)
866 if (re_exec (net
->Name
+ 2) != 1)
872 if (strcasecmp (net
->Name
+ 2, tofind
))
875 if (SeekPad (net
->Entry
, &conn
, false))
880 x
= ((PinType
*) (conn
.ptr2
))->X
;
881 y
= ((PinType
*) (conn
.ptr2
))->Y
;
885 x
= ((PadType
*) (conn
.ptr2
))->Point1
.X
;
886 y
= ((PadType
*) (conn
.ptr2
))->Point1
.Y
;
897 gui
->log (_("No net named %s\n"), tofind
);
903 regfree (&elt_pattern
);
906 /* Reset all connection flags and save an undo-state to get back
907 * to the state the board was in when we started.
909 * After this, we don't add any changes to the undo system, but
910 * ensure we get back to a point where we can Undo() our changes
911 * by resetting the connections with ClearFlagOnAllObjects() before
912 * calling Undo() when we are finished.
914 ClearFlagOnAllObjects (true, FOUNDFLAG
);
915 IncrementUndoSerialNumber ();
917 length
= XYtoNetLength (x
, y
, &found
);
918 netname
= net
->Name
+ 2;
920 ClearFlagOnAllObjects (false, FOUNDFLAG
);
926 gui
->log (_("Net found, but no lines or arcs were flagged.\n"));
928 gui
->log (_("Net not found.\n"));
935 pcb_snprintf(buf
, 50, _("%$m*"), Settings
.grid_unit
->suffix
, length
);
937 gui
->log (_("Net \"%s\" length: %s\n"), netname
, buf
);
939 gui
->log (_("Net length: %s\n"), buf
);
945 /* ---------------------------------------------------------------------------
946 * reports on an object
950 static const char report_syntax
[] =
951 N_("Report(Object|DrillReport|FoundPins|NetLength|AllNetLengths|[,name])");
953 static const char report_help
[] = N_("Produce various report.");
955 /* %start-doc actions Report
960 The object under the crosshair will be reported, describing various
961 aspects of the object.
964 A report summarizing the number of drill sizes used, and how many of
965 each, will be produced.
968 A report listing all pins and pads which are marked as ``found'' will
972 The name and length of the net under the crosshair will be reported to
976 The name and length of the net under the crosshair will be reported to
977 the message log. An optional parameter specifies mm, mil, pcb, or in
985 Report (int argc
, char **argv
, Coord x
, Coord y
)
987 if ((argc
< 1) || (argc
> 2))
989 else if (strcasecmp (argv
[0], "Object") == 0)
991 gui
->get_coords (_("Click on an object"), &x
, &y
);
992 return ReportDialog (argc
- 1, argv
+ 1, x
, y
);
994 else if (strcasecmp (argv
[0], "DrillReport") == 0)
995 return ReportDrills (argc
- 1, argv
+ 1, x
, y
);
996 else if (strcasecmp (argv
[0], "FoundPins") == 0)
997 return ReportFoundPins (argc
- 1, argv
+ 1, x
, y
);
998 else if ((strcasecmp (argv
[0], "NetLength") == 0) && (argc
== 1))
999 return ReportNetLength (argc
- 1, argv
+ 1, x
, y
);
1000 else if (strcasecmp (argv
[0], "AllNetLengths") == 0)
1001 return ReportAllNetLengths (argc
- 1, argv
+ 1, x
, y
);
1002 else if ((strcasecmp (argv
[0], "NetLength") == 0) && (argc
== 2))
1003 return ReportNetLengthByName (argv
[1], x
, y
);
1011 HID_Action report_action_list
[] = {
1012 {"ReportObject", N_("Click on an object"), ReportDialog
,
1013 reportdialog_help
, reportdialog_syntax
}
1015 {"Report", 0, Report
,
1016 report_help
, report_syntax
}
1019 REGISTER_ACTIONS (report_action_list
)