Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
0
Файл: report.c Проект: veox/pcb
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;
}
Пример #5
0
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;
}
Пример #6
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;
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
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;
}
Пример #10
0
/*
 * 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;
}
Пример #11
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;
}
Пример #12
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;
}
Пример #13
0
int mps_lib_callback_default_get_EOF(void)
{
  AFAIL("mps_lib_get_EOF needs to be provided");
  return 0;
}
Пример #14
0
unsigned long mps_lib_callback_default_telemetry_control(void)
{
  AFAIL("mps_lib_telemetry_control needs to be provided");
  return 0;
}
Пример #15
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;
}
Пример #16
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;
}
Пример #17
0
mps_lib_FILE *mps_lib_callback_default_get_stdout(void)
{
  AFAIL("mps_lib_get_stdout needs to be provided");
  return NULL;
}
Пример #18
0
mps_clock_t mps_lib_callback_default_clocks_per_sec(void)
{
  AFAIL("mps_clocks_per_sec needs to be provided");
  return 0;
}
Пример #19
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;
}