int mps_lib_callback_default_fputs(const char *s_, mps_lib_FILE *f_) { UNUSED(s_); UNUSED(f_); AFAIL("mps_lib_fputs needs to be provided"); return 0; }
int mps_lib_callback_default_fputc(int c_, mps_lib_FILE *f_) { UNUSED(c_); UNUSED(f_); AFAIL("mps_lib_fputc needs to be provided"); return 0; }
int ActionSetLayertype (int argc, char **argv, Coord x, Coord y) { int index; LayertypeType type; if (argc != 2) AFAIL (setlayertype); /* layer array is zero-based, file format counts layers starting at 1. */ index = atoi (argv[0]) - 1; if (index < 0 || index >= max_copper_layer + SILK_LAYER) { Message (N_("Layer index %d out of range, must be 0 ... %d\n"), index + 1, max_copper_layer + SILK_LAYER); return 1; } if (isdigit (argv[1][0])) type = atoi (argv[1]); else type = string_to_layertype (argv[1], NULL); if (type < 0 || type >= LT_NUM_LAYERTYPES) { Message (N_("Invalid layer type (%d) requested. " "See ListLayertypes() for a list.\n"), type); return 1; } PCB->Data->Layer[index].Type = type; return 0; }
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; }
int mps_lib_callback_default_memcmp(const void *p_, const void *q_, size_t n_) { UNUSED(p_); UNUSED(q_); UNUSED(n_); AFAIL("mps_lib_memcmp needs to be provided"); return 0; }
void *mps_lib_callback_default_memcpy(void *p_, const void *q_, size_t n_) { UNUSED(p_); UNUSED(q_); UNUSED(n_); AFAIL("mps_lib_memcpy needs to be provided"); return NULL; }
void *mps_lib_callback_default_memset(void *p_, int c_, size_t n_) { UNUSED(p_); UNUSED(c_); UNUSED(n_); AFAIL("mps_lib_memset needs to be provided"); return NULL; }
int LoadFootprint (int argc, char **argv, Coord x, Coord y) { char *name = ARG(0); char *refdes = ARG(1); char *value = ARG(2); ElementType *e; if (!name) AFAIL (loadfootprint); if (LoadFootprintByName (PASTEBUFFER, name)) return 1; if (PASTEBUFFER->Data->ElementN == 0) { Message(_("Footprint %s contains no elements"), name); return 1; } if (PASTEBUFFER->Data->ElementN > 1) { Message(_("Footprint %s contains multiple elements"), name); return 1; } e = PASTEBUFFER->Data->Element->data; if (e->Name[0].TextString) free (e->Name[0].TextString); e->Name[0].TextString = strdup (name); if (e->Name[1].TextString) free (e->Name[1].TextString); e->Name[1].TextString = refdes ? strdup (refdes) : 0; if (e->Name[2].TextString) free (e->Name[2].TextString); e->Name[2].TextString = value ? strdup (value) : 0; return 0; }
static int Report (int argc, char **argv, int x, int y) { if (argc < 1) 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) return ReportNetLength (argc - 1, argv + 1, x, y); else if (strcasecmp (argv[0], "AllNetLengths") == 0) return ReportAllNetLengths (argc - 1, argv + 1, x, y); else AFAIL (report); return 1; }
/* * DistributeText(X, [Lefts/Rights/Centers/Gaps, [First/Last/Crosshair, First/Last/Crosshair[, Gridless]]]) * DistributeText(Y, [Tops/Bottoms/Centers/Gaps, [First/Last/Crosshair, First/Last/Crosshair[, Gridless]]]) * * As with align, plus: * * Gaps - Make gaps even rather than spreading points evenly * First, Last, * Crosshair - Two arguments specifying both ends of the * distribution, they can't both be the same. * * Defaults are Lefts/Tops, First, Last * * Distributed texts always retain the same relative order they had * before they were distributed. */ static int distributetext(int argc, char **argv, Coord x, Coord y) { int dir; int point; int refa, refb; int gridless; Coord s, e, slack; int divisor; int changed = 0; int i; if (argc < 1 || argc == 3 || argc > 4) { AFAIL(distributetext); } /* parse direction arg */ switch ((dir = keyword(ARG(0)))) { case K_X: case K_Y: break; default: AFAIL(distributetext); } /* parse point (within each element) which will be distributed */ switch ((point = keyword(ARG(1)))) { case K_Centers: case K_Gaps: break; case K_Lefts: case K_Rights: if (dir == K_Y) { AFAIL(distributetext); } break; case K_Tops: case K_Bottoms: if (dir == K_X) { AFAIL(distributetext); } break; case K_none: /* default value */ if (dir == K_X) { point = K_Lefts; } else { point = K_Tops; } break; default: AFAIL(distributetext); } /* parse reference which will determine first distribution coordinate */ switch ((refa = keyword(ARG(2)))) { case K_First: case K_Last: case K_Average: case K_Crosshair: break; case K_none: refa = K_First; /* default value */ break; default: AFAIL(distributetext); } /* parse reference which will determine final distribution coordinate */ switch ((refb = keyword(ARG(3)))) { case K_First: case K_Last: case K_Average: case K_Crosshair: break; case K_none: refb = K_Last; /* default value */ break; default: AFAIL(distributetext); } if (refa == refb) { AFAIL(distributetext); } /* optionally work off the grid (solar cells!) */ switch (keyword(ARG(4))) { case K_Gridless: gridless = 1; break; case K_none: gridless = 0; break; default: AFAIL(distributetext); } SaveUndoSerialNumber(); /* build list of texts in orthogonal axis order */ sort_texts_by_pos(K_distributetext, dir, point); /* find the endpoints given the above options */ s = reference_coord(K_distributetext, x, y, dir, point, refa); e = reference_coord(K_distributetext, x, y, dir, point, refb); slack = e - s; /* use this divisor to calculate spacing (for 1 elt, avoid 1/0) */ divisor = (ntexts_by_pos > 1) ? (ntexts_by_pos - 1) : 1; /* even the gaps instead of the edges or whatnot */ /* find the "slack" in the row */ if (point == K_Gaps) { Coord w; /* subtract all the "widths" from the slack */ for (i = 0; i < ntexts_by_pos; ++i) { TextType *text = texts_by_pos[i].text; /* coord doesn't care if I mix Lefts/Tops */ w = texts_by_pos[i].width = coord(text, dir, K_Rights) - coord(text, dir, K_Lefts); /* Gaps distribution is on centers, so half of * first and last text don't count */ if (i == 0 || i == ntexts_by_pos - 1) { w /= 2; } slack -= w; } /* slack could be negative */ } /* move all selected texts to the new coordinate */ for (i = 0; i < ntexts_by_pos; ++i) { TextType *text = texts_by_pos[i].text; int type = texts_by_pos[i].type; Coord p, q, dp, dx, dy; /* find reference point for this text */ q = s + slack * i / divisor; /* find delta from reference point to reference point */ p = coord(text, dir, point); dp = q - p; /* ...but if we're gridful, keep the mark on the grid */ /* TODO re-enable grid if (! gridless) { dp -= (coord(text, dir, K_Marks) + dp) % (long) (PCB->Grid); } */ if (dp) { /* move from generic to X or Y */ dx = dy = dp; if (dir == K_X) dy = 0; else dx = 0; /* need to know if the text is part of an element, * all are TEXT_TYPE, but text associated with an * element is also ELEMENTNAME_TYPE. For undo, this is * significant in search.c: SearchObjectByID. * * MoveObject() is better as in aligntext(), but we * didn't keep the element reference when sorting. * */ MOVE_TEXT_LOWLEVEL(text, dx, dy); AddObjectToMoveUndoList(type, NULL, NULL, text, dx, dy); changed = 1; } /* in gaps mode, accumulate part widths */ if (point == K_Gaps) { /* move remaining half of our text */ s += texts_by_pos[i].width / 2; /* move half of next text */ if (i < ntexts_by_pos - 1) s += texts_by_pos[i + 1].width / 2; } } if (changed) { RestoreUndoSerialNumber(); IncrementUndoSerialNumber(); Redraw(); SetChangedFlag(true); } free_texts_by_pos(); return 0; }
/* * AlignText(X, [Lefts/Rights/Centers, [First/Last/Crosshair/Average[, Gridless]]]) * AlignText(Y, [Tops/Bottoms/Centers, [First/Last/Crosshair/Average[, Gridless]]]) * * X or Y - Select which axis will move, other is untouched * Lefts, Rights, * Tops, Bottoms, * Centers - Pick alignment point within each element. * NB: text objects have no Mark * First, Last, * Crosshair, * Average - Alignment reference, First=Topmost/Leftmost, * Last=Bottommost/Rightmost, Average or Crosshair point * Gridless - Do not force results to align to prevailing grid * * Defaults are Lefts/Tops, First */ static int aligntext(int argc, char **argv, Coord x, Coord y) { int dir; int point; int reference; int gridless; Coord q; Coord p, dp, dx, dy; int changed = 0; if (argc < 1 || argc > 4) { AFAIL(aligntext); } /* parse direction arg */ switch ((dir = keyword(ARG(0)))) { case K_X: case K_Y: break; default: AFAIL(aligntext); } /* parse point (within each element) which will be aligned */ switch ((point = keyword(ARG(1)))) { case K_Centers: break; case K_Lefts: case K_Rights: if (dir == K_Y) { AFAIL(aligntext); } break; case K_Tops: case K_Bottoms: if (dir == K_X) { AFAIL(aligntext); } break; case K_none: /* default value */ if (dir == K_X) { point = K_Lefts; } else { point = K_Tops; } break; default: AFAIL(aligntext); } /* parse reference which will determine alignment coordinates */ switch ((reference = keyword(ARG(2)))) { case K_First: case K_Last: case K_Average: case K_Crosshair: break; case K_none: reference = K_First; /* default value */ break; default: AFAIL(aligntext); } /* optionally work off the grid (solar cells!) */ switch (keyword(ARG(3))) { case K_Gridless: gridless = 1; break; case K_none: gridless = 0; break; default: AFAIL(aligntext); } SaveUndoSerialNumber(); /* find the final alignment coordinate using the above options */ q = reference_coord(K_aligntext, Crosshair.X, Crosshair.Y, dir, point, reference); /* move all selected elements to the new coordinate */ /* selected text part of an element */ ELEMENT_LOOP(PCB->Data); { TextType *text; text = &(element)->Name[NAME_INDEX(PCB)]; if (! TEST_FLAG (SELECTEDFLAG, text)) continue; /* find delta from reference point to reference point */ p = coord(text, dir, point); dp = q - p; /* ...but if we're gridful, keep the mark on the grid */ /* TODO re-enable for text, need textcoord() if (! gridless) { dp -= (coord(text, dir, K_Marks) + dp) % (long) (PCB->Grid); } */ if (dp) { /* move from generic to X or Y */ dx = dy = dp; if (dir == K_X) dy = 0; else dx = 0; MoveObject(ELEMENTNAME_TYPE, element, text, text, dx, dy); changed = 1; } } END_LOOP; /* Selected bare text objects */ ALLTEXT_LOOP (PCB->Data); { if (TEST_FLAG (SELECTEDFLAG, text)) { /* find delta from reference point to reference point */ p = coord(text, dir, point); dp = q - p; /* ...but if we're gridful, keep the mark on the grid */ /* TODO re-enable for text, need textcoord() if (! gridless) { dp -= (coord(text, dir, K_Marks) + dp) % (long) (PCB->Grid); } */ if (dp) { /* move from generic to X or Y */ dx = dy = dp; if (dir == K_X) dy = 0; else dx = 0; MoveObject(TEXT_TYPE, layer, text, text, dx, dy); changed = 1; } } } ENDALL_LOOP; if (changed) { RestoreUndoSerialNumber(); IncrementUndoSerialNumber(); Redraw(); SetChangedFlag(true); } free_texts_by_pos(); return 0; }
int ActionLoadVendorFrom (int argc, char **argv, Coord x, Coord y) { int i; char *fname = NULL; static char *default_file = NULL; char *sval; Resource *res, *drcres, *drlres; int type; bool free_fname = false; cached_drill = -1; fname = argc ? argv[0] : 0; if (!fname || !*fname) { fname = gui->fileselect (_("Load Vendor Resource File..."), _("Picks a vendor resource file to load.\n" "This file can contain drc settings for a\n" "particular vendor as well as a list of\n" "predefined drills which are allowed."), default_file, ".res", "vendor", HID_FILESELECT_READ); if (fname == NULL) AFAIL (load_vendor); free_fname = true; free (default_file); default_file = NULL; if (fname && *fname) default_file = strdup (fname); } /* Unload any vendor table we may have had */ n_vendor_drills = 0; n_refdes = 0; n_value = 0; n_descr = 0; FREE (vendor_drills); FREE (ignore_refdes); FREE (ignore_value); FREE (ignore_descr); /* load the resource file */ res = resource_parse (fname, NULL); if (res == NULL) { Message (_("Could not load vendor resource file \"%s\"\n"), fname); return 1; } /* figure out the vendor name, if specified */ vendor_name = (char *)UNKNOWN (resource_value (res, "vendor")); /* figure out the units, if specified */ sval = resource_value (res, "units"); if (sval == NULL) { sf = MIL_TO_COORD(1); } else if ((NSTRCMP (sval, "mil") == 0) || (NSTRCMP (sval, "mils") == 0)) { sf = MIL_TO_COORD(1); } else if ((NSTRCMP (sval, "inch") == 0) || (NSTRCMP (sval, "inches") == 0)) { sf = INCH_TO_COORD(1); } else if (NSTRCMP (sval, "mm") == 0) { sf = MM_TO_COORD(1); } else { Message ("\"%s\" is not a supported units. Defaulting to inch\n", sval); sf = INCH_TO_COORD(1); } /* default to ROUND_UP */ rounding_method = ROUND_UP; /* extract the drillmap resource */ drlres = resource_subres (res, "drillmap"); if (drlres == NULL) { Message (_("No drillmap resource found\n")); } else { sval = resource_value (drlres, "round"); if (sval != NULL) { if (NSTRCMP (sval, "up") == 0) { rounding_method = ROUND_UP; } else if (NSTRCMP (sval, "nearest") == 0) { rounding_method = CLOSEST; } else { Message (_ ("\"%s\" is not a valid rounding type. Defaulting to up\n"), sval); rounding_method = ROUND_UP; } } process_skips (resource_subres (drlres, "skips")); for (i = 0; i < drlres->c; i++) { type = resource_type (drlres->v[i]); switch (type) { case 10: /* just a number */ add_to_drills (drlres->v[i].value); break; default: break; } } } /* Extract the DRC resource */ drcres = resource_subres (res, "drc"); sval = resource_value (drcres, "copper_space"); if (sval != NULL) { PCB->Bloat = floor (sf * atof (sval) + 0.5); Message (_("Set DRC minimum copper spacing to %.2f mils\n"), 0.01 * PCB->Bloat); } sval = resource_value (drcres, "copper_overlap"); if (sval != NULL) { PCB->Shrink = floor (sf * atof (sval) + 0.5); Message (_("Set DRC minimum copper overlap to %.2f mils\n"), 0.01 * PCB->Shrink); } sval = resource_value (drcres, "copper_width"); if (sval != NULL) { PCB->minWid = floor (sf * atof (sval) + 0.5); Message (_("Set DRC minimum copper spacing to %.2f mils\n"), 0.01 * PCB->minWid); } sval = resource_value (drcres, "silk_width"); if (sval != NULL) { PCB->minSlk = floor (sf * atof (sval) + 0.5); Message (_("Set DRC minimum silk width to %.2f mils\n"), 0.01 * PCB->minSlk); } sval = resource_value (drcres, "min_drill"); if (sval != NULL) { PCB->minDrill = floor (sf * atof (sval) + 0.5); Message (_("Set DRC minimum drill diameter to %.2f mils\n"), 0.01 * PCB->minDrill); } sval = resource_value (drcres, "min_ring"); if (sval != NULL) { PCB->minRing = floor (sf * atof (sval) + 0.5); Message (_("Set DRC minimum annular ring to %.2f mils\n"), 0.01 * PCB->minRing); } Message (_("Loaded %d vendor drills from %s\n"), n_vendor_drills, fname); Message (_("Loaded %d RefDes skips, %d Value skips, %d Descr skips\n"), n_refdes, n_value, n_descr); vendorMapEnable = true; apply_vendor_map (); if (free_fname) free (fname); return 0; }
int mps_lib_callback_default_get_EOF(void) { AFAIL("mps_lib_get_EOF needs to be provided"); return 0; }
unsigned long mps_lib_callback_default_telemetry_control(void) { AFAIL("mps_lib_telemetry_control needs to be provided"); return 0; }
/* * Distribute(X, [Lefts/Rights/Centers/Marks/Gaps, [First/Last/Crosshair, First/Last/Crosshair[, Gridless]]]) * Distribute(Y, [Tops/Bottoms/Centers/Marks/Gaps, [First/Last/Crosshair, First/Last/Crosshair[, Gridless]]]) * * As with align, plus: * * Gaps - Make gaps even rather than spreading points evenly * First, Last, * Crosshair - Two arguments specifying both ends of the * distribution, they can't both be the same. * * Defaults are Marks, First, Last * * Distributed elements always retain the same relative order they had * before they were distributed. */ static int distribute(int argc, char **argv, Coord x, Coord y) { int dir; int point; int refa, refb; int gridless; Coord s, e, slack; int divisor; int changed = 0; int i; if (argc < 1 || argc == 3 || argc > 4) { AFAIL(distribute); } /* parse direction arg */ switch ((dir = keyword(ARG(0)))) { case K_X: case K_Y: break; default: AFAIL(distribute); } /* parse point (within each element) which will be distributed */ switch ((point = keyword(ARG(1)))) { case K_Centers: case K_Marks: case K_Gaps: break; case K_Lefts: case K_Rights: if (dir == K_Y) { AFAIL(distribute); } break; case K_Tops: case K_Bottoms: if (dir == K_X) { AFAIL(distribute); } break; case K_none: point = K_Marks; /* default value */ break; default: AFAIL(distribute); } /* parse reference which will determine first distribution coordinate */ switch ((refa = keyword(ARG(2)))) { case K_First: case K_Last: case K_Average: case K_Crosshair: break; case K_none: refa = K_First; /* default value */ break; default: AFAIL(distribute); } /* parse reference which will determine final distribution coordinate */ switch ((refb = keyword(ARG(3)))) { case K_First: case K_Last: case K_Average: case K_Crosshair: break; case K_none: refb = K_Last; /* default value */ break; default: AFAIL(distribute); } if (refa == refb) { AFAIL(distribute); } /* optionally work off the grid (solar cells!) */ switch (keyword(ARG(4))) { case K_Gridless: gridless = 1; break; case K_none: gridless = 0; break; default: AFAIL(distribute); } /* build list of elements in orthogonal axis order */ sort_elements_by_pos(K_distribute, dir, point); /* find the endpoints given the above options */ s = reference_coord(K_distribute, x, y, dir, point, refa); e = reference_coord(K_distribute, x, y, dir, point, refb); slack = e - s; /* use this divisor to calculate spacing (for 1 elt, avoid 1/0) */ divisor = (nelements_by_pos > 1) ? (nelements_by_pos - 1) : 1; /* even the gaps instead of the edges or whatnot */ /* find the "slack" in the row */ if (point == K_Gaps) { Coord w; /* subtract all the "widths" from the slack */ for (i = 0; i < nelements_by_pos; ++i) { ElementType *element = elements_by_pos[i].element; /* coord doesn't care if I mix Lefts/Tops */ w = elements_by_pos[i].width = coord(element, dir, K_Rights) - coord(element, dir, K_Lefts); /* Gaps distribution is on centers, so half of * first and last element don't count */ if (i == 0 || i == nelements_by_pos - 1) { w /= 2; } slack -= w; } /* slack could be negative */ } /* move all selected elements to the new coordinate */ for (i = 0; i < nelements_by_pos; ++i) { ElementType *element = elements_by_pos[i].element; Coord p, q, dp, dx, dy; /* find reference point for this element */ q = s + slack * i / divisor; /* find delta from reference point to reference point */ p = coord(element, dir, point); dp = q - p; /* ...but if we're gridful, keep the mark on the grid */ if (! gridless) { dp -= (coord(element, dir, K_Marks) + dp) % (long) (PCB->Grid); } if (dp) { /* move from generic to X or Y */ dx = dy = dp; if (dir == K_X) dy = 0; else dx = 0; MoveElementLowLevel(PCB->Data, element, dx, dy); AddObjectToMoveUndoList(ELEMENT_TYPE, NULL, NULL, element, dx, dy); changed = 1; } /* in gaps mode, accumulate part widths */ if (point == K_Gaps) { /* move remaining half of our element */ s += elements_by_pos[i].width / 2; /* move half of next element */ if (i < nelements_by_pos - 1) s += elements_by_pos[i + 1].width / 2; } } if (changed) { IncrementUndoSerialNumber(); Redraw(); SetChangedFlag(1); } free_elements_by_pos(); return 0; }
/* %start-doc actions SmartDisperse The @code{SmartDisperse([All|Selected])} action is a special-purpose optimization for dispersing elements. Run with @code{:SmartDisperse()} or @code{:SmartDisperse(Selected)} (you can also say @code{:SmartDisperse(All)}, but that's the default). %end-doc */ static int smartdisperse (int argc, char **argv, Coord x, Coord y) { char *function = ARG(0); NetListType *Nets; char *visited; // PointerListType stack = { 0, 0, NULL }; int all; // int changed = 0; // int i; if (! function) { all = 1; } else if (strcmp(function, "All") == 0) { all = 1; } else if (strcmp(function, "Selected") == 0) { all = 0; } else { AFAIL (smartdisperse); } Nets = ProcNetlist (&PCB->NetlistLib); if (! Nets) { Message (_("Can't use SmartDisperse because no netlist is loaded.\n")); return 0; } /* remember which elements we finish with */ visited = calloc (PCB->Data->ElementN, sizeof(*visited)); /* if we're not doing all, mark the unselected elements as "visited" */ ELEMENT_LOOP (PCB->Data); { if (! (all || TEST_FLAG (SELECTEDFLAG, element))) { visited[n] = 1; } } END_LOOP; /* initialize variables for place() */ minx = GAP; miny = GAP; maxx = GAP; maxy = GAP; /* * Pick nets with two connections. This is the start of a more * elaborate algorithm to walk serial nets, but the datastructures * are too gross so I'm going with the 80% solution. */ NET_LOOP (Nets); { ConnectionType *conna, *connb; ElementType *ea, *eb; // ElementType *epp; if (net->ConnectionN != 2) continue; conna = &net->Connection[0]; connb = &net->Connection[1]; if (!IS_ELEMENT(conna) || !IS_ELEMENT(conna)) continue; ea = (ElementType *) conna->ptr1; eb = (ElementType *) connb->ptr1; /* place this pair if possible */ if (VISITED((GList *)ea) || VISITED((GList *)eb)) continue; VISITED ((GList *)ea) = 1; VISITED ((GList *)eb) = 1; /* a weak attempt to get the linked pads side-by-side */ if (padorder(conna, connb)) { place ((ElementType *) ea); place ((ElementType *) eb); } else { place (eb); place (ea); } } END_LOOP; /* Place larger nets, still grouping by net */ NET_LOOP (Nets); { CONNECTION_LOOP (net); { ElementType *element; if (! IS_ELEMENT(connection)) continue; element = (ElementType *) connection->ptr1; /* place this one if needed */ if (VISITED ((GList *) element)) continue; VISITED ((GList *) element) = 1; place (element); } END_LOOP; } END_LOOP; /* Place up anything else */ ELEMENT_LOOP (PCB->Data); { if (! visited[n]) { place (element); } } END_LOOP; free (visited); IncrementUndoSerialNumber (); Redraw (); SetChangedFlag (1); return 0; }
mps_lib_FILE *mps_lib_callback_default_get_stdout(void) { AFAIL("mps_lib_get_stdout needs to be provided"); return NULL; }
mps_clock_t mps_lib_callback_default_clocks_per_sec(void) { AFAIL("mps_clocks_per_sec needs to be provided"); return 0; }
/* * Align(X, [Lefts/Rights/Centers/Marks, [First/Last/Crosshair/Average[, Gridless]]]) * Align(Y, [Tops/Bottoms/Centers/Marks, [First/Last/Crosshair/Average[, Gridless]]]) * * X or Y - Select which axis will move, other is untouched * Lefts, Rights, * Tops, Bottoms, * Centers, Marks - Pick alignment point within each element * First, Last, * Crosshair, * Average - Alignment reference, First=Topmost/Leftmost, * Last=Bottommost/Rightmost, Average or Crosshair point * Gridless - Do not force results to align to prevailing grid * * Defaults are Marks, First */ static int align(int argc, char **argv, Coord x, Coord y) { int dir; int point; int reference; int gridless; Coord q; int changed = 0; if (argc < 1 || argc > 4) { AFAIL(align); } /* parse direction arg */ switch ((dir = keyword(ARG(0)))) { case K_X: case K_Y: break; default: AFAIL(align); } /* parse point (within each element) which will be aligned */ switch ((point = keyword(ARG(1)))) { case K_Centers: case K_Marks: break; case K_Lefts: case K_Rights: if (dir == K_Y) { AFAIL(align); } break; case K_Tops: case K_Bottoms: if (dir == K_X) { AFAIL(align); } break; case K_none: point = K_Marks; /* default value */ break; default: AFAIL(align); } /* parse reference which will determine alignment coordinates */ switch ((reference = keyword(ARG(2)))) { case K_First: case K_Last: case K_Average: case K_Crosshair: break; case K_none: reference = K_First; /* default value */ break; default: AFAIL(align); } /* optionally work off the grid (solar cells!) */ switch (keyword(ARG(3))) { case K_Gridless: gridless = 1; break; case K_none: gridless = 0; break; default: AFAIL(align); } /* find the final alignment coordinate using the above options */ q = reference_coord(K_align, Crosshair.X, Crosshair.Y, dir, point, reference); /* move all selected elements to the new coordinate */ ELEMENT_LOOP(PCB->Data); { Coord p, dp, dx, dy; if (! TEST_FLAG (SELECTEDFLAG, element)) continue; /* find delta from reference point to reference point */ p = coord(element, dir, point); dp = q - p; /* ...but if we're gridful, keep the mark on the grid */ if (! gridless) { dp -= (coord(element, dir, K_Marks) + dp) % (long) (PCB->Grid); } if (dp) { /* move from generic to X or Y */ dx = dy = dp; if (dir == K_X) dy = 0; else dx = 0; MoveElementLowLevel(PCB->Data, element, dx, dy); AddObjectToMoveUndoList(ELEMENT_TYPE, NULL, NULL, element, dx, dy); changed = 1; } } END_LOOP; if (changed) { IncrementUndoSerialNumber(); Redraw(); SetChangedFlag(1); } free_elements_by_pos(); return 0; }