4 * \brief Action routines for output window.
8 * <h1><b>Copyright.</b></h1>\n
10 * PCB, interactive printed circuit board design
12 * Copyright (C) 1994,1995,1996 Thomas Nau
14 * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 * Contact addresses for paper mail and Email:
31 * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA
32 * haceaton@aplcomm.jhuapl.edu
42 #include "autoplace.h"
43 #include "autoroute.h"
48 #include "crosshair.h"
62 /*#include "print.h"*/
67 #include "rubberband.h"
75 #include "pcb-printf.h"
79 #include <stdlib.h> /* rand() */
81 #ifdef HAVE_LIBDMALLOC
85 /* for fork() and friends */
90 #ifdef HAVE_SYS_WAIT_H
96 /* ---------------------------------------------------------------------------
130 F_ElementConnections
,
171 F_ResetLinesAndPolygons
,
172 F_ResetPinsViasAndPads
,
193 F_ToggleAllDirections
,
204 F_ToggleRubberBandMode
,
205 F_ToggleStartDirection
,
210 F_ToggleThindrawPoly
,
223 F_ToggleAutoBuriedVias
227 typedef struct /* used to identify subfunctions */
234 /* --------------------------------------------------------------------------- */
236 /* %start-doc actions 00delta
238 Many actions take a @code{delta} parameter as the last parameter,
239 which is an amount to change something. That @code{delta} may include
240 units, as an additional parameter, such as @code{Action(Object,5,mm)}.
241 If no units are specified, the default is PCB's native units
242 (currently 1/100 mil). Also, if the delta is prefixed by @code{+} or
243 @code{-}, the size is increased or decreased by that amount.
244 Otherwise, the size size is set to the given amount.
248 Action(Object,+0.5,mm)
252 Actions which take a @code{delta} parameter which do not accept all
253 these options will specify what they do take.
257 /* %start-doc actions 00objects
259 Many actions act on indicated objects on the board. They will have
260 parameters like @code{ToggleObject} or @code{SelectedVias} to indicate
261 what group of objects they act on. Unless otherwise specified, these
262 parameters are defined as follows:
268 Affects the object under the mouse pointer. If this action is invoked
269 from a menu or script, the user will be prompted to click on an
270 object, which is then the object affected.
273 @itemx SelectedObjects
275 Affects all objects which are currently selected. At least, all
276 selected objects for which the given action makes sense.
280 @itemx Selected@var{Type}
282 Affects all objects which are both selected and of the @var{Type} specified.
288 /* %start-doc actions 00macros
292 Pins, pads, and vias can have various shapes. All may be round. Pins
293 and pads may be square (obviously "square" pads are usually
294 rectangular). Pins and vias may be octagonal. When you change a
295 shape flag of an element, you actually change all of its pins and
298 Note that the square flag takes precedence over the octagon flag,
299 thus, if both the square and octagon flags are set, the object is
300 square. When the square flag is cleared, the pins and pads will be
301 either round or, if the octagon flag is set, octagonal.
307 /* ---------------------------------------------------------------------------
308 * some local identifiers
310 static PointType InsertedPoint
;
311 static LayerType
*lastLayer
;
324 bool Moving
; /* selected type clicked on */
325 int Hit
; /* move type clicked on */
332 static int defer_updates
= 0;
333 static int defer_needs_update
= 0;
335 static Cardinal polyIndex
= 0;
336 static bool saved_mode
= false;
337 #ifdef HAVE_LIBSTROKE
338 static bool mid_stroke
= false;
339 static BoxType StrokeBox
;
341 static FunctionType Functions
[] = {
342 {"AddSelected", F_AddSelected
},
344 {"AllConnections", F_AllConnections
},
345 {"AllRats", F_AllRats
},
346 {"AllUnusedPins", F_AllUnusedPins
},
350 {"Description", F_Description
},
351 {"Cancel", F_Cancel
},
352 {"Center", F_Center
},
354 {"ClearAndRedraw", F_ClearAndRedraw
},
355 {"ClearList", F_ClearList
},
357 {"CreatePins", F_CreatePins
},
358 {"CreateVias", F_CreateVias
},
359 {"CreateHoles", F_CreateHoles
},
361 {"Connection", F_Connection
},
362 {"Convert", F_Convert
},
364 {"CycleClip", F_CycleClip
},
365 {"CycleCrosshair", F_CycleCrosshair
},
366 {"DeleteRats", F_DeleteRats
},
368 {"DrillReport", F_DrillReport
},
369 {"Element", F_Element
},
370 {"ElementByName", F_ElementByName
},
371 {"ElementConnections", F_ElementConnections
},
372 {"ElementToBuffer", F_ElementToBuffer
},
373 {"Escape", F_Escape
},
375 {"FlipElement", F_FlipElement
},
376 {"FoundPins", F_FoundPins
},
378 {"InsertPoint", F_InsertPoint
},
380 {"Layout", F_Layout
},
381 {"LayoutAs", F_LayoutAs
},
382 {"LayoutToBuffer", F_LayoutToBuffer
},
384 {"LineSize", F_LineSize
},
386 {"Mirror", F_Mirror
},
388 {"NameOnPCB", F_NameOnPCB
},
389 {"Netlist", F_Netlist
},
390 {"NetByName", F_NetByName
},
392 {"Notify", F_Notify
},
393 {"Object", F_Object
},
394 {"ObjectByName", F_ObjectByName
},
395 {"PasteBuffer", F_PasteBuffer
},
396 {"PadByName", F_PadByName
},
397 {"PinByName", F_PinByName
},
398 {"PinOrPadName", F_PinOrPadName
},
399 {"Pinout", F_Pinout
},
400 {"Polygon", F_Polygon
},
401 {"PolygonHole", F_PolygonHole
},
402 {"PreviousPoint", F_PreviousPoint
},
403 {"RatsNest", F_RatsNest
},
404 {"Rectangle", F_Rectangle
},
405 {"Redraw", F_Redraw
},
406 {"Release", F_Release
},
407 {"Remove", F_Remove
},
408 {"RemoveSelected", F_RemoveSelected
},
409 {"Report", F_Report
},
411 {"ResetLinesAndPolygons", F_ResetLinesAndPolygons
},
412 {"ResetPinsViasAndPads", F_ResetPinsViasAndPads
},
413 {"Restore", F_Restore
},
414 {"Revert", F_Revert
},
415 {"Rotate", F_Rotate
},
417 {"Selected", F_Selected
},
418 {"SelectedArcs", F_SelectedArcs
},
419 {"SelectedElements", F_SelectedElements
},
420 {"SelectedLines", F_SelectedLines
},
421 {"SelectedNames", F_SelectedNames
},
422 {"SelectedObjects", F_SelectedObjects
},
423 {"SelectedPins", F_SelectedPins
},
424 {"SelectedPads", F_SelectedPads
},
425 {"SelectedRats", F_SelectedRats
},
426 {"SelectedTexts", F_SelectedTexts
},
427 {"SelectedVias", F_SelectedVias
},
428 {"Stroke", F_Stroke
},
430 {"TextByName", F_TextByName
},
431 {"TextScale", F_TextScale
},
432 {"Thermal", F_Thermal
},
433 {"ToLayout", F_ToLayout
},
434 {"Toggle45Degree", F_ToggleAllDirections
},
435 {"ToggleClearLine", F_ToggleClearLine
},
436 {"ToggleFullPoly", F_ToggleFullPoly
},
437 {"ToggleGrid", F_ToggleGrid
},
438 {"ToggleMask", F_ToggleMask
},
439 {"ToggleName", F_ToggleName
},
440 {"ToggleObject", F_ToggleObject
},
441 {"ToggleRubberBandMode", F_ToggleRubberBandMode
},
442 {"ToggleStartDirection", F_ToggleStartDirection
},
443 {"ToggleSnapPin", F_ToggleSnapPin
},
444 {"ToggleThindraw", F_ToggleThindraw
},
445 {"ToggleThindrawPoly", F_ToggleThindrawPoly
},
446 {"ToggleLockNames", F_ToggleLockNames
},
447 {"ToggleOnlyNames", F_ToggleOnlyNames
},
448 {"ToggleHideNames", F_ToggleHideNames
},
449 {"ToggleCheckPlanes", F_ToggleCheckPlanes
},
450 {"ToggleLocalRef", F_ToggleLocalRef
},
451 {"ToggleOrthoMove", F_ToggleOrthoMove
},
452 {"ToggleShowDRC", F_ToggleShowDRC
},
453 {"ToggleLiveRoute", F_ToggleLiveRoute
},
454 {"ToggleAutoDRC", F_ToggleAutoDRC
},
455 {"ToggleUniqueNames", F_ToggleUniqueNames
},
458 {"ViaByName", F_ViaByName
},
459 {"ViaSize", F_ViaSize
},
460 {"ViaDrillingHole", F_ViaDrillingHole
},
462 {"ThroughHole", F_ThroughHole
},
463 {"TH", F_ThroughHole
},
464 {"BuriedVias", F_BuriedVias
},
465 {"ToggleAutoBuriedVias", F_ToggleAutoBuriedVias
}
468 /* ---------------------------------------------------------------------------
469 * some local routines
471 static int GetFunctionID (String
);
472 static void AdjustAttachedBox (void);
473 static void NotifyLine (void);
474 static void NotifyBlock (void);
475 static void NotifyMode (void);
476 static void ClearWarnings (void);
477 #ifdef HAVE_LIBSTROKE
478 static void FinishStroke (void);
479 extern void stroke_init (void);
480 extern void stroke_record (int x
, int y
);
481 extern int stroke_trans (char *s
);
483 static void ChangeFlag (char *, char *, int, char *);
485 #define ARG(n) (argc > (n) ? argv[n] : NULL)
487 #ifdef HAVE_LIBSTROKE
490 * \brief Try to recognize the stroke sent.
498 void *ptr1
, *ptr2
, *ptr3
;
501 if (stroke_trans (msg
))
507 if (Settings
.Mode
== LINE_MODE
)
517 RotateScreenObject (StrokeBox
.X1
, StrokeBox
.Y1
, SWAP_IDENT
? 1 : 3);
523 RotateScreenObject (StrokeBox
.X1
, StrokeBox
.Y1
, SWAP_IDENT
? 3 : 1);
529 SetMode (ARROW_MODE
);
554 /* XXX: FIXME: Call a zoom-extents action */
565 /* XXX: FIXME: Zoom to fit the box StrokeBox.[X1,Y1] - StrokeBox.[X2,Y2] */
569 Message (_("Unknown stroke %s\n"), msg
);
579 * \brief Clear warning color from pins/pads.
584 Settings
.RatWarn
= false;
585 ALLPIN_LOOP (PCB
->Data
);
587 if (TEST_FLAG (WARNFLAG
, pin
))
589 CLEAR_FLAG (WARNFLAG
, pin
);
594 ALLPAD_LOOP (PCB
->Data
);
596 if (TEST_FLAG (WARNFLAG
, pad
))
598 CLEAR_FLAG (WARNFLAG
, pad
);
607 * \brief Click callback.
609 * This is called a clicktime after a mouse down, to we can distinguish
610 * between short clicks (typically: select or create something) and long
611 * clicks. Long clicks typically drag something.
618 notify_crosshair_change (false);
620 if (Note
.Moving
&& !gui
->shift_is_pressed ())
622 Note
.Buffer
= Settings
.BufferNumber
;
623 SetBufferNumber (MAX_BUFFER
- 1);
624 ClearBuffer (PASTEBUFFER
);
625 AddSelectedToBuffer (PASTEBUFFER
, Note
.X
, Note
.Y
, true);
626 SaveUndoSerialNumber ();
630 SetMode (PASTEBUFFER_MODE
);
632 else if (Note
.Hit
&& !gui
->shift_is_pressed ())
636 SetMode (gui
->control_is_pressed ()? COPY_MODE
: MOVE_MODE
);
637 Crosshair
.AttachedObject
.Ptr1
= Note
.ptr1
;
638 Crosshair
.AttachedObject
.Ptr2
= Note
.ptr2
;
639 Crosshair
.AttachedObject
.Ptr3
= Note
.ptr3
;
640 Crosshair
.AttachedObject
.Type
= Note
.Hit
;
641 AttachForCopy (Note
.X
, Note
.Y
);
649 SaveUndoSerialNumber ();
654 /* unselect first if shift key not down */
655 if (!gui
->shift_is_pressed () && SelectBlock (&box
, false))
656 SetChangedFlag (true);
658 Crosshair
.AttachedBox
.Point1
.X
= Note
.X
;
659 Crosshair
.AttachedBox
.Point1
.Y
= Note
.Y
;
661 notify_crosshair_change (true);
666 * \brief This is typically called when the mouse has moved or the mouse
667 * button was released.
683 Note
.Click
= false; /* inhibit timer action */
684 SaveUndoSerialNumber ();
685 /* unselect first if shift key not down */
686 if (!gui
->shift_is_pressed ())
688 if (SelectBlock (&box
, false))
689 SetChangedFlag (true);
697 /* Restore the SN so that if we select something the deselect/select combo
699 RestoreUndoSerialNumber();
701 SetChangedFlag (true);
703 /* We didn't select anything new, so, the deselection should get its
705 IncrementUndoSerialNumber();
709 else if (Note
.Moving
)
711 RestoreUndoSerialNumber ();
713 ClearBuffer (PASTEBUFFER
);
714 SetBufferNumber (Note
.Buffer
);
723 else if (Settings
.Mode
== ARROW_MODE
)
725 box
.X1
= MIN (Crosshair
.AttachedBox
.Point1
.X
,
726 Crosshair
.AttachedBox
.Point2
.X
);
727 box
.Y1
= MIN (Crosshair
.AttachedBox
.Point1
.Y
,
728 Crosshair
.AttachedBox
.Point2
.Y
);
729 box
.X2
= MAX (Crosshair
.AttachedBox
.Point1
.X
,
730 Crosshair
.AttachedBox
.Point2
.X
);
731 box
.Y2
= MAX (Crosshair
.AttachedBox
.Point1
.Y
,
732 Crosshair
.AttachedBox
.Point2
.Y
);
733 RestoreUndoSerialNumber ();
734 if (SelectBlock (&box
, true))
735 SetChangedFlag (true);
737 IncrementUndoSerialNumber ();
738 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
746 static char function_hash
[HSIZE
];
747 static int hash_initted
= 0;
756 i
= (i
* 13) ^ (unsigned char)tolower((int) *s
);
759 i
= (unsigned int)i
% HSIZE
;
764 * \brief Get function ID of passed string.
767 GetFunctionID (String Ident
)
777 if (HSIZE
< ENTRIES (Functions
) * 2)
779 fprintf(stderr
, _("Error: function hash size too small (%d vs %lu at %s:%d)\n"),
780 HSIZE
, (unsigned long) ENTRIES (Functions
)*2, __FILE__
, __LINE__
);
783 if (ENTRIES (Functions
) > 254)
785 /* Change 'char' to 'int' and remove this when we get to 256
787 fprintf(stderr
, _("Error: function hash type too small (%d vs %lu at %s:%d)\n"),
788 256, (unsigned long) ENTRIES (Functions
), __FILE__
, __LINE__
);
792 for (i
=ENTRIES (Functions
)-1; i
>=0; i
--)
794 h
= hashfunc (Functions
[i
].Identifier
);
795 while (function_hash
[h
])
797 function_hash
[h
] = i
+ 1;
801 i
= hashfunc (Ident
);
804 /* We enforce the "hash table bigger than function table" rule,
805 so we know there will be at least one zero entry to find. */
806 if (!function_hash
[i
])
808 if (!strcasecmp (Ident
, Functions
[function_hash
[i
]-1].Identifier
))
809 return ((int) Functions
[function_hash
[i
]-1].ID
);
815 * \brief Set new coordinates if in 'RECTANGLE' mode.
817 * The cursor shape is also adjusted.
820 AdjustAttachedBox (void)
822 if (Settings
.Mode
== ARC_MODE
)
824 Crosshair
.AttachedBox
.otherway
= gui
->shift_is_pressed ();
827 switch (Crosshair
.AttachedBox
.State
)
829 case STATE_SECOND
: /* one corner is selected */
831 /* update coordinates */
832 Crosshair
.AttachedBox
.Point2
.X
= Crosshair
.X
;
833 Crosshair
.AttachedBox
.Point2
.Y
= Crosshair
.Y
;
840 * \brief Adjusts the objects which are to be created like attached
844 AdjustAttachedObjects (void)
847 switch (Settings
.Mode
)
849 /* update at least an attached block (selection) */
852 if (Crosshair
.AttachedBox
.State
)
854 Crosshair
.AttachedBox
.Point2
.X
= Crosshair
.X
;
855 Crosshair
.AttachedBox
.Point2
.Y
= Crosshair
.Y
;
859 /* rectangle creation mode */
862 AdjustAttachedBox ();
865 /* polygon creation mode */
867 case POLYGONHOLE_MODE
:
868 AdjustAttachedLine ();
870 /* line creation mode */
872 if (PCB
->RatDraw
|| PCB
->Clipping
== 0)
873 AdjustAttachedLine ();
875 AdjustTwoLine (PCB
->Clipping
- 1);
877 /* point insertion mode */
878 case INSERTPOINT_MODE
:
879 pnt
= AdjustInsertPoint ();
881 InsertedPoint
= *pnt
;
889 * \brief Creates points of a line.
895 void *ptr1
, *ptr2
, *ptr3
;
897 if (!Marked
.status
|| TEST_FLAG (LOCALREFFLAG
, PCB
))
898 SetLocalRef (Crosshair
.X
, Crosshair
.Y
, true);
899 switch (Crosshair
.AttachedLine
.State
)
901 case STATE_FIRST
: /* first point */
902 if (PCB
->RatDraw
&& SearchScreen (Crosshair
.X
, Crosshair
.Y
,
903 PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr1
,
909 if (Settings
.Mode
== LINE_MODE
)
911 if (TEST_FLAG (AUTODRCFLAG
, PCB
))
913 type
= SearchScreen (Crosshair
.X
, Crosshair
.Y
,
914 PIN_TYPE
| PAD_TYPE
| VIA_TYPE
, &ptr1
, &ptr2
,
916 LookupConnection (Crosshair
.X
, Crosshair
.Y
, true, 1, CONNECTEDFLAG
, false, true);
917 LookupConnection (Crosshair
.X
, Crosshair
.Y
, true, 1, FOUNDFLAG
, true, true);
918 /* XXX: What about undo serial number? */
920 /* XXX: NEED TO FIGURE OUT WHAT NET CLASS THIS IS, AND/OR STORE FOR USE WITH DRC */
921 // Crosshair.Netclass = get_netclass_at_xy (LAYER_ON_STACK(0), Crosshair.X, Crosshair.Y); /* XXX: Not sure about the layer! */
922 // PCB->Bloat = get_min_clearance_for_netclass (Crosshair.Netclass);
924 if (type
== PIN_TYPE
|| type
== VIA_TYPE
)
926 Crosshair
.AttachedLine
.Point1
.X
=
927 Crosshair
.AttachedLine
.Point2
.X
= ((PinType
*) ptr2
)->X
;
928 Crosshair
.AttachedLine
.Point1
.Y
=
929 Crosshair
.AttachedLine
.Point2
.Y
= ((PinType
*) ptr2
)->Y
;
931 else if (type
== PAD_TYPE
)
933 PadType
*pad
= (PadType
*) ptr2
;
934 double d1
= Distance (Crosshair
.X
, Crosshair
.Y
, pad
->Point1
.X
, pad
->Point1
.Y
);
935 double d2
= Distance (Crosshair
.X
, Crosshair
.Y
, pad
->Point2
.X
, pad
->Point2
.Y
);
938 Crosshair
.AttachedLine
.Point1
=
939 Crosshair
.AttachedLine
.Point2
= pad
->Point2
;
943 Crosshair
.AttachedLine
.Point1
=
944 Crosshair
.AttachedLine
.Point2
= pad
->Point1
;
949 Crosshair
.AttachedLine
.Point1
.X
=
950 Crosshair
.AttachedLine
.Point2
.X
= Crosshair
.X
;
951 Crosshair
.AttachedLine
.Point1
.Y
=
952 Crosshair
.AttachedLine
.Point2
.Y
= Crosshair
.Y
;
954 Crosshair
.AttachedLine
.State
= STATE_SECOND
;
958 /* fall through to third state too */
960 default: /* all following points */
961 Crosshair
.AttachedLine
.State
= STATE_THIRD
;
967 * \brief Create first or second corner of a marked block.
972 notify_crosshair_change (false);
973 switch (Crosshair
.AttachedBox
.State
)
975 case STATE_FIRST
: /* setup first point */
976 Crosshair
.AttachedBox
.Point1
.X
=
977 Crosshair
.AttachedBox
.Point2
.X
= Crosshair
.X
;
978 Crosshair
.AttachedBox
.Point1
.Y
=
979 Crosshair
.AttachedBox
.Point2
.Y
= Crosshair
.Y
;
980 Crosshair
.AttachedBox
.State
= STATE_SECOND
;
983 case STATE_SECOND
: /* setup second point */
984 Crosshair
.AttachedBox
.State
= STATE_THIRD
;
987 notify_crosshair_change (true);
992 * \brief This is called after every mode change, like mouse button pressed,
993 * mouse button released, dragging something started or a different tool
996 * It does what's appropriate for the current mode setting.
997 * This can also mean creation of an object at the current crosshair location.
999 * New created objects are added to the create undo list of course.
1004 void *ptr1
, *ptr2
, *ptr3
;
1007 if (Settings
.RatWarn
)
1009 switch (Settings
.Mode
)
1017 /* do something after click time */
1018 gui
->add_timer (click_cb
, CLICK_TIME
, hv
);
1020 /* see if we clicked on something already selected
1021 * (Note.Moving) or clicked on a MOVE_TYPE
1024 for (test
= (SELECT_TYPES
| MOVE_TYPES
) & ~RATLINE_TYPE
;
1025 test
; test
&= ~type
)
1027 type
= SearchScreen (Note
.X
, Note
.Y
, test
, &ptr1
, &ptr2
, &ptr3
);
1028 if (!Note
.Hit
&& (type
& MOVE_TYPES
) &&
1029 !TEST_FLAG (LOCKFLAG
, (PinType
*) ptr2
))
1036 if (!Note
.Moving
&& (type
& SELECT_TYPES
) &&
1037 TEST_FLAG (SELECTEDFLAG
, (PinType
*) ptr2
))
1039 if ((Note
.Hit
&& Note
.Moving
) || type
== NO_TYPE
)
1051 Message (_("You must turn via visibility on before\n"
1052 "you can place vias\n"));
1055 if ((via
= CreateNewVia (PCB
->Data
, Note
.X
, Note
.Y
,
1056 Settings
.ViaThickness
, 2 * Settings
.Keepaway
,
1057 0, Settings
.ViaDrillingHole
, NULL
,
1058 NoFlags ())) != NULL
)
1060 AddObjectToCreateUndoList (VIA_TYPE
, via
, via
, via
);
1061 if (gui
->shift_is_pressed ())
1062 ChangeObjectThermal (VIA_TYPE
, via
, via
, via
, PCB
->ThermStyle
);
1063 IncrementUndoSerialNumber ();
1072 switch (Crosshair
.AttachedBox
.State
)
1075 Crosshair
.AttachedBox
.Point1
.X
=
1076 Crosshair
.AttachedBox
.Point2
.X
= Note
.X
;
1077 Crosshair
.AttachedBox
.Point1
.Y
=
1078 Crosshair
.AttachedBox
.Point2
.Y
= Note
.Y
;
1079 Crosshair
.AttachedBox
.State
= STATE_SECOND
;
1089 wx
= Note
.X
- Crosshair
.AttachedBox
.Point1
.X
;
1090 wy
= Note
.Y
- Crosshair
.AttachedBox
.Point1
.Y
;
1091 if (XOR (Crosshair
.AttachedBox
.otherway
, abs (wy
) > abs (wx
)))
1093 Crosshair
.AttachedBox
.Point2
.X
=
1094 Crosshair
.AttachedBox
.Point1
.X
+ abs (wy
) * SGNZ (wx
);
1095 sa
= (wx
>= 0) ? 0 : 180;
1097 if (abs (wy
) / 2 >= abs (wx
))
1098 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 45 : -45;
1101 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 90 : -90;
1105 Crosshair
.AttachedBox
.Point2
.Y
=
1106 Crosshair
.AttachedBox
.Point1
.Y
+ abs (wx
) * SGNZ (wy
);
1107 sa
= (wy
>= 0) ? -90 : 90;
1109 if (abs (wx
) / 2 >= abs (wy
))
1110 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -45 : 45;
1113 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -90 : 90;
1116 if (abs (wy
) > 0 && (arc
= CreateNewArcOnLayer (CURRENT
,
1140 bx
= GetArcEnds (arc
);
1141 Crosshair
.AttachedBox
.Point1
.X
=
1142 Crosshair
.AttachedBox
.Point2
.X
= bx
->X2
;
1143 Crosshair
.AttachedBox
.Point1
.Y
=
1144 Crosshair
.AttachedBox
.Point2
.Y
= bx
->Y2
;
1145 AddObjectToCreateUndoList (ARC_TYPE
, CURRENT
, arc
, arc
);
1146 IncrementUndoSerialNumber ();
1148 DrawArc (CURRENT
, arc
);
1150 Crosshair
.AttachedBox
.State
= STATE_THIRD
;
1159 type
= SearchScreen (Note
.X
, Note
.Y
, LOCK_TYPES
, &ptr1
, &ptr2
, &ptr3
);
1160 if (type
== ELEMENT_TYPE
)
1162 ElementType
*element
= (ElementType
*) ptr2
;
1164 TOGGLE_FLAG (LOCKFLAG
, element
);
1167 TOGGLE_FLAG (LOCKFLAG
, pin
);
1168 CLEAR_FLAG (SELECTEDFLAG
, pin
);
1173 TOGGLE_FLAG (LOCKFLAG
, pad
);
1174 CLEAR_FLAG (SELECTEDFLAG
, pad
);
1177 CLEAR_FLAG (SELECTEDFLAG
, element
);
1178 /* always re-draw it since I'm too lazy
1179 * to tell if a selected flag changed
1181 DrawElement (element
);
1183 SetChangedFlag (true);
1185 else if (type
!= NO_TYPE
)
1187 TextType
*thing
= (TextType
*) ptr3
;
1188 TOGGLE_FLAG (LOCKFLAG
, thing
);
1189 if (TEST_FLAG (LOCKFLAG
, thing
)
1190 && TEST_FLAG (SELECTEDFLAG
, thing
))
1192 /* this is not un-doable since LOCK isn't */
1193 CLEAR_FLAG (SELECTEDFLAG
, thing
);
1194 DrawObject (type
, ptr1
, ptr2
);
1197 SetChangedFlag (true);
1205 SearchScreen (Note
.X
, Note
.Y
, PIN_TYPES
, &ptr1
, &ptr2
,
1207 && !TEST_FLAG (HOLEFLAG
, (PinType
*) ptr3
))
1209 if (gui
->shift_is_pressed ())
1211 int tstyle
= GET_THERM (INDEXOFCURRENT
, (PinType
*) ptr3
);
1215 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, tstyle
);
1217 else if (GET_THERM (INDEXOFCURRENT
, (PinType
*) ptr3
))
1218 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, 0);
1220 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, PCB
->ThermStyle
);
1226 /* do update of position */
1228 if (Crosshair
.AttachedLine
.State
!= STATE_THIRD
)
1231 /* Remove anchor if clicking on start point;
1232 * this means we can't paint 0 length lines
1233 * which could be used for square SMD pads.
1234 * Instead use a very small delta, or change
1235 * the file after saving.
1237 if (Crosshair
.X
== Crosshair
.AttachedLine
.Point1
.X
1238 && Crosshair
.Y
== Crosshair
.AttachedLine
.Point1
.Y
)
1240 SetMode (LINE_MODE
);
1247 if ((line
= AddNet ()))
1250 AddObjectToCreateUndoList (RATLINE_TYPE
, line
, line
, line
);
1251 IncrementUndoSerialNumber ();
1253 Crosshair
.AttachedLine
.Point1
.X
=
1254 Crosshair
.AttachedLine
.Point2
.X
;
1255 Crosshair
.AttachedLine
.Point1
.Y
=
1256 Crosshair
.AttachedLine
.Point2
.Y
;
1262 /* create line if both ends are determined && length != 0 */
1267 if (TEST_FLAG (AUTODRCFLAG
, PCB
) && !TEST_SILK_LAYER (CURRENT
))
1268 line_flags
|= CONNECTEDFLAG
| FOUNDFLAG
;
1270 if (TEST_FLAG (CLEARNEWFLAG
, PCB
))
1271 line_flags
|= CLEARLINEFLAG
;
1274 && Crosshair
.AttachedLine
.Point1
.X
==
1275 Crosshair
.AttachedLine
.Point2
.X
1276 && Crosshair
.AttachedLine
.Point1
.Y
==
1277 Crosshair
.AttachedLine
.Point2
.Y
1278 && (Crosshair
.AttachedLine
.Point2
.X
!= Note
.X
1279 || Crosshair
.AttachedLine
.Point2
.Y
!= Note
.Y
))
1281 /* We will only need to paint the second line segment.
1282 Since we only check for vias on the first segment,
1283 swap them so the non-empty segment is the first segment. */
1284 Crosshair
.AttachedLine
.Point2
.X
= Note
.X
;
1285 Crosshair
.AttachedLine
.Point2
.Y
= Note
.Y
;
1288 if ((Crosshair
.AttachedLine
.Point1
.X
!=
1289 Crosshair
.AttachedLine
.Point2
.X
1290 || Crosshair
.AttachedLine
.Point1
.Y
!=
1291 Crosshair
.AttachedLine
.Point2
.Y
))
1294 Cardinal last_layer_num
, current_layer_num
;
1295 Cardinal layer_from
, layer_to
;
1298 CreateDrawnLineOnLayer (CURRENT
,
1299 Crosshair
.AttachedLine
.Point1
.X
,
1300 Crosshair
.AttachedLine
.Point1
.Y
,
1301 Crosshair
.AttachedLine
.Point2
.X
,
1302 Crosshair
.AttachedLine
.Point2
.Y
,
1303 Settings
.LineThickness
,
1304 2 * Settings
.Keepaway
,
1305 MakeFlags (line_flags
))) != NULL
)
1308 AddObjectToCreateUndoList (LINE_TYPE
, CURRENT
, line
, line
);
1309 DrawLine (CURRENT
, line
);
1311 /* place a via if vias are visible, the layer is
1312 in a new group since the last line and there
1313 isn't a pin already here */
1314 if (TEST_FLAG (AUTOBURIEDVIASFLAG
, PCB
))
1316 layer_from
= GetLayerNumber (PCB
->Data
, lastLayer
);
1317 layer_to
= GetLayerNumber (PCB
->Data
, CURRENT
);
1319 layer_from
= MIN (last_layer_num
, current_layer_num
);
1320 layer_to
= MAX (last_layer_num
, current_layer_num
);
1328 if (PCB
->ViaOn
&& GetLayerGroupNumberByPointer (CURRENT
) !=
1329 GetLayerGroupNumberByPointer (lastLayer
) &&
1330 SearchObjectByLocation (PIN_TYPES
, &ptr1
, &ptr2
, &ptr3
,
1331 Crosshair
.AttachedLine
.Point1
.X
,
1332 Crosshair
.AttachedLine
.Point1
.Y
,
1333 Settings
.ViaThickness
/ 2) ==
1336 CreateNewViaEx (PCB
->Data
,
1337 Crosshair
.AttachedLine
.Point1
.X
,
1338 Crosshair
.AttachedLine
.Point1
.Y
,
1339 Settings
.ViaThickness
,
1340 2 * Settings
.Keepaway
, 0,
1341 Settings
.ViaDrillingHole
, NULL
,
1342 NoFlags (), layer_from
, layer_to
)) != NULL
)
1344 AddObjectToCreateUndoList (VIA_TYPE
, via
, via
, via
);
1347 /* copy the coordinates */
1348 Crosshair
.AttachedLine
.Point1
.X
=
1349 Crosshair
.AttachedLine
.Point2
.X
;
1350 Crosshair
.AttachedLine
.Point1
.Y
=
1351 Crosshair
.AttachedLine
.Point2
.Y
;
1352 IncrementUndoSerialNumber ();
1353 lastLayer
= CURRENT
;
1355 if (PCB
->Clipping
&& (Note
.X
!= Crosshair
.AttachedLine
.Point2
.X
1357 Crosshair
.AttachedLine
.Point2
.Y
))
1360 CreateDrawnLineOnLayer (CURRENT
,
1361 Crosshair
.AttachedLine
.Point2
.X
,
1362 Crosshair
.AttachedLine
.Point2
.Y
,
1364 Settings
.LineThickness
,
1365 2 * Settings
.Keepaway
,
1366 MakeFlags (line_flags
))) != NULL
)
1369 AddObjectToCreateUndoList (LINE_TYPE
, CURRENT
, line
, line
);
1370 IncrementUndoSerialNumber ();
1371 DrawLine (CURRENT
, line
);
1373 /* move to new start point */
1374 Crosshair
.AttachedLine
.Point1
.X
= Note
.X
;
1375 Crosshair
.AttachedLine
.Point1
.Y
= Note
.Y
;
1376 Crosshair
.AttachedLine
.Point2
.X
= Note
.X
;
1377 Crosshair
.AttachedLine
.Point2
.Y
= Note
.Y
;
1378 if (TEST_FLAG (SWAPSTARTDIRFLAG
, PCB
))
1383 if (TEST_FLAG (AUTODRCFLAG
, PCB
) && !TEST_SILK_LAYER (CURRENT
))
1384 LookupConnection (Note
.X
, Note
.Y
, true, 1, CONNECTEDFLAG
, false, true);
1389 case RECTANGLE_MODE
:
1390 /* do update of position */
1393 /* create rectangle if both corners are determined
1394 * and width, height are != 0
1396 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
&&
1397 Crosshair
.AttachedBox
.Point1
.X
!= Crosshair
.AttachedBox
.Point2
.X
&&
1398 Crosshair
.AttachedBox
.Point1
.Y
!= Crosshair
.AttachedBox
.Point2
.Y
)
1400 PolygonType
*polygon
;
1402 int flags
= CLEARPOLYFLAG
;
1403 if (TEST_FLAG (NEWFULLPOLYFLAG
, PCB
))
1404 flags
|= FULLPOLYFLAG
;
1405 if ((polygon
= CreateNewPolygonFromRectangle (CURRENT
,
1407 AttachedBox
.Point1
.X
,
1409 AttachedBox
.Point1
.Y
,
1411 AttachedBox
.Point2
.X
,
1413 AttachedBox
.Point2
.Y
,
1418 AddObjectToCreateUndoList (POLYGON_TYPE
, CURRENT
,
1420 IncrementUndoSerialNumber ();
1421 DrawPolygon (CURRENT
, polygon
);
1425 /* reset state to 'first corner' */
1426 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
1434 if ((string
= gui
->prompt_for (_("Enter text:"), "")) != NULL
)
1436 if (strlen(string
) > 0)
1439 int flag
= CLEARLINEFLAG
;
1441 if (GetLayerGroupNumberByNumber (INDEXOFCURRENT
) ==
1442 GetLayerGroupNumberBySide (BOTTOM_SIDE
))
1443 flag
|= ONSOLDERFLAG
;
1444 if ((text
= CreateNewText (CURRENT
, &PCB
->Font
, Note
.X
,
1445 Note
.Y
, 0, Settings
.TextScale
,
1446 string
, MakeFlags (flag
))) != NULL
)
1448 AddObjectToCreateUndoList (TEXT_TYPE
, CURRENT
, text
, text
);
1449 IncrementUndoSerialNumber ();
1450 DrawText (CURRENT
, text
);
1461 PointType
*points
= Crosshair
.AttachedPolygon
.Points
;
1462 Cardinal n
= Crosshair
.AttachedPolygon
.PointN
;
1464 /* do update of position; use the 'LINE_MODE' mechanism */
1467 /* check if this is the last point of a polygon */
1469 points
->X
== Crosshair
.AttachedLine
.Point2
.X
&&
1470 points
->Y
== Crosshair
.AttachedLine
.Point2
.Y
)
1472 CopyAttachedPolygonToLayer ();
1477 /* create new point if it's the first one or if it's
1478 * different to the last one
1481 points
[n
- 1].X
!= Crosshair
.AttachedLine
.Point2
.X
||
1482 points
[n
- 1].Y
!= Crosshair
.AttachedLine
.Point2
.Y
)
1484 CreateNewPointInPolygon (&Crosshair
.AttachedPolygon
,
1485 Crosshair
.AttachedLine
.Point2
.X
,
1486 Crosshair
.AttachedLine
.Point2
.Y
,
1489 /* copy the coordinates */
1490 Crosshair
.AttachedLine
.Point1
.X
= Crosshair
.AttachedLine
.Point2
.X
;
1491 Crosshair
.AttachedLine
.Point1
.Y
= Crosshair
.AttachedLine
.Point2
.Y
;
1496 case POLYGONHOLE_MODE
:
1498 switch (Crosshair
.AttachedObject
.State
)
1500 /* first notify, lookup object */
1502 Crosshair
.AttachedObject
.Type
=
1503 SearchScreen (Note
.X
, Note
.Y
, POLYGON_TYPE
,
1504 &Crosshair
.AttachedObject
.Ptr1
,
1505 &Crosshair
.AttachedObject
.Ptr2
,
1506 &Crosshair
.AttachedObject
.Ptr3
);
1508 if (Crosshair
.AttachedObject
.Type
== NO_TYPE
)
1510 Message (_("The first point of a polygon hole must be on a polygon.\n"));
1511 break; /* don't start doing anything if clicked outside of polys */
1514 if (TEST_FLAG(LOCKFLAG
, (PolygonType
*) Crosshair
.AttachedObject
.Ptr2
))
1516 Message (_("Sorry, the object is locked\n"));
1517 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1521 Crosshair
.AttachedObject
.State
= STATE_SECOND
;
1522 /* Fall thru: first click is also the first point of the
1525 /* second notify, insert new point into object */
1528 PointType
*points
= Crosshair
.AttachedPolygon
.Points
;
1529 Cardinal n
= Crosshair
.AttachedPolygon
.PointN
;
1530 POLYAREA
*original
, *new_hole
, *result
;
1533 /* do update of position; use the 'LINE_MODE' mechanism */
1536 /* check if this is the last point of a polygon */
1538 points
->X
== Crosshair
.AttachedLine
.Point2
.X
&&
1539 points
->Y
== Crosshair
.AttachedLine
.Point2
.Y
)
1541 /* Create POLYAREAs from the original polygon
1542 * and the new hole polygon */
1543 original
= PolygonToPoly ((PolygonType
*)Crosshair
.AttachedObject
.Ptr2
);
1544 new_hole
= PolygonToPoly (&Crosshair
.AttachedPolygon
);
1546 /* Subtract the hole from the original polygon shape */
1547 poly_Boolean_free (original
, new_hole
, &result
, PBO_SUB
);
1549 /* Convert the resulting polygon(s) into a new set of nodes
1550 * and place them on the page. Delete the original polygon.
1552 SaveUndoSerialNumber ();
1553 Flags
= ((PolygonType
*)Crosshair
.AttachedObject
.Ptr2
)->Flags
;
1554 PolyToPolygonsOnLayer (PCB
->Data
, (LayerType
*)Crosshair
.AttachedObject
.Ptr1
,
1556 RemoveObject (POLYGON_TYPE
,
1557 Crosshair
.AttachedObject
.Ptr1
,
1558 Crosshair
.AttachedObject
.Ptr2
,
1559 Crosshair
.AttachedObject
.Ptr3
);
1560 RestoreUndoSerialNumber ();
1561 IncrementUndoSerialNumber ();
1564 /* reset state of attached line */
1565 memset (&Crosshair
.AttachedPolygon
, 0, sizeof (PolygonType
));
1566 Crosshair
.AttachedObject
.State
= STATE_FIRST
;
1572 /* create new point if it's the first one or if it's
1573 * different to the last one
1576 points
[n
- 1].X
!= Crosshair
.AttachedLine
.Point2
.X
||
1577 points
[n
- 1].Y
!= Crosshair
.AttachedLine
.Point2
.Y
)
1579 CreateNewPointInPolygon (&Crosshair
.AttachedPolygon
,
1580 Crosshair
.AttachedLine
.Point2
.X
,
1581 Crosshair
.AttachedLine
.Point2
.Y
,
1584 /* copy the coordinates */
1585 Crosshair
.AttachedLine
.Point1
.X
= Crosshair
.AttachedLine
.Point2
.X
;
1586 Crosshair
.AttachedLine
.Point1
.Y
= Crosshair
.AttachedLine
.Point2
.Y
;
1595 case PASTEBUFFER_MODE
:
1597 TextType estr
[MAX_ELEMENTNAMES
];
1600 if (gui
->shift_is_pressed ())
1603 SearchScreen (Note
.X
, Note
.Y
, ELEMENT_TYPE
, &ptr1
, &ptr2
,
1605 if (type
== ELEMENT_TYPE
)
1607 e
= (ElementType
*) ptr1
;
1612 memcpy (estr
, e
->Name
,
1613 MAX_ELEMENTNAMES
* sizeof (TextType
));
1614 for (i
= 0; i
< MAX_ELEMENTNAMES
; ++i
)
1615 estr
[i
].TextString
= estr
[i
].TextString
? strdup(estr
[i
].TextString
) : NULL
;
1620 if (CopyPastebufferToLayout (Note
.X
, Note
.Y
))
1621 SetChangedFlag (true);
1625 SearchScreen (Note
.X
, Note
.Y
, ELEMENT_TYPE
, &ptr1
, &ptr2
,
1627 if (type
== ELEMENT_TYPE
&& ptr1
)
1630 e
= (ElementType
*) ptr1
;
1632 save_n
= NAME_INDEX (PCB
);
1634 for (i
= 0; i
< MAX_ELEMENTNAMES
; i
++)
1637 EraseElementName (e
);
1638 r_delete_entry (PCB
->Data
->name_tree
[i
],
1639 (BoxType
*) & (e
->Name
[i
]));
1640 memcpy (&(e
->Name
[i
]), &(estr
[i
]), sizeof (TextType
));
1641 e
->Name
[i
].Element
= e
;
1642 SetTextBoundingBox (&PCB
->Font
, &(e
->Name
[i
]));
1643 r_insert_entry (PCB
->Data
->name_tree
[i
],
1644 (BoxType
*) & (e
->Name
[i
]), 0);
1646 DrawElementName (e
);
1655 SearchScreen (Note
.X
, Note
.Y
, REMOVE_TYPES
, &ptr1
, &ptr2
,
1658 if (TEST_FLAG (LOCKFLAG
, (LineType
*) ptr2
))
1660 Message (_("Sorry, the object is locked\n"));
1663 if (type
== ELEMENT_TYPE
)
1665 RubberbandType
*ptr
;
1668 Crosshair
.AttachedObject
.RubberbandN
= 0;
1669 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
1670 ptr
= Crosshair
.AttachedObject
.Rubberband
;
1671 for (i
= 0; i
< Crosshair
.AttachedObject
.RubberbandN
; i
++)
1674 EraseRat ((RatType
*) ptr
->Line
);
1675 if (TEST_FLAG (RUBBERENDFLAG
, ptr
->Line
))
1676 MoveObjectToRemoveUndoList (RATLINE_TYPE
,
1677 ptr
->Line
, ptr
->Line
,
1680 TOGGLE_FLAG (RUBBERENDFLAG
, ptr
->Line
); /* only remove line once */
1684 RemoveObject (type
, ptr1
, ptr2
, ptr3
);
1685 IncrementUndoSerialNumber ();
1686 SetChangedFlag (true);
1691 RotateScreenObject (Note
.X
, Note
.Y
,
1692 gui
->shift_is_pressed ()? (SWAP_IDENT
?
1694 : (SWAP_IDENT
? 3 : 1));
1697 /* both are almost the same */
1700 switch (Crosshair
.AttachedObject
.State
)
1702 /* first notify, lookup object */
1705 int types
= (Settings
.Mode
== COPY_MODE
) ?
1706 COPY_TYPES
: MOVE_TYPES
;
1708 Crosshair
.AttachedObject
.Type
=
1709 SearchScreen (Note
.X
, Note
.Y
, types
,
1710 &Crosshair
.AttachedObject
.Ptr1
,
1711 &Crosshair
.AttachedObject
.Ptr2
,
1712 &Crosshair
.AttachedObject
.Ptr3
);
1713 if (Crosshair
.AttachedObject
.Type
!= NO_TYPE
)
1715 if (Settings
.Mode
== MOVE_MODE
&&
1716 TEST_FLAG (LOCKFLAG
, (PinType
*)
1717 Crosshair
.AttachedObject
.Ptr2
))
1719 Message (_("Sorry, the object is locked\n"));
1720 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1723 AttachForCopy (Note
.X
, Note
.Y
);
1728 /* second notify, move or copy object */
1730 if (Settings
.Mode
== COPY_MODE
)
1731 CopyObject (Crosshair
.AttachedObject
.Type
,
1732 Crosshair
.AttachedObject
.Ptr1
,
1733 Crosshair
.AttachedObject
.Ptr2
,
1734 Crosshair
.AttachedObject
.Ptr3
,
1735 Note
.X
- Crosshair
.AttachedObject
.X
,
1736 Note
.Y
- Crosshair
.AttachedObject
.Y
);
1739 MoveObjectAndRubberband (Crosshair
.AttachedObject
.Type
,
1740 Crosshair
.AttachedObject
.Ptr1
,
1741 Crosshair
.AttachedObject
.Ptr2
,
1742 Crosshair
.AttachedObject
.Ptr3
,
1743 Note
.X
- Crosshair
.AttachedObject
.X
,
1744 Note
.Y
- Crosshair
.AttachedObject
.Y
);
1745 SetLocalRef (0, 0, false);
1747 SetChangedFlag (true);
1749 /* reset identifiers */
1750 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1751 Crosshair
.AttachedObject
.State
= STATE_FIRST
;
1756 /* insert a point into a polygon/line/... */
1757 case INSERTPOINT_MODE
:
1758 switch (Crosshair
.AttachedObject
.State
)
1760 /* first notify, lookup object */
1762 Crosshair
.AttachedObject
.Type
=
1763 SearchScreen (Note
.X
, Note
.Y
, INSERT_TYPES
,
1764 &Crosshair
.AttachedObject
.Ptr1
,
1765 &Crosshair
.AttachedObject
.Ptr2
,
1766 &Crosshair
.AttachedObject
.Ptr3
);
1768 if (Crosshair
.AttachedObject
.Type
!= NO_TYPE
)
1770 if (TEST_FLAG (LOCKFLAG
, (PolygonType
*)
1771 Crosshair
.AttachedObject
.Ptr2
))
1773 Message (_("Sorry, the object is locked\n"));
1774 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1779 /* get starting point of nearest segment */
1780 if (Crosshair
.AttachedObject
.Type
== POLYGON_TYPE
)
1783 (PolygonType
*) Crosshair
.AttachedObject
.Ptr2
;
1785 GetLowestDistancePolygonPoint (fake
.poly
, Note
.X
,
1787 fake
.line
.Point1
= fake
.poly
->Points
[polyIndex
];
1788 fake
.line
.Point2
= fake
.poly
->Points
[
1789 prev_contour_point (fake
.poly
, polyIndex
)];
1790 Crosshair
.AttachedObject
.Ptr2
= &fake
.line
;
1793 Crosshair
.AttachedObject
.State
= STATE_SECOND
;
1794 InsertedPoint
= *AdjustInsertPoint ();
1799 /* second notify, insert new point into object */
1801 if (Crosshair
.AttachedObject
.Type
== POLYGON_TYPE
)
1802 InsertPointIntoObject (POLYGON_TYPE
,
1803 Crosshair
.AttachedObject
.Ptr1
, fake
.poly
,
1805 InsertedPoint
.X
, InsertedPoint
.Y
, 0, false, false);
1807 InsertPointIntoObject (Crosshair
.AttachedObject
.Type
,
1808 Crosshair
.AttachedObject
.Ptr1
,
1809 Crosshair
.AttachedObject
.Ptr2
,
1811 InsertedPoint
.X
, InsertedPoint
.Y
, 0, false, false);
1812 SetChangedFlag (true);
1814 /* reset identifiers */
1815 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1816 Crosshair
.AttachedObject
.State
= STATE_FIRST
;
1824 /* --------------------------------------------------------------------------- */
1826 static const char atomic_syntax
[] = N_("Atomic(Save|Restore|Close|Block)");
1828 static const char atomic_help
[] = N_("Save or restore the undo serial number.");
1830 /* %start-doc actions Atomic
1832 This action allows making multiple-action bindings into an atomic
1833 operation that will be undone by a single Undo command. For example,
1834 to optimize rat lines, you'd delete the rats and re-add them. To
1835 group these into a single undo, you'd want the deletions and the
1836 additions to have the same undo serial number. So, you @code{Save},
1837 delete the rats, @code{Restore}, add the rats - using the same serial
1838 number as the deletes, then @code{Block}, which checks to see if the
1839 deletions or additions actually did anything. If not, the serial
1840 number is set to the saved number, as there's nothing to undo. If
1841 something did happen, the serial number is incremented so that these
1842 actions are counted as a single undo step.
1847 Saves the undo serial number.
1850 Returns it to the last saved number.
1853 Sets it to 1 greater than the last save.
1856 Does a Restore if there was nothing to undo, else does a Close.
1863 ActionAtomic (int argc
, char **argv
, Coord x
, Coord y
)
1868 switch (GetFunctionID (argv
[0]))
1871 SaveUndoSerialNumber ();
1874 RestoreUndoSerialNumber ();
1877 RestoreUndoSerialNumber ();
1878 IncrementUndoSerialNumber ();
1881 RestoreUndoSerialNumber ();
1883 IncrementUndoSerialNumber ();
1889 /* -------------------------------------------------------------------------- */
1891 static const char drc_syntax
[] = N_("DRC()");
1893 static const char drc_help
[] = N_("Invoke the DRC check.");
1895 /* %start-doc actions DRC
1897 Note that the design rule check uses the current board rule settings,
1898 not the current style settings.
1903 ActionDRCheck (int argc
, char **argv
, Coord x
, Coord y
)
1907 if (gui
->drc_gui
== NULL
|| gui
->drc_gui
->log_drc_overview
)
1909 Message (_("%m+Rules are minspace %$mS, minoverlap %$mS "
1910 "minwidth %$mS, minsilk %$mS\n"
1911 "min drill %$mS, min annular ring %$mS\n"),
1912 Settings
.grid_unit
->allow
,
1913 PCB
->Bloat
, PCB
->Shrink
,
1914 PCB
->minWid
, PCB
->minSlk
,
1915 PCB
->minDrill
, PCB
->minRing
);
1918 if (gui
->drc_gui
== NULL
|| gui
->drc_gui
->log_drc_overview
)
1921 Message (_("No DRC problems found.\n"));
1923 Message (_("Found %d design rule errors.\n"), count
);
1925 Message (_("Aborted DRC after %d design rule errors.\n"), -count
);
1930 /* -------------------------------------------------------------------------- */
1932 static const char dumplibrary_syntax
[] = N_("DumpLibrary()");
1934 static const char dumplibrary_help
[] =
1935 N_("Display the entire contents of the libraries.");
1937 /* %start-doc actions DumpLibrary
1943 ActionDumpLibrary (int argc
, char **argv
, Coord x
, Coord y
)
1947 printf ("**** Do not count on this format. It will change ****\n\n");
1948 printf ("MenuN = %d\n", (int) Library
.MenuN
);
1949 printf ("MenuMax = %d\n", (int) Library
.MenuMax
);
1950 for (i
= 0; i
< Library
.MenuN
; i
++)
1952 printf ("Library #%d:\n", i
);
1953 printf (" EntryN = %d\n", (int) Library
.Menu
[i
].EntryN
);
1954 printf (" EntryMax = %d\n", (int) Library
.Menu
[i
].EntryMax
);
1955 printf (" Name = \"%s\"\n", UNKNOWN (Library
.Menu
[i
].Name
));
1956 printf (" directory = \"%s\"\n",
1957 UNKNOWN (Library
.Menu
[i
].directory
));
1958 printf (" Style = \"%s\"\n", UNKNOWN (Library
.Menu
[i
].Style
));
1959 printf (" flag = %d\n", Library
.Menu
[i
].flag
);
1961 for (j
= 0; j
< Library
.Menu
[i
].EntryN
; j
++)
1963 printf (" #%4d: ", j
);
1964 if (Library
.Menu
[i
].Entry
[j
].Template
== (char *) -1)
1966 printf ("newlib: \"%s\"\n",
1967 UNKNOWN (Library
.Menu
[i
].Entry
[j
].ListEntry
));
1971 printf ("\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"\n",
1972 UNKNOWN (Library
.Menu
[i
].Entry
[j
].ListEntry
),
1973 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Template
),
1974 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Package
),
1975 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Value
),
1976 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Description
));
1984 /* -------------------------------------------------------------------------- */
1986 static const char flip_syntax
[] = N_("Flip(Object|Selected|SelectedElements)");
1988 static const char flip_help
[] =
1989 N_("Flip an element to the opposite side of the board.");
1991 /* %start-doc actions Flip
1993 Note that the location of the element will be symmetric about the
1994 cursor location; i.e. if the part you are pointing at will still be at
1995 the same spot once the element is on the other side. When flipping
1996 multiple elements, this retains their positions relative to each
1997 other, not their absolute positions on the board.
2002 ActionFlip (int argc
, char **argv
, Coord x
, Coord y
)
2004 char *function
= ARG (0);
2005 ElementType
*element
;
2011 switch (GetFunctionID (function
))
2014 if ((SearchScreen (x
, y
, ELEMENT_TYPE
,
2015 &ptrtmp
, &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
2017 element
= (ElementType
*) ptrtmp
;
2018 ChangeElementSide (element
, 2 * Crosshair
.Y
- PCB
->MaxHeight
);
2019 IncrementUndoSerialNumber ();
2024 case F_SelectedElements
:
2025 ChangeSelectedElementSide ();
2038 /* -------------------------------------------------------------------------- */
2040 static const char message_syntax
[] = N_("Message(message)");
2042 static const char message_help
[] = N_("Writes a message to the log window.");
2044 /* %start-doc actions Message
2046 This action displays a message to the log window. This action is primarily
2047 provided for use by other programs which may interface with PCB. If
2048 multiple arguments are given, each one is sent to the log window
2049 followed by a newline.
2054 ActionMessage (int argc
, char **argv
, Coord x
, Coord y
)
2061 for (i
= 0; i
< argc
; i
++)
2071 /* -------------------------------------------------------------------------- */
2073 static const char setthermal_syntax
[] =
2074 "SetThermal(Object|SelectedPins|SelectedVias|Selected, Style)";
2076 static const char setthermal_help
[] =
2077 N_("Set the thermal (on the current layer) of pins or vias to the given style.\n"
2078 "Style = 0 means no thermal.\n"
2079 "Style = 1 has diagonal fingers with sharp edges.\n"
2080 "Style = 2 has horizontal and vertical fingers with sharp edges.\n"
2081 "Style = 3 is a solid connection to the plane.\n"
2082 "Style = 4 has diagonal fingers with rounded edges.\n"
2083 "Style = 5 has horizontal and vertical fingers with rounded edges.\n");
2085 /* %start-doc actions SetThermal
2087 This changes how/whether pins or vias connect to any rectangle or polygon
2088 on the current layer. The first argument can specify one object, or all
2089 selected pins, or all selected vias, or all selected pins and vias.
2090 The second argument specifies the style of connection.
2091 There are 5 possibilities:
2093 1 - 45 degree fingers with sharp edges,
2094 2 - horizontal & vertical fingers with sharp edges,
2095 3 - solid connection,
2096 4 - 45 degree fingers with rounded corners,
2097 5 - horizontal & vertical fingers with rounded corners.
2099 Pins and Vias may have thermals whether or not there is a polygon available
2100 to connect with. However, they will have no effect without the polygon.
2104 ActionSetThermal (int argc
, char **argv
, Coord x
, Coord y
)
2106 char *function
= ARG (0);
2107 char *style
= ARG (1);
2108 void *ptr1
, *ptr2
, *ptr3
;
2112 if (function
&& *function
)
2116 if ( ! style
|| ! *style
)
2118 kind
= PCB
->ThermStyle
;
2122 kind
= GetUnitlessValue (style
, &absolute
);
2124 /* To allow relative values we could search for the first selected
2125 item and make 'kind' relative to that, but that's not too useful
2126 and requires quite some code. For example there's no
2127 GetFirstSelectedPin() function available. Let's postpone this
2128 functionality, there are more urgent things to do. */
2131 switch (GetFunctionID (function
))
2135 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGETHERMAL_TYPES
,
2136 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
2138 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, kind
);
2139 IncrementUndoSerialNumber ();
2143 case F_SelectedPins
:
2144 ChangeSelectedThermals (PIN_TYPE
, kind
);
2146 case F_SelectedVias
:
2147 ChangeSelectedThermals (VIA_TYPE
, kind
);
2150 case F_SelectedElements
:
2151 ChangeSelectedThermals (CHANGETHERMAL_TYPES
, kind
);
2170 * \brief Event handler to set the cursor according to the X pointer
2171 * position called from inside main.c.
2173 * \warning !!! no action routine !!!
2176 EventMoveCrosshair (int ev_x
, int ev_y
)
2178 #ifdef HAVE_LIBSTROKE
2181 StrokeBox
.X2
= ev_x
;
2182 StrokeBox
.Y2
= ev_y
;
2183 stroke_record (ev_x
, ev_y
);
2186 #endif /* HAVE_LIBSTROKE */
2187 if (MoveCrosshairAbsolute (ev_x
, ev_y
))
2189 /* update object position and cursor location */
2190 AdjustAttachedObjects ();
2191 notify_crosshair_change (true);
2195 /* --------------------------------------------------------------------------- */
2197 static const char setvalue_syntax
[] =
2198 N_("SetValue(Grid|Line|LineSize|Text|TextScale|ViaDrillingHole|Via|ViaSize, "
2201 static const char setvalue_help
[] =
2202 N_("Change various board-wide values and sizes.");
2204 /* %start-doc actions SetValue
2208 @item ViaDrillingHole
2209 Changes the diameter of the drill for new vias.
2212 Sets the grid spacing.
2216 Changes the thickness of new lines.
2220 Changes the diameter of new vias.
2224 Changes the size of new text.
2231 ActionSetValue (int argc
, char **argv
, Coord x
, Coord y
)
2233 char *function
= ARG (0);
2234 char *val
= ARG (1);
2235 char *units
= ARG (2);
2236 bool absolute
; /* flag for 'absolute' value */
2241 if (function
&& val
)
2243 value
= GetValue (val
, units
, &absolute
);
2244 switch (GetFunctionID (function
))
2246 case F_ViaDrillingHole
:
2247 SetViaDrillingHole (absolute
? value
:
2248 value
+ Settings
.ViaDrillingHole
,
2250 hid_action ("RouteStylesChanged");
2255 SetGrid (value
, false);
2259 value
= val
[0] == '-' ? -Settings
.increments
->grid
2260 : Settings
.increments
->grid
;
2261 /* On the way down, short against the minimum
2262 * PCB drawing unit */
2263 if ((value
+ PCB
->Grid
) < 1)
2265 else if (PCB
->Grid
== 1)
2266 SetGrid (value
, false);
2268 SetGrid (value
+ PCB
->Grid
, false);
2274 if (!absolute
&& value
== 0)
2275 value
= val
[0] == '-' ? -Settings
.increments
->line
2276 : Settings
.increments
->line
;
2277 SetLineSize (absolute
? value
: value
+ Settings
.LineThickness
);
2278 hid_action ("RouteStylesChanged");
2283 SetViaSize (absolute
? value
: value
+ Settings
.ViaThickness
, false);
2284 hid_action ("RouteStylesChanged");
2289 text_scale
= value
/ (double)FONT_CAPHEIGHT
* 100.;
2291 text_scale
+= Settings
.TextScale
;
2292 SetTextScale (text_scale
);
2306 /* --------------------------------------------------------------------------- */
2308 static const char quit_syntax
[] = N_("Quit()");
2310 static const char quit_help
[] = N_("Quits the application after confirming.");
2312 /* %start-doc actions Quit
2314 If you have unsaved changes, you will be prompted to confirm (or
2315 save) before quitting.
2320 ActionQuit (int argc
, char **argv
, Coord x
, Coord y
)
2322 char *force
= ARG (0);
2323 if (force
&& strcasecmp (force
, "force") == 0)
2328 if (!PCB
->Changed
|| gui
->close_confirm_dialog () == HID_CLOSE_CONFIRM_OK
)
2333 /* --------------------------------------------------------------------------- */
2335 static const char connection_syntax
[] =
2336 N_("Connection(Find|ResetLinesAndPolygons|ResetPinsAndVias|Reset)");
2338 static const char connection_help
[] =
2339 N_("Searches connections of the object at the cursor position.");
2341 /* %start-doc actions Connection
2343 Connections found with this action will be highlighted in the
2344 ``connected-color'' color and will have the ``found'' flag set.
2349 The net under the cursor is ``found''.
2351 @item ResetLinesAndPolygons
2352 Any ``found'' lines and polygons are marked ``not found''.
2354 @item ResetPinsAndVias
2355 Any ``found'' pins and vias are marked ``not found''.
2358 All ``found'' objects are marked ``not found''.
2365 ActionConnection (int argc
, char **argv
, Coord x
, Coord y
)
2367 char *function
= ARG (0);
2370 switch (GetFunctionID (function
))
2374 gui
->get_coords (_("Click on a connection"), &x
, &y
);
2375 LookupConnection (x
, y
, true, 1, CONNECTEDFLAG
, false, true);
2376 LookupConnection (x
, y
, true, 1, FOUNDFLAG
, true, true);
2380 case F_ResetLinesAndPolygons
:
2381 if (ClearFlagOnLinesAndPolygons (true, CONNECTEDFLAG
| FOUNDFLAG
, true))
2383 IncrementUndoSerialNumber ();
2388 case F_ResetPinsViasAndPads
:
2389 if (ClearFlagOnPinsViasAndPads (true, CONNECTEDFLAG
| FOUNDFLAG
, true))
2391 IncrementUndoSerialNumber ();
2397 if (ClearFlagOnAllObjects (true, CONNECTEDFLAG
| FOUNDFLAG
, true))
2399 IncrementUndoSerialNumber ();
2410 /* --------------------------------------------------------------------------- */
2412 static const char disperseelements_syntax
[] =
2413 N_("DisperseElements(All|Selected)");
2415 static const char disperseelements_help
[] = N_("Disperses elements.");
2417 /* %start-doc actions DisperseElements
2419 Normally this is used when starting a board, by selecting all elements
2420 and then dispersing them. This scatters the elements around the board
2421 so that you can pick individual ones, rather than have all the
2422 elements at the same 0,0 coordinate and thus impossible to choose
2427 #define GAP MIL_TO_COORD(100)
2430 ActionDisperseElements (int argc
, char **argv
, Coord x
, Coord y
)
2432 char *function
= ARG (0);
2437 int all
= 0, bad
= 0;
2439 if (!function
|| !*function
)
2445 switch (GetFunctionID (function
))
2462 AFAIL (disperseelements
);
2466 ELEMENT_LOOP (PCB
->Data
);
2469 * If we want to disperse selected elements, maybe we need smarter
2470 * code here to avoid putting components on top of others which
2471 * are not selected. For now, I'm assuming that this is typically
2472 * going to be used either with a brand new design or a scratch
2473 * design holding some new components
2475 if (!TEST_FLAG (LOCKFLAG
, element
) && (all
|| TEST_FLAG (SELECTEDFLAG
, element
)))
2478 /* figure out how much to move the element */
2479 dx
= minx
- element
->BoundingBox
.X1
;
2481 /* snap to the grid */
2482 dx
-= (element
->MarkX
+ dx
) % PCB
->Grid
;
2485 * and add one grid size so we make sure we always space by GAP or
2490 /* Figure out if this row has room. If not, start a new row */
2491 if (GAP
+ element
->BoundingBox
.X2
+ dx
> PCB
->MaxWidth
)
2497 /* figure out how much to move the element */
2498 dx
= minx
- element
->BoundingBox
.X1
;
2499 dy
= miny
- element
->BoundingBox
.Y1
;
2501 /* snap to the grid */
2502 dx
-= (element
->MarkX
+ dx
) % PCB
->Grid
;
2504 dy
-= (element
->MarkY
+ dy
) % PCB
->Grid
;
2507 /* move the element */
2508 MoveElementLowLevel (PCB
->Data
, element
, dx
, dy
);
2510 /* and add to the undo list so we can undo this operation */
2511 AddObjectToMoveUndoList (ELEMENT_TYPE
, NULL
, NULL
, element
, dx
, dy
);
2513 /* keep track of how tall this row is */
2514 minx
+= element
->BoundingBox
.X2
- element
->BoundingBox
.X1
+ GAP
;
2515 if (maxy
< element
->BoundingBox
.Y2
)
2517 maxy
= element
->BoundingBox
.Y2
;
2524 /* done with our action so increment the undo # */
2525 IncrementUndoSerialNumber ();
2528 SetChangedFlag (true);
2535 /* --------------------------------------------------------------------------- */
2537 static const char display_syntax
[] =
2538 N_("Display(NameOnPCB|Description|Value)\n"
2539 "Display(Grid|Redraw)\n"
2540 "Display(CycleClip|CycleCrosshair|Toggle45Degree|ToggleStartDirection)\n"
2541 "Display(ToggleGrid|ToggleRubberBandMode|ToggleUniqueNames)\n"
2542 "Display(ToggleMask|ToggleName|ToggleClearLine|ToggleFullPoly|ToggleSnapPin)\n"
2543 "Display(ToggleThindraw|ToggleThindrawPoly|ToggleOrthoMove|ToggleLocalRef)\n"
2544 "Display(ToggleCheckPlanes|ToggleShowDRC|ToggleAutoDRC)\n"
2545 "Display(ToggleLiveRoute|LockNames|OnlyNames)\n"
2546 "Display(Pinout|PinOrPadName)");
2548 static const char display_help
[] = N_("Several display-related actions.");
2550 /* %start-doc actions Display
2557 Specify whether all elements show their name, description, or value.
2560 Redraw the whole board.
2562 @item Toggle45Degree
2563 When clear, lines can be drawn at any angle. When set, lines are
2564 restricted to multiples of 45 degrees and requested lines may be
2565 broken up according to the clip setting.
2568 Changes the way lines are restricted to 45 degree increments. The
2569 various settings are: straight only, orthogonal then angled, and angled
2570 then orthogonal. If AllDirections is set, this action disables it.
2572 @item CycleCrosshair
2573 Changes crosshair drawing. Crosshair may accept form of 4-ray,
2574 8-ray and 12-ray cross.
2576 @item ToggleRubberBandMode
2577 If set, moving an object moves all the lines attached to it too.
2579 @item ToggleStartDirection
2580 If set, each time you set a point in a line, the Clip toggles between
2581 orth-angle and angle-ortho.
2583 @item ToggleUniqueNames
2584 If set, you will not be permitted to change the name of an element to
2585 match that of another element.
2588 If set, pin centers and pad end points are treated as additional grid
2589 points that the cursor can snap to.
2591 @item ToggleLocalRef
2592 If set, the mark is automatically set to the beginning of any move, so
2593 you can see the relative distance you've moved.
2595 @item ToggleThindraw
2596 If set, objects on the screen are drawn as outlines (lines are drawn
2597 as center-lines). This lets you see line endpoints hidden under pins,
2600 @item ToggleThindrawPoly
2601 If set, polygons on the screen are drawn as outlines.
2604 If set, pending objects (i.e. lines you're in the process of drawing)
2605 will be drawn with an outline showing how far away from other copper
2608 @item ToggleLiveRoute
2609 If set, the progress of the autorouter will be visible on the screen.
2612 If set, you will not be permitted to make connections which violate
2613 the current DRC and netlist settings.
2615 @item ToggleCheckPlanes
2616 If set, lines and arcs aren't drawn, which usually leaves just the
2617 polygons. If you also disable all but the layer you're interested in,
2618 this allows you to check for isolated regions.
2620 @item ToggleOrthoMove
2621 If set, the crosshair is only allowed to move orthogonally from its
2622 previous position. I.e. you can move an element or line up, down,
2623 left, or right, but not up+left or down+right.
2626 Selects whether the pinouts show the pin names or the pin numbers.
2628 @item ToggleLockNames
2629 If set, text will ignore left mouse clicks and actions that work on
2630 objects under the mouse. You can still select text with a lasso (left
2631 mouse drag) and perform actions on the selection.
2633 @item ToggleOnlyNames
2634 If set, only text will be sensitive for mouse clicks and actions that
2635 work on objects under the mouse. You can still select other objects
2636 with a lasso (left mouse drag) and perform actions on the selection.
2639 Turns the solder mask on or off.
2641 @item ToggleClearLine
2642 When set, the clear-line flag causes new lines and arcs to have their
2643 ``clear polygons'' flag set, so they won't be electrically connected
2644 to any polygons they overlap.
2646 @item ToggleFullPoly
2647 When set, the full-poly flag causes new polygons to have their
2648 ``full polygon'' flag set, so all parts of them will be displayed
2649 instead of only the biggest one.
2652 Resets the origin of the current grid to be wherever the mouse pointer
2653 is (not where the crosshair currently is). If you provide two numbers
2654 after this, the origin is set to that coordinate.
2657 Toggles whether the grid is displayed or not.
2660 Causes the pinout of the element indicated by the cursor to be
2661 displayed, usually in a separate window.
2664 Toggles whether the names of pins, pads, or (yes) vias will be
2665 displayed. If the cursor is over an element, all of its pins and pads
2668 @item ToggleAutoBuriedVias
2669 If set, automatically created vias are buried vias.
2675 static enum crosshair_shape
2676 CrosshairShapeIncrement (enum crosshair_shape shape
)
2680 case Basic_Crosshair_Shape
:
2681 shape
= Union_Jack_Crosshair_Shape
;
2683 case Union_Jack_Crosshair_Shape
:
2684 shape
= Dozen_Crosshair_Shape
;
2686 case Dozen_Crosshair_Shape
:
2687 shape
= Crosshair_Shapes_Number
;
2689 case Crosshair_Shapes_Number
:
2690 shape
= Basic_Crosshair_Shape
;
2697 ActionDisplay (int argc
, char **argv
, Coord childX
, Coord childY
)
2699 char *function
, *str_dir
;
2706 if (function
&& (!str_dir
|| !*str_dir
))
2708 switch (id
= GetFunctionID (function
))
2712 case F_ClearAndRedraw
:
2717 /* change the displayed name of elements */
2721 ELEMENT_LOOP (PCB
->Data
);
2723 EraseElementName (element
);
2726 CLEAR_FLAG (DESCRIPTIONFLAG
| NAMEONPCBFLAG
, PCB
);
2732 SET_FLAG (NAMEONPCBFLAG
, PCB
);
2735 SET_FLAG (DESCRIPTIONFLAG
, PCB
);
2738 ELEMENT_LOOP (PCB
->Data
);
2740 DrawElementName (element
);
2746 /* toggle line-adjust flag */
2747 case F_ToggleAllDirections
:
2748 TOGGLE_FLAG (ALLDIRECTIONFLAG
, PCB
);
2749 AdjustAttachedObjects ();
2753 notify_crosshair_change (false);
2754 if (TEST_FLAG (ALLDIRECTIONFLAG
, PCB
))
2756 TOGGLE_FLAG (ALLDIRECTIONFLAG
, PCB
);
2760 PCB
->Clipping
= (PCB
->Clipping
+ 1) % 3;
2761 AdjustAttachedObjects ();
2762 notify_crosshair_change (true);
2765 case F_CycleCrosshair
:
2766 notify_crosshair_change (false);
2767 Crosshair
.shape
= CrosshairShapeIncrement(Crosshair
.shape
);
2768 if (Crosshair_Shapes_Number
== Crosshair
.shape
)
2769 Crosshair
.shape
= Basic_Crosshair_Shape
;
2770 notify_crosshair_change (true);
2773 case F_ToggleRubberBandMode
:
2774 notify_crosshair_change (false);
2775 TOGGLE_FLAG (RUBBERBANDFLAG
, PCB
);
2776 notify_crosshair_change (true);
2779 case F_ToggleAutoBuriedVias
:
2780 notify_crosshair_change (false);
2781 TOGGLE_FLAG (AUTOBURIEDVIASFLAG
, PCB
);
2782 notify_crosshair_change (true);
2785 case F_ToggleStartDirection
:
2786 notify_crosshair_change (false);
2787 TOGGLE_FLAG (SWAPSTARTDIRFLAG
, PCB
);
2788 notify_crosshair_change (true);
2791 case F_ToggleUniqueNames
:
2792 TOGGLE_FLAG (UNIQUENAMEFLAG
, PCB
);
2795 case F_ToggleSnapPin
:
2796 notify_crosshair_change (false);
2797 TOGGLE_FLAG (SNAPPINFLAG
, PCB
);
2798 notify_crosshair_change (true);
2801 case F_ToggleLocalRef
:
2802 TOGGLE_FLAG (LOCALREFFLAG
, PCB
);
2805 case F_ToggleThindraw
:
2806 TOGGLE_FLAG (THINDRAWFLAG
, PCB
);
2810 case F_ToggleThindrawPoly
:
2811 TOGGLE_FLAG (THINDRAWPOLYFLAG
, PCB
);
2815 case F_ToggleLockNames
:
2816 TOGGLE_FLAG (LOCKNAMESFLAG
, PCB
);
2817 CLEAR_FLAG (ONLYNAMESFLAG
, PCB
);
2820 case F_ToggleOnlyNames
:
2821 TOGGLE_FLAG (ONLYNAMESFLAG
, PCB
);
2822 CLEAR_FLAG (LOCKNAMESFLAG
, PCB
);
2825 case F_ToggleHideNames
:
2826 TOGGLE_FLAG (HIDENAMESFLAG
, PCB
);
2830 case F_ToggleShowDRC
:
2831 TOGGLE_FLAG (SHOWDRCFLAG
, PCB
);
2834 case F_ToggleLiveRoute
:
2835 TOGGLE_FLAG (LIVEROUTEFLAG
, PCB
);
2838 case F_ToggleAutoDRC
:
2839 notify_crosshair_change (false);
2840 TOGGLE_FLAG (AUTODRCFLAG
, PCB
);
2841 if (TEST_FLAG (AUTODRCFLAG
, PCB
) && Settings
.Mode
== LINE_MODE
)
2843 if (ClearFlagOnAllObjects (true, CONNECTEDFLAG
| FOUNDFLAG
, true))
2845 IncrementUndoSerialNumber ();
2848 if (Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
2850 LookupConnection (Crosshair
.AttachedLine
.Point1
.X
,
2851 Crosshair
.AttachedLine
.Point1
.Y
,
2852 true, 1, CONNECTEDFLAG
, false, true);
2853 LookupConnection (Crosshair
.AttachedLine
.Point1
.X
,
2854 Crosshair
.AttachedLine
.Point1
.Y
,
2855 true, 1, FOUNDFLAG
, true, true);
2858 notify_crosshair_change (true);
2861 case F_ToggleCheckPlanes
:
2862 TOGGLE_FLAG (CHECKPLANESFLAG
, PCB
);
2866 case F_ToggleOrthoMove
:
2867 TOGGLE_FLAG (ORTHOMOVEFLAG
, PCB
);
2871 TOGGLE_FLAG (SHOWNUMBERFLAG
, PCB
);
2876 TOGGLE_FLAG (SHOWMASKFLAG
, PCB
);
2880 case F_ToggleClearLine
:
2881 TOGGLE_FLAG (CLEARNEWFLAG
, PCB
);
2884 case F_ToggleFullPoly
:
2885 TOGGLE_FLAG (NEWFULLPOLYFLAG
, PCB
);
2888 /* shift grid alignment */
2891 Coord oldGrid
= PCB
->Grid
;
2894 if (MoveCrosshairAbsolute (Crosshair
.X
, Crosshair
.Y
))
2895 notify_crosshair_change (true); /* first notify was in MoveCrosshairAbs */
2896 SetGrid (oldGrid
, true);
2900 /* toggle displaying of the grid */
2902 Settings
.DrawGrid
= !Settings
.DrawGrid
;
2906 /* display the pinout of an element */
2909 ElementType
*element
;
2913 gui
->get_coords (_("Click on an element"), &x
, &y
);
2915 (x
, y
, ELEMENT_TYPE
, &ptrtmp
,
2916 &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
2918 element
= (ElementType
*) ptrtmp
;
2919 gui
->show_item (element
);
2924 /* toggle displaying of pin/pad/via names */
2925 case F_PinOrPadName
:
2927 void *ptr1
, *ptr2
, *ptr3
;
2930 gui
->get_coords(_("Click on an element"), &x
, &y
);
2932 switch (SearchScreen (x
, y
,
2933 ELEMENT_TYPE
| PIN_TYPE
| PAD_TYPE
|
2934 VIA_TYPE
, (void **) &ptr1
, (void **) &ptr2
,
2938 PIN_LOOP ((ElementType
*) ptr1
);
2940 if (TEST_FLAG (DISPLAYNAMEFLAG
, pin
))
2944 AddObjectToFlagUndoList (PIN_TYPE
, ptr1
, pin
, pin
);
2945 TOGGLE_FLAG (DISPLAYNAMEFLAG
, pin
);
2948 PAD_LOOP ((ElementType
*) ptr1
);
2950 if (TEST_FLAG (DISPLAYNAMEFLAG
, pad
))
2954 AddObjectToFlagUndoList (PAD_TYPE
, ptr1
, pad
, pad
);
2955 TOGGLE_FLAG (DISPLAYNAMEFLAG
, pad
);
2958 SetChangedFlag (true);
2959 IncrementUndoSerialNumber ();
2964 if (TEST_FLAG (DISPLAYNAMEFLAG
, (PinType
*) ptr2
))
2965 ErasePinName ((PinType
*) ptr2
);
2967 DrawPinName ((PinType
*) ptr2
);
2968 AddObjectToFlagUndoList (PIN_TYPE
, ptr1
, ptr2
, ptr3
);
2969 TOGGLE_FLAG (DISPLAYNAMEFLAG
, (PinType
*) ptr2
);
2970 SetChangedFlag (true);
2971 IncrementUndoSerialNumber ();
2976 if (TEST_FLAG (DISPLAYNAMEFLAG
, (PadType
*) ptr2
))
2977 ErasePadName ((PadType
*) ptr2
);
2979 DrawPadName ((PadType
*) ptr2
);
2980 AddObjectToFlagUndoList (PAD_TYPE
, ptr1
, ptr2
, ptr3
);
2981 TOGGLE_FLAG (DISPLAYNAMEFLAG
, (PadType
*) ptr2
);
2982 SetChangedFlag (true);
2983 IncrementUndoSerialNumber ();
2987 if (TEST_FLAG (DISPLAYNAMEFLAG
, (PinType
*) ptr2
))
2988 EraseViaName ((PinType
*) ptr2
);
2990 DrawViaName ((PinType
*) ptr2
);
2991 AddObjectToFlagUndoList (VIA_TYPE
, ptr1
, ptr2
, ptr3
);
2992 TOGGLE_FLAG (DISPLAYNAMEFLAG
, (PinType
*) ptr2
);
2993 SetChangedFlag (true);
2994 IncrementUndoSerialNumber ();
3004 else if (function
&& str_dir
)
3006 switch (GetFunctionID (function
))
3011 PCB
->GridOffsetX
= GetValue (argv
[1], NULL
, NULL
);
3012 PCB
->GridOffsetY
= GetValue (argv
[2], NULL
, NULL
);
3013 if (Settings
.DrawGrid
)
3032 /* --------------------------------------------------------------------------- */
3034 static const char mode_syntax
[] =
3035 N_("Mode(Arc|Arrow|Copy|InsertPoint|Line|Lock|Move|None|PasteBuffer)\n"
3036 "Mode(Polygon|Rectangle|Remove|Rotate|Text|Thermal|Via)\n"
3037 "Mode(Notify|Release|Cancel|Stroke)\n"
3038 "Mode(Save|Restore)");
3040 static const char mode_help
[] = N_("Change or use the tool mode.");
3042 /* %start-doc actions Mode
3062 Select the indicated tool.
3065 Called when you press the mouse button, or move the mouse.
3068 Called when you release the mouse button.
3071 Cancels any pending tool activity, allowing you to restart elsewhere.
3072 For example, this allows you to start a new line rather than attach a
3073 line to the previous line.
3076 Similar to Cancel but calling this action a second time will return
3080 If your @code{pcb} was built with libstroke, this invokes the stroke
3081 input method. If not, this will restart a drawing mode if you were
3082 drawing, else it will select objects.
3085 Remembers the current tool.
3088 Restores the tool to the last saved tool.
3095 ActionMode (int argc
, char **argv
, Coord x
, Coord y
)
3097 char *function
= ARG (0);
3101 Note
.X
= Crosshair
.X
;
3102 Note
.Y
= Crosshair
.Y
;
3103 notify_crosshair_change (false);
3104 switch (GetFunctionID (function
))
3110 SetMode (ARROW_MODE
);
3113 SetMode (COPY_MODE
);
3116 SetMode (INSERTPOINT_MODE
);
3119 SetMode (LINE_MODE
);
3122 SetMode (LOCK_MODE
);
3125 SetMode (MOVE_MODE
);
3132 int saved_mode
= Settings
.Mode
;
3134 SetMode (saved_mode
);
3139 switch (Settings
.Mode
)
3142 case PASTEBUFFER_MODE
:
3148 case INSERTPOINT_MODE
:
3149 case RUBBERBANDMOVE_MODE
:
3153 SetMode (ARROW_MODE
);
3157 if (Crosshair
.AttachedLine
.State
== STATE_FIRST
)
3158 SetMode (ARROW_MODE
);
3162 SetMode (LINE_MODE
);
3166 case RECTANGLE_MODE
:
3167 if (Crosshair
.AttachedBox
.State
== STATE_FIRST
)
3168 SetMode (ARROW_MODE
);
3172 SetMode (RECTANGLE_MODE
);
3177 if (Crosshair
.AttachedLine
.State
== STATE_FIRST
)
3178 SetMode (ARROW_MODE
);
3182 SetMode (POLYGON_MODE
);
3186 case POLYGONHOLE_MODE
:
3187 if (Crosshair
.AttachedLine
.State
== STATE_FIRST
)
3188 SetMode (ARROW_MODE
);
3192 SetMode (POLYGONHOLE_MODE
);
3197 if (Crosshair
.AttachedBox
.State
== STATE_FIRST
)
3198 SetMode (ARROW_MODE
);
3219 SetMode (PASTEBUFFER_MODE
);
3222 SetMode (POLYGON_MODE
);
3225 SetMode (POLYGONHOLE_MODE
);
3227 #ifndef HAVE_LIBSTROKE
3240 SetMode (REMOVE_MODE
);
3243 SetMode (RECTANGLE_MODE
);
3246 SetMode (ROTATE_MODE
);
3249 #ifdef HAVE_LIBSTROKE
3251 StrokeBox
.X1
= Crosshair
.X
;
3252 StrokeBox
.Y1
= Crosshair
.Y
;
3255 /* Handle middle mouse button restarts of drawing mode. If not in
3256 | a drawing mode, middle mouse button will select objects.
3258 if (Settings
.Mode
== LINE_MODE
3259 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
3261 SetMode (LINE_MODE
);
3263 else if (Settings
.Mode
== ARC_MODE
3264 && Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
3266 else if (Settings
.Mode
== RECTANGLE_MODE
3267 && Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
3268 SetMode (RECTANGLE_MODE
);
3269 else if (Settings
.Mode
== POLYGON_MODE
3270 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
3271 SetMode (POLYGON_MODE
);
3276 SetMode (ARROW_MODE
);
3282 SetMode (TEXT_MODE
);
3285 SetMode (THERMAL_MODE
);
3291 case F_Restore
: /* restore the last saved mode */
3295 case F_Save
: /* save currently selected mode */
3299 notify_crosshair_change (true);
3306 /* --------------------------------------------------------------------------- */
3308 static const char removeselected_syntax
[] = N_("RemoveSelected()");
3310 static const char removeselected_help
[] = N_("Removes any selected objects.");
3312 /* %start-doc actions RemoveSelected
3317 ActionRemoveSelected (int argc
, char **argv
, Coord x
, Coord y
)
3319 if (RemoveSelected ())
3320 SetChangedFlag (true);
3324 /* --------------------------------------------------------------------------- */
3326 static const char renumber_syntax
[] = N_("Renumber()\n"
3327 "Renumber(filename)");
3329 static const char renumber_help
[] =
3330 N_("Renumber all elements. The changes will be recorded to filename\n"
3331 "for use in backannotating these changes to the schematic.");
3333 /* %start-doc actions Renumber
3338 ActionRenumber (int argc
, char **argv
, Coord x
, Coord y
)
3340 bool changed
= false;
3341 ElementType
**element_list
;
3342 ElementType
**locked_element_list
;
3343 unsigned int i
, j
, k
, cnt
, lock_cnt
;
3349 static char * default_file
= NULL
;
3350 size_t cnt_list_sz
= 100;
3356 char **was
, **is
, *pin
;
3357 unsigned int c_cnt
= 0;
3364 * We deal with the case where name already exists in this
3365 * function so the GUI doesn't need to deal with it
3367 name
= gui
->fileselect (_("Save Renumber Annotation File As ..."),
3368 _("Choose a file to record the renumbering to.\n"
3369 "This file may be used to back annotate the\n"
3370 "change to the schematics.\n"),
3371 default_file
, ".eco", "eco",
3381 free (default_file
);
3382 default_file
= NULL
;
3387 default_file
= strdup (name
);
3390 if ((out
= fopen (name
, "r")))
3393 if (!gui
->confirm_dialog (_("File exists! Ok to overwrite?"), 0))
3395 if (free_name
&& name
)
3401 if ((out
= fopen (name
, "w")) == NULL
)
3403 Message (_("Could not open %s\n"), name
);
3404 if (free_name
&& name
)
3409 if (free_name
&& name
)
3412 fprintf (out
, "*COMMENT* PCB Annotation File\n");
3413 fprintf (out
, "*FILEVERSION* 20061031\n");
3416 * Make a first pass through all of the elements and sort them out
3417 * by location on the board. While here we also collect a list of
3420 * We'll actually renumber things in the 2nd pass.
3422 element_list
= (ElementType
**)calloc (PCB
->Data
->ElementN
, sizeof (ElementType
*));
3423 locked_element_list
= (ElementType
**)calloc (PCB
->Data
->ElementN
, sizeof (ElementType
*));
3424 was
= (char **)calloc (PCB
->Data
->ElementN
, sizeof (char *));
3425 is
= (char **)calloc (PCB
->Data
->ElementN
, sizeof (char *));
3426 if (element_list
== NULL
|| locked_element_list
== NULL
|| was
== NULL
3429 fprintf (stderr
, "calloc() failed in %s\n", __FUNCTION__
);
3436 ELEMENT_LOOP (PCB
->Data
);
3438 if (TEST_FLAG (LOCKFLAG
, element
->Name
) || TEST_FLAG (LOCKFLAG
, element
))
3441 * add to the list of locked elements which we won't try to
3442 * renumber and whose reference designators are now reserved.
3445 "*WARN* Element \"%s\" at %$md is locked and will not be renumbered.\n",
3446 UNKNOWN (NAMEONPCB_NAME (element
)), element
->MarkX
, element
->MarkY
);
3447 locked_element_list
[lock_cnt
] = element
;
3453 /* count of devices which will be renumbered */
3456 /* search for correct position in the list */
3458 while (element_list
[i
] && element
->MarkY
> element_list
[i
]->MarkY
)
3462 * We have found the position where we have the first element that
3463 * has the same Y value or a lower Y value. Now move forward if
3464 * needed through the X values
3466 while (element_list
[i
]
3467 && element
->MarkY
== element_list
[i
]->MarkY
3468 && element
->MarkX
> element_list
[i
]->MarkX
)
3471 for (j
= cnt
- 1; j
> i
; j
--)
3473 element_list
[j
] = element_list
[j
- 1];
3475 element_list
[i
] = element
;
3482 * Now that the elements are sorted by board position, we go through
3483 * and renumber them.
3487 * turn off the flag which requires unique names so it doesn't get
3488 * in our way. When we're done with the renumber we will have unique
3491 unique
= TEST_FLAG (UNIQUENAMEFLAG
, PCB
);
3492 CLEAR_FLAG (UNIQUENAMEFLAG
, PCB
);
3494 cnt_list
= (struct _cnt_list
*)calloc (cnt_list_sz
, sizeof (struct _cnt_list
));
3495 for (i
= 0; i
< cnt
; i
++)
3497 /* If there is no refdes, maybe just spit out a warning */
3498 if (NAMEONPCB_NAME (element_list
[i
]))
3500 /* figure out the prefix */
3501 tmps
= strdup (NAMEONPCB_NAME (element_list
[i
]));
3503 while (tmps
[j
] && (tmps
[j
] < '0' || tmps
[j
] > '9')
3508 /* check the counter for this prefix */
3510 cnt_list
[j
].name
&& (strcmp (cnt_list
[j
].name
, tmps
) != 0)
3511 && j
< cnt_list_sz
; j
++);
3513 /* grow the list if needed */
3514 if (j
== cnt_list_sz
)
3517 cnt_list
= (struct _cnt_list
*)realloc (cnt_list
, cnt_list_sz
);
3518 if (cnt_list
== NULL
)
3520 fprintf (stderr
, _("realloc() failed in %s()\n"), __FUNCTION__
);
3523 /* zero out the memory that we added */
3524 for (tmpi
= j
; tmpi
< cnt_list_sz
; tmpi
++)
3526 cnt_list
[tmpi
].name
= NULL
;
3527 cnt_list
[tmpi
].cnt
= 0;
3532 * start a new counter if we don't have a counter for this
3535 if (!cnt_list
[j
].name
)
3537 cnt_list
[j
].name
= strdup (tmps
);
3538 cnt_list
[j
].cnt
= 0;
3542 * check to see if the new refdes is already used by a
3551 /* space for the prefix plus 1 digit plus the '\0' */
3552 sz
= strlen (cnt_list
[j
].name
) + 2;
3554 /* and 1 more per extra digit needed to hold the number */
3555 tmpi
= cnt_list
[j
].cnt
;
3561 tmps
= (char *)malloc (sz
* sizeof (char));
3562 sprintf (tmps
, "%s%d", cnt_list
[j
].name
, (int) cnt_list
[j
].cnt
);
3565 * now compare to the list of reserved (by locked
3568 for (k
= 0; k
< lock_cnt
; k
++)
3571 (UNKNOWN (NAMEONPCB_NAME (locked_element_list
[k
])),
3582 if (strcmp (tmps
, NAMEONPCB_NAME (element_list
[i
])) != 0)
3584 fprintf (out
, "*RENAME* \"%s\" \"%s\"\n",
3585 NAMEONPCB_NAME (element_list
[i
]), tmps
);
3587 /* add this rename to our table of renames so we can update the netlist */
3588 was
[c_cnt
] = strdup (NAMEONPCB_NAME (element_list
[i
]));
3589 is
[c_cnt
] = strdup (tmps
);
3592 AddObjectToChangeNameUndoList (ELEMENT_TYPE
, NULL
, NULL
,
3594 NAMEONPCB_NAME (element_list
3597 ChangeObjectName (ELEMENT_TYPE
, element_list
[i
], NULL
, NULL
,
3601 /* we don't free tmps in this case because it is used */
3608 pcb_fprintf (out
, "*WARN* Element at %$md has no name.\n",
3609 element_list
[i
]->MarkX
, element_list
[i
]->MarkY
);
3616 /* restore the unique flag setting */
3618 SET_FLAG (UNIQUENAMEFLAG
, PCB
);
3623 /* update the netlist */
3624 AddNetlistLibToUndoList (&(PCB
->NetlistLib
));
3626 /* iterate over each net */
3627 for (i
= 0; i
< PCB
->NetlistLib
.MenuN
; i
++)
3630 /* iterate over each pin on the net */
3631 for (j
= 0; j
< PCB
->NetlistLib
.Menu
[i
].EntryN
; j
++)
3634 /* figure out the pin number part from strings like U3-21 */
3635 tmps
= strdup (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
);
3636 for (k
= 0; tmps
[k
] && tmps
[k
] != '-'; k
++);
3640 /* iterate over the list of changed reference designators */
3641 for (k
= 0; k
< c_cnt
; k
++)
3644 * if the pin needs to change, change it and quit
3645 * searching in the list.
3647 if (strcmp (tmps
, was
[k
]) == 0)
3649 free (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
);
3650 PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
=
3651 (char *)malloc ((strlen (is
[k
]) + strlen (pin
) +
3652 2) * sizeof (char));
3653 sprintf (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
,
3654 "%s-%s", is
[k
], pin
);
3662 for (k
= 0; k
< c_cnt
; k
++)
3669 IncrementUndoSerialNumber ();
3670 SetChangedFlag (true);
3673 free (locked_element_list
);
3674 free (element_list
);
3682 /* --------------------------------------------------------------------------- */
3684 static const char ripup_syntax
[] = N_("RipUp(All|Selected|Element)");
3686 static const char ripup_help
[] =
3687 N_("Ripup auto-routed tracks, or convert an element to parts.");
3689 /* %start-doc actions RipUp
3694 Removes all lines and vias which were created by the autorouter.
3697 Removes all selected lines and vias which were created by the
3701 Converts the element under the cursor to parts (vias and lines). Note
3702 that this uses the highest numbered paste buffer.
3709 ActionRipUp (int argc
, char **argv
, Coord x
, Coord y
)
3711 char *function
= ARG (0);
3712 bool changed
= false;
3716 switch (GetFunctionID (function
))
3719 ALLLINE_LOOP (PCB
->Data
);
3721 if (TEST_FLAG (AUTOFLAG
, line
) && !TEST_FLAG (LOCKFLAG
, line
))
3723 RemoveObject (LINE_TYPE
, layer
, line
, line
);
3728 ALLARC_LOOP (PCB
->Data
);
3730 if (TEST_FLAG (AUTOFLAG
, arc
) && !TEST_FLAG (LOCKFLAG
, arc
))
3732 RemoveObject (ARC_TYPE
, layer
, arc
, arc
);
3737 VIA_LOOP (PCB
->Data
);
3739 if (TEST_FLAG (AUTOFLAG
, via
) && !TEST_FLAG (LOCKFLAG
, via
))
3741 RemoveObject (VIA_TYPE
, via
, via
, via
);
3749 IncrementUndoSerialNumber ();
3750 SetChangedFlag (true);
3754 VISIBLELINE_LOOP (PCB
->Data
);
3756 if (TEST_FLAGS (AUTOFLAG
| SELECTEDFLAG
, line
)
3757 && !TEST_FLAG (LOCKFLAG
, line
))
3759 RemoveObject (LINE_TYPE
, layer
, line
, line
);
3765 VIA_LOOP (PCB
->Data
);
3767 if (TEST_FLAGS (AUTOFLAG
| SELECTEDFLAG
, via
)
3768 && !TEST_FLAG (LOCKFLAG
, via
))
3770 RemoveObject (VIA_TYPE
, via
, via
, via
);
3777 IncrementUndoSerialNumber ();
3778 SetChangedFlag (true);
3783 void *ptr1
, *ptr2
, *ptr3
;
3785 if (SearchScreen (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
,
3786 &ptr1
, &ptr2
, &ptr3
) != NO_TYPE
)
3788 Note
.Buffer
= Settings
.BufferNumber
;
3789 SetBufferNumber (MAX_BUFFER
- 1);
3790 ClearBuffer (PASTEBUFFER
);
3791 CopyObjectToBuffer (PASTEBUFFER
->Data
, PCB
->Data
,
3792 ELEMENT_TYPE
, ptr1
, ptr2
, ptr3
);
3793 SmashBufferElement (PASTEBUFFER
);
3796 SaveUndoSerialNumber ();
3797 EraseObject (ELEMENT_TYPE
, ptr1
, ptr1
);
3798 MoveObjectToRemoveUndoList (ELEMENT_TYPE
, ptr1
, ptr2
, ptr3
);
3799 RestoreUndoSerialNumber ();
3800 CopyPastebufferToLayout (0, 0);
3801 SetBufferNumber (Note
.Buffer
);
3802 SetChangedFlag (true);
3811 /* --------------------------------------------------------------------------- */
3813 static const char addrats_syntax
[] = N_("AddRats(AllRats|SelectedRats|Close)");
3815 static const char addrats_help
[] =
3816 N_("Add one or more rat lines to the board.");
3818 /* %start-doc actions AddRats
3823 Create rat lines for all loaded nets that aren't already connected on
3827 Similarly, but only add rat lines for nets connected to selected pins
3831 Selects the shortest unselected rat on the board.
3838 ActionAddRats (int argc
, char **argv
, Coord x
, Coord y
)
3840 char *function
= ARG (0);
3846 if (Settings
.RatWarn
)
3848 switch (GetFunctionID (function
))
3851 if (AddAllRats (false, NULL
))
3852 SetChangedFlag (true);
3853 UpdateLineNetnames (); /* XXX: KLUDGE */
3855 case F_SelectedRats
:
3857 if (AddAllRats (true, NULL
))
3858 SetChangedFlag (true);
3861 small
= SQUARE (MAX_COORD
);
3863 RAT_LOOP (PCB
->Data
);
3865 if (TEST_FLAG (SELECTEDFLAG
, line
))
3867 len
= SQUARE (line
->Point1
.X
- line
->Point2
.X
) +
3868 SQUARE (line
->Point1
.Y
- line
->Point2
.Y
);
3878 AddObjectToFlagUndoList (RATLINE_TYPE
, shorty
, shorty
, shorty
);
3879 SET_FLAG (SELECTEDFLAG
, shorty
);
3882 CenterDisplay ((shorty
->Point2
.X
+ shorty
->Point1
.X
) / 2,
3883 (shorty
->Point2
.Y
+ shorty
->Point1
.Y
) / 2,
3892 /* --------------------------------------------------------------------------- */
3894 static const char delete_syntax
[] =
3895 N_("Delete(Object|Selected)\n"
3896 "Delete(AllRats|SelectedRats)");
3898 static const char delete_help
[] = N_("Delete stuff.");
3900 /* %start-doc actions Delete
3905 ActionDelete (int argc
, char **argv
, Coord x
, Coord y
)
3907 char *function
= ARG (0);
3908 int id
= GetFunctionID (function
);
3910 Note
.X
= Crosshair
.X
;
3911 Note
.Y
= Crosshair
.Y
;
3913 if (id
== -1) /* no arg */
3915 if (RemoveSelected() == false)
3923 SetMode(REMOVE_MODE
);
3931 if (DeleteRats (false))
3932 SetChangedFlag (true);
3934 case F_SelectedRats
:
3935 if (DeleteRats (true))
3936 SetChangedFlag (true);
3943 /* --------------------------------------------------------------------------- */
3945 static const char deleterats_syntax
[] =
3946 N_("DeleteRats(AllRats|Selected|SelectedRats)");
3948 static const char deleterats_help
[] = N_("Delete rat lines.");
3950 /* %start-doc actions DeleteRats
3955 ActionDeleteRats (int argc
, char **argv
, Coord x
, Coord y
)
3957 char *function
= ARG (0);
3960 if (Settings
.RatWarn
)
3962 switch (GetFunctionID (function
))
3965 if (DeleteRats (false))
3966 SetChangedFlag (true);
3968 case F_SelectedRats
:
3970 if (DeleteRats (true))
3971 SetChangedFlag (true);
3978 /* --------------------------------------------------------------------------- */
3980 static const char autoplace_syntax
[] = N_("AutoPlaceSelected()");
3982 static const char autoplace_help
[] = N_("Auto-place selected components.");
3984 /* %start-doc actions AutoPlaceSelected
3986 Attempts to re-arrange the selected components such that the nets
3987 connecting them are minimized. Note that you cannot undo this.
3992 ActionAutoPlaceSelected (int argc
, char **argv
, Coord x
, Coord y
)
3995 if (gui
->confirm_dialog (_("Auto-placement can NOT be undone.\n"
3996 "Do you want to continue anyway?\n"), 0))
3998 if (AutoPlaceSelected ())
3999 SetChangedFlag (true);
4004 /* --------------------------------------------------------------------------- */
4006 static const char autoroute_syntax
[] = N_("AutoRoute(AllRats|SelectedRats)");
4008 static const char autoroute_help
[] = N_("Auto-route some or all rat lines.");
4010 /* %start-doc actions AutoRoute
4015 Attempt to autoroute all rats.
4018 Attempt to autoroute the selected rats.
4022 Before autorouting, it's important to set up a few things. First,
4023 make sure any layers you aren't using are disabled, else the
4024 autorouter may use them. Next, make sure the current line and via
4025 styles are set accordingly. Last, make sure "new lines clear
4026 polygons" is set, in case you eventually want to add a copper pour.
4028 Autorouting takes a while. During this time, the program may not be
4034 ActionAutoRoute (int argc
, char **argv
, Coord x
, Coord y
)
4036 char *function
= ARG (0);
4038 if (function
) /* one parameter */
4040 switch (GetFunctionID (function
))
4043 if (AutoRoute (false))
4044 SetChangedFlag (true);
4046 case F_SelectedRats
:
4048 if (AutoRoute (true))
4049 SetChangedFlag (true);
4056 /* --------------------------------------------------------------------------- */
4058 static const char markcrosshair_syntax
[] =
4059 N_("MarkCrosshair()\n"
4060 "MarkCrosshair(Center)");
4062 static const char markcrosshair_help
[] = N_("Set/Reset the Crosshair mark.");
4064 /* %start-doc actions MarkCrosshair
4066 The ``mark'' is a small X-shaped target on the display which is
4067 treated like a second origin (the normal origin is the upper let
4068 corner of the board). The GUI will display a second set of
4069 coordinates for this mark, which tells you how far you are from it.
4071 If no argument is given, the mark is toggled - disabled if it was
4072 enabled, or enabled at the current cursor position of disabled. If
4073 the @code{Center} argument is given, the mark is moved to the current
4079 ActionMarkCrosshair (int argc
, char **argv
, Coord x
, Coord y
)
4081 char *function
= ARG (0);
4082 if (!function
|| !*function
)
4086 notify_mark_change (false);
4087 Marked
.status
= false;
4088 notify_mark_change (true);
4092 notify_mark_change (false);
4093 Marked
.status
= false;
4094 Marked
.status
= true;
4095 Marked
.X
= Crosshair
.X
;
4096 Marked
.Y
= Crosshair
.Y
;
4097 notify_mark_change (true);
4100 else if (GetFunctionID (function
) == F_Center
)
4102 notify_mark_change (false);
4103 Marked
.status
= true;
4104 Marked
.X
= Crosshair
.X
;
4105 Marked
.Y
= Crosshair
.Y
;
4106 notify_mark_change (true);
4111 /* --------------------------------------------------------------------------- */
4113 static const char changesize_syntax
[] =
4114 N_("ChangeSize(Object, delta)\n"
4115 "ChangeSize(SelectedObjects|Selected, delta)\n"
4116 "ChangeSize(SelectedLines|SelectedPins|SelectedVias, delta)\n"
4117 "ChangeSize(SelectedPads|SelectedTexts|SelectedNames, delta)\n"
4118 "ChangeSize(SelectedElements, delta)");
4120 static const char changesize_help
[] = N_("Changes the size of objects.");
4122 /* %start-doc actions ChangeSize
4124 For lines and arcs, this changes the width. For pins and vias, this
4125 changes the overall diameter of the copper annulus. For pads, this
4126 changes the width and, indirectly, the length. For texts and names,
4127 this changes the scaling factor. For elements, this changes the width
4128 of the silk layer lines and arcs for this element.
4133 ActionChangeSize (int argc
, char **argv
, Coord x
, Coord y
)
4135 char *function
= ARG (0);
4136 char *delta
= ARG (1);
4137 char *units
= ARG (2);
4138 bool absolute
; /* indicates if absolute size is given */
4141 if (function
&& delta
)
4143 value
= GetValue (delta
, units
, &absolute
);
4145 value
= delta
[0] == '-' ? -Settings
.increments
->size
4146 : Settings
.increments
->size
;
4147 switch (GetFunctionID (function
))
4152 void *ptr1
, *ptr2
, *ptr3
;
4155 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGESIZE_TYPES
,
4156 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4157 if (TEST_FLAG (LOCKFLAG
, (PinType
*) ptr2
))
4158 Message (_("Sorry, the object is locked\n"));
4159 if (ChangeObjectSize (type
, ptr1
, ptr2
, ptr3
, value
, absolute
))
4160 SetChangedFlag (true);
4164 case F_SelectedVias
:
4165 if (ChangeSelectedSize (VIA_TYPE
, value
, absolute
))
4166 SetChangedFlag (true);
4169 case F_SelectedPins
:
4170 if (ChangeSelectedSize (PIN_TYPE
, value
, absolute
))
4171 SetChangedFlag (true);
4174 case F_SelectedPads
:
4175 if (ChangeSelectedSize (PAD_TYPE
, value
, absolute
))
4176 SetChangedFlag (true);
4179 case F_SelectedArcs
:
4180 if (ChangeSelectedSize (ARC_TYPE
, value
, absolute
))
4181 SetChangedFlag (true);
4184 case F_SelectedLines
:
4185 if (ChangeSelectedSize (LINE_TYPE
, value
, absolute
))
4186 SetChangedFlag (true);
4189 case F_SelectedTexts
:
4190 if (ChangeSelectedSize (TEXT_TYPE
, value
, absolute
))
4191 SetChangedFlag (true);
4194 case F_SelectedNames
:
4195 if (ChangeSelectedSize (ELEMENTNAME_TYPE
, value
, absolute
))
4196 SetChangedFlag (true);
4199 case F_SelectedElements
:
4200 if (ChangeSelectedSize (ELEMENT_TYPE
, value
, absolute
))
4201 SetChangedFlag (true);
4205 case F_SelectedObjects
:
4206 if (ChangeSelectedSize (CHANGESIZE_TYPES
, value
, absolute
))
4207 SetChangedFlag (true);
4214 /* --------------------------------------------------------------------------- */
4216 static const char changedrillsize_syntax
[] =
4217 N_("ChangeDrillSize(Object, delta)\n"
4218 "ChangeDrillSize(SelectedPins|SelectedVias|Selected|SelectedObjects, delta)");
4220 static const char changedrillsize_help
[] =
4221 N_("Changes the drilling hole size of objects.");
4223 /* %start-doc actions ChangeDrillSize
4228 ActionChange2ndSize (int argc
, char **argv
, Coord x
, Coord y
)
4230 char *function
= ARG (0);
4231 char *delta
= ARG (1);
4232 char *units
= ARG (2);
4236 if (function
&& delta
)
4238 value
= GetValue (delta
, units
, &absolute
);
4239 switch (GetFunctionID (function
))
4244 void *ptr1
, *ptr2
, *ptr3
;
4246 gui
->get_coords (_("Select an Object"), &x
, &y
);
4248 SearchScreen (x
, y
, CHANGE2NDSIZE_TYPES
,
4249 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4250 if (ChangeObject2ndSize
4251 (type
, ptr1
, ptr2
, ptr3
, value
, absolute
, true))
4252 SetChangedFlag (true);
4256 case F_SelectedVias
:
4257 if (ChangeSelected2ndSize (VIA_TYPE
, value
, absolute
))
4258 SetChangedFlag (true);
4261 case F_SelectedPins
:
4262 if (ChangeSelected2ndSize (PIN_TYPE
, value
, absolute
))
4263 SetChangedFlag (true);
4266 case F_SelectedObjects
:
4267 if (ChangeSelected2ndSize (PIN_TYPES
, value
, absolute
))
4268 SetChangedFlag (true);
4275 /* --------------------------------------------------------------------------- */
4277 static const char changeclearsize_syntax
[] =
4278 N_("ChangeClearSize(Object, delta)\n"
4279 "ChangeClearSize(SelectedPins|SelectedPads|SelectedVias, delta)\n"
4280 "ChangeClearSize(SelectedLines|SelectedArcs, delta\n"
4281 "ChangeClearSize(Selected|SelectedObjects, delta)");
4283 static const char changeclearsize_help
[] =
4284 N_("Changes the clearance size of objects.");
4286 /* %start-doc actions ChangeClearSize
4288 If the solder mask is currently showing, this action changes the
4289 solder mask clearance. If the mask is not showing, this action
4290 changes the polygon clearance.
4295 ActionChangeClearSize (int argc
, char **argv
, Coord x
, Coord y
)
4297 char *function
= ARG (0);
4298 char *delta
= ARG (1);
4299 char *units
= ARG (2);
4303 if (function
&& delta
)
4305 value
= 2 * GetValue (delta
, units
, &absolute
);
4307 value
= delta
[0] == '-' ? -Settings
.increments
->clear
4308 : Settings
.increments
->clear
;
4309 switch (GetFunctionID (function
))
4314 void *ptr1
, *ptr2
, *ptr3
;
4316 gui
->get_coords (_("Select an Object"), &x
, &y
);
4319 CHANGECLEARSIZE_TYPES
, &ptr1
, &ptr2
,
4321 if (ChangeObjectClearSize (type
, ptr1
, ptr2
, ptr3
, value
, absolute
))
4322 SetChangedFlag (true);
4325 case F_SelectedVias
:
4326 if (ChangeSelectedClearSize (VIA_TYPE
, value
, absolute
))
4327 SetChangedFlag (true);
4329 case F_SelectedPads
:
4330 if (ChangeSelectedClearSize (PAD_TYPE
, value
, absolute
))
4331 SetChangedFlag (true);
4333 case F_SelectedPins
:
4334 if (ChangeSelectedClearSize (PIN_TYPE
, value
, absolute
))
4335 SetChangedFlag (true);
4337 case F_SelectedLines
:
4338 if (ChangeSelectedClearSize (LINE_TYPE
, value
, absolute
))
4339 SetChangedFlag (true);
4341 case F_SelectedArcs
:
4342 if (ChangeSelectedClearSize (ARC_TYPE
, value
, absolute
))
4343 SetChangedFlag (true);
4346 case F_SelectedObjects
:
4347 if (ChangeSelectedClearSize (CHANGECLEARSIZE_TYPES
, value
, absolute
))
4348 SetChangedFlag (true);
4355 /* --------------------------------------------------------------------------- */
4357 static const char minmaskgap_syntax
[] =
4358 N_("MinMaskGap(delta)\n"
4359 "MinMaskGap(Selected, delta)");
4361 static const char minmaskgap_help
[] =
4362 N_("Ensures the mask is a minimum distance from pins and pads.");
4364 /* %start-doc actions MinMaskGap
4366 Checks all specified pins and/or pads, and increases the mask if
4367 needed to ensure a minimum distance between the pin or pad edge and
4373 ActionMinMaskGap (int argc
, char **argv
, Coord x
, Coord y
)
4375 char *function
= ARG (0);
4376 char *delta
= ARG (1);
4377 char *units
= ARG (2);
4385 if (strcasecmp (function
, "Selected") == 0)
4386 flags
= SELECTEDFLAG
;
4393 value
= 2 * GetValue (delta
, units
, &absolute
);
4395 SaveUndoSerialNumber ();
4396 ELEMENT_LOOP (PCB
->Data
);
4400 if (!TEST_FLAGS (flags
, pin
) || ! pin
->Mask
)
4403 thickness
= pin
->DrillingHole
;
4405 if (pin
->Thickness
> thickness
)
4406 thickness
= pin
->Thickness
;
4410 if (pin
->Mask
< thickness
)
4412 ChangeObjectMaskSize (PIN_TYPE
, element
, pin
, 0, thickness
, 1);
4413 RestoreUndoSerialNumber ();
4419 if (!TEST_FLAGS (flags
, pad
) || ! pad
->Mask
)
4421 if (pad
->Mask
< pad
->Thickness
+ value
)
4423 ChangeObjectMaskSize (PAD_TYPE
, element
, pad
, 0,
4424 pad
->Thickness
+ value
, 1);
4425 RestoreUndoSerialNumber ();
4431 VIA_LOOP (PCB
->Data
);
4433 if (!TEST_FLAGS (flags
, via
) || ! via
->Mask
)
4436 thickness
= via
->DrillingHole
;
4437 if (via
->Thickness
> thickness
)
4438 thickness
= via
->Thickness
;
4441 if (via
->Mask
< thickness
)
4443 ChangeObjectMaskSize (VIA_TYPE
, via
, 0, 0, thickness
, 1);
4444 RestoreUndoSerialNumber ();
4448 RestoreUndoSerialNumber ();
4449 IncrementUndoSerialNumber ();
4453 /* --------------------------------------------------------------------------- */
4455 static const char mincleargap_syntax
[] =
4456 N_("MinClearGap(delta)\n"
4457 "MinClearGap(Selected, delta)");
4459 static const char mincleargap_help
[] =
4460 N_("Ensures that polygons are a minimum distance from objects.");
4462 /* %start-doc actions MinClearGap
4464 Checks all specified objects, and increases the polygon clearance if
4465 needed to ensure a minimum distance between their edges and the
4471 ActionMinClearGap (int argc
, char **argv
, Coord x
, Coord y
)
4473 char *function
= ARG (0);
4474 char *delta
= ARG (1);
4475 char *units
= ARG (2);
4482 if (strcasecmp (function
, "Selected") == 0)
4483 flags
= SELECTEDFLAG
;
4490 value
= 2 * GetValue (delta
, units
, &absolute
);
4492 SaveUndoSerialNumber ();
4493 ELEMENT_LOOP (PCB
->Data
);
4497 if (!TEST_FLAGS (flags
, pin
))
4499 if (pin
->Clearance
< value
)
4501 ChangeObjectClearSize (PIN_TYPE
, element
, pin
, 0,
4503 RestoreUndoSerialNumber ();
4509 if (!TEST_FLAGS (flags
, pad
))
4511 if (pad
->Clearance
< value
)
4513 ChangeObjectClearSize (PAD_TYPE
, element
, pad
, 0,
4515 RestoreUndoSerialNumber ();
4521 VIA_LOOP (PCB
->Data
);
4523 if (!TEST_FLAGS (flags
, via
))
4525 if (via
->Clearance
< value
)
4527 ChangeObjectClearSize (VIA_TYPE
, via
, 0, 0, value
, 1);
4528 RestoreUndoSerialNumber ();
4532 ALLLINE_LOOP (PCB
->Data
);
4534 if (!TEST_FLAGS (flags
, line
))
4536 if (line
->Clearance
< value
)
4538 ChangeObjectClearSize (LINE_TYPE
, layer
, line
, 0, value
, 1);
4539 RestoreUndoSerialNumber ();
4543 ALLARC_LOOP (PCB
->Data
);
4545 if (!TEST_FLAGS (flags
, arc
))
4547 if (arc
->Clearance
< value
)
4549 ChangeObjectClearSize (ARC_TYPE
, layer
, arc
, 0, value
, 1);
4550 RestoreUndoSerialNumber ();
4554 RestoreUndoSerialNumber ();
4555 IncrementUndoSerialNumber ();
4559 /* --------------------------------------------------------------------------- */
4561 static const char changepinname_syntax
[] =
4562 N_("ChangePinName(ElementName,PinNumber,PinName)");
4564 static const char changepinname_help
[] =
4565 N_("Sets the name of a specific pin on a specific element.");
4567 /* %start-doc actions ChangePinName
4569 This can be especially useful for annotating pin names from a
4570 schematic to the layout without requiring knowledge of the pcb file
4574 ChangePinName(U3, 7, VCC)
4580 ActionChangePinName (int argc
, char **argv
, Coord x
, Coord y
)
4583 char *refdes
, *pinnum
, *pinname
;
4587 AFAIL (changepinname
);
4594 ELEMENT_LOOP (PCB
->Data
);
4596 if (NSTRCMP (refdes
, NAMEONPCB_NAME (element
)) == 0)
4600 if (NSTRCMP (pinnum
, pin
->Number
) == 0)
4602 AddObjectToChangeNameUndoList (PIN_TYPE
, NULL
, NULL
,
4605 * Note: we can't free() pin->Name first because
4606 * it is used in the undo list
4608 pin
->Name
= strdup (pinname
);
4609 SetChangedFlag (true);
4617 if (NSTRCMP (pinnum
, pad
->Number
) == 0)
4619 AddObjectToChangeNameUndoList (PAD_TYPE
, NULL
, NULL
,
4622 * Note: we can't free() pad->Name first because
4623 * it is used in the undo list
4625 pad
->Name
= strdup (pinname
);
4626 SetChangedFlag (true);
4635 * done with our action so increment the undo # if we actually
4641 defer_needs_update
= 1;
4644 IncrementUndoSerialNumber ();
4645 gui
->invalidate_all ();
4652 /* --------------------------------------------------------------------------- */
4654 static const char changename_syntax
[] =
4655 N_("ChangeName(Object)\n"
4656 "ChangeName(Layout|Layer)");
4658 static const char changename_help
[] = N_("Sets the name of objects.");
4660 /* %start-doc actions ChangeName
4665 Changes the name of the element under the cursor.
4668 Changes the name of the layout. This is printed on the fab drawings.
4671 Changes the name of the currently active layer.
4678 ActionChangeName (int argc
, char **argv
, Coord x
, Coord y
)
4680 char *function
= ARG (0);
4685 switch (GetFunctionID (function
))
4687 /* change the name of an object */
4691 void *ptr1
, *ptr2
, *ptr3
;
4693 gui
->get_coords (_("Select an Object"), &x
, &y
);
4695 SearchScreen (x
, y
, CHANGENAME_TYPES
,
4696 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4698 SaveUndoSerialNumber ();
4699 if (QueryInputAndChangeObjectName (type
, ptr1
, ptr2
, ptr3
))
4701 SetChangedFlag (true);
4702 if (type
== ELEMENT_TYPE
)
4704 RubberbandType
*ptr
;
4707 RestoreUndoSerialNumber ();
4708 Crosshair
.AttachedObject
.RubberbandN
= 0;
4709 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
4710 ptr
= Crosshair
.AttachedObject
.Rubberband
;
4711 for (i
= 0; i
< Crosshair
.AttachedObject
.RubberbandN
;
4715 EraseRat ((RatType
*) ptr
->Line
);
4716 MoveObjectToRemoveUndoList (RATLINE_TYPE
,
4717 ptr
->Line
, ptr
->Line
,
4720 IncrementUndoSerialNumber ();
4728 /* change the layout's name */
4731 gui
->prompt_for (_("Enter the layout name:"), EMPTY (PCB
->Name
));
4732 /* NB: ChangeLayoutName takes ownership of the passed memory */
4733 if (name
&& ChangeLayoutName (name
))
4734 SetChangedFlag (true);
4737 /* change the name of the active layer */
4739 name
= gui
->prompt_for (_("Enter the layer name:"),
4740 EMPTY (CURRENT
->Name
));
4741 /* NB: ChangeLayerName takes ownership of the passed memory */
4742 if (name
&& ChangeLayerName (CURRENT
, name
))
4743 SetChangedFlag (true);
4751 /* --------------------------------------------------------------------------- */
4753 static const char morphpolygon_syntax
[] = N_("MorphPolygon(Object|Selected)");
4755 static const char morphpolygon_help
[] =
4756 N_("Converts dead polygon islands into separate polygons.");
4758 /* %start-doc actions MorphPolygon
4760 If a polygon is divided into unconnected "islands", you can use
4761 this command to convert the otherwise disappeared islands into
4762 separate polygons. Be sure the cursor is over a portion of the
4763 polygon that remains visible. Very small islands that may flake
4764 off are automatically deleted.
4769 ActionMorphPolygon (int argc
, char **argv
, Coord x
, Coord y
)
4771 char *function
= ARG (0);
4774 switch (GetFunctionID (function
))
4779 void *ptr1
, *ptr2
, *ptr3
;
4781 gui
->get_coords (_("Select an Object"), &x
, &y
);
4782 if ((type
= SearchScreen (x
, y
, POLYGON_TYPE
,
4783 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4785 MorphPolygon ((LayerType
*) ptr1
, (PolygonType
*) ptr3
);
4787 IncrementUndoSerialNumber ();
4792 case F_SelectedObjects
:
4793 ALLPOLYGON_LOOP (PCB
->Data
);
4795 if (TEST_FLAG (SELECTEDFLAG
, polygon
))
4796 MorphPolygon (layer
, polygon
);
4800 IncrementUndoSerialNumber ();
4807 /* --------------------------------------------------------------------------- */
4809 static const char togglehidename_syntax
[] =
4810 N_("ToggleHideName(Object|SelectedElements)");
4812 static const char togglehidename_help
[] =
4813 N_("Toggles the visibility of element names.");
4815 /* %start-doc actions ToggleHideName
4817 If names are hidden you won't see them on the screen and they will not
4818 appear on the silk layer when you print the layout.
4823 ActionToggleHideName (int argc
, char **argv
, Coord x
, Coord y
)
4825 char *function
= ARG (0);
4826 if (function
&& PCB
->ElementOn
)
4828 switch (GetFunctionID (function
))
4833 void *ptr1
, *ptr2
, *ptr3
;
4835 gui
->get_coords (_("Select an Object"), &x
, &y
);
4836 if ((type
= SearchScreen (x
, y
, ELEMENT_TYPE
,
4837 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4839 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr3
);
4840 EraseElementName ((ElementType
*) ptr2
);
4841 TOGGLE_FLAG (HIDENAMEFLAG
, (ElementType
*) ptr2
);
4842 DrawElementName ((ElementType
*) ptr2
);
4844 IncrementUndoSerialNumber ();
4848 case F_SelectedElements
:
4851 bool changed
= false;
4852 ELEMENT_LOOP (PCB
->Data
);
4854 if ((TEST_FLAG (SELECTEDFLAG
, element
) ||
4855 TEST_FLAG (SELECTEDFLAG
,
4856 &NAMEONPCB_TEXT (element
)))
4857 && (FRONT (element
) || PCB
->InvisibleObjectsOn
))
4859 AddObjectToFlagUndoList (ELEMENT_TYPE
, element
,
4861 EraseElementName (element
);
4862 TOGGLE_FLAG (HIDENAMEFLAG
, element
);
4863 DrawElementName (element
);
4871 IncrementUndoSerialNumber ();
4879 /* --------------------------------------------------------------------------- */
4881 static const char changejoin_syntax
[] =
4882 N_("ChangeJoin(ToggleObject|SelectedLines|SelectedArcs|Selected)");
4884 static const char changejoin_help
[] =
4885 N_("Changes the join (clearance through polygons) of objects.");
4887 /* %start-doc actions ChangeJoin
4889 The join flag determines whether a line or arc, drawn to intersect a
4890 polygon, electrically connects to the polygon or not. When joined,
4891 the line/arc is simply drawn over the polygon, making an electrical
4892 connection. When not joined, a gap is drawn between the line and the
4893 polygon, insulating them from each other.
4898 ActionChangeJoin (int argc
, char **argv
, Coord x
, Coord y
)
4900 char *function
= ARG (0);
4903 switch (GetFunctionID (function
))
4905 case F_ToggleObject
:
4909 void *ptr1
, *ptr2
, *ptr3
;
4911 gui
->get_coords (_("Select an Object"), &x
, &y
);
4913 SearchScreen (x
, y
, CHANGEJOIN_TYPES
,
4914 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4915 if (ChangeObjectJoin (type
, ptr1
, ptr2
, ptr3
))
4916 SetChangedFlag (true);
4920 case F_SelectedLines
:
4921 if (ChangeSelectedJoin (LINE_TYPE
))
4922 SetChangedFlag (true);
4925 case F_SelectedArcs
:
4926 if (ChangeSelectedJoin (ARC_TYPE
))
4927 SetChangedFlag (true);
4931 case F_SelectedObjects
:
4932 if (ChangeSelectedJoin (CHANGEJOIN_TYPES
))
4933 SetChangedFlag (true);
4940 /* --------------------------------------------------------------------------- */
4942 static const char changesquare_syntax
[] =
4943 N_("ChangeSquare(ToggleObject)\n"
4944 "ChangeSquare(SelectedElements|SelectedPins)\n"
4945 "ChangeSquare(Selected|SelectedObjects)");
4947 static const char changesquare_help
[] =
4948 N_("Changes the square flag of pins and pads.");
4950 /* %start-doc actions ChangeSquare
4952 Note that @code{Pins} means both pins and pads.
4959 ActionChangeSquare (int argc
, char **argv
, Coord x
, Coord y
)
4961 char *function
= ARG (0);
4964 switch (GetFunctionID (function
))
4966 case F_ToggleObject
:
4970 void *ptr1
, *ptr2
, *ptr3
;
4972 gui
->get_coords (_("Select an Object"), &x
, &y
);
4974 SearchScreen (x
, y
, CHANGESQUARE_TYPES
,
4975 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4976 if (ChangeObjectSquare (type
, ptr1
, ptr2
, ptr3
))
4977 SetChangedFlag (true);
4981 case F_SelectedElements
:
4982 if (ChangeSelectedSquare (ELEMENT_TYPE
))
4983 SetChangedFlag (true);
4986 case F_SelectedPins
:
4987 if (ChangeSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4988 SetChangedFlag (true);
4992 case F_SelectedObjects
:
4993 if (ChangeSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4994 SetChangedFlag (true);
5001 /* --------------------------------------------------------------------------- */
5003 static const char setsquare_syntax
[] =
5004 N_("SetSquare(ToggleObject|SelectedElements|SelectedPins)");
5006 static const char setsquare_help
[] = N_("sets the square-flag of objects.");
5008 /* %start-doc actions SetSquare
5010 Note that @code{Pins} means pins and pads.
5017 ActionSetSquare (int argc
, char **argv
, Coord x
, Coord y
)
5019 char *function
= ARG (0);
5020 if (function
&& *function
)
5022 switch (GetFunctionID (function
))
5024 case F_ToggleObject
:
5028 void *ptr1
, *ptr2
, *ptr3
;
5030 gui
->get_coords (_("Select an Object"), &x
, &y
);
5032 SearchScreen (x
, y
, CHANGESQUARE_TYPES
,
5033 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
5034 if (SetObjectSquare (type
, ptr1
, ptr2
, ptr3
))
5035 SetChangedFlag (true);
5039 case F_SelectedElements
:
5040 if (SetSelectedSquare (ELEMENT_TYPE
))
5041 SetChangedFlag (true);
5044 case F_SelectedPins
:
5045 if (SetSelectedSquare (PIN_TYPE
| PAD_TYPE
))
5046 SetChangedFlag (true);
5050 case F_SelectedObjects
:
5051 if (SetSelectedSquare (PIN_TYPE
| PAD_TYPE
))
5052 SetChangedFlag (true);
5059 /* --------------------------------------------------------------------------- */
5061 static const char clearsquare_syntax
[] =
5062 N_("ClearSquare(ToggleObject|SelectedElements|SelectedPins)");
5064 static const char clearsquare_help
[] =
5065 N_("Clears the square-flag of pins and pads.");
5067 /* %start-doc actions ClearSquare
5069 Note that @code{Pins} means pins and pads.
5076 ActionClearSquare (int argc
, char **argv
, Coord x
, Coord y
)
5078 char *function
= ARG (0);
5079 if (function
&& *function
)
5081 switch (GetFunctionID (function
))
5083 case F_ToggleObject
:
5087 void *ptr1
, *ptr2
, *ptr3
;
5089 gui
->get_coords (_("Select an Object"), &x
, &y
);
5091 SearchScreen (x
, y
, CHANGESQUARE_TYPES
,
5092 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
5093 if (ClrObjectSquare (type
, ptr1
, ptr2
, ptr3
))
5094 SetChangedFlag (true);
5098 case F_SelectedElements
:
5099 if (ClrSelectedSquare (ELEMENT_TYPE
))
5100 SetChangedFlag (true);
5103 case F_SelectedPins
:
5104 if (ClrSelectedSquare (PIN_TYPE
| PAD_TYPE
))
5105 SetChangedFlag (true);
5109 case F_SelectedObjects
:
5110 if (ClrSelectedSquare (PIN_TYPE
| PAD_TYPE
))
5111 SetChangedFlag (true);
5118 /* --------------------------------------------------------------------------- */
5120 static const char changeoctagon_syntax
[] =
5121 N_("ChangeOctagon(Object|ToggleObject|SelectedObjects|Selected)\n"
5122 "ChangeOctagon(SelectedElements|SelectedPins|SelectedVias)");
5124 static const char changeoctagon_help
[] =
5125 N_("Changes the octagon-flag of pins and vias.");
5127 /* %start-doc actions ChangeOctagon
5134 ActionChangeOctagon (int argc
, char **argv
, Coord x
, Coord y
)
5136 char *function
= ARG (0);
5139 switch (GetFunctionID (function
))
5141 case F_ToggleObject
:
5145 void *ptr1
, *ptr2
, *ptr3
;
5147 gui
->get_coords (_("Select an Object"), &x
, &y
);
5149 SearchScreen (x
, y
, CHANGEOCTAGON_TYPES
,
5150 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
5151 if (ChangeObjectOctagon (type
, ptr1
, ptr2
, ptr3
))
5152 SetChangedFlag (true);
5156 case F_SelectedElements
:
5157 if (ChangeSelectedOctagon (ELEMENT_TYPE
))
5158 SetChangedFlag (true);
5161 case F_SelectedPins
:
5162 if (ChangeSelectedOctagon (PIN_TYPE
))
5163 SetChangedFlag (true);
5166 case F_SelectedVias
:
5167 if (ChangeSelectedOctagon (VIA_TYPE
))
5168 SetChangedFlag (true);
5172 case F_SelectedObjects
:
5173 if (ChangeSelectedOctagon (PIN_TYPES
))
5174 SetChangedFlag (true);
5181 /* --------------------------------------------------------------------------- */
5183 static const char setoctagon_syntax
[] =
5184 N_("SetOctagon(Object|ToggleObject|SelectedElements|Selected)");
5186 static const char setoctagon_help
[] = N_("Sets the octagon-flag of objects.");
5188 /* %start-doc actions SetOctagon
5195 ActionSetOctagon (int argc
, char **argv
, Coord x
, Coord y
)
5197 char *function
= ARG (0);
5200 switch (GetFunctionID (function
))
5202 case F_ToggleObject
:
5206 void *ptr1
, *ptr2
, *ptr3
;
5208 gui
->get_coords (_("Select an Object"), &x
, &y
);
5210 SearchScreen (x
, y
, CHANGEOCTAGON_TYPES
,
5211 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
5212 if (SetObjectOctagon (type
, ptr1
, ptr2
, ptr3
))
5213 SetChangedFlag (true);
5217 case F_SelectedElements
:
5218 if (SetSelectedOctagon (ELEMENT_TYPE
))
5219 SetChangedFlag (true);
5222 case F_SelectedPins
:
5223 if (SetSelectedOctagon (PIN_TYPE
))
5224 SetChangedFlag (true);
5227 case F_SelectedVias
:
5228 if (SetSelectedOctagon (VIA_TYPE
))
5229 SetChangedFlag (true);
5233 case F_SelectedObjects
:
5234 if (SetSelectedOctagon (PIN_TYPES
))
5235 SetChangedFlag (true);
5242 /* --------------------------------------------------------------------------- */
5244 static const char clearoctagon_syntax
[] =
5245 N_("ClearOctagon(ToggleObject|Object|SelectedObjects|Selected)\n"
5246 "ClearOctagon(SelectedElements|SelectedPins|SelectedVias)");
5248 static const char clearoctagon_help
[] =
5249 N_("Clears the octagon-flag of pins and vias.");
5251 /* %start-doc actions ClearOctagon
5258 ActionClearOctagon (int argc
, char **argv
, Coord x
, Coord y
)
5260 char *function
= ARG (0);
5263 switch (GetFunctionID (function
))
5265 case F_ToggleObject
:
5269 void *ptr1
, *ptr2
, *ptr3
;
5271 gui
->get_coords (_("Select an Object"), &x
, &y
);
5273 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGEOCTAGON_TYPES
,
5274 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
5275 if (ClrObjectOctagon (type
, ptr1
, ptr2
, ptr3
))
5276 SetChangedFlag (true);
5280 case F_SelectedElements
:
5281 if (ClrSelectedOctagon (ELEMENT_TYPE
))
5282 SetChangedFlag (true);
5285 case F_SelectedPins
:
5286 if (ClrSelectedOctagon (PIN_TYPE
))
5287 SetChangedFlag (true);
5290 case F_SelectedVias
:
5291 if (ClrSelectedOctagon (VIA_TYPE
))
5292 SetChangedFlag (true);
5296 case F_SelectedObjects
:
5297 if (ClrSelectedOctagon (PIN_TYPES
))
5298 SetChangedFlag (true);
5305 /* --------------------------------------------------------------------------- */
5307 static const char changehold_syntax
[] =
5308 N_("ChangeHole(ToggleObject|Object|SelectedVias|Selected)");
5310 static const char changehold_help
[] = N_("Changes the hole flag of objects.");
5312 /* %start-doc actions ChangeHole
5314 The "hole flag" of a via determines whether the via is a
5315 plated-through hole (not set), or an unplated hole (set).
5320 ActionChangeHole (int argc
, char **argv
, Coord x
, Coord y
)
5322 char *function
= ARG (0);
5325 switch (GetFunctionID (function
))
5327 case F_ToggleObject
:
5331 void *ptr1
, *ptr2
, *ptr3
;
5333 gui
->get_coords (_("Select an Object"), &x
, &y
);
5334 if ((type
= SearchScreen (x
, y
, VIA_TYPE
,
5335 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
5336 && ChangeHole ((PinType
*) ptr3
))
5337 IncrementUndoSerialNumber ();
5341 case F_SelectedVias
:
5343 if (ChangeSelectedHole ())
5344 SetChangedFlag (true);
5351 /* --------------------------------------------------------------------------- */
5353 static const char changepaste_syntax
[] =
5354 N_("ChangePaste(ToggleObject|Object|SelectedPads|Selected)");
5356 static const char changepaste_help
[] =
5357 N_("Changes the no paste flag of objects.");
5359 /* %start-doc actions ChangePaste
5361 The "no paste flag" of a pad determines whether the solderpaste
5362 stencil will have an opening for the pad (no set) or if there wil be
5363 no solderpaste on the pad (set). This is used for things such as
5369 ActionChangePaste (int argc
, char **argv
, Coord x
, Coord y
)
5371 char *function
= ARG (0);
5374 switch (GetFunctionID (function
))
5376 case F_ToggleObject
:
5380 void *ptr1
, *ptr2
, *ptr3
;
5382 gui
->get_coords (_("Select an Object"), &x
, &y
);
5383 if ((type
= SearchScreen (x
, y
, PAD_TYPE
,
5384 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
5385 && ChangePaste ((PadType
*) ptr3
))
5386 IncrementUndoSerialNumber ();
5390 case F_SelectedPads
:
5392 if (ChangeSelectedPaste ())
5393 SetChangedFlag (true);
5400 /* --------------------------------------------------------------------------- */
5402 static const char select_syntax
[] =
5403 N_("Select(Object|ToggleObject)\n"
5404 "Select(All|Block|Connection|BuriedVias)\n"
5405 "Select(ElementByName|ObjectByName|PadByName|PinByName)\n"
5406 "Select(ElementByName|ObjectByName|PadByName|PinByName, Name)\n"
5407 "Select(TextByName|ViaByName|NetByName)\n"
5408 "Select(TextByName|ViaByName|NetByName, Name)\n"
5411 static const char select_help
[] = N_("Toggles or sets the selection.");
5413 /* %start-doc actions Select
5425 These all rely on having a regular expression parser built into
5426 @code{pcb}. If the name is not specified then the user is prompted
5427 for a pattern, and all objects that match the pattern and are of the
5428 type specified are selected.
5432 Selects the object under the cursor.
5435 Selects all objects in a rectangle indicated by the cursor.
5438 Selects all objects on the board.
5441 Selects all connections with the ``found'' flag set.
5444 Selects all connections with the ``connected'' flag set.
5447 Selects all blind and buried vias.
5450 Converts the selected objects to an element. This uses the highest
5451 numbered paste buffer.
5458 ActionSelect (int argc
, char **argv
, Coord x
, Coord y
)
5460 char *function
= ARG (0);
5463 switch (GetFunctionID (function
))
5465 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
5467 /* select objects by their names */
5468 case F_ElementByName
:
5469 type
= ELEMENT_TYPE
;
5471 case F_ObjectByName
:
5492 char *pattern
= ARG (1);
5496 gui
->prompt_for (_("Enter pattern:"), "")) != NULL
)
5498 if (SelectObjectByName (type
, pattern
, true))
5499 SetChangedFlag (true);
5500 if (ARG (1) == NULL
)
5505 #endif /* defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) */
5507 /* select a single object */
5508 case F_ToggleObject
:
5510 if (SelectObject ())
5511 SetChangedFlag (true);
5514 /* all objects in block */
5519 box
.X1
= MIN (Crosshair
.AttachedBox
.Point1
.X
,
5520 Crosshair
.AttachedBox
.Point2
.X
);
5521 box
.Y1
= MIN (Crosshair
.AttachedBox
.Point1
.Y
,
5522 Crosshair
.AttachedBox
.Point2
.Y
);
5523 box
.X2
= MAX (Crosshair
.AttachedBox
.Point1
.X
,
5524 Crosshair
.AttachedBox
.Point2
.X
);
5525 box
.Y2
= MAX (Crosshair
.AttachedBox
.Point1
.Y
,
5526 Crosshair
.AttachedBox
.Point2
.Y
);
5527 notify_crosshair_change (false);
5529 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
&&
5530 SelectBlock (&box
, true))
5532 SetChangedFlag (true);
5533 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
5535 notify_crosshair_change (true);
5539 /* select all visible objects */
5544 box
.X1
= -MAX_COORD
;
5545 box
.Y1
= -MAX_COORD
;
5548 if (SelectBlock (&box
, true))
5549 SetChangedFlag (true);
5553 /* all logical connections */
5555 if (SelectByFlag (FOUNDFLAG
, true))
5558 IncrementUndoSerialNumber ();
5559 SetChangedFlag (true);
5563 /* all physical connections */
5565 if (SelectByFlag (CONNECTEDFLAG
, true))
5568 IncrementUndoSerialNumber ();
5569 SetChangedFlag (true);
5574 if (SelectBuriedVias (true))
5577 IncrementUndoSerialNumber ();
5578 SetChangedFlag (true);
5585 Note
.Buffer
= Settings
.BufferNumber
;
5586 SetBufferNumber (MAX_BUFFER
- 1);
5587 ClearBuffer (PASTEBUFFER
);
5588 gui
->get_coords (_("Select the Element's Mark Location"), &x
, &y
);
5589 x
= GridFit (x
, PCB
->Grid
, PCB
->GridOffsetX
);
5590 y
= GridFit (y
, PCB
->Grid
, PCB
->GridOffsetY
);
5591 AddSelectedToBuffer (PASTEBUFFER
, x
, y
, true);
5592 SaveUndoSerialNumber ();
5594 ConvertBufferToElement (PASTEBUFFER
);
5595 RestoreUndoSerialNumber ();
5596 CopyPastebufferToLayout (x
, y
);
5597 SetBufferNumber (Note
.Buffer
);
5609 /* FLAG(have_regex,FlagHaveRegex,0) */
5611 FlagHaveRegex (int parm
)
5613 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
5620 /* --------------------------------------------------------------------------- */
5622 static const char unselect_syntax
[] =
5623 N_("Unselect(All|Block|Connection)\n"
5624 "Unselect(ElementByName|ObjectByName|PadByName|PinByName)\n"
5625 "Unselect(ElementByName|ObjectByName|PadByName|PinByName, Name)\n"
5626 "Unselect(TextByName|ViaByName)\n"
5627 "Unselect(TextByName|ViaByName, Name)\n");
5629 static const char unselect_help
[] =
5630 N_("Unselects the object at the pointer location or the specified objects.");
5632 /* %start-doc actions Unselect
5637 Unselect all objects.
5640 Unselect all objects in a rectangle given by the cursor.
5643 Unselect all connections with the ``found'' flag set.
5652 These all rely on having a regular expression parser built into
5653 @code{pcb}. If the name is not specified then the user is prompted
5654 for a pattern, and all objects that match the pattern and are of the
5655 type specified are unselected.
5663 ActionUnselect (int argc
, char **argv
, Coord x
, Coord y
)
5665 char *function
= ARG (0);
5668 switch (GetFunctionID (function
))
5670 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
5672 /* select objects by their names */
5673 case F_ElementByName
:
5674 type
= ELEMENT_TYPE
;
5676 case F_ObjectByName
:
5697 char *pattern
= ARG (1);
5701 gui
->prompt_for (_("Enter pattern:"), "")) != NULL
)
5703 if (SelectObjectByName (type
, pattern
, false))
5704 SetChangedFlag (true);
5705 if (ARG (1) == NULL
)
5710 #endif /* defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) */
5712 /* all objects in block */
5717 box
.X1
= MIN (Crosshair
.AttachedBox
.Point1
.X
,
5718 Crosshair
.AttachedBox
.Point2
.X
);
5719 box
.Y1
= MIN (Crosshair
.AttachedBox
.Point1
.Y
,
5720 Crosshair
.AttachedBox
.Point2
.Y
);
5721 box
.X2
= MAX (Crosshair
.AttachedBox
.Point1
.X
,
5722 Crosshair
.AttachedBox
.Point2
.X
);
5723 box
.Y2
= MAX (Crosshair
.AttachedBox
.Point1
.Y
,
5724 Crosshair
.AttachedBox
.Point2
.Y
);
5725 notify_crosshair_change (false);
5727 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
&&
5728 SelectBlock (&box
, false))
5730 SetChangedFlag (true);
5731 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
5733 notify_crosshair_change (true);
5737 /* unselect all visible objects */
5742 box
.X1
= -MAX_COORD
;
5743 box
.Y1
= -MAX_COORD
;
5746 if (SelectBlock (&box
, false))
5747 SetChangedFlag (true);
5751 /* all logical connections */
5753 if (SelectByFlag (FOUNDFLAG
, false))
5756 IncrementUndoSerialNumber ();
5757 SetChangedFlag (true);
5761 /* all physical connections */
5763 if (SelectByFlag (CONNECTEDFLAG
, false))
5766 IncrementUndoSerialNumber ();
5767 SetChangedFlag (true);
5780 /* --------------------------------------------------------------------------- */
5782 static const char saveto_syntax
[] =
5783 N_("SaveTo(Layout|LayoutAs,filename)\n"
5784 "SaveTo(AllConnections|AllUnusedPins|ElementConnections,filename)\n"
5785 "SaveTo(PasteBuffer,filename)");
5787 static const char saveto_help
[] = N_("Saves data to a file.");
5789 /* %start-doc actions SaveTo
5794 Saves the current layout.
5797 Saves the current layout, and remembers the filename used.
5799 @item AllConnections
5800 Save all connections to a file.
5803 List all unused pins to a file.
5805 @item ElementConnections
5806 Save connections to the element at the cursor to a file.
5809 Save the content of the active Buffer to a file. This is the graphical way to create a footprint.
5816 ActionSaveTo (int argc
, char **argv
, Coord x
, Coord y
)
5823 if ( ! function
|| strcasecmp (function
, "Layout") == 0)
5825 if (SavePCB (PCB
->Filename
) == 0)
5826 SetChangedFlag (false);
5835 if (strcasecmp (function
, "LayoutAs") == 0)
5837 if (SavePCB (name
) == 0)
5839 SetChangedFlag (false);
5840 free (PCB
->Filename
);
5841 PCB
->Filename
= strdup (name
);
5842 if (gui
->notify_filename_changed
!= NULL
)
5843 gui
->notify_filename_changed ();
5848 if (strcasecmp (function
, "AllConnections") == 0)
5852 if ((fp
= CheckAndOpenFile (name
, true, false, &result
, NULL
)) != NULL
)
5854 LookupConnectionsToAllElements (fp
);
5856 SetChangedFlag (true);
5861 if (strcasecmp (function
, "AllUnusedPins") == 0)
5865 if ((fp
= CheckAndOpenFile (name
, true, false, &result
, NULL
)) != NULL
)
5867 LookupUnusedPins (fp
);
5869 SetChangedFlag (true);
5874 if (strcasecmp (function
, "ElementConnections") == 0)
5876 ElementType
*element
;
5881 if ((SearchScreen (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
,
5882 &ptrtmp
, &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
5884 element
= (ElementType
*) ptrtmp
;
5886 CheckAndOpenFile (name
, true, false, &result
, NULL
)) != NULL
)
5888 LookupElementConnections (element
, fp
);
5890 SetChangedFlag (true);
5896 if (strcasecmp (function
, "PasteBuffer") == 0)
5898 return SaveBufferElements (name
);
5904 /* --------------------------------------------------------------------------- */
5906 static const char savesettings_syntax
[] =
5907 N_("SaveSettings()\n"
5908 "SaveSettings(local)");
5910 static const char savesettings_help
[] = N_("Saves settings.");
5912 /* %start-doc actions SaveSettings
5914 If you pass no arguments, the settings are stored in
5915 @code{$HOME/.pcb/settings}. If you pass the word @code{local} they're
5916 saved in @code{./pcb.settings}.
5921 ActionSaveSettings (int argc
, char **argv
, Coord x
, Coord y
)
5923 int locally
= argc
> 0 ? (strncasecmp (argv
[0], "local", 5) == 0) : 0;
5924 hid_save_settings (locally
);
5928 /* --------------------------------------------------------------------------- */
5930 static const char loadfrom_syntax
[] =
5931 N_("LoadFrom(Layout|LayoutToBuffer|ElementToBuffer|STEPOutlineToBufferLines|STEPOutlineToBufferPolys|Netlist|Revert,filename)");
5933 static const char loadfrom_help
[] = N_("Load layout data from a file.");
5935 /* %start-doc actions LoadFrom
5937 This action assumes you know what the filename is. The various GUIs
5938 should have a similar @code{Load} action where the filename is
5939 optional, and will provide their own file selection mechanism to let
5940 you choose the file name.
5945 Loads an entire PCB layout, replacing the current one.
5947 @item LayoutToBuffer
5948 Loads an entire PCB layout to the paste buffer.
5950 @item ElementToBuffer
5951 Loads the given element file into the paste buffer. Element files
5952 contain only a single @code{Element} definition, such as the
5953 ``newlib'' library uses.
5956 Loads a new netlist, replacing any current netlist.
5959 Re-loads the current layout from its disk file, reverting any changes
5967 ActionLoadFrom (int argc
, char **argv
, Coord x
, Coord y
)
5978 if (strcasecmp (function
, "ElementToBuffer") == 0)
5980 notify_crosshair_change (false);
5981 if (LoadElementToBuffer (PASTEBUFFER
, name
, true))
5982 SetMode (PASTEBUFFER_MODE
);
5983 notify_crosshair_change (true);
5986 else if (strcasecmp (function
, "LayoutToBuffer") == 0)
5988 notify_crosshair_change (false);
5989 if (LoadLayoutToBuffer (PASTEBUFFER
, name
))
5990 SetMode (PASTEBUFFER_MODE
);
5991 notify_crosshair_change (true);
5994 else if (strcasecmp (function
, "STEPOutlineTobufferLines") == 0)
5996 notify_crosshair_change (false);
5997 if (!hid_actionl ("LoadSTEPOutlineToBuffer", name
, NULL
))
5998 SetMode (PASTEBUFFER_MODE
);
5999 notify_crosshair_change (true);
6002 else if (strcasecmp (function
, "STEPOutlineTobufferPolys") == 0)
6004 notify_crosshair_change (false);
6005 if (!hid_actionl ("LoadSTEPOutlineToBuffer", name
, "polys", NULL
))
6006 SetMode (PASTEBUFFER_MODE
);
6007 notify_crosshair_change (true);
6010 else if (strcasecmp (function
, "Layout") == 0)
6012 if (!PCB
->Changed
||
6013 gui
->confirm_dialog (_("OK to override layout data?"), 0))
6017 else if (strcasecmp (function
, "Netlist") == 0)
6019 if (PCB
->Netlistname
)
6020 free (PCB
->Netlistname
);
6021 PCB
->Netlistname
= StripWhiteSpaceAndDup (name
);
6022 FreeLibraryMemory (&PCB
->NetlistLib
);
6023 ImportNetlist (PCB
->Netlistname
);
6026 else if (strcasecmp (function
, "Revert") == 0 && PCB
->Filename
6028 || gui
->confirm_dialog (_("OK to override changes?"), 0)))
6036 /* --------------------------------------------------------------------------- */
6038 static const char new_syntax
[] = N_("New([name])");
6040 static const char new_help
[] = N_("Starts a new layout.");
6042 /* %start-doc actions New
6044 If a name is not given, one is prompted for.
6049 ActionNew (int argc
, char **argv
, Coord x
, Coord y
)
6051 char *name
= ARG (0);
6053 if (!PCB
->Changed
|| gui
->confirm_dialog (_("OK to clear layout data?"), 0))
6056 name
= strdup (name
);
6058 name
= gui
->prompt_for (_("Enter the layout name:"), "");
6063 notify_crosshair_change (false);
6064 /* do emergency saving
6065 * clear the old struct and allocate memory for the new one
6067 if (PCB
->Changed
&& Settings
.SaveInTMP
)
6071 PCB
= CreateNewPCB ();
6072 CreateNewPCBPost (PCB
, 1);
6074 /* setup the new name and reset some values to default */
6078 ResetStackAndVisibility ();
6079 SetCrosshairRange (0, 0, PCB
->MaxWidth
, PCB
->MaxHeight
);
6080 CenterDisplay (PCB
->MaxWidth
/ 2, PCB
->MaxHeight
/ 2, false);
6083 hid_action ("PCBChanged");
6084 notify_crosshair_change (true);
6091 * \brief No operation, just for testing purposes.
6092 * syntax: Bell(volume)
6095 ActionBell (char *volume
)
6100 /* --------------------------------------------------------------------------- */
6102 static const char pastebuffer_syntax
[] =
6103 N_("PasteBuffer(AddSelected|Clear|1..MAX_BUFFER)\n"
6104 "PasteBuffer(Rotate, 1..3)\n"
6105 "PasteBuffer(Convert|Save|Restore|Mirror)\n"
6106 "PasteBuffer(ToLayout, X, Y, units)");
6108 static const char pastebuffer_help
[] =
6109 N_("Various operations on the paste buffer.");
6111 /* %start-doc actions PasteBuffer
6113 There are a number of paste buffers; the actual limit is a
6114 compile-time constant @code{MAX_BUFFER} in @file{globalconst.h}. It
6115 is currently @code{5}. One of these is the ``current'' paste buffer,
6116 often referred to as ``the'' paste buffer.
6121 Copies the selected objects to the current paste buffer.
6124 Remove all objects from the current paste buffer.
6127 Convert the current paste buffer to an element. Vias are converted to
6128 pins, lines are converted to pads.
6131 Convert any elements in the paste buffer back to vias and lines.
6134 Flip all objects in the paste buffer vertically (up/down flip). To mirror
6135 horizontally, combine this with rotations.
6138 Rotates the current buffer. The number to pass is 1..3, where 1 means
6139 90 degrees counter clockwise, 2 means 180 degrees, and 3 means 90
6140 degrees clockwise (270 CCW).
6143 Saves any elements in the current buffer to the indicated file.
6146 Pastes any elements in the current buffer to the indicated X, Y
6147 coordinates in the layout. The @code{X} and @code{Y} are treated like
6148 @code{delta} is for many other objects. For each, if it's prefixed by
6149 @code{+} or @code{-}, then that amount is relative to the last
6150 location. Otherwise, it's absolute. Units can be
6151 @code{mil} or @code{mm}; if unspecified, units are PCB's internal
6152 units, currently 1/100 mil.
6156 Selects the given buffer to be the current paste buffer.
6163 ActionPasteBuffer (int argc
, char **argv
, Coord x
, Coord y
)
6165 char *function
= argc
? argv
[0] : (char *)"";
6166 char *sbufnum
= argc
> 1 ? argv
[1] : (char *)"";
6168 static char *default_file
= NULL
;
6171 notify_crosshair_change (false);
6174 switch (GetFunctionID (function
))
6176 /* clear contents of paste buffer */
6178 ClearBuffer (PASTEBUFFER
);
6181 /* copies objects to paste buffer */
6183 AddSelectedToBuffer (PASTEBUFFER
, 0, 0, false);
6186 /* converts buffer contents into an element */
6188 ConvertBufferToElement (PASTEBUFFER
);
6191 /* break up element for editing */
6193 SmashBufferElement (PASTEBUFFER
);
6198 MirrorBuffer (PASTEBUFFER
);
6204 RotateBuffer (PASTEBUFFER
, (BYTE
) atoi (sbufnum
));
6205 SetCrosshairRangeToBuffer ();
6210 if (PASTEBUFFER
->Data
->ElementN
== 0)
6212 Message (_("Buffer has no elements!\n"));
6218 name
= gui
->fileselect (_("Save Paste Buffer As ..."),
6219 _("Choose a file to save the contents of the\n"
6220 "paste buffer to.\n"),
6221 default_file
, ".fp", "footprint",
6226 free (default_file
);
6227 default_file
= NULL
;
6231 default_file
= strdup (name
);
6242 if ((exist
= fopen (name
, "r")))
6246 confirm_dialog (_("File exists! Ok to overwrite?"), 0))
6247 SaveBufferElements (name
);
6250 SaveBufferElements (name
);
6252 if (free_name
&& name
)
6259 static Coord oldx
= 0, oldy
= 0;
6267 else if (argc
== 3 || argc
== 4)
6269 x
= GetValue (ARG (1), ARG (3), &absolute
);
6272 y
= GetValue (ARG (2), ARG (3), &absolute
);
6278 notify_crosshair_change (true);
6279 AFAIL (pastebuffer
);
6284 if (CopyPastebufferToLayout (x
, y
))
6285 SetChangedFlag (true);
6292 int number
= atoi (function
);
6294 /* correct number */
6296 SetBufferNumber (number
- 1);
6301 notify_crosshair_change (true);
6305 /* --------------------------------------------------------------------------- */
6307 static const char undo_syntax
[] = N_("Undo()\n"
6310 static const char undo_help
[] = N_("Undo recent changes.");
6312 /* %start-doc actions Undo
6314 The unlimited undo feature of @code{Pcb} allows you to recover from
6315 most operations that materially affect you work. Calling
6316 @code{Undo()} without any parameter recovers from the last (non-undo)
6317 operation. @code{ClearList} is used to release the allocated
6318 memory. @code{ClearList} is called whenever a new layout is started or
6319 loaded. See also @code{Redo} and @code{Atomic}.
6321 Note that undo groups operations by serial number; changes with the
6322 same serial number will be undone (or redone) as a group. See
6328 ActionUndo (int argc
, char **argv
, Coord x
, Coord y
)
6330 char *function
= ARG (0);
6331 if (!function
|| !*function
)
6333 /* don't allow undo in the middle of an operation */
6334 if (Settings
.Mode
!= POLYGONHOLE_MODE
&&
6335 Crosshair
.AttachedObject
.State
!= STATE_FIRST
)
6337 if (Crosshair
.AttachedBox
.State
!= STATE_FIRST
6338 && Settings
.Mode
!= ARC_MODE
)
6340 /* undo the last operation */
6342 notify_crosshair_change (false);
6343 if ((Settings
.Mode
== POLYGON_MODE
||
6344 Settings
.Mode
== POLYGONHOLE_MODE
) &&
6345 Crosshair
.AttachedPolygon
.PointN
)
6347 GoToPreviousPoint ();
6348 notify_crosshair_change (true);
6351 /* move anchor point if undoing during line creation */
6352 if (Settings
.Mode
== LINE_MODE
)
6354 if (Crosshair
.AttachedLine
.State
== STATE_SECOND
)
6356 if (TEST_FLAG (AUTODRCFLAG
, PCB
))
6357 Undo (true); /* undo the connection find */
6358 Crosshair
.AttachedLine
.State
= STATE_FIRST
;
6359 SetLocalRef (0, 0, false);
6360 notify_crosshair_change (true);
6363 if (Crosshair
.AttachedLine
.State
== STATE_THIRD
)
6366 void *ptr1
, *ptr3
, *ptrtmp
;
6368 /* this search is guaranteed to succeed */
6369 SearchObjectByLocation (LINE_TYPE
| RATLINE_TYPE
, &ptr1
,
6371 Crosshair
.AttachedLine
.Point1
.X
,
6372 Crosshair
.AttachedLine
.Point1
.Y
, 0);
6373 ptr2
= (LineType
*) ptrtmp
;
6375 /* save both ends of line */
6376 Crosshair
.AttachedLine
.Point2
.X
= ptr2
->Point1
.X
;
6377 Crosshair
.AttachedLine
.Point2
.Y
= ptr2
->Point1
.Y
;
6378 if ((type
= Undo (true)))
6379 SetChangedFlag (true);
6380 /* check that the undo was of the right type */
6381 if ((type
& UNDO_CREATE
) == 0)
6383 /* wrong undo type, restore anchor points */
6384 Crosshair
.AttachedLine
.Point2
.X
=
6385 Crosshair
.AttachedLine
.Point1
.X
;
6386 Crosshair
.AttachedLine
.Point2
.Y
=
6387 Crosshair
.AttachedLine
.Point1
.Y
;
6388 notify_crosshair_change (true);
6391 /* move to new anchor */
6392 Crosshair
.AttachedLine
.Point1
.X
=
6393 Crosshair
.AttachedLine
.Point2
.X
;
6394 Crosshair
.AttachedLine
.Point1
.Y
=
6395 Crosshair
.AttachedLine
.Point2
.Y
;
6396 /* check if an intermediate point was removed */
6397 if (type
& UNDO_REMOVE
)
6399 /* this search should find the restored line */
6400 SearchObjectByLocation (LINE_TYPE
| RATLINE_TYPE
, &ptr1
,
6403 Crosshair
.AttachedLine
.Point2
.X
,
6404 Crosshair
.AttachedLine
.Point2
.Y
, 0);
6405 ptr2
= (LineType
*) ptrtmp
;
6406 if (TEST_FLAG (AUTODRCFLAG
, PCB
))
6408 /* undo loses CONNECTEDFLAG and FOUNDFLAG */
6409 SET_FLAG(CONNECTEDFLAG
, ptr2
);
6410 SET_FLAG(FOUNDFLAG
, ptr2
);
6411 DrawLine (CURRENT
, ptr2
);
6413 Crosshair
.AttachedLine
.Point1
.X
=
6414 Crosshair
.AttachedLine
.Point2
.X
= ptr2
->Point2
.X
;
6415 Crosshair
.AttachedLine
.Point1
.Y
=
6416 Crosshair
.AttachedLine
.Point2
.Y
= ptr2
->Point2
.Y
;
6418 FitCrosshairIntoGrid (Crosshair
.X
, Crosshair
.Y
);
6419 AdjustAttachedObjects ();
6420 if (--addedLines
== 0)
6422 Crosshair
.AttachedLine
.State
= STATE_SECOND
;
6423 lastLayer
= CURRENT
;
6427 /* this search is guaranteed to succeed too */
6428 SearchObjectByLocation (LINE_TYPE
| RATLINE_TYPE
, &ptr1
,
6431 Crosshair
.AttachedLine
.Point1
.X
,
6432 Crosshair
.AttachedLine
.Point1
.Y
, 0);
6433 ptr2
= (LineType
*) ptrtmp
;
6434 lastLayer
= (LayerType
*) ptr1
;
6436 notify_crosshair_change (true);
6440 if (Settings
.Mode
== ARC_MODE
)
6442 if (Crosshair
.AttachedBox
.State
== STATE_SECOND
)
6444 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
6445 notify_crosshair_change (true);
6448 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
)
6450 void *ptr1
, *ptr2
, *ptr3
;
6452 /* guaranteed to succeed */
6453 SearchObjectByLocation (ARC_TYPE
, &ptr1
, &ptr2
, &ptr3
,
6454 Crosshair
.AttachedBox
.Point1
.X
,
6455 Crosshair
.AttachedBox
.Point1
.Y
, 0);
6456 bx
= GetArcEnds ((ArcType
*) ptr2
);
6457 Crosshair
.AttachedBox
.Point1
.X
=
6458 Crosshair
.AttachedBox
.Point2
.X
= bx
->X1
;
6459 Crosshair
.AttachedBox
.Point1
.Y
=
6460 Crosshair
.AttachedBox
.Point2
.Y
= bx
->Y1
;
6461 AdjustAttachedObjects ();
6462 if (--addedLines
== 0)
6463 Crosshair
.AttachedBox
.State
= STATE_SECOND
;
6466 /* undo the last destructive operation */
6468 SetChangedFlag (true);
6472 switch (GetFunctionID (function
))
6474 /* clear 'undo objects' list */
6476 ClearUndoList (false);
6480 notify_crosshair_change (true);
6484 /* --------------------------------------------------------------------------- */
6486 static const char redo_syntax
[] = N_("Redo()");
6488 static const char redo_help
[] = N_("Redo recent \"undo\" operations.");
6490 /* %start-doc actions Redo
6492 This routine allows you to recover from the last undo command. You
6493 might want to do this if you thought that undo was going to revert
6494 something other than what it actually did (in case you are confused
6495 about which operations are un-doable), or if you have been backing up
6496 through a long undo list and over-shoot your stopping point. Any
6497 change that is made since the undo in question will trim the redo
6498 list. For example if you add ten lines, then undo three of them you
6499 could use redo to put them back, but if you move a line on the board
6500 before performing the redo, you will lose the ability to "redo" the
6501 three "undone" lines.
6506 ActionRedo (int argc
, char **argv
, Coord x
, Coord y
)
6508 if (((Settings
.Mode
== POLYGON_MODE
||
6509 Settings
.Mode
== POLYGONHOLE_MODE
) &&
6510 Crosshair
.AttachedPolygon
.PointN
) ||
6511 Crosshair
.AttachedLine
.State
== STATE_SECOND
)
6513 notify_crosshair_change (false);
6516 SetChangedFlag (true);
6517 if (Settings
.Mode
== LINE_MODE
&&
6518 Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
6520 LineType
*line
= g_list_last (CURRENT
->Line
)->data
;
6521 Crosshair
.AttachedLine
.Point1
.X
=
6522 Crosshair
.AttachedLine
.Point2
.X
= line
->Point2
.X
;
6523 Crosshair
.AttachedLine
.Point1
.Y
=
6524 Crosshair
.AttachedLine
.Point2
.Y
= line
->Point2
.Y
;
6528 notify_crosshair_change (true);
6532 /* --------------------------------------------------------------------------- */
6534 static const char polygon_syntax
[] = N_("Polygon(Close|PreviousPoint)");
6536 static const char polygon_help
[] = N_("Some polygon related stuff.");
6538 /* %start-doc actions Polygon
6540 Polygons need a special action routine to make life easier.
6545 Creates the final segment of the polygon. This may fail if clipping
6546 to 45 degree lines is switched on, in which case a warning is issued.
6549 Resets the newly entered corner to the previous one. The Undo action
6550 will call Polygon(PreviousPoint) when appropriate to do so.
6557 ActionPolygon (int argc
, char **argv
, Coord x
, Coord y
)
6559 char *function
= ARG (0);
6560 if (function
&& Settings
.Mode
== POLYGON_MODE
)
6562 notify_crosshair_change (false);
6563 switch (GetFunctionID (function
))
6565 /* close open polygon if possible */
6570 /* go back to the previous point */
6571 case F_PreviousPoint
:
6572 GoToPreviousPoint ();
6575 notify_crosshair_change (true);
6580 /* --------------------------------------------------------------------------- */
6582 static const char routestyle_syntax
[] = N_("RouteStyle(1|2|3|4)");
6584 static const char routestyle_help
[] =
6585 N_("Copies the indicated routing style into the current sizes.");
6587 /* %start-doc actions RouteStyle
6592 ActionRouteStyle (int argc
, char **argv
, Coord x
, Coord y
)
6594 char *str
= ARG (0);
6595 RouteStyleType
*rts
;
6600 number
= atoi (str
);
6601 if (number
> 0 && number
<= NUM_STYLES
)
6603 rts
= &PCB
->RouteStyle
[number
- 1];
6604 SetLineSize (rts
->Thick
);
6605 SetViaSize (rts
->Diameter
, true);
6606 SetViaDrillingHole (rts
->Hole
, true);
6607 SetKeepawayWidth (rts
->Keepaway
);
6608 hid_action("RouteStylesChanged");
6615 /* --------------------------------------------------------------------------- */
6617 static const char moveobject_syntax
[] = N_("MoveObject(X,Y,dim)");
6619 static const char moveobject_help
[] =
6620 N_("Moves the object under the crosshair.");
6622 /* %start-doc actions MoveObject
6624 The @code{X} and @code{Y} are treated like @code{delta} is for many
6625 other objects. For each, if it's prefixed by @code{+} or @code{-},
6626 then that amount is relative. Otherwise, it's absolute. Units can be
6627 @code{mil} or @code{mm}; if unspecified, units are PCB's internal
6628 units, currently 1/100 mil.
6633 ActionMoveObject (int argc
, char **argv
, Coord x
, Coord y
)
6635 char *x_str
= ARG (0);
6636 char *y_str
= ARG (1);
6637 char *units
= ARG (2);
6639 bool absolute1
, absolute2
;
6640 void *ptr1
, *ptr2
, *ptr3
;
6643 ny
= GetValue (y_str
, units
, &absolute1
);
6644 nx
= GetValue (x_str
, units
, &absolute2
);
6646 type
= SearchScreen (x
, y
, MOVE_TYPES
, &ptr1
, &ptr2
, &ptr3
);
6647 if (type
== NO_TYPE
)
6649 Message (_("Nothing found under crosshair\n"));
6656 Crosshair
.AttachedObject
.RubberbandN
= 0;
6657 if (TEST_FLAG (RUBBERBANDFLAG
, PCB
))
6658 LookupRubberbandLines (type
, ptr1
, ptr2
, ptr3
);
6659 if (type
== ELEMENT_TYPE
)
6660 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
6661 MoveObjectAndRubberband (type
, ptr1
, ptr2
, ptr3
, nx
, ny
);
6662 SetChangedFlag (true);
6666 /* --------------------------------------------------------------------------- */
6668 static const char movetocurrentlayer_syntax
[] =
6669 N_("MoveToCurrentLayer(Object|SelectedObjects)");
6671 static const char movetocurrentlayer_help
[] =
6672 N_("Moves objects to the current layer.");
6674 /* %start-doc actions MoveToCurrentLayer
6676 Note that moving an element from a component layer to a solder layer,
6677 or from solder to component, won't automatically flip it. Use the
6678 @code{Flip()} action to do that.
6683 ActionMoveToCurrentLayer (int argc
, char **argv
, Coord x
, Coord y
)
6685 char *function
= ARG (0);
6688 switch (GetFunctionID (function
))
6693 void *ptr1
, *ptr2
, *ptr3
;
6695 gui
->get_coords (_("Select an Object"), &x
, &y
);
6697 SearchScreen (x
, y
, MOVETOLAYER_TYPES
,
6698 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
6699 if (MoveObjectToLayer (type
, ptr1
, ptr2
, ptr3
, CURRENT
, false))
6700 SetChangedFlag (true);
6704 case F_SelectedObjects
:
6706 if (MoveSelectedObjectsToLayer (CURRENT
))
6707 SetChangedFlag (true);
6715 static const char setsame_syntax
[] = N_("SetSame()");
6717 static const char setsame_help
[] =
6718 N_("Sets current layer and sizes to match indicated item.");
6720 /* %start-doc actions SetSame
6722 When invoked over any line, arc, polygon, or via, this changes the
6723 current layer to be the layer that item is on, and changes the current
6724 sizes (thickness, keepaway, drill, etc) according to that item.
6729 ActionSetSame (int argc
, char **argv
, Coord x
, Coord y
)
6731 void *ptr1
, *ptr2
, *ptr3
;
6733 LayerType
*layer
= CURRENT
;
6735 type
= SearchScreen (x
, y
, CLONE_TYPES
, &ptr1
, &ptr2
, &ptr3
);
6736 /* set layer current and size from line or arc */
6740 notify_crosshair_change (false);
6741 Settings
.LineThickness
= ((LineType
*) ptr2
)->Thickness
;
6742 Settings
.Keepaway
= ((LineType
*) ptr2
)->Clearance
/ 2;
6743 layer
= (LayerType
*) ptr1
;
6744 if (Settings
.Mode
!= LINE_MODE
)
6745 SetMode (LINE_MODE
);
6746 notify_crosshair_change (true);
6747 hid_action ("RouteStylesChanged");
6751 notify_crosshair_change (false);
6752 Settings
.LineThickness
= ((ArcType
*) ptr2
)->Thickness
;
6753 Settings
.Keepaway
= ((ArcType
*) ptr2
)->Clearance
/ 2;
6754 layer
= (LayerType
*) ptr1
;
6755 if (Settings
.Mode
!= ARC_MODE
)
6757 notify_crosshair_change (true);
6758 hid_action ("RouteStylesChanged");
6762 layer
= (LayerType
*) ptr1
;
6766 notify_crosshair_change (false);
6767 Settings
.ViaThickness
= ((PinType
*) ptr2
)->Thickness
;
6768 Settings
.ViaDrillingHole
= ((PinType
*) ptr2
)->DrillingHole
;
6769 Settings
.Keepaway
= ((PinType
*) ptr2
)->Clearance
/ 2;
6770 if (Settings
.Mode
!= VIA_MODE
)
6772 notify_crosshair_change (true);
6773 hid_action ("RouteStylesChanged");
6779 if (layer
!= CURRENT
)
6781 ChangeGroupVisibility (GetLayerNumber (PCB
->Data
, layer
), true, true);
6788 /* --------------------------------------------------------------------------- */
6790 static const char setflag_syntax
[] =
6791 N_("SetFlag(Object|Selected|SelectedObjects, flag)\n"
6792 "SetFlag(SelectedLines|SelectedPins|SelectedVias, flag)\n"
6793 "SetFlag(SelectedPads|SelectedTexts|SelectedNames, flag)\n"
6794 "SetFlag(SelectedElements, flag)\n"
6795 "flag = square | octagon | thermal | join");
6797 static const char setflag_help
[] = N_("Sets flags on objects.");
6799 /* %start-doc actions SetFlag
6801 Turns the given flag on, regardless of its previous setting. See
6805 SetFlag(SelectedPins,thermal)
6811 ActionSetFlag (int argc
, char **argv
, Coord x
, Coord y
)
6813 char *function
= ARG (0);
6814 char *flag
= ARG (1);
6815 ChangeFlag (function
, flag
, 1, "SetFlag");
6819 /* --------------------------------------------------------------------------- */
6821 static const char clrflag_syntax
[] =
6822 N_("ClrFlag(Object|Selected|SelectedObjects, flag)\n"
6823 "ClrFlag(SelectedLines|SelectedPins|SelectedVias, flag)\n"
6824 "ClrFlag(SelectedPads|SelectedTexts|SelectedNames, flag)\n"
6825 "ClrFlag(SelectedElements, flag)\n"
6826 "flag = square | octagon | thermal | join");
6828 static const char clrflag_help
[] = N_("Clears flags on objects.");
6830 /* %start-doc actions ClrFlag
6832 Turns the given flag off, regardless of its previous setting. See
6836 ClrFlag(SelectedLines,join)
6842 ActionClrFlag (int argc
, char **argv
, Coord x
, Coord y
)
6844 char *function
= ARG (0);
6845 char *flag
= ARG (1);
6846 ChangeFlag (function
, flag
, 0, "ClrFlag");
6850 /* --------------------------------------------------------------------------- */
6852 static const char changeflag_syntax
[] =
6853 N_("ChangeFlag(Object|Selected|SelectedObjects, flag, value)\n"
6854 "ChangeFlag(SelectedLines|SelectedPins|SelectedVias, flag, value)\n"
6855 "ChangeFlag(SelectedPads|SelectedTexts|SelectedNames, flag, value)\n"
6856 "ChangeFlag(SelectedElements, flag, value)\n"
6857 "flag = square | octagon | thermal | join\n"
6860 static const char changeflag_help
[] = N_("Sets or clears flags on objects.");
6862 /* %start-doc actions ChangeFlag
6864 Toggles the given flag on the indicated object(s). The flag may be
6865 one of the flags listed above (square, octagon, thermal, join). The
6866 value may be the number 0 or 1. If the value is 0, the flag is
6867 cleared. If the value is 1, the flag is set.
6872 ActionChangeFlag (int argc
, char **argv
, Coord x
, Coord y
)
6874 char *function
= ARG (0);
6875 char *flag
= ARG (1);
6876 int value
= argc
> 2 ? atoi (argv
[2]) : -1;
6877 if (value
!= 0 && value
!= 1)
6880 ChangeFlag (function
, flag
, value
, "ChangeFlag");
6886 ChangeFlag (char *what
, char *flag_name
, int value
, char *cmd_name
)
6888 bool (*set_object
) (int, void *, void *, void *);
6889 bool (*set_selected
) (int);
6891 if (NSTRCMP (flag_name
, "square") == 0)
6893 set_object
= value
? SetObjectSquare
: ClrObjectSquare
;
6894 set_selected
= value
? SetSelectedSquare
: ClrSelectedSquare
;
6896 else if (NSTRCMP (flag_name
, "octagon") == 0)
6898 set_object
= value
? SetObjectOctagon
: ClrObjectOctagon
;
6899 set_selected
= value
? SetSelectedOctagon
: ClrSelectedOctagon
;
6901 else if (NSTRCMP (flag_name
, "join") == 0)
6903 /* Note: these are backwards, because the flag is "clear" but
6904 the command is "join". */
6905 set_object
= value
? ClrObjectJoin
: SetObjectJoin
;
6906 set_selected
= value
? ClrSelectedJoin
: SetSelectedJoin
;
6910 Message (_("%s(): Flag \"%s\" is not valid\n"), cmd_name
, flag_name
);
6914 switch (GetFunctionID (what
))
6919 void *ptr1
, *ptr2
, *ptr3
;
6922 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGESIZE_TYPES
,
6923 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
6924 if (TEST_FLAG (LOCKFLAG
, (PinType
*) ptr2
))
6925 Message (_("Sorry, the object is locked\n"));
6926 if (set_object (type
, ptr1
, ptr2
, ptr3
))
6927 SetChangedFlag (true);
6931 case F_SelectedVias
:
6932 if (set_selected (VIA_TYPE
))
6933 SetChangedFlag (true);
6936 case F_SelectedPins
:
6937 if (set_selected (PIN_TYPE
))
6938 SetChangedFlag (true);
6941 case F_SelectedPads
:
6942 if (set_selected (PAD_TYPE
))
6943 SetChangedFlag (true);
6946 case F_SelectedLines
:
6947 if (set_selected (LINE_TYPE
))
6948 SetChangedFlag (true);
6951 case F_SelectedTexts
:
6952 if (set_selected (TEXT_TYPE
))
6953 SetChangedFlag (true);
6956 case F_SelectedNames
:
6957 if (set_selected (ELEMENTNAME_TYPE
))
6958 SetChangedFlag (true);
6961 case F_SelectedElements
:
6962 if (set_selected (ELEMENT_TYPE
))
6963 SetChangedFlag (true);
6967 case F_SelectedObjects
:
6968 if (set_selected (CHANGESIZE_TYPES
))
6969 SetChangedFlag (true);
6974 /* --------------------------------------------------------------------------- */
6976 static const char executefile_syntax
[] = N_("ExecuteFile(filename)");
6978 static const char executefile_help
[] = N_("Run actions from the given file.");
6980 /* %start-doc actions ExecuteFile
6982 Lines starting with @code{#} are ignored.
6987 ActionExecuteFile (int argc
, char **argv
, Coord x
, Coord y
)
6996 AFAIL (executefile
);
7000 if ((fp
= fopen (fname
, "r")) == NULL
)
7002 fprintf (stderr
, _("Could not open actions file \"%s\".\n"), fname
);
7007 defer_needs_update
= 0;
7008 while (fgets (line
, sizeof (line
), fp
) != NULL
)
7013 /* eat the trailing newline */
7014 while (*sp
&& *sp
!= '\r' && *sp
!= '\n')
7018 /* eat leading spaces and tabs */
7020 while (*sp
&& (*sp
== ' ' || *sp
== '\t'))
7024 * if we have anything left and its not a comment line
7028 if (*sp
&& *sp
!= '#')
7030 /*Message ("%s : line %-3d : \"%s\"\n", fname, n, sp);*/
7031 hid_parse_actions (sp
);
7036 if (defer_needs_update
)
7038 IncrementUndoSerialNumber ();
7039 gui
->invalidate_all ();
7045 /* --------------------------------------------------------------------------- */
7048 ActionPSCalib (int argc
, char **argv
, Coord x
, Coord y
)
7050 HID
*ps
= hid_find_exporter ("ps");
7051 ps
->calibrate (0.0,0.0);
7055 /* --------------------------------------------------------------------------- */
7057 static ElementType
*element_cache
= NULL
;
7059 static ElementType
*
7060 find_element_by_refdes (char *refdes
)
7063 && NAMEONPCB_NAME(element_cache
)
7064 && strcmp (NAMEONPCB_NAME(element_cache
), refdes
) == 0)
7065 return element_cache
;
7067 ELEMENT_LOOP (PCB
->Data
);
7069 if (NAMEONPCB_NAME(element
)
7070 && strcmp (NAMEONPCB_NAME(element
), refdes
) == 0)
7072 element_cache
= element
;
7073 return element_cache
;
7080 static AttributeType
*
7081 lookup_attr (AttributeListType
*list
, const char *name
)
7084 for (i
=0; i
<list
->Number
; i
++)
7085 if (strcmp (list
->List
[i
].name
, name
) == 0)
7086 return & list
->List
[i
];
7091 delete_attr (AttributeListType
*list
, AttributeType
*attr
)
7093 int idx
= attr
- list
->List
;
7094 if (idx
< 0 || idx
>= list
->Number
)
7096 if (list
->Number
- idx
> 1)
7097 memmove (attr
, attr
+1, (list
->Number
- idx
- 1) * sizeof(AttributeType
));
7101 /* ---------------------------------------------------------------- */
7102 static const char elementlist_syntax
[] =
7103 N_("ElementList(Start|Done|Need,<refdes>,<footprint>,<value>)");
7105 static const char elementlist_help
[] =
7106 N_("Adds the given element if it doesn't already exist.");
7108 /* %start-doc actions elementlist
7113 Indicates the start of an element list; call this before any Need
7117 Searches the board for an element with a matching refdes.
7119 If found, the value and footprint are updated.
7121 If not found, a new element is created with the given footprint and value.
7124 Compares the list of elements needed since the most recent
7125 @code{start} with the list of elements actually on the board. Any
7126 elements that weren't listed are selected, so that the user may delete
7133 static int number_of_footprints_not_found
;
7136 parse_layout_attribute_units (char *name
, int def
)
7138 const char *as
= AttributeGet (PCB
, name
);
7141 return GetValue (as
, NULL
, NULL
);
7145 ActionElementList (int argc
, char **argv
, Coord x
, Coord y
)
7147 ElementType
*e
= NULL
;
7148 char *refdes
, *value
, *footprint
, *old
;
7153 AFAIL (elementlist
);
7158 printf("Entered ActionElementList, executing function %s\n", function
);
7161 if (strcasecmp (function
, "start") == 0)
7163 ELEMENT_LOOP (PCB
->Data
);
7165 CLEAR_FLAG (FOUNDFLAG
, element
);
7168 element_cache
= NULL
;
7169 number_of_footprints_not_found
= 0;
7173 if (strcasecmp (function
, "done") == 0)
7175 ELEMENT_LOOP (PCB
->Data
);
7177 if (TEST_FLAG (FOUNDFLAG
, element
))
7179 CLEAR_FLAG (FOUNDFLAG
, element
);
7181 else if (! EMPTY_STRING_P (NAMEONPCB_NAME (element
)))
7183 /* Unnamed elements should remain untouched */
7184 SET_FLAG (SELECTEDFLAG
, element
);
7188 if (number_of_footprints_not_found
> 0)
7189 gui
->confirm_dialog (_("Not all requested footprints were found.\n"
7190 "See the message log for details"),
7195 if (strcasecmp (function
, "need") != 0)
7196 AFAIL (elementlist
);
7199 AFAIL (elementlist
);
7208 args
[0] = footprint
;
7213 printf(" ... footprint = %s\n", footprint
);
7214 printf(" ... refdes = %s\n", refdes
);
7215 printf(" ... value = %s\n", value
);
7218 e
= find_element_by_refdes (refdes
);
7225 printf(" ... Footprint not on board, need to add it.\n");
7227 /* Not on board, need to add it. */
7228 if (LoadFootprint(argc
, args
, x
, y
))
7230 number_of_footprints_not_found
++;
7234 nx
= PCB
->MaxWidth
/ 2;
7235 ny
= PCB
->MaxHeight
/ 2;
7236 d
= MIN (PCB
->MaxWidth
, PCB
->MaxHeight
) / 10;
7238 nx
= parse_layout_attribute_units ("import::newX", nx
);
7239 ny
= parse_layout_attribute_units ("import::newY", ny
);
7240 d
= parse_layout_attribute_units ("import::disperse", d
);
7244 nx
+= rand () % (d
*2) - d
;
7245 ny
+= rand () % (d
*2) - d
;
7250 if (nx
>= PCB
->MaxWidth
)
7251 nx
= PCB
->MaxWidth
- 1;
7254 if (ny
>= PCB
->MaxHeight
)
7255 ny
= PCB
->MaxHeight
- 1;
7257 /* Place components onto center of board. */
7258 if (CopyPastebufferToLayout (nx
, ny
))
7259 SetChangedFlag (true);
7262 else if (e
&& DESCRIPTION_NAME(e
) && strcmp (DESCRIPTION_NAME(e
), footprint
) != 0)
7269 printf(" ... Footprint on board, but different from footprint loaded.\n");
7271 /* Different footprint, we need to swap them out. */
7272 if (LoadFootprint(argc
, args
, x
, y
))
7274 number_of_footprints_not_found
++;
7278 er
= ElementOrientation (e
);
7279 pe
= PASTEBUFFER
->Data
->Element
->data
;
7281 MirrorElementCoordinates (PASTEBUFFER
->Data
, pe
, pe
->MarkY
*2 - PCB
->MaxHeight
);
7282 pr
= ElementOrientation (pe
);
7288 RotateElementLowLevel (PASTEBUFFER
->Data
, pe
, pe
->MarkX
, pe
->MarkY
, (er
-pr
+4)%4);
7290 for (i
=0; i
<MAX_ELEMENTNAMES
; i
++)
7292 pe
->Name
[i
].X
= e
->Name
[i
].X
- mx
+ pe
->MarkX
;
7293 pe
->Name
[i
].Y
= e
->Name
[i
].Y
- my
+ pe
->MarkY
;
7294 pe
->Name
[i
].Direction
= e
->Name
[i
].Direction
;
7295 pe
->Name
[i
].Scale
= e
->Name
[i
].Scale
;
7300 if (CopyPastebufferToLayout (mx
, my
))
7301 SetChangedFlag (true);
7304 /* Now reload footprint */
7305 element_cache
= NULL
;
7306 e
= find_element_by_refdes (refdes
);
7308 old
= ChangeElementText (PCB
, PCB
->Data
, e
, NAMEONPCB_INDEX
, strdup (refdes
));
7311 old
= ChangeElementText (PCB
, PCB
->Data
, e
, VALUE_INDEX
, strdup (value
));
7315 SET_FLAG (FOUNDFLAG
, e
);
7318 printf(" ... Leaving ActionElementList.\n");
7324 /* ---------------------------------------------------------------- */
7325 static const char elementsetattr_syntax
[] =
7326 N_("ElementSetAttr(refdes,name[,value])");
7328 static const char elementsetattr_help
[] =
7329 N_("Sets or clears an element-specific attribute.");
7331 /* %start-doc actions elementsetattr
7333 If a value is specified, the named attribute is added (if not already
7334 present) or changed (if it is) to the given value. If the value is
7335 not specified, the given attribute is removed if present.
7340 ActionElementSetAttr (int argc
, char **argv
, Coord x
, Coord y
)
7342 ElementType
*e
= NULL
;
7343 char *refdes
, *name
, *value
;
7344 AttributeType
*attr
;
7348 AFAIL (elementsetattr
);
7355 ELEMENT_LOOP (PCB
->Data
);
7357 if (NSTRCMP (refdes
, NAMEONPCB_NAME (element
)) == 0)
7367 Message(_("Cannot change attribute of %s - element not found\n"), refdes
);
7371 attr
= lookup_attr (&e
->Attributes
, name
);
7376 attr
->value
= strdup (value
);
7378 if (attr
&& ! value
)
7380 delete_attr (& e
->Attributes
, attr
);
7384 CreateNewAttribute (& e
->Attributes
, name
, value
);
7390 /* ---------------------------------------------------------------- */
7391 static const char execcommand_syntax
[] = N_("ExecCommand(command)");
7393 static const char execcommand_help
[] = N_("Runs a command.");
7395 /* %start-doc actions execcommand
7397 Runs the given command, which is a system executable.
7402 ActionExecCommand (int argc
, char **argv
, Coord x
, Coord y
)
7408 AFAIL (execcommand
);
7413 if (system (command
))
7418 /* ---------------------------------------------------------------- */
7421 pcb_spawnvp (char **argv
)
7423 #ifdef HAVE__SPAWNVP
7424 int result
= _spawnvp (_P_WAIT
, argv
[0], (const char * const *) argv
);
7435 Message(_("Cannot fork!"));
7441 execvp (argv
[0], argv
);
7454 /* ---------------------------------------------------------------- */
7457 * \brief Creates a new temporary file name.
7459 * Hopefully the operating system provides a mkdtemp() function to
7460 * securily create a temporary directory with mode 0700.\n
7461 * If so then that directory is created and the returned string is made
7462 * up of the directory plus the name variable.\n
7465 * tempfile_name_new ("myfile") might return
7466 * "/var/tmp/pcb.123456/myfile".
7468 * If mkdtemp() is not available then 'name' is ignored and the
7469 * insecure tmpnam() function is used.
7471 * Files/names created with tempfile_name_new() should be unlinked
7472 * with tempfile_unlink to make sure the temporary directory is also
7473 * removed when mkdtemp() is used.
7476 tempfile_name_new (char * name
)
7478 char *tmpfile
= NULL
;
7480 char *tmpdir
, *mytmpdir
;
7484 assert ( name
!= NULL
);
7487 #define TEMPLATE "pcb.XXXXXXXX"
7490 tmpdir
= getenv ("TMPDIR");
7492 /* FIXME -- what about win32? */
7493 if (tmpdir
== NULL
) {
7497 mytmpdir
= (char *) malloc (sizeof(char) *
7502 if (mytmpdir
== NULL
) {
7503 fprintf (stderr
, "%s(): malloc failed()\n", __FUNCTION__
);
7508 (void)strcat (mytmpdir
, tmpdir
);
7509 (void)strcat (mytmpdir
, PCB_DIR_SEPARATOR_S
);
7510 (void)strcat (mytmpdir
, TEMPLATE
);
7511 if (mkdtemp (mytmpdir
) == NULL
) {
7512 fprintf (stderr
, "%s(): mkdtemp (\"%s\") failed\n", __FUNCTION__
, mytmpdir
);
7518 len
= strlen (mytmpdir
) + /* the temp directory name */
7519 1 + /* the directory sep. */
7520 strlen (name
) + /* the file name */
7521 1 /* the \0 termination */
7524 tmpfile
= (char *) malloc (sizeof (char) * len
);
7527 (void)strcat (tmpfile
, mytmpdir
);
7528 (void)strcat (tmpfile
, PCB_DIR_SEPARATOR_S
);
7529 (void)strcat (tmpfile
, name
);
7535 * tmpnam() uses a static buffer so strdup() the result right away
7536 * in case someone decides to create multiple temp names.
7538 tmpfile
= strdup (tmpnam (NULL
));
7541 /* Guile doesn't like \ separators */
7543 for (c
= tmpfile
; *c
; c
++)
7553 /* ---------------------------------------------------------------- */
7556 * \brief Unlink a temporary file.
7558 * If we have mkdtemp() then our temp file lives in a temporary
7559 * directory and we need to remove that directory too.
7562 tempfile_unlink (char * name
)
7565 /* SDB says: Want to keep old temp files for examiniation when debugging */
7574 /* it is possible that the file was never created so it is OK if the
7577 /* now figure out the directory name to remove */
7578 e
= strlen (name
) - 1;
7579 while (e
> 0 && name
[e
] != PCB_DIR_SEPARATOR_C
) {e
--;}
7581 dname
= strdup (name
);
7585 * at this point, e *should* point to the end of the directory part
7586 * but lets make sure.
7589 rc2
= rmdir (dname
);
7595 fprintf (stderr
, _("%s(): Unable to determine temp directory name from the temp file\n"),
7597 fprintf (stderr
, "%s(): \"%s\"\n",
7598 __FUNCTION__
, name
);
7602 /* name was allocated with malloc */
7607 * FIXME - should also return -1 if the temp file exists and was not
7614 #else /* HAVE_MKDTEMP */
7615 int rc
= unlink (name
);
7618 fprintf (stderr
, _("Failed to unlink \"%s\"\n"), name
);
7624 #endif /* HAVE_MKDTEMP */
7630 /* ---------------------------------------------------------------- */
7631 static const char import_syntax
[] =
7633 "Import([gnetlist|make[,source,source,...]])\n"
7634 "Import(setnewpoint[,(mark|center|X,Y)])\n"
7635 "Import(setdisperse,D,units)\n");
7637 static const char import_help
[] = N_("Import schematics.");
7639 /* %start-doc actions Import
7641 Imports element and netlist data from the schematics (or some other
7642 source). The first parameter, which is optional, is the mode. If not
7643 specified, the @code{import::mode} attribute in the PCB is used.
7644 @code{gnetlist} means gnetlist is used to obtain the information from
7645 the schematics. @code{make} invokes @code{make}, assuming the user
7646 has a @code{Makefile} in the current directory. The @code{Makefile}
7647 will be invoked with the following variables set:
7652 The name of the .pcb file
7655 A space-separated list of source files
7658 The name of the file in which to put the command script, which may
7659 contain any @pcb{} actions. By default, this is a temporary file
7660 selected by @pcb{}, but if you specify an @code{import::outfile}
7661 attribute, that file name is used instead (and not automatically
7662 deleted afterwards).
7666 The target specified to be built is the first of these that apply:
7671 The target specified by an @code{import::target} attribute.
7674 The output file specified by an @code{import::outfile} attribute.
7677 If nothing else is specified, the target is @code{pcb_import}.
7681 If you specify an @code{import::makefile} attribute, then "-f <that
7682 file>" will be added to the command line.
7684 If you specify the mode, you may also specify the source files
7685 (schematics). If you do not specify any, the list of schematics is
7686 obtained by reading the @code{import::src@var{N}} attributes (like
7687 @code{import::src0}, @code{import::src1}, etc).
7689 For compatibility with future extensions to the import file format,
7690 the generated file @emph{must not} start with the two characters
7693 If a temporary file is needed the @code{TMPDIR} environment variable
7694 is used to select its location.
7696 Note that the programs @code{gnetlist} and @code{make} may be
7697 overridden by the user via the @code{make-program} and @code{gnetlist}
7698 @code{pcb} settings (i.e. in @code{~/.pcb/settings} or on the command
7701 If @pcb{} cannot determine which schematic(s) to import from, the GUI
7702 is called to let user choose (see @code{ImportGUI()}).
7704 Note that Import() doesn't delete anything - after an Import, elements
7705 which shouldn't be on the board are selected and may be removed once
7706 it's determined that the deletion is appropriate.
7708 If @code{Import()} is called with @code{setnewpoint}, then the location
7709 of new components can be specified. This is where parts show up when
7710 they're added to the board. The default is the center of the board.
7714 @item Import(setnewpoint)
7716 Prompts the user to click on the board somewhere, uses that point. If
7717 called by a hotkey, uses the current location of the crosshair.
7719 @item Import(setnewpoint,mark)
7721 Uses the location of the mark. If no mark is present, the point is
7724 @item Import(setnewpoint,center)
7726 Resets the point to the center of the board.
7728 @item Import(setnewpoint,X,Y,units)
7730 Sets the point to the specific coordinates given. Example:
7731 @code{Import(setnewpoint,50,25,mm)}
7735 Note that the X and Y locations are stored in attributes named
7736 @code{import::newX} and @code{import::newY} so you could change them
7737 manually if you wished.
7739 Calling @code{Import(setdisperse,D,units)} sets how much the newly
7740 placed elements are dispersed relative to the set point. For example,
7741 @code{Import(setdisperse,10,mm)} will offset each part randomly up to
7742 10mm away from the point. The default dispersion is 1/10th of the
7743 smallest board dimension. Dispersion is saved in the
7744 @code{import::disperse} attribute.
7749 ActionImport (int argc
, char **argv
, Coord x
, Coord y
)
7752 char **sources
= NULL
;
7756 printf("ActionImport: =========== Entering ActionImport ============\n");
7761 if (mode
&& strcasecmp (mode
, "setdisperse") == 0)
7770 const char *as
= AttributeGet (PCB
, "import::disperse");
7771 ds
= gui
->prompt_for(_("Enter dispersion:"), as
? as
: "0");
7775 sprintf(buf
, "%s%s", ds
, units
);
7776 AttributePut (PCB
, "import::disperse", buf
);
7779 AttributePut (PCB
, "import::disperse", ds
);
7780 if (ARG (1) == NULL
)
7785 if (mode
&& strcasecmp (mode
, "setnewpoint") == 0)
7787 const char *xs
, *ys
, *units
;
7797 gui
->get_coords (_("Click on a location"), &x
, &y
);
7799 else if (strcasecmp (xs
, "center") == 0)
7801 AttributeRemove (PCB
, "import::newX");
7802 AttributeRemove (PCB
, "import::newY");
7805 else if (strcasecmp (xs
, "mark") == 0)
7815 x
= GetValue (xs
, units
, NULL
);
7816 y
= GetValue (ys
, units
, NULL
);
7820 Message (_("Bad syntax for Import(setnewpoint)"));
7824 pcb_snprintf (buf
, sizeof (buf
), "%$ms", x
);
7825 AttributePut (PCB
, "import::newX", buf
);
7826 pcb_snprintf (buf
, sizeof (buf
), "%$ms", y
);
7827 AttributePut (PCB
, "import::newY", buf
);
7832 mode
= AttributeGet (PCB
, "import::mode");
7839 nsources
= argc
- 1;
7850 sprintf(sname
, "import::src%d", nsources
);
7851 src
= AttributeGet (PCB
, sname
);
7856 sources
= (char **) malloc ((nsources
+ 1) * sizeof (char *));
7860 sprintf(sname
, "import::src%d", nsources
);
7861 src
= AttributeGet (PCB
, sname
);
7862 sources
[nsources
] = src
;
7869 /* Replace .pcb with .sch and hope for the best. */
7870 char *pcbname
= PCB
->Filename
;
7872 char *dot
, *slash
, *bslash
;
7875 return hid_action("ImportGUI");
7877 schname
= (char *) malloc (strlen(pcbname
) + 5);
7878 strcpy (schname
, pcbname
);
7879 dot
= strchr (schname
, '.');
7880 slash
= strchr (schname
, '/');
7881 bslash
= strchr (schname
, '\\');
7882 if (dot
&& slash
&& dot
< slash
)
7884 if (dot
&& bslash
&& dot
< bslash
)
7888 strcat (schname
, ".sch");
7890 if (access (schname
, F_OK
))
7893 return hid_action("ImportGUI");
7896 sources
= (char **) malloc (2 * sizeof (char *));
7897 sources
[0] = schname
;
7902 if (strcasecmp (mode
, "gnetlist") == 0)
7904 char *tmpfile
= tempfile_name_new ("gnetlist_output");
7908 if (tmpfile
== NULL
) {
7909 Message (_("Could not create temp file"));
7913 cmd
= (char **) malloc ((7 + nsources
) * sizeof (char *));
7914 cmd
[0] = Settings
.GnetlistProgram
;
7920 for (i
=0; i
<nsources
; i
++)
7921 cmd
[6+i
] = sources
[i
];
7922 cmd
[6+nsources
] = NULL
;
7925 printf("ActionImport: =========== About to run gnetlist ============\n");
7926 printf("%s %s %s %s %s %s %s ...\n",
7927 cmd
[0], cmd
[1], cmd
[2], cmd
[3], cmd
[4], cmd
[5], cmd
[6]);
7930 if (pcb_spawnvp (cmd
))
7937 printf("ActionImport: =========== About to run ActionExecuteFile, file = %s ============\n", tmpfile
);
7942 ActionExecuteFile (1, cmd
, 0, 0);
7945 tempfile_unlink (tmpfile
);
7947 else if (strcasecmp (mode
, "make") == 0)
7949 int must_free_tmpfile
= 0;
7955 char *user_outfile
= NULL
;
7956 char *user_makefile
= NULL
;
7957 char *user_target
= NULL
;
7960 user_outfile
= AttributeGet (PCB
, "import::outfile");
7961 user_makefile
= AttributeGet (PCB
, "import::makefile");
7962 user_target
= AttributeGet (PCB
, "import::target");
7963 if (user_outfile
&& !user_target
)
7964 user_target
= user_outfile
;
7967 tmpfile
= user_outfile
;
7970 tmpfile
= tempfile_name_new ("gnetlist_output");
7971 if (tmpfile
== NULL
) {
7972 Message (_("Could not create temp file"));
7976 must_free_tmpfile
= 1;
7979 srclen
= sizeof("SRCLIST=") + 2;
7980 for (i
=0; i
<nsources
; i
++)
7981 srclen
+= strlen (sources
[i
]) + 2;
7982 srclist
= (char *) malloc (srclen
);
7983 strcpy (srclist
, "SRCLIST=");
7984 for (i
=0; i
<nsources
; i
++)
7987 strcat (srclist
, " ");
7988 strcat (srclist
, sources
[i
]);
7991 cmd
[0] = Settings
.MakeProgram
;
7993 cmd
[2] = Concat ("PCB=", PCB
->Filename
, NULL
);
7995 cmd
[4] = Concat ("OUT=", tmpfile
, NULL
);
8000 cmd
[i
++] = user_makefile
;
8002 cmd
[i
++] = user_target
? user_target
: (char *)"pcb_import";
8005 if (pcb_spawnvp (cmd
))
8007 if (must_free_tmpfile
)
8017 ActionExecuteFile (1, cmd
, 0, 0);
8022 if (must_free_tmpfile
)
8023 tempfile_unlink (tmpfile
);
8027 Message (_("Unknown import mode: %s\n"), mode
);
8032 AddAllRats (false, NULL
);
8035 printf("ActionImport: =========== Leaving ActionImport ============\n");
8041 /* ------------------------------------------------------------ */
8043 static const char attributes_syntax
[] =
8044 N_("Attributes(Layout|Layer|Element)\n"
8045 "Attributes(Layer,layername)");
8047 static const char attributes_help
[] =
8048 N_("Let the user edit the attributes of the layout, current or given\n"
8049 "layer, or selected element.");
8051 /* %start-doc actions Attributes
8053 This just pops up a dialog letting the user edit the attributes of the
8054 pcb, an element, or a layer.
8060 ActionAttributes (int argc
, char **argv
, Coord x
, Coord y
)
8062 char *function
= ARG (0);
8063 char *layername
= ARG (1);
8069 if (!gui
->edit_attributes
)
8071 Message (_("This GUI doesn't support Attribute Editing\n"));
8075 switch (GetFunctionID (function
))
8079 gui
->edit_attributes(_("Layout Attributes"), &(PCB
->Attributes
));
8085 LayerType
*layer
= CURRENT
;
8090 for (i
=0; i
<max_copper_layer
; i
++)
8091 if (strcmp (PCB
->Data
->Layer
[i
].Name
, layername
) == 0)
8093 layer
= & (PCB
->Data
->Layer
[i
]);
8098 Message (_("No layer named %s\n"), layername
);
8102 buf
= (char *) malloc (strlen (layer
->Name
) +
8103 strlen (_("Layer %s Attributes")));
8104 sprintf (buf
, _("Layer %s Attributes"), layer
->Name
);
8105 gui
->edit_attributes(buf
, &(layer
->Attributes
));
8113 ElementType
*e
= NULL
;
8114 ELEMENT_LOOP (PCB
->Data
);
8116 if (TEST_FLAG (SELECTEDFLAG
, element
))
8125 Message (_("Too many elements selected\n"));
8131 gui
->get_coords (_("Click on an element"), &x
, &y
);
8133 (x
, y
, ELEMENT_TYPE
, &ptrtmp
,
8134 &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
8135 e
= (ElementType
*) ptrtmp
;
8138 Message (_("No element found there\n"));
8143 if (NAMEONPCB_NAME(e
))
8145 buf
= (char *) malloc (strlen (NAMEONPCB_NAME(e
)) +
8146 strlen (_("Element %s Attributes")));
8147 sprintf(buf
, _("Element %s Attributes"), NAMEONPCB_NAME(e
));
8151 buf
= strdup (_("Unnamed Element Attributes"));
8153 gui
->edit_attributes(buf
, &(e
->Attributes
));
8165 /* ------------------------------------------------------------ */
8167 static const char smash_syntax
[] = N_("Smash(Object|Selected|SelectedElements)");
8168 static const char smash_help
[] = N_("Smash an element or elements into pieces.");
8170 /* %start-doc actions Attributes
8172 This smashes the given object into pieces in-place on the PCB.
8178 SmashElement (ElementType
*element
)
8181 LayerType
*top_copper
, *bottom_copper
;
8182 LayerType
*top_silk
, *bottom_silk
;
8188 group
= GetLayerGroupNumberBySide (TOP_SIDE
);
8189 top_copper
= &PCB
->Data
->Layer
[PCB
->LayerGroups
.Entries
[group
][0]];
8190 group
= GetLayerGroupNumberBySide (BOTTOM_SIDE
);
8191 bottom_copper
= &PCB
->Data
->Layer
[PCB
->LayerGroups
.Entries
[group
][0]];
8192 top_silk
= &PCB
->Data
->Layer
[top_silk_layer
];
8193 bottom_silk
= &PCB
->Data
->Layer
[bottom_silk_layer
];
8195 ELEMENTLINE_LOOP (element
);
8197 layer
= TEST_FLAG (ONSOLDERFLAG
, element
) ? bottom_silk
: top_silk
;
8198 new_line
= CreateNewLineOnLayer (layer
,
8199 line
->Point1
.X
, line
->Point1
.Y
,
8200 line
->Point2
.X
, line
->Point2
.Y
,
8201 line
->Thickness
, 0, NoFlags ());
8204 new_line
->Number
= STRDUP (NAMEONPCB_NAME (element
));
8205 AddObjectToCreateUndoList (LINE_TYPE
, layer
, new_line
, new_line
);
8211 layer
= TEST_FLAG (ONSOLDERFLAG
, element
) ? bottom_silk
: top_silk
;
8212 new_arc
= CreateNewArcOnLayer (layer
,
8213 arc
->X
, arc
->Y
, arc
->Width
, arc
->Height
, arc
->StartAngle
,
8214 arc
->Delta
, arc
->Thickness
, 0, NoFlags ());
8216 AddObjectToCreateUndoList (LINE_TYPE
, layer
, new_arc
, new_arc
);
8222 FlagType f
= NoFlags ();
8223 AddFlags (f
, VIAFLAG
);
8224 if (TEST_FLAG (HOLEFLAG
, pin
))
8225 AddFlags (f
, HOLEFLAG
);
8227 new_via
= CreateNewVia (PCB
->Data
, pin
->X
, pin
->Y
,
8228 pin
->Thickness
, pin
->Clearance
, pin
->Mask
,
8229 pin
->DrillingHole
, pin
->Number
, f
);
8231 AddObjectToCreateUndoList (VIA_TYPE
, new_via
, new_via
, new_via
);
8236 layer
= TEST_FLAG (ONSOLDERFLAG
, pad
) ? bottom_copper
: top_copper
;
8237 new_line
= CreateNewLineOnLayer (layer
,
8238 pad
->Point1
.X
, pad
->Point1
.Y
,
8239 pad
->Point2
.X
, pad
->Point2
.Y
,
8240 pad
->Thickness
, pad
->Clearance
, NoFlags ());
8243 new_line
->Number
= STRDUP (pad
->Number
);
8244 AddObjectToCreateUndoList (LINE_TYPE
, layer
, new_line
, new_line
);
8248 RemoveElement (element
);
8251 /*---------------------------------------------------------------------------
8253 * break selected element(s) into pieces
8256 ActionSmash (int argc
, char **argv
, Coord x
, Coord y
)
8258 char *function
= ARG (0);
8259 ElementType
*element
;
8260 void *ptr1
, *ptr2
, *ptr3
;
8261 bool change
= false;
8265 switch (GetFunctionID (function
))
8268 if (SearchScreen (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
,
8269 &ptr1
, &ptr2
, &ptr3
) != NO_TYPE
)
8273 SmashElement (element
);
8278 case F_SelectedElements
:
8279 if (PCB
->PinOn
&& PCB
->ElementOn
)
8281 ELEMENT_LOOP (PCB
->Data
);
8283 if (TEST_FLAG (SELECTEDFLAG
, element
))
8286 SmashElement (element
);
8299 SetChangedFlag (true);
8301 IncrementUndoSerialNumber ();
8310 static const char repairdrills_syntax
[] = N_("RepairDrills(CreatePins|CreateVias|CreateHoles,<layername>)");
8311 static const char repairdrills_help
[] = N_("Repair and reconstruct elements containing pins, or discrete vias, where two matching single-pad elements are found (top and bottom sides, and a 0-length line represeting the drill size on the named layer.");
8314 GetLayerByName (char *name
)
8319 for (i
= 0; i
< max_copper_layer
; i
++)
8321 layer
= PCB
->Data
->Layer
+ i
;
8323 if (strcmp (layer
->Name
, name
) == 0)
8330 /*---------------------------------------------------------------------------
8332 * break selected element(s) into pieces
8335 ActionRepairDrills (int argc
, char **argv
, Coord x
, Coord y
)
8338 bool save_show_bottom_side
;
8339 bool save_invisible_objects
;
8341 LayerType
*drill_layer
;
8344 AFAIL (repairdrills
);
8346 function
= GetFunctionID (ARG(0));
8347 drill_layer
= GetLayerByName (ARG(1));
8349 if (drill_layer
== NULL
||
8350 (function
!= F_CreatePins
&&
8351 function
!= F_CreateVias
&&
8352 function
!= F_CreateHoles
))
8353 AFAIL (repairdrills
);
8355 save_show_bottom_side
= Settings
.ShowBottomSide
;
8356 save_invisible_objects
= PCB
->InvisibleObjectsOn
;
8358 PCB
->InvisibleObjectsOn
= false;
8360 /* ITERATE OVER ALL LINE SEGMENTS ON "drill_layer" */
8361 LINE_LOOP (drill_layer
);
8363 ElementType
*top_pad_element
;
8364 ElementType
*bottom_pad_element
;
8366 PadType
*bottom_pad
;
8369 /* Pass over any lines which are not zero length */
8370 if (line
->Point1
.X
!= line
->Point2
.X
||
8371 line
->Point1
.Y
!= line
->Point2
.Y
)
8374 /* Now we have a target "drill", of width line->Thickness, we need to check
8375 * for corresponding pads on the top and bottom layers for it to mate with.
8377 * XXX: Should we delete those here, and make a list of new vias / pins to add?
8379 pcb_printf ("Found potential drill at (%$ms, %$ms) width is %$ms\t", line
->Point1
.X
, line
->Point1
.Y
, line
->Thickness
);
8381 /* Find a top side pad which corresponds to the drill location */
8382 Settings
.ShowBottomSide
= false;
8383 if (SearchObjectByLocation (PAD_TYPE
, (void **)&top_pad_element
, (void **)&top_pad
, (void **)&dummy
, line
->Point1
.X
, line
->Point1
.Y
, 0) != PAD_TYPE
||
8384 top_pad
->Point1
.X
!= line
->Point1
.X
||
8385 top_pad
->Point1
.Y
!= line
->Point1
.Y
||
8386 top_pad
->Point2
.X
!= line
->Point1
.X
||
8387 top_pad
->Point2
.Y
!= line
->Point1
.Y
)
8389 printf ("Could not find top-side pad\n");
8393 if (function
== F_CreateHoles
) {
8394 /* Create a hole at given location */
8396 pcb_printf ("Found a viable pin/via at (%$ms, %$ms), pad width %$ms, drill size %$ms\n",
8397 line
->Point1
.X
, line
->Point1
.Y
, top_pad
->Thickness
, line
->Thickness
);
8401 /* Find a bottom side pad which corresponds to the drill location */
8402 Settings
.ShowBottomSide
= true;
8403 if (SearchObjectByLocation (PAD_TYPE
, (void **)&bottom_pad_element
, (void **)&bottom_pad
, (void **)&dummy
, line
->Point1
.X
, line
->Point1
.Y
, 0) != PAD_TYPE
||
8404 bottom_pad
->Point1
.X
!= line
->Point1
.X
||
8405 bottom_pad
->Point1
.Y
!= line
->Point1
.Y
||
8406 bottom_pad
->Point2
.X
!= line
->Point1
.X
||
8407 bottom_pad
->Point2
.Y
!= line
->Point1
.Y
)
8409 printf ("Could not find bottom-side pad\n");
8413 /* If the top and bottom pads are not the same radius, give up */
8414 if (top_pad
->Thickness
!= bottom_pad
->Thickness
)
8416 printf ("top-side and bottom-side pad are not equal thickness\n");
8422 pcb_printf ("Found a viable pin/via at (%$ms, %$ms), pad width %$ms, drill size %$ms\n",
8423 line
->Point1
.X
, line
->Point1
.Y
, top_pad
->Thickness
, line
->Thickness
);
8428 Settings
.ShowBottomSide
= save_show_bottom_side
;
8429 PCB
->InvisibleObjectsOn
= save_invisible_objects
;
8434 /* --------------------------------------------------------------------------- */
8436 static const char setvialayers_syntax
[] =
8437 N_("SetViaLayers(Object|SelectedVias|Selected[,ThroughHole|TH])\n"
8438 "SetViaLayers(Object|SelectedVias|Selected,from,to)\n"
8439 "SetViaLayers(Object|SelectedVias|Selected,[c|-|from],[c|-|to])"
8442 static const char setvialayers_help
[] =
8443 N_("Sets starting and ending layer for burried/blind/standard vias.");
8445 /* %start-doc actions setvialayers
8447 Specifies layers, which are connected by via.
8451 @item TH|ThroughHole
8452 The vias will be set as through-hole, connecting all layers
8455 layer name or layer number of the first layer to be connected by via; "-" stands for unchanged, "c" stands for currently selected layer
8458 layer name or layer number of the last layer to be connected by via; "-" stands for unchanged, "c" stands for currently selected layer
8462 If no parameter us used, dialog is displayed (if implemented in the respective GUI HID).
8468 identify_layer (char *layer_name
, Cardinal
*layer_no
)
8472 if (strcmp (layer_name
, "-") == 0)
8478 if (strcmp (layer_name
, "c") == 0)
8480 if ((unsigned int)INDEXOFCURRENT
< max_copper_layer
)
8482 *layer_no
= INDEXOFCURRENT
;
8487 layer
= SearchLayerByName (PCB
->Data
, layer_name
);
8490 if (sscanf (layer_name
, "%d", &layer
) != 1)
8497 return (layer
!= -1);
8501 ActionSetViaLayers (int argc
, char **argv
, Coord x
, Coord y
)
8503 char *function
= ARG (0);
8504 char *layername_from
= ARG (1);
8505 char *layername_to
= ARG (2);
8506 Cardinal layer_from
;
8507 Cardinal layer_to
= -1;
8510 AFAIL (setvialayers
);
8512 if ( /* !gui->edit_attributes &&*/ argc
< 2)
8514 Message (_("This GUI doesn't support Via Layers editing\n"));
8518 if (GetFunctionID (layername_from
) == F_ThroughHole
)
8525 if (!identify_layer (layername_from
, &layer_from
)
8526 || !identify_layer (layername_to
, &layer_to
))
8528 Message (_("Sorry, wrong layers specified.\n"));
8533 /* ensure that layer_from < layer_to */
8534 if (layer_from
!= -1
8536 && layer_from
> layer_to
)
8541 layer_from
= layer_to
;
8546 layer_to
= min (layer_to
, max_copper_layer
-1);
8548 switch (GetFunctionID (function
))
8553 void *ptr1
, *ptr2
, *ptr3
;
8556 SearchScreen (Crosshair
.X
, Crosshair
.Y
, VIA_TYPE
,
8557 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
8559 if (TEST_FLAG (LOCKFLAG
, (PinType
*) ptr1
))
8560 Message (_("Sorry, the object is locked\n"));
8563 if (ChangeObjectViaLayers (ptr1
, ptr2
, ptr3
, layer_from
, layer_to
))
8565 SetChangedFlag (true);
8570 case F_SelectedVias
:
8572 if (ChangeSelectedViaLayers (layer_from
, layer_to
))
8574 SetChangedFlag (true);
8582 /* --------------------------------------------------------------------------- */
8584 HID_Action action_action_list
[] = {
8585 {"AddRats", 0, ActionAddRats
,
8586 addrats_help
, addrats_syntax
}
8588 {"Attributes", 0, ActionAttributes
,
8589 attributes_help
, attributes_syntax
}
8591 {"Atomic", 0, ActionAtomic
,
8592 atomic_help
, atomic_syntax
}
8594 {"AutoPlaceSelected", 0, ActionAutoPlaceSelected
,
8595 autoplace_help
, autoplace_syntax
}
8597 {"AutoRoute", 0, ActionAutoRoute
,
8598 autoroute_help
, autoroute_syntax
}
8600 {"ChangeClearSize", 0, ActionChangeClearSize
,
8601 changeclearsize_help
, changeclearsize_syntax
}
8603 {"ChangeDrillSize", 0, ActionChange2ndSize
,
8604 changedrillsize_help
, changedrillsize_syntax
}
8606 {"ChangeHole", 0, ActionChangeHole
,
8607 changehold_help
, changehold_syntax
}
8609 {"ChangeJoin", 0, ActionChangeJoin
,
8610 changejoin_help
, changejoin_syntax
}
8612 {"ChangeName", 0, ActionChangeName
,
8613 changename_help
, changename_syntax
}
8615 {"ChangePaste", 0, ActionChangePaste
,
8616 changepaste_help
, changepaste_syntax
}
8618 {"ChangePinName", 0, ActionChangePinName
,
8619 changepinname_help
, changepinname_syntax
}
8621 {"ChangeSize", 0, ActionChangeSize
,
8622 changesize_help
, changesize_syntax
}
8624 {"ChangeSquare", 0, ActionChangeSquare
,
8625 changesquare_help
, changesquare_syntax
}
8627 {"ChangeOctagon", 0, ActionChangeOctagon
,
8628 changeoctagon_help
, changeoctagon_syntax
}
8630 {"ClearSquare", 0, ActionClearSquare
,
8631 clearsquare_help
, clearsquare_syntax
}
8633 {"ClearOctagon", 0, ActionClearOctagon
,
8634 clearoctagon_help
, clearoctagon_syntax
}
8636 {"Connection", 0, ActionConnection
,
8637 connection_help
, connection_syntax
}
8639 {"Delete", 0, ActionDelete
,
8640 delete_help
, delete_syntax
}
8642 {"DeleteRats", 0, ActionDeleteRats
,
8643 deleterats_help
, deleterats_syntax
}
8645 {"DisperseElements", 0, ActionDisperseElements
,
8646 disperseelements_help
, disperseelements_syntax
}
8648 {"Display", 0, ActionDisplay
,
8649 display_help
, display_syntax
}
8651 {"DRC", 0, ActionDRCheck
,
8652 drc_help
, drc_syntax
}
8654 {"DumpLibrary", 0, ActionDumpLibrary
,
8655 dumplibrary_help
, dumplibrary_syntax
}
8657 {"ExecuteFile", 0, ActionExecuteFile
,
8658 executefile_help
, executefile_syntax
}
8660 {"Flip", N_("Click on Object or Flip Point"), ActionFlip
,
8661 flip_help
, flip_syntax
}
8663 {"LoadFrom", 0, ActionLoadFrom
,
8664 loadfrom_help
, loadfrom_syntax
}
8666 {"MarkCrosshair", 0, ActionMarkCrosshair
,
8667 markcrosshair_help
, markcrosshair_syntax
}
8669 {"Message", 0, ActionMessage
,
8670 message_help
, message_syntax
}
8672 {"MinMaskGap", 0, ActionMinMaskGap
,
8673 minmaskgap_help
, minmaskgap_syntax
}
8675 {"MinClearGap", 0, ActionMinClearGap
,
8676 mincleargap_help
, mincleargap_syntax
}
8678 {"Mode", 0, ActionMode
,
8679 mode_help
, mode_syntax
}
8681 {"MorphPolygon", 0, ActionMorphPolygon
,
8682 morphpolygon_help
, morphpolygon_syntax
}
8684 {"PasteBuffer", 0, ActionPasteBuffer
,
8685 pastebuffer_help
, pastebuffer_syntax
}
8687 {"Quit", 0, ActionQuit
,
8688 quit_help
, quit_syntax
}
8690 {"RemoveSelected", 0, ActionRemoveSelected
,
8691 removeselected_help
, removeselected_syntax
}
8693 {"Renumber", 0, ActionRenumber
,
8694 renumber_help
, renumber_syntax
}
8696 {"RepairDrills", 0, ActionRepairDrills
,
8697 repairdrills_help
, repairdrills_syntax
}
8699 {"RipUp", 0, ActionRipUp
,
8700 ripup_help
, ripup_syntax
}
8702 {"Select", 0, ActionSelect
,
8703 select_help
, select_syntax
}
8705 {"Unselect", 0, ActionUnselect
,
8706 unselect_help
, unselect_syntax
}
8708 {"SaveSettings", 0, ActionSaveSettings
,
8709 savesettings_help
, savesettings_syntax
}
8711 {"SaveTo", 0, ActionSaveTo
,
8712 saveto_help
, saveto_syntax
}
8714 {"SetSquare", 0, ActionSetSquare
,
8715 setsquare_help
, setsquare_syntax
}
8717 {"SetOctagon", 0, ActionSetOctagon
,
8718 setoctagon_help
, setoctagon_syntax
}
8720 {"SetThermal", 0, ActionSetThermal
,
8721 setthermal_help
, setthermal_syntax
}
8723 {"SetValue", 0, ActionSetValue
,
8724 setvalue_help
, setvalue_syntax
}
8726 {"Smash", 0, ActionSmash
,
8727 smash_help
, smash_syntax
}
8729 {"ToggleHideName", 0, ActionToggleHideName
,
8730 togglehidename_help
, togglehidename_syntax
}
8732 {"Undo", 0, ActionUndo
,
8733 undo_help
, undo_syntax
}
8735 {"Redo", 0, ActionRedo
,
8736 redo_help
, redo_syntax
}
8738 {"SetSame", N_("Select item to use attributes from"), ActionSetSame
,
8739 setsame_help
, setsame_syntax
}
8741 {"SetFlag", 0, ActionSetFlag
,
8742 setflag_help
, setflag_syntax
}
8744 {"ClrFlag", 0, ActionClrFlag
,
8745 clrflag_help
, clrflag_syntax
}
8747 {"ChangeFlag", 0, ActionChangeFlag
,
8748 changeflag_help
, changeflag_syntax
}
8750 {"Polygon", 0, ActionPolygon
,
8751 polygon_help
, polygon_syntax
}
8753 {"RouteStyle", 0, ActionRouteStyle
,
8754 routestyle_help
, routestyle_syntax
}
8756 {"MoveObject", N_("Select an Object"), ActionMoveObject
,
8757 moveobject_help
, moveobject_syntax
}
8759 {"MoveToCurrentLayer", 0, ActionMoveToCurrentLayer
,
8760 movetocurrentlayer_help
, movetocurrentlayer_syntax
}
8762 {"New", 0, ActionNew
,
8763 new_help
, new_syntax
}
8765 {"pscalib", 0, ActionPSCalib
}
8767 {"ElementList", 0, ActionElementList
,
8768 elementlist_help
, elementlist_syntax
}
8770 {"ElementSetAttr", 0, ActionElementSetAttr
,
8771 elementsetattr_help
, elementsetattr_syntax
}
8773 {"ExecCommand", 0, ActionExecCommand
,
8774 execcommand_help
, execcommand_syntax
}
8776 {"Import", 0, ActionImport
,
8777 import_help
, import_syntax
}
8779 {"SetViaLayers", 0, ActionSetViaLayers
,
8780 setvialayers_help
, setvialayers_syntax
}
8784 REGISTER_ACTIONS (action_action_list
)