Index: doc-rnd/TODO =================================================================== --- doc-rnd/TODO (revision 1388) +++ doc-rnd/TODO (revision 1389) @@ -11,8 +11,6 @@ - mods: - move rubberband - move libpcbfp - - move report - - move strflags.c embedded test code to regression RELEASE: - mention the harmless gtk/lesstif uninit warnings in the release notes? Index: scconfig/plugins.h =================================================================== --- scconfig/plugins.h (revision 1388) +++ scconfig/plugins.h (revision 1389) @@ -12,6 +12,7 @@ plugin_def("fontmode", "font editor", sbuildin) plugin_def("legacy_func", "legacy functions", sbuildin) plugin_def("stroke", "libstroke gestures", sdisable) +plugin_def("report", "reprot actions", sbuildin) plugin_header("\nImport plugins:\n") plugin_def("import_sch", "import sch", sbuildin) Index: src/report.c =================================================================== --- src/report.c (revision 1388) +++ src/report.c (nonexistent) @@ -1,926 +0,0 @@ -/* - * COPYRIGHT - * - * PCB, interactive printed circuit board design - * Copyright (C) 1994,1995,1996,1997,1998,1999 Thomas Nau - * - * This module, report.c, was written and is Copyright (C) 1997 harry eaton - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Contact addresses for paper mail and Email: - * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany - * Thomas.Nau@rz.uni-ulm.de - * - */ - - -#include "config.h" - -#include - -#include "report.h" -#include "crosshair.h" -#include "data.h" -#include "drill.h" -#include "error.h" -#include "search.h" -#include "misc.h" -#include "mymem.h" -#include "rats.h" -#include "rtree.h" -#include "strflags.h" -#include "macro.h" -#include "undo.h" -#include "find.h" -#include "draw.h" -#include "pcb-printf.h" -#ifdef HAVE_REGEX_H -#include -#endif - -#ifdef HAVE_REGCOMP -#undef HAVE_RE_COMP -#endif - -#if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) -#define USE_RE -#endif - - -#define USER_UNITMASK (Settings.grid_unit->allow) - -static int ReportDrills(int argc, char **argv, Coord x, Coord y) -{ - DrillInfoTypePtr AllDrills; - Cardinal n; - char *stringlist, *thestring; - int total_drills = 0; - - AllDrills = GetDrillInfo(PCB->Data); - RoundDrillInfo(AllDrills, 100); - - for (n = 0; n < AllDrills->DrillN; n++) { - total_drills += AllDrills->Drill[n].PinCount; - total_drills += AllDrills->Drill[n].ViaCount; - total_drills += AllDrills->Drill[n].UnplatedCount; - } - - stringlist = (char *) malloc(512L + AllDrills->DrillN * 64L); - - /* Use tabs for formatting since can't count on a fixed font anymore. - | And even that probably isn't going to work in all cases. - */ - sprintf(stringlist, - "There are %d different drill sizes used in this layout, %d holes total\n\n" - "Drill Diam. (%s)\t# of Pins\t# of Vias\t# of Elements\t# Unplated\n", - AllDrills->DrillN, total_drills, Settings.grid_unit->suffix); - thestring = stringlist; - while (*thestring != '\0') - thestring++; - for (n = 0; n < AllDrills->DrillN; n++) { - pcb_sprintf(thestring, - "%10m*\t\t%d\t\t%d\t\t%d\t\t%d\n", - Settings.grid_unit->suffix, - AllDrills->Drill[n].DrillSize, - AllDrills->Drill[n].PinCount, AllDrills->Drill[n].ViaCount, - AllDrills->Drill[n].ElementN, AllDrills->Drill[n].UnplatedCount); - while (*thestring != '\0') - thestring++; - } - FreeDrillInfo(AllDrills); - /* create dialog box */ - gui->report_dialog("Drill Report", stringlist); - - free(stringlist); - return 0; -} - - -static const char reportdialog_syntax[] = "ReportObject()"; - -static const char reportdialog_help[] = "Report on the object under the crosshair"; - -/* %start-doc actions ReportDialog - -This is a shortcut for @code{Report(Object)}. - -%end-doc */ - -static int ReportDialog(int argc, char **argv, Coord x, Coord y) -{ - void *ptr1, *ptr2, *ptr3; - int type; - char *report = NULL; - - type = SearchScreen(x, y, REPORT_TYPES, &ptr1, &ptr2, &ptr3); - if (type == NO_TYPE) - type = SearchScreen(x, y, REPORT_TYPES | LOCKED_TYPE, &ptr1, &ptr2, &ptr3); - - switch (type) { - case VIA_TYPE: - { - PinTypePtr via; -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - __r_dump_tree(PCB->Data->via_tree->root, 0); - return 0; - } -#endif - via = (PinTypePtr) ptr2; - if (TEST_FLAG(HOLEFLAG, via)) - report = pcb_strdup_printf("%m+VIA ID# %ld; Flags:%s\n" - "(X,Y) = %$mD.\n" - "It is a pure hole of diameter %$mS.\n" - "Name = \"%s\"." - "%s", USER_UNITMASK, via->ID, flags_to_string(via->Flags, VIA_TYPE), - via->X, via->Y, via->DrillingHole, EMPTY(via->Name), TEST_FLAG(LOCKFLAG, via) ? "It is LOCKED.\n" : ""); - else - report = pcb_strdup_printf("%m+VIA ID# %ld; Flags:%s\n" - "(X,Y) = %$mD.\n" - "Copper width = %$mS. Drill width = %$mS.\n" - "Clearance width in polygons = %$mS.\n" - "Annulus = %$mS.\n" - "Solder mask hole = %$mS (gap = %$mS).\n" - "Name = \"%s\"." - "%s", USER_UNITMASK, via->ID, flags_to_string(via->Flags, VIA_TYPE), - via->X, via->Y, - via->Thickness, - via->DrillingHole, - via->Clearance / 2, - (via->Thickness - via->DrillingHole) / 2, - via->Mask, - (via->Mask - via->Thickness) / 2, EMPTY(via->Name), TEST_FLAG(LOCKFLAG, via) ? "It is LOCKED.\n" : ""); - break; - } - case PIN_TYPE: - { - PinTypePtr Pin; - ElementTypePtr element; -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - __r_dump_tree(PCB->Data->pin_tree->root, 0); - return 0; - } -#endif - Pin = (PinTypePtr) ptr2; - element = (ElementTypePtr) ptr1; - - PIN_LOOP(element); - { - if (pin == Pin) - break; - } - END_LOOP; - if (TEST_FLAG(HOLEFLAG, Pin)) - report = pcb_strdup_printf("%m+PIN ID# %ld; Flags:%s\n" - "(X,Y) = %$mD.\n" - "It is a mounting hole. Drill width = %$mS.\n" - "It is owned by element %$mS.\n" - "%s", USER_UNITMASK, Pin->ID, flags_to_string(Pin->Flags, PIN_TYPE), - Pin->X, Pin->Y, Pin->DrillingHole, - EMPTY(element->Name[1].TextString), TEST_FLAG(LOCKFLAG, Pin) ? "It is LOCKED.\n" : ""); - else - report = pcb_strdup_printf( - "%m+PIN ID# %ld; Flags:%s\n" "(X,Y) = %$mD.\n" - "Copper width = %$mS. Drill width = %$mS.\n" - "Clearance width to Polygon = %$mS.\n" - "Annulus = %$mS.\n" - "Solder mask hole = %$mS (gap = %$mS).\n" - "Name = \"%s\".\n" - "It is owned by element %s\n as pin number %s.\n" - "%s", USER_UNITMASK, - Pin->ID, flags_to_string(Pin->Flags, PIN_TYPE), - Pin->X, Pin->Y, Pin->Thickness, - Pin->DrillingHole, - Pin->Clearance / 2, - (Pin->Thickness - Pin->DrillingHole) / 2, - Pin->Mask, - (Pin->Mask - Pin->Thickness) / 2, - EMPTY(Pin->Name), - EMPTY(element->Name[1].TextString), EMPTY(Pin->Number), TEST_FLAG(LOCKFLAG, Pin) ? "It is LOCKED.\n" : ""); - break; - } - case LINE_TYPE: - { - LineTypePtr line; -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - LayerTypePtr layer = (LayerTypePtr) ptr1; - __r_dump_tree(layer->line_tree->root, 0); - return 0; - } -#endif - line = (LineTypePtr) ptr2; - report = pcb_strdup_printf("%m+LINE ID# %ld; Flags:%s\n" - "FirstPoint(X,Y) = %$mD, ID = %ld.\n" - "SecondPoint(X,Y) = %$mD, ID = %ld.\n" - "Width = %$mS.\nClearance width in polygons = %$mS.\n" - "It is on layer %d\n" - "and has name \"%s\".\n" - "%s", USER_UNITMASK, - line->ID, flags_to_string(line->Flags, LINE_TYPE), - line->Point1.X, line->Point1.Y, line->Point1.ID, - line->Point2.X, line->Point2.Y, line->Point2.ID, - line->Thickness, line->Clearance / 2, - GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1), - UNKNOWN(line->Number), TEST_FLAG(LOCKFLAG, line) ? "It is LOCKED.\n" : ""); - break; - } - case RATLINE_TYPE: - { - RatTypePtr line; -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - __r_dump_tree(PCB->Data->rat_tree->root, 0); - return 0; - } -#endif - line = (RatTypePtr) ptr2; - report = pcb_strdup_printf("%m+RAT-LINE ID# %ld; Flags:%s\n" - "FirstPoint(X,Y) = %$mD; ID = %ld; " - "connects to layer group %d.\n" - "SecondPoint(X,Y) = %$mD; ID = %ld; " - "connects to layer group %d.\n", - USER_UNITMASK, line->ID, flags_to_string(line->Flags, LINE_TYPE), - line->Point1.X, line->Point1.Y, - line->Point1.ID, line->group1, line->Point2.X, line->Point2.Y, line->Point2.ID, line->group2); - break; - } - case ARC_TYPE: - { - ArcTypePtr Arc; - BoxTypePtr box; -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - LayerTypePtr layer = (LayerTypePtr) ptr1; - __r_dump_tree(layer->arc_tree->root, 0); - return 0; - } -#endif - Arc = (ArcTypePtr) ptr2; - box = GetArcEnds(Arc); - - report = pcb_strdup_printf("%m+ARC ID# %ld; Flags:%s\n" - "CenterPoint(X,Y) = %$mD.\n" - "Radius = %$mS, Thickness = %$mS.\n" - "Clearance width in polygons = %$mS.\n" - "StartAngle = %ma degrees, DeltaAngle = %ma degrees.\n" - "Bounding Box is %$mD, %$mD.\n" - "That makes the end points at %$mD and %$mD.\n" - "It is on layer %d.\n" - "%s", USER_UNITMASK, Arc->ID, flags_to_string(Arc->Flags, ARC_TYPE), - Arc->X, Arc->Y, - Arc->Width, Arc->Thickness, - Arc->Clearance / 2, Arc->StartAngle, Arc->Delta, - Arc->BoundingBox.X1, Arc->BoundingBox.Y1, - Arc->BoundingBox.X2, Arc->BoundingBox.Y2, - box->X1, box->Y1, - box->X2, box->Y2, - GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1), TEST_FLAG(LOCKFLAG, Arc) ? "It is LOCKED.\n" : ""); - break; - } - case POLYGON_TYPE: - { - PolygonTypePtr Polygon; -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - LayerTypePtr layer = (LayerTypePtr) ptr1; - __r_dump_tree(layer->polygon_tree->root, 0); - return 0; - } -#endif - Polygon = (PolygonTypePtr) ptr2; - - report = pcb_strdup_printf("%m+POLYGON ID# %ld; Flags:%s\n" - "Its bounding box is %$mD %$mD.\n" - "It has %d points and could store %d more\n" - " without using more memory.\n" - "It has %d holes and resides on layer %d.\n" - "%s", USER_UNITMASK, Polygon->ID, - flags_to_string(Polygon->Flags, POLYGON_TYPE), - Polygon->BoundingBox.X1, Polygon->BoundingBox.Y1, - Polygon->BoundingBox.X2, Polygon->BoundingBox.Y2, - Polygon->PointN, Polygon->PointMax - Polygon->PointN, - Polygon->HoleIndexN, - GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1), TEST_FLAG(LOCKFLAG, Polygon) ? "It is LOCKED.\n" : ""); - break; - } - case PAD_TYPE: - { - Coord len; - PadTypePtr Pad; - ElementTypePtr element; -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - __r_dump_tree(PCB->Data->pad_tree->root, 0); - return 0; - } -#endif - Pad = (PadTypePtr) ptr2; - element = (ElementTypePtr) ptr1; - - PAD_LOOP(element); - { - { - if (pad == Pad) - break; - } - } - END_LOOP; - len = Distance(Pad->Point1.X, Pad->Point1.Y, Pad->Point2.X, Pad->Point2.Y); - report = pcb_strdup_printf("%m+PAD ID# %ld; Flags:%s\n" - "FirstPoint(X,Y) = %$mD; ID = %ld.\n" - "SecondPoint(X,Y) = %$mD; ID = %ld.\n" - "Width = %$mS. Length = %$mS.\n" - "Clearance width in polygons = %$mS.\n" - "Solder mask = %$mS x %$mS (gap = %$mS).\n" - "Name = \"%s\".\n" - "It is owned by SMD element %s\n" - " as pin number %s and is on the %s\n" - "side of the board.\n" - "%s", USER_UNITMASK, Pad->ID, - flags_to_string(Pad->Flags, PAD_TYPE), - Pad->Point1.X, Pad->Point1.Y, Pad->Point1.ID, - Pad->Point2.X, Pad->Point2.Y, Pad->Point2.ID, - Pad->Thickness, len + Pad->Thickness, - Pad->Clearance / 2, - Pad->Mask, len + Pad->Mask, - (Pad->Mask - Pad->Thickness) / 2, - EMPTY(Pad->Name), - EMPTY(element->Name[1].TextString), - EMPTY(Pad->Number), - TEST_FLAG(ONSOLDERFLAG, - Pad) ? "solder (bottom)" : "component", TEST_FLAG(LOCKFLAG, Pad) ? "It is LOCKED.\n" : ""); - break; - } - case ELEMENT_TYPE: - { - ElementTypePtr element; -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - __r_dump_tree(PCB->Data->element_tree->root, 0); - return 0; - } -#endif - element = (ElementTypePtr) ptr2; - report = pcb_strdup_printf("%m+ELEMENT ID# %ld; Flags:%s\n" - "BoundingBox %$mD %$mD.\n" - "Descriptive Name \"%s\".\n" - "Name on board \"%s\".\n" - "Part number name \"%s\".\n" - "It is %$mS tall and is located at (X,Y) = %$mD %s.\n" - "Mark located at point (X,Y) = %$mD.\n" - "It is on the %s side of the board.\n" - "%s", USER_UNITMASK, - element->ID, flags_to_string(element->Flags, ELEMENT_TYPE), - element->BoundingBox.X1, element->BoundingBox.Y1, - element->BoundingBox.X2, element->BoundingBox.Y2, - EMPTY(element->Name[0].TextString), - EMPTY(element->Name[1].TextString), - EMPTY(element->Name[2].TextString), - SCALE_TEXT(FONT_CAPHEIGHT, element->Name[1].Scale), - element->Name[1].X, element->Name[1].Y, - TEST_FLAG(HIDENAMEFLAG, element) ? ",\n but it's hidden" : "", - element->MarkX, element->MarkY, - TEST_FLAG(ONSOLDERFLAG, element) ? "solder (bottom)" : "component", - TEST_FLAG(LOCKFLAG, element) ? "It is LOCKED.\n" : ""); - break; - } - case TEXT_TYPE: -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - LayerTypePtr layer = (LayerTypePtr) ptr1; - __r_dump_tree(layer->text_tree->root, 0); - return 0; - } -#endif - case ELEMENTNAME_TYPE: - { - char laynum[32]; - TextTypePtr text; -#ifndef NDEBUG - if (gui->shift_is_pressed()) { - __r_dump_tree(PCB->Data->name_tree[NAME_INDEX(PCB)]->root, 0); - return 0; - } -#endif - text = (TextTypePtr) ptr2; - - if (type == TEXT_TYPE) - sprintf(laynum, "It is on layer %d.", GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1)); - report = pcb_strdup_printf("%m+TEXT ID# %ld; Flags:%s\n" - "Located at (X,Y) = %$mD.\n" - "Characters are %$mS tall.\n" - "Value is \"%s\".\n" - "Direction is %d.\n" - "The bounding box is %$mD %$mD.\n" - "%s\n" - "%s", USER_UNITMASK, text->ID, flags_to_string(text->Flags, TEXT_TYPE), - text->X, text->Y, SCALE_TEXT(FONT_CAPHEIGHT, text->Scale), - text->TextString, text->Direction, - text->BoundingBox.X1, text->BoundingBox.Y1, - text->BoundingBox.X2, text->BoundingBox.Y2, - (type == TEXT_TYPE) ? laynum : "It is an element name.", TEST_FLAG(LOCKFLAG, text) ? "It is LOCKED.\n" : ""); - break; - } - case LINEPOINT_TYPE: - case POLYGONPOINT_TYPE: - { - PointTypePtr point = (PointTypePtr) ptr2; - report = pcb_strdup_printf("%m+POINT ID# %ld.\n" - "Located at (X,Y) = %$mD.\n" - "It belongs to a %s on layer %d.\n", USER_UNITMASK, point->ID, - point->X, point->Y, - (type == LINEPOINT_TYPE) ? "line" : "polygon", GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1)); - break; - } - case NO_TYPE: - report[0] = '\0'; - break; - - default: - report = pcb_strdup_printf("Unknown\n"); - break; - } - - if ((report == NULL) || (report == '\0')) { - Message(_("Nothing found to report on\n")); - return 1; - } - /* create dialog box */ - gui->report_dialog("Report", report); - free(report); - return 0; -} - -static int ReportFoundPins(int argc, char **argv, Coord x, Coord y) -{ - gds_t list; - int col = 0; - - gds_init(&list); - gds_append_str(&list, "The following pins/pads are FOUND:\n"); - ELEMENT_LOOP(PCB->Data); - { - PIN_LOOP(element); - { - if (TEST_FLAG(FOUNDFLAG, pin)) - pcb_append_printf(&list, "%s-%s,%c", NAMEONPCB_NAME(element), pin->Number, ((col++ % (COLUMNS + 1)) == COLUMNS) ? '\n' : ' '); - } - END_LOOP; - PAD_LOOP(element); - { - if (TEST_FLAG(FOUNDFLAG, pad)) - pcb_append_printf(&list, "%s-%s,%c", NAMEONPCB_NAME(element), pad->Number, ((col++ % (COLUMNS + 1)) == COLUMNS) ? '\n' : ' '); - } - END_LOOP; - } - END_LOOP; - - gui->report_dialog("Report", list.array); - gds_uninit(&list); - return 0; -} - -/* Assumes that we start with a blank connection state, - * e.g. ResetConnections() has been run. - * Does not add its own changes to the undo system - */ -static double XYtoNetLength(Coord x, Coord y, int *found) -{ - double length; - - length = 0; - *found = 0; - - /* NB: The third argument here, 'false' ensures LookupConnection - * does not add its changes to the undo system. - */ - LookupConnection(x, y, false, PCB->Grid, FOUNDFLAG); - - ALLLINE_LOOP(PCB->Data); - { - if (TEST_FLAG(FOUNDFLAG, line)) { - double l; - int dx, dy; - dx = line->Point1.X - line->Point2.X; - dy = line->Point1.Y - line->Point2.Y; - l = sqrt((double) dx * dx + (double) dy * dy); - length += l; - *found = 1; - } - } - ENDALL_LOOP; - - ALLARC_LOOP(PCB->Data); - { - if (TEST_FLAG(FOUNDFLAG, arc)) { - double l; - /* FIXME: we assume width==height here */ - l = M_PI * 2 * arc->Width * abs(arc->Delta) / 360.0; - length += l; - *found = 1; - } - } - ENDALL_LOOP; - - return length; -} - -static int ReportAllNetLengths(int argc, char **argv, Coord x, Coord y) -{ - int ni; - int found; - - /* Reset all connection flags and save an undo-state to get back - * to the state the board was in when we started this function. - * - * After this, we don't add any changes to the undo system, but - * ensure we get back to a point where we can Undo() our changes - * by resetting the connections with ResetConnections() before - * calling Undo() at the end of the procedure. - */ - ResetConnections(true); - IncrementUndoSerialNumber(); - - for (ni = 0; ni < PCB->NetlistLib[NETLIST_EDITED].MenuN; ni++) { - char *netname = PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Name + 2; - char *ename = PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Entry[0].ListEntry; - char *pname; - bool got_one = 0; - - ename = strdup(ename); - pname = strchr(ename, '-'); - if (!pname) { - free(ename); - continue; - } - *pname++ = 0; - - ELEMENT_LOOP(PCB->Data); - { - char *es = element->Name[NAMEONPCB_INDEX].TextString; - if (es && strcmp(es, ename) == 0) { - PIN_LOOP(element); - { - if (strcmp(pin->Number, pname) == 0) { - x = pin->X; - y = pin->Y; - got_one = 1; - break; - } - } - END_LOOP; - PAD_LOOP(element); - { - if (strcmp(pad->Number, pname) == 0) { - x = (pad->Point1.X + pad->Point2.X) / 2; - y = (pad->Point1.Y + pad->Point2.Y) / 2; - got_one = 1; - break; - } - } - END_LOOP; - } - } - END_LOOP; - - if (got_one) { - char buf[50]; - const char *units_name = argv[0]; - Coord length; - - if (argc < 1) - units_name = Settings.grid_unit->suffix; - - length = XYtoNetLength(x, y, &found); - - /* Reset connectors for the next lookup */ - ResetConnections(false); - - pcb_snprintf(buf, sizeof(buf), "%$m*", units_name, length); - gui->log("Net %s length %s\n", netname, buf); - } - } - - ResetConnections(false); - Undo(true); - return 0; -} - -static int ReportNetLength(int argc, char **argv, Coord x, Coord y) -{ - Coord length = 0; - char *netname = 0; - int found = 0; - - gui->get_coords("Click on a connection", &x, &y); - - /* Reset all connection flags and save an undo-state to get back - * to the state the board was in when we started this function. - * - * After this, we don't add any changes to the undo system, but - * ensure we get back to a point where we can Undo() our changes - * by resetting the connections with ResetConnections() before - * calling Undo() at the end of the procedure. - */ - ResetConnections(true); - IncrementUndoSerialNumber(); - - length = XYtoNetLength(x, y, &found); - - if (!found) { - ResetConnections(false); - Undo(true); - gui->log("No net under cursor.\n"); - return 1; - } - - ELEMENT_LOOP(PCB->Data); - { - PIN_LOOP(element); - { - if (TEST_FLAG(FOUNDFLAG, pin)) { - int ni, nei; - char *ename = element->Name[NAMEONPCB_INDEX].TextString; - char *pname = pin->Number; - char *n; - - if (ename && pname) { - n = Concat(ename, "-", pname, NULL); - for (ni = 0; ni < PCB->NetlistLib[NETLIST_EDITED].MenuN; ni++) - for (nei = 0; nei < PCB->NetlistLib[NETLIST_EDITED].Menu[ni].EntryN; nei++) { - if (strcmp(PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Entry[nei].ListEntry, n) == 0) { - netname = PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Name + 2; - goto got_net_name; /* four for loops deep */ - } - } - } - } - } - END_LOOP; - PAD_LOOP(element); - { - if (TEST_FLAG(FOUNDFLAG, pad)) { - int ni, nei; - char *ename = element->Name[NAMEONPCB_INDEX].TextString; - char *pname = pad->Number; - char *n; - - if (ename && pname) { - n = Concat(ename, "-", pname, NULL); - for (ni = 0; ni < PCB->NetlistLib[NETLIST_EDITED].MenuN; ni++) - for (nei = 0; nei < PCB->NetlistLib[NETLIST_EDITED].Menu[ni].EntryN; nei++) { - if (strcmp(PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Entry[nei].ListEntry, n) == 0) { - netname = PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Name + 2; - goto got_net_name; /* four for loops deep */ - } - } - } - } - } - END_LOOP; - } - END_LOOP; - -got_net_name: - ResetConnections(false); - Undo(true); - - { - char buf[50]; - pcb_snprintf(buf, sizeof(buf), "%$m*", Settings.grid_unit->suffix, length); - if (netname) - gui->log("Net \"%s\" length: %s\n", netname, buf); - else - gui->log("Net length: %s\n", buf); - } - - return 0; -} - -static int ReportNetLengthByName(char *tofind, int x, int y) -{ - int result; - char *netname = 0; - Coord length = 0; - int found = 0; - int i; - LibraryMenuType *net; - ConnectionType conn; - int net_found = 0; -#if defined(USE_RE) - int use_re = 0; -#endif -#if defined(HAVE_REGCOMP) - regex_t elt_pattern; - regmatch_t match; -#endif -#if defined(HAVE_RE_COMP) - char *elt_pattern; -#endif - - if (!PCB) - return 1; - - if (!tofind) - return 1; - -#if defined(USE_RE) - use_re = 1; - for (i = 0; i < PCB->NetlistLib[NETLIST_EDITED].MenuN; i++) { - net = PCB->NetlistLib[NETLIST_EDITED].Menu + i; - if (strcasecmp(tofind, net->Name + 2) == 0) - use_re = 0; - } - if (use_re) { -#if defined(HAVE_REGCOMP) - result = regcomp(&elt_pattern, tofind, REG_EXTENDED | REG_ICASE | REG_NOSUB); - if (result) { - char errorstring[128]; - - regerror(result, &elt_pattern, errorstring, 128); - Message(_("regexp error: %s\n"), errorstring); - regfree(&elt_pattern); - return (1); - } -#endif -#if defined(HAVE_RE_COMP) - if ((elt_pattern = re_comp(tofind)) != NULL) { - Message(_("re_comp error: %s\n"), elt_pattern); - return (1); - } -#endif - } -#endif - - for (i = 0; i < PCB->NetlistLib[NETLIST_EDITED].MenuN; i++) { - net = PCB->NetlistLib[NETLIST_EDITED].Menu + i; - -#if defined(USE_RE) - if (use_re) { -#if defined(HAVE_REGCOMP) - if (regexec(&elt_pattern, net->Name + 2, 1, &match, 0) != 0) - continue; -#endif -#if defined(HAVE_RE_COMP) - if (re_exec(net->Name + 2) != 1) - continue; -#endif - } - else -#endif - if (strcasecmp(net->Name + 2, tofind)) - continue; - - if (SeekPad(net->Entry, &conn, false)) { - switch (conn.type) { - case PIN_TYPE: - x = ((PinType *) (conn.ptr2))->X; - y = ((PinType *) (conn.ptr2))->Y; - net_found = 1; - break; - case PAD_TYPE: - x = ((PadType *) (conn.ptr2))->Point1.X; - y = ((PadType *) (conn.ptr2))->Point1.Y; - net_found = 1; - break; - } - if (net_found) - break; - } - } - - if (!net_found) { - gui->log("No net named %s\n", tofind); - return 1; - } - -#ifdef HAVE_REGCOMP - if (use_re) - regfree(&elt_pattern); -#endif - - /* Reset all connection flags and save an undo-state to get back - * to the state the board was in when we started. - * - * After this, we don't add any changes to the undo system, but - * ensure we get back to a point where we can Undo() our changes - * by resetting the connections with ResetConnections() before - * calling Undo() when we are finished. - */ - ResetConnections(true); - IncrementUndoSerialNumber(); - - length = XYtoNetLength(x, y, &found); - netname = net->Name + 2; - - ResetConnections(false); - Undo(true); - - if (!found) { - if (net_found) - gui->log("Net found, but no lines or arcs were flagged.\n"); - else - gui->log("Net not found.\n"); - - return 1; - } - - { - char buf[50]; - pcb_snprintf(buf, sizeof(buf), "%$m*", Settings.grid_unit->suffix, length); - if (netname) - gui->log("Net \"%s\" length: %s\n", netname, buf); - else - gui->log("Net length: %s\n", buf); - } - - return 0; -} - -/* --------------------------------------------------------------------------- - * reports on an object - * syntax: - */ - -static const char report_syntax[] = "Report(Object|DrillReport|FoundPins|NetLength|AllNetLengths|[,name])"; - -static const char report_help[] = "Produce various report."; - -/* %start-doc actions Report - -@table @code - -@item Object -The object under the crosshair will be reported, describing various -aspects of the object. - -@item DrillReport -A report summarizing the number of drill sizes used, and how many of -each, will be produced. - -@item FoundPins -A report listing all pins and pads which are marked as ``found'' will -be produced. - -@item NetLength -The name and length of the net under the crosshair will be reported to -the message log. - -@item AllNetLengths -The name and length of the net under the crosshair will be reported to -the message log. An optional parameter specifies mm, mil, pcb, or in -units - -@end table - -%end-doc */ - -static int Report(int argc, char **argv, Coord x, Coord y) -{ - if ((argc < 1) || (argc > 2)) - AUSAGE(report); - else if (strcasecmp(argv[0], "Object") == 0) { - gui->get_coords("Click on an object", &x, &y); - return ReportDialog(argc - 1, argv + 1, x, y); - } - else if (strcasecmp(argv[0], "DrillReport") == 0) - return ReportDrills(argc - 1, argv + 1, x, y); - else if (strcasecmp(argv[0], "FoundPins") == 0) - return ReportFoundPins(argc - 1, argv + 1, x, y); - else if ((strcasecmp(argv[0], "NetLength") == 0) && (argc == 1)) - return ReportNetLength(argc - 1, argv + 1, x, y); - else if (strcasecmp(argv[0], "AllNetLengths") == 0) - return ReportAllNetLengths(argc - 1, argv + 1, x, y); - else if ((strcasecmp(argv[0], "NetLength") == 0) && (argc == 2)) - return ReportNetLengthByName(argv[1], x, y); - else if (argc == 2) - AUSAGE(report); - else - AFAIL(report); - return 1; -} - -HID_Action report_action_list[] = { - {"ReportObject", "Click on an object", ReportDialog, - reportdialog_help, reportdialog_syntax} - , - {"Report", 0, Report, - report_help, report_syntax} -}; - -REGISTER_ACTIONS(report_action_list, NULL) Index: src/report.h =================================================================== --- src/report.h (revision 1388) +++ src/report.h (nonexistent) @@ -1,38 +0,0 @@ -/* - * COPYRIGHT - * - * PCB, interactive printed circuit board design - * Copyright (C) 1994,1995,1996 Thomas Nau - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Contact addresses for paper mail and Email: - * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany - * Thomas.Nau@rz.uni-ulm.de - * - * RCS: $Id$ - */ - -#ifndef PCB_REPORT_H -#define PCB_REPORT_H - -#include "global.h" - -#define REPORT_TYPES \ - (VIA_TYPE | LINE_TYPE | TEXT_TYPE | POLYGON_TYPE | ELEMENT_TYPE | \ - RATLINE_TYPE | PIN_TYPE | PAD_TYPE | ELEMENTNAME_TYPE | ARC_TYPE \ - | POLYGONPOINT_TYPE | LINEPOINT_TYPE) - -#endif Index: src/Makefile.dep =================================================================== --- src/Makefile.dep (revision 1388) +++ src/Makefile.dep (revision 1389) @@ -614,17 +614,6 @@ ../src_3rd/genvector/genvector_undef.h hid.h global_element.h \ list_element.h libpcb_fp.h data.h action_helper.h change.h error.h \ undo.h set.h remove.h funchash_core.h funchash.h funchash_core_list.h -report.o: report.c ../config.h ../config.manual.h ../config.auto.h \ - report.h global.h const.h ../globalconst.h ../config.h macro.h \ - global_typedefs.h global_objs.h ../src_3rd/genlist/gendlist.h polyarea.h \ - list_common.h list_line.h ../src_3rd/genlist/gentdlist_impl.h \ - ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ - list_arc.h list_text.h list_poly.h list_pad.h list_pin.h list_rat.h \ - vtonpoint.h ../src_3rd/genvector/genvector_impl.h \ - ../src_3rd/genvector/genvector_undef.h hid.h global_element.h \ - list_element.h libpcb_fp.h crosshair.h data.h drill.h error.h search.h \ - misc.h ../src_3rd/genvector/gds_char.h mymem.h rats.h rtree.h strflags.h \ - undo.h find.h draw.h pcb-printf.h rotate.o: rotate.c ../config.h ../config.manual.h ../config.auto.h \ global.h const.h ../globalconst.h ../config.h macro.h global_typedefs.h \ global_objs.h ../src_3rd/genlist/gendlist.h polyarea.h list_common.h \ @@ -1025,6 +1014,20 @@ list_element.h libpcb_fp.h data.h global.h action_helper.h change.h \ error.h undo.h misc.h ../src_3rd/genvector/gds_char.h mymem.h set.h \ plugins.h hid_actions.h pcb-printf.h dolists.h +../src_plugins/report/report.o: ../src_plugins/report/report.c \ + ../config.h ../config.manual.h ../config.auto.h \ + ../src_plugins/report/report.h global.h const.h ../globalconst.h \ + ../config.h macro.h global_typedefs.h global_objs.h \ + ../src_3rd/genlist/gendlist.h polyarea.h list_common.h list_line.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h list_arc.h list_text.h list_poly.h \ + list_pad.h list_pin.h list_rat.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h global_element.h \ + list_element.h libpcb_fp.h crosshair.h global.h data.h drill.h error.h \ + search.h misc.h ../src_3rd/genvector/gds_char.h mymem.h mymem.h rats.h \ + rtree.h strflags.h macro.h undo.h find.h draw.h pcb-printf.h plugins.h \ + dolists.h ../src_plugins/import_sch/import_sch.o: \ ../src_plugins/import_sch/import_sch.c ../config.h ../config.manual.h \ ../config.auto.h global.h const.h ../globalconst.h ../config.h macro.h \ @@ -1536,8 +1539,8 @@ ../src_plugins/hid_gtk/gui-pinout-preview.h action_helper.h buffer.h \ change.h command.h copy.h create.h crosshair.h draw.h error.h file.h \ find.h gpcb-menu.h insert.h line.h mymem.h move.h pcb-printf.h polygon.h \ - rats.h remove.h report.h rotate.h rubberband.h search.h select.h set.h \ - undo.h event.h free_atexit.h paths.h \ + rats.h remove.h rotate.h rubberband.h search.h select.h set.h undo.h \ + event.h free_atexit.h paths.h \ ../src_plugins/hid_gtk/gui-icons-mode-buttons.data \ ../src_plugins/hid_gtk/gui-icons-misc.data hid_attrib.h hid_actions.h \ hid_flags.h @@ -1576,91 +1579,6 @@ ../src_plugins/hid_gtk/ghid-route-style-selector.h resource.h \ ../src_plugins/hid_gtk/gui-pinout-preview.h hid_draw_helpers.h \ hid_attrib.h hid_helper.h hid_color.h -../src_plugins/hid_lesstif/dialogs.o: \ - ../src_plugins/hid_lesstif/dialogs.c ../config.h ../config.manual.h \ - ../config.auto.h ../src_plugins/hid_lesstif/xincludes.h compat.h \ - global.h const.h ../globalconst.h ../config.h macro.h global_typedefs.h \ - global_objs.h ../src_3rd/genlist/gendlist.h polyarea.h list_common.h \ - list_line.h ../src_3rd/genlist/gentdlist_impl.h \ - ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ - list_arc.h list_text.h list_poly.h list_pad.h list_pin.h list_rat.h \ - vtonpoint.h ../src_3rd/genvector/genvector_impl.h \ - ../src_3rd/genvector/genvector_undef.h hid.h global_element.h \ - list_element.h libpcb_fp.h data.h global.h crosshair.h misc.h \ - ../src_3rd/genvector/gds_char.h mymem.h pcb-printf.h hid.h \ - ../src_plugins/hid_lesstif/lesstif.h hid_attrib.h hid_actions.h \ - hid_init.h -../src_plugins/hid_lesstif/library.o: \ - ../src_plugins/hid_lesstif/library.c ../config.h ../config.manual.h \ - ../config.auto.h ../src_plugins/hid_lesstif/xincludes.h compat.h \ - global.h const.h ../globalconst.h ../config.h macro.h global_typedefs.h \ - global_objs.h ../src_3rd/genlist/gendlist.h polyarea.h list_common.h \ - list_line.h ../src_3rd/genlist/gentdlist_impl.h \ - ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ - list_arc.h list_text.h list_poly.h list_pad.h list_pin.h list_rat.h \ - vtonpoint.h ../src_3rd/genvector/genvector_impl.h \ - ../src_3rd/genvector/genvector_undef.h hid.h global_element.h \ - list_element.h libpcb_fp.h data.h global.h misc.h \ - ../src_3rd/genvector/gds_char.h mymem.h set.h buffer.h hid.h \ - ../src_plugins/hid_lesstif/lesstif.h -../src_plugins/hid_lesstif/main.o: ../src_plugins/hid_lesstif/main.c \ - ../config.h ../config.manual.h ../config.auto.h \ - ../src_plugins/hid_lesstif/xincludes.h global.h const.h ../globalconst.h \ - ../config.h macro.h global_typedefs.h global_objs.h \ - ../src_3rd/genlist/gendlist.h polyarea.h list_common.h list_line.h \ - ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ - ../src_3rd/genlist/gentdlist_undef.h list_arc.h list_text.h list_poly.h \ - list_pad.h list_pin.h list_rat.h vtonpoint.h \ - ../src_3rd/genvector/genvector_impl.h \ - ../src_3rd/genvector/genvector_undef.h hid.h global_element.h \ - list_element.h libpcb_fp.h data.h global.h action_helper.h crosshair.h \ - mymem.h misc.h ../src_3rd/genvector/gds_char.h mymem.h pcb-printf.h \ - resource.h clip.h event.h error.h plugins.h hid.h hid_nogui.h \ - hid_draw_helpers.h hid_resource.h resource.h \ - ../src_plugins/hid_lesstif/lesstif.h hid_attrib.h hid_helper.h \ - hid_init.h hid_color.h hid_extents.h hid_flags.h hid_actions.h dolists.h -../src_plugins/hid_lesstif/menu.o: ../src_plugins/hid_lesstif/menu.c \ - ../config.h ../config.manual.h ../config.auto.h \ - ../src_plugins/hid_lesstif/xincludes.h global.h const.h ../globalconst.h \ - ../config.h macro.h global_typedefs.h global_objs.h \ - ../src_3rd/genlist/gendlist.h polyarea.h list_common.h list_line.h \ - ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ - ../src_3rd/genlist/gentdlist_undef.h list_arc.h list_text.h list_poly.h \ - list_pad.h list_pin.h list_rat.h vtonpoint.h \ - ../src_3rd/genvector/genvector_impl.h \ - ../src_3rd/genvector/genvector_undef.h hid.h global_element.h \ - list_element.h libpcb_fp.h data.h global.h error.h misc.h \ - ../src_3rd/genvector/gds_char.h mymem.h pcb-printf.h hid.h \ - hid_resource.h resource.h resource.h \ - ../src_plugins/hid_lesstif/lesstif.h mymem.h paths.h hid_actions.h \ - hid_flags.h pcb-menu.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ - ../src_3rd/genht/ht_inlines.h ../src_3rd/genht/hash.h -../src_plugins/hid_lesstif/netlist.o: \ - ../src_plugins/hid_lesstif/netlist.c ../config.h ../config.manual.h \ - ../config.auto.h ../src_plugins/hid_lesstif/xincludes.h compat.h \ - global.h const.h ../globalconst.h ../config.h macro.h global_typedefs.h \ - global_objs.h ../src_3rd/genlist/gendlist.h polyarea.h list_common.h \ - list_line.h ../src_3rd/genlist/gentdlist_impl.h \ - ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ - list_arc.h list_text.h list_poly.h list_pad.h list_pin.h list_rat.h \ - vtonpoint.h ../src_3rd/genvector/genvector_impl.h \ - ../src_3rd/genvector/genvector_undef.h hid.h global_element.h \ - list_element.h libpcb_fp.h data.h global.h find.h rats.h select.h undo.h \ - remove.h crosshair.h draw.h hid.h hid_actions.h \ - ../src_plugins/hid_lesstif/lesstif.h -../src_plugins/hid_lesstif/styles.o: ../src_plugins/hid_lesstif/styles.c \ - ../config.h ../config.manual.h ../config.auto.h \ - ../src_plugins/hid_lesstif/xincludes.h compat.h global.h const.h \ - ../globalconst.h ../config.h macro.h global_typedefs.h global_objs.h \ - ../src_3rd/genlist/gendlist.h polyarea.h list_common.h list_line.h \ - ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ - ../src_3rd/genlist/gentdlist_undef.h list_arc.h list_text.h list_poly.h \ - list_pad.h list_pin.h list_rat.h vtonpoint.h \ - ../src_3rd/genvector/genvector_impl.h \ - ../src_3rd/genvector/genvector_undef.h hid.h global_element.h \ - list_element.h libpcb_fp.h data.h global.h set.h misc.h \ - ../src_3rd/genvector/gds_char.h mymem.h mymem.h pcb-printf.h hid.h \ - ../src_plugins/hid_lesstif/lesstif.h hid_flags.h ../src_plugins/toporouter/toporouter.o: \ ../src_plugins/toporouter/toporouter.c \ ../src_plugins/toporouter/toporouter.h data.h global.h ../config.h \ Index: src/Makefile.in =================================================================== --- src/Makefile.in (revision 1388) +++ src/Makefile.in (revision 1389) @@ -76,7 +76,6 @@ rats_patch.o remove.o remove_act.o - report.o rotate.o rtree.o rubberband.o @@ -115,7 +114,7 @@ action_act.c buffer.c change_act.c command.c file_act.c find_act.c flags.c gui_act.c main.c misc.c move.c netlist.c object_act.c plugins.c polygon_act.c rats_act.c rats_patch.c - remove_act.c report.c select_act.c undo_act.c + remove_act.c select_act.c undo_act.c } #---- modules ----# @@ -148,6 +147,7 @@ include {../src_plugins/legacy_func/Plug.tmpasm} include {../src_plugins/renumber/Plug.tmpasm} include {../src_plugins/stroke/Plug.tmpasm} +include {../src_plugins/report/Plug.tmpasm} include {../src_plugins/import_sch/Plug.tmpasm} include {../src_plugins/export_ps/Plug.tmpasm} include {../src_plugins/export_lpr/Plug.tmpasm} Index: src_plugins/hid_gtk/gui-top-window.c =================================================================== --- src_plugins/hid_gtk/gui-top-window.c (revision 1388) +++ src_plugins/hid_gtk/gui-top-window.c (revision 1389) @@ -90,7 +90,6 @@ #include "polygon.h" #include "rats.h" #include "remove.h" -#include "report.h" #include "resource.h" #include "rotate.h" #include "rubberband.h" Index: src_plugins/report/Makefile =================================================================== --- src_plugins/report/Makefile (nonexistent) +++ src_plugins/report/Makefile (revision 1389) @@ -0,0 +1,6 @@ +all: + cd ../../src && make mod_report + + +clean: + rm *.o *.so 2>/dev/null ; true Index: src_plugins/report/Plug.tmpasm =================================================================== --- src_plugins/report/Plug.tmpasm (nonexistent) +++ src_plugins/report/Plug.tmpasm (revision 1389) @@ -0,0 +1,8 @@ +put /local/pcb/mod {report} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/report/report.o @] + +switch /local/pcb/report/controls + case {buildin} include {Makefile.in.mod/Buildin}; end; + case {plugin} include {Makefile.in.mod/Plugin}; end; + case {disable} include {Makefile.in.mod/Disable}; end; +end Index: src_plugins/report/README =================================================================== --- src_plugins/report/README (nonexistent) +++ src_plugins/report/README (revision 1389) @@ -0,0 +1,4 @@ +Report() and ReportObject() actions - print a report about design objects. + +#state: works +#default: buildin Index: src_plugins/report/report.c =================================================================== --- src_plugins/report/report.c (nonexistent) +++ src_plugins/report/report.c (revision 1389) @@ -0,0 +1,944 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996,1997,1998,1999 Thomas Nau + * + * This module, report.c, was written and is Copyright (C) 1997 harry eaton + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +#include "config.h" + +#include + +#include "report.h" +#include "crosshair.h" +#include "data.h" +#include "drill.h" +#include "error.h" +#include "search.h" +#include "misc.h" +#include "mymem.h" +#include "rats.h" +#include "rtree.h" +#include "strflags.h" +#include "macro.h" +#include "undo.h" +#include "find.h" +#include "draw.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "hid_actions.h" + +#ifdef HAVE_REGEX_H +#include +#endif + +#ifdef HAVE_REGCOMP +#undef HAVE_RE_COMP +#endif + +#if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) +#define USE_RE +#endif + + +#define USER_UNITMASK (Settings.grid_unit->allow) + +static int ReportDrills(int argc, char **argv, Coord x, Coord y) +{ + DrillInfoTypePtr AllDrills; + Cardinal n; + char *stringlist, *thestring; + int total_drills = 0; + + AllDrills = GetDrillInfo(PCB->Data); + RoundDrillInfo(AllDrills, 100); + + for (n = 0; n < AllDrills->DrillN; n++) { + total_drills += AllDrills->Drill[n].PinCount; + total_drills += AllDrills->Drill[n].ViaCount; + total_drills += AllDrills->Drill[n].UnplatedCount; + } + + stringlist = (char *) malloc(512L + AllDrills->DrillN * 64L); + + /* Use tabs for formatting since can't count on a fixed font anymore. + | And even that probably isn't going to work in all cases. + */ + sprintf(stringlist, + "There are %d different drill sizes used in this layout, %d holes total\n\n" + "Drill Diam. (%s)\t# of Pins\t# of Vias\t# of Elements\t# Unplated\n", + AllDrills->DrillN, total_drills, Settings.grid_unit->suffix); + thestring = stringlist; + while (*thestring != '\0') + thestring++; + for (n = 0; n < AllDrills->DrillN; n++) { + pcb_sprintf(thestring, + "%10m*\t\t%d\t\t%d\t\t%d\t\t%d\n", + Settings.grid_unit->suffix, + AllDrills->Drill[n].DrillSize, + AllDrills->Drill[n].PinCount, AllDrills->Drill[n].ViaCount, + AllDrills->Drill[n].ElementN, AllDrills->Drill[n].UnplatedCount); + while (*thestring != '\0') + thestring++; + } + FreeDrillInfo(AllDrills); + /* create dialog box */ + gui->report_dialog("Drill Report", stringlist); + + free(stringlist); + return 0; +} + + +static const char reportdialog_syntax[] = "ReportObject()"; + +static const char reportdialog_help[] = "Report on the object under the crosshair"; + +/* %start-doc actions ReportDialog + +This is a shortcut for @code{Report(Object)}. + +%end-doc */ + +static int ReportDialog(int argc, char **argv, Coord x, Coord y) +{ + void *ptr1, *ptr2, *ptr3; + int type; + char *report = NULL; + + type = SearchScreen(x, y, REPORT_TYPES, &ptr1, &ptr2, &ptr3); + if (type == NO_TYPE) + type = SearchScreen(x, y, REPORT_TYPES | LOCKED_TYPE, &ptr1, &ptr2, &ptr3); + + switch (type) { + case VIA_TYPE: + { + PinTypePtr via; +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + __r_dump_tree(PCB->Data->via_tree->root, 0); + return 0; + } +#endif + via = (PinTypePtr) ptr2; + if (TEST_FLAG(HOLEFLAG, via)) + report = pcb_strdup_printf("%m+VIA ID# %ld; Flags:%s\n" + "(X,Y) = %$mD.\n" + "It is a pure hole of diameter %$mS.\n" + "Name = \"%s\"." + "%s", USER_UNITMASK, via->ID, flags_to_string(via->Flags, VIA_TYPE), + via->X, via->Y, via->DrillingHole, EMPTY(via->Name), TEST_FLAG(LOCKFLAG, via) ? "It is LOCKED.\n" : ""); + else + report = pcb_strdup_printf("%m+VIA ID# %ld; Flags:%s\n" + "(X,Y) = %$mD.\n" + "Copper width = %$mS. Drill width = %$mS.\n" + "Clearance width in polygons = %$mS.\n" + "Annulus = %$mS.\n" + "Solder mask hole = %$mS (gap = %$mS).\n" + "Name = \"%s\"." + "%s", USER_UNITMASK, via->ID, flags_to_string(via->Flags, VIA_TYPE), + via->X, via->Y, + via->Thickness, + via->DrillingHole, + via->Clearance / 2, + (via->Thickness - via->DrillingHole) / 2, + via->Mask, + (via->Mask - via->Thickness) / 2, EMPTY(via->Name), TEST_FLAG(LOCKFLAG, via) ? "It is LOCKED.\n" : ""); + break; + } + case PIN_TYPE: + { + PinTypePtr Pin; + ElementTypePtr element; +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + __r_dump_tree(PCB->Data->pin_tree->root, 0); + return 0; + } +#endif + Pin = (PinTypePtr) ptr2; + element = (ElementTypePtr) ptr1; + + PIN_LOOP(element); + { + if (pin == Pin) + break; + } + END_LOOP; + if (TEST_FLAG(HOLEFLAG, Pin)) + report = pcb_strdup_printf("%m+PIN ID# %ld; Flags:%s\n" + "(X,Y) = %$mD.\n" + "It is a mounting hole. Drill width = %$mS.\n" + "It is owned by element %$mS.\n" + "%s", USER_UNITMASK, Pin->ID, flags_to_string(Pin->Flags, PIN_TYPE), + Pin->X, Pin->Y, Pin->DrillingHole, + EMPTY(element->Name[1].TextString), TEST_FLAG(LOCKFLAG, Pin) ? "It is LOCKED.\n" : ""); + else + report = pcb_strdup_printf( + "%m+PIN ID# %ld; Flags:%s\n" "(X,Y) = %$mD.\n" + "Copper width = %$mS. Drill width = %$mS.\n" + "Clearance width to Polygon = %$mS.\n" + "Annulus = %$mS.\n" + "Solder mask hole = %$mS (gap = %$mS).\n" + "Name = \"%s\".\n" + "It is owned by element %s\n as pin number %s.\n" + "%s", USER_UNITMASK, + Pin->ID, flags_to_string(Pin->Flags, PIN_TYPE), + Pin->X, Pin->Y, Pin->Thickness, + Pin->DrillingHole, + Pin->Clearance / 2, + (Pin->Thickness - Pin->DrillingHole) / 2, + Pin->Mask, + (Pin->Mask - Pin->Thickness) / 2, + EMPTY(Pin->Name), + EMPTY(element->Name[1].TextString), EMPTY(Pin->Number), TEST_FLAG(LOCKFLAG, Pin) ? "It is LOCKED.\n" : ""); + break; + } + case LINE_TYPE: + { + LineTypePtr line; +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + LayerTypePtr layer = (LayerTypePtr) ptr1; + __r_dump_tree(layer->line_tree->root, 0); + return 0; + } +#endif + line = (LineTypePtr) ptr2; + report = pcb_strdup_printf("%m+LINE ID# %ld; Flags:%s\n" + "FirstPoint(X,Y) = %$mD, ID = %ld.\n" + "SecondPoint(X,Y) = %$mD, ID = %ld.\n" + "Width = %$mS.\nClearance width in polygons = %$mS.\n" + "It is on layer %d\n" + "and has name \"%s\".\n" + "%s", USER_UNITMASK, + line->ID, flags_to_string(line->Flags, LINE_TYPE), + line->Point1.X, line->Point1.Y, line->Point1.ID, + line->Point2.X, line->Point2.Y, line->Point2.ID, + line->Thickness, line->Clearance / 2, + GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1), + UNKNOWN(line->Number), TEST_FLAG(LOCKFLAG, line) ? "It is LOCKED.\n" : ""); + break; + } + case RATLINE_TYPE: + { + RatTypePtr line; +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + __r_dump_tree(PCB->Data->rat_tree->root, 0); + return 0; + } +#endif + line = (RatTypePtr) ptr2; + report = pcb_strdup_printf("%m+RAT-LINE ID# %ld; Flags:%s\n" + "FirstPoint(X,Y) = %$mD; ID = %ld; " + "connects to layer group %d.\n" + "SecondPoint(X,Y) = %$mD; ID = %ld; " + "connects to layer group %d.\n", + USER_UNITMASK, line->ID, flags_to_string(line->Flags, LINE_TYPE), + line->Point1.X, line->Point1.Y, + line->Point1.ID, line->group1, line->Point2.X, line->Point2.Y, line->Point2.ID, line->group2); + break; + } + case ARC_TYPE: + { + ArcTypePtr Arc; + BoxTypePtr box; +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + LayerTypePtr layer = (LayerTypePtr) ptr1; + __r_dump_tree(layer->arc_tree->root, 0); + return 0; + } +#endif + Arc = (ArcTypePtr) ptr2; + box = GetArcEnds(Arc); + + report = pcb_strdup_printf("%m+ARC ID# %ld; Flags:%s\n" + "CenterPoint(X,Y) = %$mD.\n" + "Radius = %$mS, Thickness = %$mS.\n" + "Clearance width in polygons = %$mS.\n" + "StartAngle = %ma degrees, DeltaAngle = %ma degrees.\n" + "Bounding Box is %$mD, %$mD.\n" + "That makes the end points at %$mD and %$mD.\n" + "It is on layer %d.\n" + "%s", USER_UNITMASK, Arc->ID, flags_to_string(Arc->Flags, ARC_TYPE), + Arc->X, Arc->Y, + Arc->Width, Arc->Thickness, + Arc->Clearance / 2, Arc->StartAngle, Arc->Delta, + Arc->BoundingBox.X1, Arc->BoundingBox.Y1, + Arc->BoundingBox.X2, Arc->BoundingBox.Y2, + box->X1, box->Y1, + box->X2, box->Y2, + GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1), TEST_FLAG(LOCKFLAG, Arc) ? "It is LOCKED.\n" : ""); + break; + } + case POLYGON_TYPE: + { + PolygonTypePtr Polygon; +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + LayerTypePtr layer = (LayerTypePtr) ptr1; + __r_dump_tree(layer->polygon_tree->root, 0); + return 0; + } +#endif + Polygon = (PolygonTypePtr) ptr2; + + report = pcb_strdup_printf("%m+POLYGON ID# %ld; Flags:%s\n" + "Its bounding box is %$mD %$mD.\n" + "It has %d points and could store %d more\n" + " without using more memory.\n" + "It has %d holes and resides on layer %d.\n" + "%s", USER_UNITMASK, Polygon->ID, + flags_to_string(Polygon->Flags, POLYGON_TYPE), + Polygon->BoundingBox.X1, Polygon->BoundingBox.Y1, + Polygon->BoundingBox.X2, Polygon->BoundingBox.Y2, + Polygon->PointN, Polygon->PointMax - Polygon->PointN, + Polygon->HoleIndexN, + GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1), TEST_FLAG(LOCKFLAG, Polygon) ? "It is LOCKED.\n" : ""); + break; + } + case PAD_TYPE: + { + Coord len; + PadTypePtr Pad; + ElementTypePtr element; +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + __r_dump_tree(PCB->Data->pad_tree->root, 0); + return 0; + } +#endif + Pad = (PadTypePtr) ptr2; + element = (ElementTypePtr) ptr1; + + PAD_LOOP(element); + { + { + if (pad == Pad) + break; + } + } + END_LOOP; + len = Distance(Pad->Point1.X, Pad->Point1.Y, Pad->Point2.X, Pad->Point2.Y); + report = pcb_strdup_printf("%m+PAD ID# %ld; Flags:%s\n" + "FirstPoint(X,Y) = %$mD; ID = %ld.\n" + "SecondPoint(X,Y) = %$mD; ID = %ld.\n" + "Width = %$mS. Length = %$mS.\n" + "Clearance width in polygons = %$mS.\n" + "Solder mask = %$mS x %$mS (gap = %$mS).\n" + "Name = \"%s\".\n" + "It is owned by SMD element %s\n" + " as pin number %s and is on the %s\n" + "side of the board.\n" + "%s", USER_UNITMASK, Pad->ID, + flags_to_string(Pad->Flags, PAD_TYPE), + Pad->Point1.X, Pad->Point1.Y, Pad->Point1.ID, + Pad->Point2.X, Pad->Point2.Y, Pad->Point2.ID, + Pad->Thickness, len + Pad->Thickness, + Pad->Clearance / 2, + Pad->Mask, len + Pad->Mask, + (Pad->Mask - Pad->Thickness) / 2, + EMPTY(Pad->Name), + EMPTY(element->Name[1].TextString), + EMPTY(Pad->Number), + TEST_FLAG(ONSOLDERFLAG, + Pad) ? "solder (bottom)" : "component", TEST_FLAG(LOCKFLAG, Pad) ? "It is LOCKED.\n" : ""); + break; + } + case ELEMENT_TYPE: + { + ElementTypePtr element; +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + __r_dump_tree(PCB->Data->element_tree->root, 0); + return 0; + } +#endif + element = (ElementTypePtr) ptr2; + report = pcb_strdup_printf("%m+ELEMENT ID# %ld; Flags:%s\n" + "BoundingBox %$mD %$mD.\n" + "Descriptive Name \"%s\".\n" + "Name on board \"%s\".\n" + "Part number name \"%s\".\n" + "It is %$mS tall and is located at (X,Y) = %$mD %s.\n" + "Mark located at point (X,Y) = %$mD.\n" + "It is on the %s side of the board.\n" + "%s", USER_UNITMASK, + element->ID, flags_to_string(element->Flags, ELEMENT_TYPE), + element->BoundingBox.X1, element->BoundingBox.Y1, + element->BoundingBox.X2, element->BoundingBox.Y2, + EMPTY(element->Name[0].TextString), + EMPTY(element->Name[1].TextString), + EMPTY(element->Name[2].TextString), + SCALE_TEXT(FONT_CAPHEIGHT, element->Name[1].Scale), + element->Name[1].X, element->Name[1].Y, + TEST_FLAG(HIDENAMEFLAG, element) ? ",\n but it's hidden" : "", + element->MarkX, element->MarkY, + TEST_FLAG(ONSOLDERFLAG, element) ? "solder (bottom)" : "component", + TEST_FLAG(LOCKFLAG, element) ? "It is LOCKED.\n" : ""); + break; + } + case TEXT_TYPE: +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + LayerTypePtr layer = (LayerTypePtr) ptr1; + __r_dump_tree(layer->text_tree->root, 0); + return 0; + } +#endif + case ELEMENTNAME_TYPE: + { + char laynum[32]; + TextTypePtr text; +#ifndef NDEBUG + if (gui->shift_is_pressed()) { + __r_dump_tree(PCB->Data->name_tree[NAME_INDEX(PCB)]->root, 0); + return 0; + } +#endif + text = (TextTypePtr) ptr2; + + if (type == TEXT_TYPE) + sprintf(laynum, "It is on layer %d.", GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1)); + report = pcb_strdup_printf("%m+TEXT ID# %ld; Flags:%s\n" + "Located at (X,Y) = %$mD.\n" + "Characters are %$mS tall.\n" + "Value is \"%s\".\n" + "Direction is %d.\n" + "The bounding box is %$mD %$mD.\n" + "%s\n" + "%s", USER_UNITMASK, text->ID, flags_to_string(text->Flags, TEXT_TYPE), + text->X, text->Y, SCALE_TEXT(FONT_CAPHEIGHT, text->Scale), + text->TextString, text->Direction, + text->BoundingBox.X1, text->BoundingBox.Y1, + text->BoundingBox.X2, text->BoundingBox.Y2, + (type == TEXT_TYPE) ? laynum : "It is an element name.", TEST_FLAG(LOCKFLAG, text) ? "It is LOCKED.\n" : ""); + break; + } + case LINEPOINT_TYPE: + case POLYGONPOINT_TYPE: + { + PointTypePtr point = (PointTypePtr) ptr2; + report = pcb_strdup_printf("%m+POINT ID# %ld.\n" + "Located at (X,Y) = %$mD.\n" + "It belongs to a %s on layer %d.\n", USER_UNITMASK, point->ID, + point->X, point->Y, + (type == LINEPOINT_TYPE) ? "line" : "polygon", GetLayerNumber(PCB->Data, (LayerTypePtr) ptr1)); + break; + } + case NO_TYPE: + report[0] = '\0'; + break; + + default: + report = pcb_strdup_printf("Unknown\n"); + break; + } + + if ((report == NULL) || (report == '\0')) { + Message(_("Nothing found to report on\n")); + return 1; + } + /* create dialog box */ + gui->report_dialog("Report", report); + free(report); + return 0; +} + +static int ReportFoundPins(int argc, char **argv, Coord x, Coord y) +{ + gds_t list; + int col = 0; + + gds_init(&list); + gds_append_str(&list, "The following pins/pads are FOUND:\n"); + ELEMENT_LOOP(PCB->Data); + { + PIN_LOOP(element); + { + if (TEST_FLAG(FOUNDFLAG, pin)) + pcb_append_printf(&list, "%s-%s,%c", NAMEONPCB_NAME(element), pin->Number, ((col++ % (COLUMNS + 1)) == COLUMNS) ? '\n' : ' '); + } + END_LOOP; + PAD_LOOP(element); + { + if (TEST_FLAG(FOUNDFLAG, pad)) + pcb_append_printf(&list, "%s-%s,%c", NAMEONPCB_NAME(element), pad->Number, ((col++ % (COLUMNS + 1)) == COLUMNS) ? '\n' : ' '); + } + END_LOOP; + } + END_LOOP; + + gui->report_dialog("Report", list.array); + gds_uninit(&list); + return 0; +} + +/* Assumes that we start with a blank connection state, + * e.g. ResetConnections() has been run. + * Does not add its own changes to the undo system + */ +static double XYtoNetLength(Coord x, Coord y, int *found) +{ + double length; + + length = 0; + *found = 0; + + /* NB: The third argument here, 'false' ensures LookupConnection + * does not add its changes to the undo system. + */ + LookupConnection(x, y, false, PCB->Grid, FOUNDFLAG); + + ALLLINE_LOOP(PCB->Data); + { + if (TEST_FLAG(FOUNDFLAG, line)) { + double l; + int dx, dy; + dx = line->Point1.X - line->Point2.X; + dy = line->Point1.Y - line->Point2.Y; + l = sqrt((double) dx * dx + (double) dy * dy); + length += l; + *found = 1; + } + } + ENDALL_LOOP; + + ALLARC_LOOP(PCB->Data); + { + if (TEST_FLAG(FOUNDFLAG, arc)) { + double l; + /* FIXME: we assume width==height here */ + l = M_PI * 2 * arc->Width * abs(arc->Delta) / 360.0; + length += l; + *found = 1; + } + } + ENDALL_LOOP; + + return length; +} + +static int ReportAllNetLengths(int argc, char **argv, Coord x, Coord y) +{ + int ni; + int found; + + /* Reset all connection flags and save an undo-state to get back + * to the state the board was in when we started this function. + * + * After this, we don't add any changes to the undo system, but + * ensure we get back to a point where we can Undo() our changes + * by resetting the connections with ResetConnections() before + * calling Undo() at the end of the procedure. + */ + ResetConnections(true); + IncrementUndoSerialNumber(); + + for (ni = 0; ni < PCB->NetlistLib[NETLIST_EDITED].MenuN; ni++) { + char *netname = PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Name + 2; + char *ename = PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Entry[0].ListEntry; + char *pname; + bool got_one = 0; + + ename = strdup(ename); + pname = strchr(ename, '-'); + if (!pname) { + free(ename); + continue; + } + *pname++ = 0; + + ELEMENT_LOOP(PCB->Data); + { + char *es = element->Name[NAMEONPCB_INDEX].TextString; + if (es && strcmp(es, ename) == 0) { + PIN_LOOP(element); + { + if (strcmp(pin->Number, pname) == 0) { + x = pin->X; + y = pin->Y; + got_one = 1; + break; + } + } + END_LOOP; + PAD_LOOP(element); + { + if (strcmp(pad->Number, pname) == 0) { + x = (pad->Point1.X + pad->Point2.X) / 2; + y = (pad->Point1.Y + pad->Point2.Y) / 2; + got_one = 1; + break; + } + } + END_LOOP; + } + } + END_LOOP; + + if (got_one) { + char buf[50]; + const char *units_name = argv[0]; + Coord length; + + if (argc < 1) + units_name = Settings.grid_unit->suffix; + + length = XYtoNetLength(x, y, &found); + + /* Reset connectors for the next lookup */ + ResetConnections(false); + + pcb_snprintf(buf, sizeof(buf), "%$m*", units_name, length); + gui->log("Net %s length %s\n", netname, buf); + } + } + + ResetConnections(false); + Undo(true); + return 0; +} + +static int ReportNetLength(int argc, char **argv, Coord x, Coord y) +{ + Coord length = 0; + char *netname = 0; + int found = 0; + + gui->get_coords("Click on a connection", &x, &y); + + /* Reset all connection flags and save an undo-state to get back + * to the state the board was in when we started this function. + * + * After this, we don't add any changes to the undo system, but + * ensure we get back to a point where we can Undo() our changes + * by resetting the connections with ResetConnections() before + * calling Undo() at the end of the procedure. + */ + ResetConnections(true); + IncrementUndoSerialNumber(); + + length = XYtoNetLength(x, y, &found); + + if (!found) { + ResetConnections(false); + Undo(true); + gui->log("No net under cursor.\n"); + return 1; + } + + ELEMENT_LOOP(PCB->Data); + { + PIN_LOOP(element); + { + if (TEST_FLAG(FOUNDFLAG, pin)) { + int ni, nei; + char *ename = element->Name[NAMEONPCB_INDEX].TextString; + char *pname = pin->Number; + char *n; + + if (ename && pname) { + n = Concat(ename, "-", pname, NULL); + for (ni = 0; ni < PCB->NetlistLib[NETLIST_EDITED].MenuN; ni++) + for (nei = 0; nei < PCB->NetlistLib[NETLIST_EDITED].Menu[ni].EntryN; nei++) { + if (strcmp(PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Entry[nei].ListEntry, n) == 0) { + netname = PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Name + 2; + goto got_net_name; /* four for loops deep */ + } + } + } + } + } + END_LOOP; + PAD_LOOP(element); + { + if (TEST_FLAG(FOUNDFLAG, pad)) { + int ni, nei; + char *ename = element->Name[NAMEONPCB_INDEX].TextString; + char *pname = pad->Number; + char *n; + + if (ename && pname) { + n = Concat(ename, "-", pname, NULL); + for (ni = 0; ni < PCB->NetlistLib[NETLIST_EDITED].MenuN; ni++) + for (nei = 0; nei < PCB->NetlistLib[NETLIST_EDITED].Menu[ni].EntryN; nei++) { + if (strcmp(PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Entry[nei].ListEntry, n) == 0) { + netname = PCB->NetlistLib[NETLIST_EDITED].Menu[ni].Name + 2; + goto got_net_name; /* four for loops deep */ + } + } + } + } + } + END_LOOP; + } + END_LOOP; + +got_net_name: + ResetConnections(false); + Undo(true); + + { + char buf[50]; + pcb_snprintf(buf, sizeof(buf), "%$m*", Settings.grid_unit->suffix, length); + if (netname) + gui->log("Net \"%s\" length: %s\n", netname, buf); + else + gui->log("Net length: %s\n", buf); + } + + return 0; +} + +static int ReportNetLengthByName(char *tofind, int x, int y) +{ + int result; + char *netname = 0; + Coord length = 0; + int found = 0; + int i; + LibraryMenuType *net; + ConnectionType conn; + int net_found = 0; +#if defined(USE_RE) + int use_re = 0; +#endif +#if defined(HAVE_REGCOMP) + regex_t elt_pattern; + regmatch_t match; +#endif +#if defined(HAVE_RE_COMP) + char *elt_pattern; +#endif + + if (!PCB) + return 1; + + if (!tofind) + return 1; + +#if defined(USE_RE) + use_re = 1; + for (i = 0; i < PCB->NetlistLib[NETLIST_EDITED].MenuN; i++) { + net = PCB->NetlistLib[NETLIST_EDITED].Menu + i; + if (strcasecmp(tofind, net->Name + 2) == 0) + use_re = 0; + } + if (use_re) { +#if defined(HAVE_REGCOMP) + result = regcomp(&elt_pattern, tofind, REG_EXTENDED | REG_ICASE | REG_NOSUB); + if (result) { + char errorstring[128]; + + regerror(result, &elt_pattern, errorstring, 128); + Message(_("regexp error: %s\n"), errorstring); + regfree(&elt_pattern); + return (1); + } +#endif +#if defined(HAVE_RE_COMP) + if ((elt_pattern = re_comp(tofind)) != NULL) { + Message(_("re_comp error: %s\n"), elt_pattern); + return (1); + } +#endif + } +#endif + + for (i = 0; i < PCB->NetlistLib[NETLIST_EDITED].MenuN; i++) { + net = PCB->NetlistLib[NETLIST_EDITED].Menu + i; + +#if defined(USE_RE) + if (use_re) { +#if defined(HAVE_REGCOMP) + if (regexec(&elt_pattern, net->Name + 2, 1, &match, 0) != 0) + continue; +#endif +#if defined(HAVE_RE_COMP) + if (re_exec(net->Name + 2) != 1) + continue; +#endif + } + else +#endif + if (strcasecmp(net->Name + 2, tofind)) + continue; + + if (SeekPad(net->Entry, &conn, false)) { + switch (conn.type) { + case PIN_TYPE: + x = ((PinType *) (conn.ptr2))->X; + y = ((PinType *) (conn.ptr2))->Y; + net_found = 1; + break; + case PAD_TYPE: + x = ((PadType *) (conn.ptr2))->Point1.X; + y = ((PadType *) (conn.ptr2))->Point1.Y; + net_found = 1; + break; + } + if (net_found) + break; + } + } + + if (!net_found) { + gui->log("No net named %s\n", tofind); + return 1; + } + +#ifdef HAVE_REGCOMP + if (use_re) + regfree(&elt_pattern); +#endif + + /* Reset all connection flags and save an undo-state to get back + * to the state the board was in when we started. + * + * After this, we don't add any changes to the undo system, but + * ensure we get back to a point where we can Undo() our changes + * by resetting the connections with ResetConnections() before + * calling Undo() when we are finished. + */ + ResetConnections(true); + IncrementUndoSerialNumber(); + + length = XYtoNetLength(x, y, &found); + netname = net->Name + 2; + + ResetConnections(false); + Undo(true); + + if (!found) { + if (net_found) + gui->log("Net found, but no lines or arcs were flagged.\n"); + else + gui->log("Net not found.\n"); + + return 1; + } + + { + char buf[50]; + pcb_snprintf(buf, sizeof(buf), "%$m*", Settings.grid_unit->suffix, length); + if (netname) + gui->log("Net \"%s\" length: %s\n", netname, buf); + else + gui->log("Net length: %s\n", buf); + } + + return 0; +} + +/* --------------------------------------------------------------------------- + * reports on an object + * syntax: + */ + +static const char report_syntax[] = "Report(Object|DrillReport|FoundPins|NetLength|AllNetLengths|[,name])"; + +static const char report_help[] = "Produce various report."; + +/* %start-doc actions Report + +@table @code + +@item Object +The object under the crosshair will be reported, describing various +aspects of the object. + +@item DrillReport +A report summarizing the number of drill sizes used, and how many of +each, will be produced. + +@item FoundPins +A report listing all pins and pads which are marked as ``found'' will +be produced. + +@item NetLength +The name and length of the net under the crosshair will be reported to +the message log. + +@item AllNetLengths +The name and length of the net under the crosshair will be reported to +the message log. An optional parameter specifies mm, mil, pcb, or in +units + +@end table + +%end-doc */ + +static int Report(int argc, char **argv, Coord x, Coord y) +{ + if ((argc < 1) || (argc > 2)) + AUSAGE(report); + else if (strcasecmp(argv[0], "Object") == 0) { + gui->get_coords("Click on an object", &x, &y); + return ReportDialog(argc - 1, argv + 1, x, y); + } + else if (strcasecmp(argv[0], "DrillReport") == 0) + return ReportDrills(argc - 1, argv + 1, x, y); + else if (strcasecmp(argv[0], "FoundPins") == 0) + return ReportFoundPins(argc - 1, argv + 1, x, y); + else if ((strcasecmp(argv[0], "NetLength") == 0) && (argc == 1)) + return ReportNetLength(argc - 1, argv + 1, x, y); + else if (strcasecmp(argv[0], "AllNetLengths") == 0) + return ReportAllNetLengths(argc - 1, argv + 1, x, y); + else if ((strcasecmp(argv[0], "NetLength") == 0) && (argc == 2)) + return ReportNetLengthByName(argv[1], x, y); + else if (argc == 2) + AUSAGE(report); + else + AFAIL(report); + return 1; +} + +HID_Action report_action_list[] = { + {"ReportObject", "Click on an object", ReportDialog, + reportdialog_help, reportdialog_syntax} + , + {"Report", 0, Report, + report_help, report_syntax} +}; + +static const char *report_cookie = "report plugin"; + +REGISTER_ACTIONS(report_action_list, report_cookie) + +static void hid_report_uninit(void) +{ + hid_remove_actions_by_cookie(report_cookie); +} + +#include "dolists.h" +pcb_uninit_t hid_report_init(void) +{ + REGISTER_ACTIONS(report_action_list, report_cookie) + return hid_report_uninit; +} + Index: src_plugins/report/report.h =================================================================== --- src_plugins/report/report.h (nonexistent) +++ src_plugins/report/report.h (revision 1389) @@ -0,0 +1,38 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Contact addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + * RCS: $Id$ + */ + +#ifndef PCB_REPORT_H +#define PCB_REPORT_H + +#include "global.h" + +#define REPORT_TYPES \ + (VIA_TYPE | LINE_TYPE | TEXT_TYPE | POLYGON_TYPE | ELEMENT_TYPE | \ + RATLINE_TYPE | PIN_TYPE | PAD_TYPE | ELEMENTNAME_TYPE | ARC_TYPE \ + | POLYGONPOINT_TYPE | LINEPOINT_TYPE) + +#endif