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
))
580 dx
= line
->Point1
.X
- line
->Point2
.X
;
581 dy
= line
->Point1
.Y
- line
->Point2
.Y
;
582 l
= sqrt ((double)dx
*dx
+ (double)dy
*dy
);
589 ALLARC_LOOP (PCB
->Data
);
591 if (TEST_FLAG (FOUNDFLAG
, arc
))
594 /* FIXME: we assume width==height here */
595 l
= M_PI
* 2*arc
->Width
* abs(arc
->Delta
)/360.0;
606 ReportAllNetLengths (int argc
, char **argv
, Coord x
, Coord y
)
611 /* Reset all connection flags and save an undo-state to get back
612 * to the state the board was in when we started this function.
614 * After this, we don't add any changes to the undo system, but
615 * ensure we get back to a point where we can Undo() our changes
616 * by resetting the connections with ClearFlagOnAllObjects() before
617 * calling Undo() at the end of the procedure.
619 ClearFlagOnAllObjects (true, FOUNDFLAG
);
620 IncrementUndoSerialNumber ();
622 for (ni
= 0; ni
< PCB
->NetlistLib
.MenuN
; ni
++)
624 char *netname
= PCB
->NetlistLib
.Menu
[ni
].Name
+ 2;
625 char *ename
= PCB
->NetlistLib
.Menu
[ni
].Entry
[0].ListEntry
;
629 ename
= strdup (ename
);
630 pname
= strchr (ename
, '-');
638 ELEMENT_LOOP (PCB
->Data
);
640 char *es
= element
->Name
[NAMEONPCB_INDEX
].TextString
;
641 if (es
&& strcmp (es
, ename
) == 0)
645 if (strcmp (pin
->Number
, pname
) == 0)
656 if (strcmp (pad
->Number
, pname
) == 0)
658 x
= (pad
->Point1
.X
+ pad
->Point2
.X
) / 2;
659 y
= (pad
->Point1
.Y
+ pad
->Point2
.Y
) / 2;
672 const char *units_name
= argv
[0];
676 units_name
= Settings
.grid_unit
->suffix
;
678 length
= XYtoNetLength (x
, y
, &found
);
680 /* Reset connectors for the next lookup */
681 ClearFlagOnAllObjects (false, FOUNDFLAG
);
683 pcb_snprintf(buf
, sizeof (buf
), _("%$m*"), units_name
, length
);
684 gui
->log(_("Net %s length %s\n"), netname
, buf
);
688 ClearFlagOnAllObjects (false, FOUNDFLAG
);
694 ReportNetLength (int argc
, char **argv
, Coord x
, Coord y
)
700 gui
->get_coords (_("Click on a connection"), &x
, &y
);
702 /* Reset all connection flags and save an undo-state to get back
703 * to the state the board was in when we started this function.
705 * After this, we don't add any changes to the undo system, but
706 * ensure we get back to a point where we can Undo() our changes
707 * by resetting the connections with ClearFlagOnAllObjects() before
708 * calling Undo() at the end of the procedure.
710 ClearFlagOnAllObjects (true, FOUNDFLAG
);
711 IncrementUndoSerialNumber ();
713 length
= XYtoNetLength (x
, y
, &found
);
717 ClearFlagOnAllObjects (false, FOUNDFLAG
);
719 gui
->log (_("No net under cursor.\n"));
723 ELEMENT_LOOP (PCB
->Data
);
727 if (TEST_FLAG (FOUNDFLAG
, pin
))
730 char *ename
= element
->Name
[NAMEONPCB_INDEX
].TextString
;
731 char *pname
= pin
->Number
;
736 n
= Concat (ename
, _("-"), pname
, NULL
);
737 for (ni
= 0; ni
< PCB
->NetlistLib
.MenuN
; ni
++)
738 for (nei
= 0; nei
< PCB
->NetlistLib
.Menu
[ni
].EntryN
; nei
++)
740 if (strcmp (PCB
->NetlistLib
.Menu
[ni
].Entry
[nei
].ListEntry
, n
) == 0)
742 netname
= PCB
->NetlistLib
.Menu
[ni
].Name
+ 2;
743 goto got_net_name
; /* four for loops deep */
752 if (TEST_FLAG (FOUNDFLAG
, pad
))
755 char *ename
= element
->Name
[NAMEONPCB_INDEX
].TextString
;
756 char *pname
= pad
->Number
;
761 n
= Concat (ename
, _("-"), pname
, NULL
);
762 for (ni
= 0; ni
< PCB
->NetlistLib
.MenuN
; ni
++)
763 for (nei
= 0; nei
< PCB
->NetlistLib
.Menu
[ni
].EntryN
; nei
++)
765 if (strcmp (PCB
->NetlistLib
.Menu
[ni
].Entry
[nei
].ListEntry
, n
) == 0)
767 netname
= PCB
->NetlistLib
.Menu
[ni
].Name
+ 2;
768 goto got_net_name
; /* four for loops deep */
779 ClearFlagOnAllObjects (false, FOUNDFLAG
);
784 pcb_snprintf(buf
, sizeof (buf
), _("%$m*"), Settings
.grid_unit
->suffix
, length
);
786 gui
->log (_("Net \"%s\" length: %s\n"), netname
, buf
);
788 gui
->log (_("Net length: %s\n"), buf
);
795 ReportNetLengthByName (char *tofind
, int x
, int y
)
802 LibraryMenuType
*net
;
808 #if defined(HAVE_REGCOMP)
812 #if defined(HAVE_RE_COMP)
824 for (i
= 0; i
< PCB
->NetlistLib
.MenuN
; i
++)
826 net
= PCB
->NetlistLib
.Menu
+ i
;
827 if (strcasecmp (tofind
, net
->Name
+ 2) == 0)
832 #if defined(HAVE_REGCOMP)
834 regcomp (&elt_pattern
, tofind
,
835 REG_EXTENDED
| REG_ICASE
| REG_NOSUB
);
838 char errorstring
[128];
840 regerror (result
, &elt_pattern
, errorstring
, 128);
841 Message (_("regexp error: %s\n"), errorstring
);
842 regfree (&elt_pattern
);
846 #if defined(HAVE_RE_COMP)
847 if ((elt_pattern
= re_comp (tofind
)) != NULL
)
849 Message (_("re_comp error: %s\n"), elt_pattern
);
856 for (i
= 0; i
< PCB
->NetlistLib
.MenuN
; i
++)
858 net
= PCB
->NetlistLib
.Menu
+ i
;
863 #if defined(HAVE_REGCOMP)
864 if (regexec (&elt_pattern
, net
->Name
+ 2, 1, &match
, 0) != 0)
867 #if defined(HAVE_RE_COMP)
868 if (re_exec (net
->Name
+ 2) != 1)
874 if (strcasecmp (net
->Name
+ 2, tofind
))
877 if (SeekPad (net
->Entry
, &conn
, false))
882 x
= ((PinType
*) (conn
.ptr2
))->X
;
883 y
= ((PinType
*) (conn
.ptr2
))->Y
;
887 x
= ((PadType
*) (conn
.ptr2
))->Point1
.X
;
888 y
= ((PadType
*) (conn
.ptr2
))->Point1
.Y
;
899 gui
->log (_("No net named %s\n"), tofind
);
905 regfree (&elt_pattern
);
908 /* Reset all connection flags and save an undo-state to get back
909 * to the state the board was in when we started.
911 * After this, we don't add any changes to the undo system, but
912 * ensure we get back to a point where we can Undo() our changes
913 * by resetting the connections with ClearFlagOnAllObjects() before
914 * calling Undo() when we are finished.
916 ClearFlagOnAllObjects (true, FOUNDFLAG
);
917 IncrementUndoSerialNumber ();
919 length
= XYtoNetLength (x
, y
, &found
);
920 netname
= net
->Name
+ 2;
922 ClearFlagOnAllObjects (false, FOUNDFLAG
);
928 gui
->log (_("Net found, but no lines or arcs were flagged.\n"));
930 gui
->log (_("Net not found.\n"));
937 pcb_snprintf(buf
, 50, _("%$m*"), Settings
.grid_unit
->suffix
, length
);
939 gui
->log (_("Net \"%s\" length: %s\n"), netname
, buf
);
941 gui
->log (_("Net length: %s\n"), buf
);
947 /* ---------------------------------------------------------------------------
948 * reports on an object
952 static const char report_syntax
[] =
953 N_("Report(Object|DrillReport|FoundPins|NetLength|AllNetLengths|[,name])");
955 static const char report_help
[] = N_("Produce various report.");
957 /* %start-doc actions Report
962 The object under the crosshair will be reported, describing various
963 aspects of the object.
966 A report summarizing the number of drill sizes used, and how many of
967 each, will be produced.
970 A report listing all pins and pads which are marked as ``found'' will
974 The name and length of the net under the crosshair will be reported to
978 The name and length of the net under the crosshair will be reported to
979 the message log. An optional parameter specifies mm, mil, pcb, or in
987 Report (int argc
, char **argv
, Coord x
, Coord y
)
989 if ((argc
< 1) || (argc
> 2))
991 else if (strcasecmp (argv
[0], "Object") == 0)
993 gui
->get_coords (_("Click on an object"), &x
, &y
);
994 return ReportDialog (argc
- 1, argv
+ 1, x
, y
);
996 else if (strcasecmp (argv
[0], "DrillReport") == 0)
997 return ReportDrills (argc
- 1, argv
+ 1, x
, y
);
998 else if (strcasecmp (argv
[0], "FoundPins") == 0)
999 return ReportFoundPins (argc
- 1, argv
+ 1, x
, y
);
1000 else if ((strcasecmp (argv
[0], "NetLength") == 0) && (argc
== 1))
1001 return ReportNetLength (argc
- 1, argv
+ 1, x
, y
);
1002 else if (strcasecmp (argv
[0], "AllNetLengths") == 0)
1003 return ReportAllNetLengths (argc
- 1, argv
+ 1, x
, y
);
1004 else if ((strcasecmp (argv
[0], "NetLength") == 0) && (argc
== 2))
1005 return ReportNetLengthByName (argv
[1], x
, y
);
1013 HID_Action report_action_list
[] = {
1014 {"ReportObject", N_("Click on an object"), ReportDialog
,
1015 reportdialog_help
, reportdialog_syntax
}
1017 {"Report", 0, Report
,
1018 report_help
, report_syntax
}
1021 REGISTER_ACTIONS (report_action_list
)