6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996 Thomas Nau
8 * Copyright (C) 1997, 1998, 1999, 2000, 2001 Harry Eaton
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * Contact addresses for paper mail and Email:
25 * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA
26 * haceaton@aplcomm.jhuapl.edu
30 /* action routines for output window
40 #include "autoplace.h"
41 #include "autoroute.h"
47 #include "crosshair.h"
59 /*#include "print.h"*/
64 #include "rubberband.h"
72 #ifdef HAVE_LIBDMALLOC
78 /* ---------------------------------------------------------------------------
107 F_ElementConnections
,
146 F_ResetLinesAndPolygons
,
147 F_ResetPinsViasAndPads
,
169 F_ToggleAllDirections
,
178 F_ToggleRubberBandMode
,
179 F_ToggleStartDirection
,
184 F_ToggleThindrawPoly
,
198 typedef struct /* used to identify subfunctions */
203 FunctionType
, *FunctionTypePtr
;
205 /* --------------------------------------------------------------------------- */
207 /* %start-doc actions 00delta
209 Many actions take a @code{delta} parameter as the last parameter,
210 which is an amount to change something. That @code{delta} may include
211 units, as an additional parameter, such as @code{Action(Object,5,mm)}.
212 If no units are specified, the default is PCB's native units
213 (currently 1/100 mil). Also, if the delta is prefixed by @code{+} or
214 @code{-}, the size is increased or decreased by that amount.
215 Otherwise, the size size is set to the given amount.
219 Action(Object,+0.5,mm)
223 Actions which take a @code{delta} parameter which do not accept all
224 these options will specify what they do take.
228 /* %start-doc actions 00objects
230 Many actions act on indicated objects on the board. They will have
231 parameters like @code{ToggleObject} or @code{SelectedVias} to indicate
232 what group of objects they act on. Unless otherwise specified, these
233 parameters are defined as follows:
239 Affects the object under the mouse pointer. If this action is invoked
240 from a menu or script, the user will be prompted to click on an
241 object, which is then the object affected.
244 @itemx SelectedObjects
246 Affects all objects which are currently selected. At least, all
247 selected objects for which the given action makes sense.
251 @itemx Selected@var{Type}
253 Affects all objects which are both selected and of the @var{Type} specified.
259 /* %start-doc actions 00macros
263 Pins, pads, and vias can have various shapes. All may be round. Pins
264 and pads may be square (obviously "square" pads are usually
265 rectangular). Pins and vias may be octagonal. When you change a
266 shape flag of an element, you actually change all of its pins and
269 Note that the square flag takes precedence over the octagon flag,
270 thus, if both the square and octagon flags are set, the object is
271 square. When the square flag is cleared, the pins and pads will be
272 either round or, if the octagon flag is set, octagonal.
278 /* ---------------------------------------------------------------------------
279 * some local identifiers
281 static PointType InsertedPoint
;
282 static LayerTypePtr lastLayer
;
296 Boolean Moving
; /* selected type clicked on */
297 int Hit
; /* move type clicked on */
304 static Cardinal polyIndex
= 0;
305 static Boolean IgnoreMotionEvents
= False
;
306 static Boolean saved_mode
= False
;
307 #ifdef HAVE_LIBSTROKE
308 static Boolean mid_stroke
= False
;
309 static BoxType StrokeBox
;
311 static FunctionType Functions
[] = {
312 {"AddSelected", F_AddSelected
},
314 {"AllConnections", F_AllConnections
},
315 {"AllRats", F_AllRats
},
316 {"AllUnusedPins", F_AllUnusedPins
},
320 {"Description", F_Description
},
321 {"Cancel", F_Cancel
},
322 {"Center", F_Center
},
324 {"ClearAndRedraw", F_ClearAndRedraw
},
325 {"ClearList", F_ClearList
},
327 {"Connection", F_Connection
},
328 {"Convert", F_Convert
},
330 {"CycleClip", F_CycleClip
},
331 {"DeleteRats", F_DeleteRats
},
333 {"DrillReport", F_DrillReport
},
334 {"Element", F_Element
},
335 {"ElementByName", F_ElementByName
},
336 {"ElementConnections", F_ElementConnections
},
337 {"ElementToBuffer", F_ElementToBuffer
},
338 {"Escape", F_Escape
},
340 {"FlipElement", F_FlipElement
},
341 {"FoundPins", F_FoundPins
},
343 {"InsertPoint", F_InsertPoint
},
345 {"Layout", F_Layout
},
346 {"LayoutAs", F_LayoutAs
},
347 {"LayoutToBuffer", F_LayoutToBuffer
},
349 {"LineSize", F_LineSize
},
351 {"Mirror", F_Mirror
},
353 {"NameOnPCB", F_NameOnPCB
},
354 {"Netlist", F_Netlist
},
356 {"Notify", F_Notify
},
357 {"Object", F_Object
},
358 {"ObjectByName", F_ObjectByName
},
359 {"PasteBuffer", F_PasteBuffer
},
360 {"PadByName", F_PadByName
},
361 {"PinByName", F_PinByName
},
362 {"PinOrPadName", F_PinOrPadName
},
363 {"Pinout", F_Pinout
},
364 {"Polygon", F_Polygon
},
365 {"PreviousPoint", F_PreviousPoint
},
366 {"RatsNest", F_RatsNest
},
367 {"Rectangle", F_Rectangle
},
368 {"Redraw", F_Redraw
},
369 {"Release", F_Release
},
370 {"Remove", F_Remove
},
371 {"RemoveSelected", F_RemoveSelected
},
372 {"Report", F_Report
},
374 {"ResetLinesAndPolygons", F_ResetLinesAndPolygons
},
375 {"ResetPinsViasAndPads", F_ResetPinsViasAndPads
},
376 {"Restore", F_Restore
},
377 {"Revert", F_Revert
},
378 {"Rotate", F_Rotate
},
380 {"Scroll", F_Scroll
},
381 {"Selected", F_Selected
},
382 {"SelectedArcs", F_SelectedArcs
},
383 {"SelectedElements", F_SelectedElements
},
384 {"SelectedLines", F_SelectedLines
},
385 {"SelectedNames", F_SelectedNames
},
386 {"SelectedObjects", F_SelectedObjects
},
387 {"SelectedPins", F_SelectedPins
},
388 {"SelectedPads", F_SelectedPads
},
389 {"SelectedRats", F_SelectedRats
},
390 {"SelectedTexts", F_SelectedTexts
},
391 {"SelectedVias", F_SelectedVias
},
392 {"Stroke", F_Stroke
},
394 {"TextByName", F_TextByName
},
395 {"TextScale", F_TextScale
},
396 {"Thermal", F_Thermal
},
397 {"ToLayout", F_ToLayout
},
398 {"Toggle45Degree", F_ToggleAllDirections
},
399 {"ToggleClearLine", F_ToggleClearLine
},
400 {"ToggleGrid", F_ToggleGrid
},
401 {"ToggleMask", F_ToggleMask
},
402 {"ToggleName", F_ToggleName
},
403 {"ToggleObject", F_ToggleObject
},
404 {"ToggleRubberBandMode", F_ToggleRubberBandMode
},
405 {"ToggleStartDirection", F_ToggleStartDirection
},
406 {"ToggleSnapPin", F_ToggleSnapPin
},
407 {"ToggleThindraw", F_ToggleThindraw
},
408 {"ToggleThindrawPoly", F_ToggleThindrawPoly
},
409 {"ToggleLockNames", F_ToggleLockNames
},
410 {"ToggleOnlyNames", F_ToggleOnlyNames
},
411 {"ToggleCheckPlanes", F_ToggleCheckPlanes
},
412 {"ToggleLocalRef", F_ToggleLocalRef
},
413 {"ToggleOrthoMove", F_ToggleOrthoMove
},
414 {"ToggleShowDRC", F_ToggleShowDRC
},
415 {"ToggleLiveRoute", F_ToggleLiveRoute
},
416 {"ToggleAutoDRC", F_ToggleAutoDRC
},
417 {"ToggleUniqueNames", F_ToggleUniqueNames
},
420 {"ViaByName", F_ViaByName
},
421 {"ViaSize", F_ViaSize
},
422 {"ViaDrillingHole", F_ViaDrillingHole
},
426 /* ---------------------------------------------------------------------------
427 * some local routines
429 static int GetFunctionID (String
);
430 static void AdjustAttachedBox (void);
431 static void NotifyLine (void);
432 static void NotifyBlock (void);
433 static void NotifyMode (void);
434 static void ClearWarnings (void);
435 #ifdef HAVE_LIBSTROKE
436 static void FinishStroke (void);
437 extern void stroke_init (void);
438 extern void stroke_record (int x
, int y
);
439 extern int stroke_trans (char *s
);
441 static void ChangeFlag (char *, char *, int, char *);
443 #define ARG(n) (argc > (n) ? argv[n] : 0)
445 #ifdef HAVE_LIBSTROKE
447 /* ---------------------------------------------------------------------------
448 * FinishStroke - try to recognize the stroke sent
456 void *ptr1
, *ptr2
, *ptr3
;
459 if (stroke_trans (msg
))
465 if (Settings
.Mode
== LINE_MODE
)
475 RotateScreenObject (StrokeBox
.X1
, StrokeBox
.Y1
, SWAP_IDENT
? 1 : 3);
481 RotateScreenObject (StrokeBox
.X1
, StrokeBox
.Y1
, SWAP_IDENT
? 3 : 1);
487 SetMode (ARROW_MODE
);
512 SetZoom (1000); /* special zoom extents */
524 LocationType x
= (StrokeBox
.X1
+ StrokeBox
.X2
) / 2;
525 LocationType y
= (StrokeBox
.Y1
+ StrokeBox
.Y2
) / 2;
529 log (fabs (StrokeBox
.X2
- StrokeBox
.X1
) / Output
.Width
) /
534 log (fabs (StrokeBox
.Y2
- StrokeBox
.Y1
) / Output
.Height
) /
538 CenterDisplay (x
, y
, False
);
543 Message ("Unknown stroke %s\n", msg
);
552 /* ---------------------------------------------------------------------------
553 * Clear warning color from pins/pads
558 Settings
.RatWarn
= False
;
559 ALLPIN_LOOP (PCB
->Data
);
561 if (TEST_FLAG (WARNFLAG
, pin
))
563 CLEAR_FLAG (WARNFLAG
, pin
);
568 ALLPAD_LOOP (PCB
->Data
);
570 if (TEST_FLAG (WARNFLAG
, pad
))
572 CLEAR_FLAG (WARNFLAG
, pad
);
586 if (Note
.Moving
&& !gui
->shift_is_pressed ())
588 HideCrosshair (True
);
589 Note
.Buffer
= Settings
.BufferNumber
;
590 SetBufferNumber (MAX_BUFFER
- 1);
591 ClearBuffer (PASTEBUFFER
);
592 AddSelectedToBuffer (PASTEBUFFER
, Note
.X
, Note
.Y
, True
);
593 SaveUndoSerialNumber ();
597 SetMode (PASTEBUFFER_MODE
);
598 RestoreCrosshair (True
);
600 else if (Note
.Hit
&& !gui
->shift_is_pressed ())
602 HideCrosshair (True
);
605 SetMode (gui
->control_is_pressed ()? COPY_MODE
: MOVE_MODE
);
606 Crosshair
.AttachedObject
.Ptr1
= Note
.ptr1
;
607 Crosshair
.AttachedObject
.Ptr2
= Note
.ptr2
;
608 Crosshair
.AttachedObject
.Ptr3
= Note
.ptr3
;
609 Crosshair
.AttachedObject
.Type
= Note
.Hit
;
610 AttachForCopy (Note
.X
, Note
.Y
);
611 RestoreCrosshair (True
);
619 HideCrosshair (True
);
620 SaveUndoSerialNumber ();
625 /* unselect first if shift key not down */
626 if (!gui
->shift_is_pressed () && SelectBlock (&box
, False
))
627 SetChangedFlag (True
);
629 Crosshair
.AttachedBox
.Point1
.X
= Note
.X
;
630 Crosshair
.AttachedBox
.Point1
.Y
= Note
.Y
;
631 RestoreCrosshair (True
);
650 Note
.Click
= False
; /* inhibit timer action */
651 SaveUndoSerialNumber ();
652 /* unselect first if shift key not down */
653 if (!gui
->shift_is_pressed ())
655 if (SelectBlock (&box
, False
))
656 SetChangedFlag (True
);
664 RestoreUndoSerialNumber ();
666 SetChangedFlag (True
);
670 else if (Note
.Moving
)
672 RestoreUndoSerialNumber ();
674 ClearBuffer (PASTEBUFFER
);
675 SetBufferNumber (Note
.Buffer
);
684 else if (Settings
.Mode
== ARROW_MODE
)
686 box
.X1
= MIN (Crosshair
.AttachedBox
.Point1
.X
,
687 Crosshair
.AttachedBox
.Point2
.X
);
688 box
.Y1
= MIN (Crosshair
.AttachedBox
.Point1
.Y
,
689 Crosshair
.AttachedBox
.Point2
.Y
);
690 box
.X2
= MAX (Crosshair
.AttachedBox
.Point1
.X
,
691 Crosshair
.AttachedBox
.Point2
.X
);
692 box
.Y2
= MAX (Crosshair
.AttachedBox
.Point1
.Y
,
693 Crosshair
.AttachedBox
.Point2
.Y
);
694 RestoreUndoSerialNumber ();
695 if (SelectBlock (&box
, True
))
696 SetChangedFlag (True
);
698 IncrementUndoSerialNumber ();
699 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
706 /* ---------------------------------------------------------------------------
707 * get function ID of passed string
710 static char function_hash
[HSIZE
];
711 static int hash_initted
= 0;
720 i
= (i
* 13) ^ (unsigned char)tolower(*s
);
723 i
= (unsigned int)i
% HSIZE
;
728 GetFunctionID (String Ident
)
735 if (HSIZE
< ENTRIES (Functions
) * 2)
737 fprintf(stderr
, "Error: function hash size too small (%d vs %ld at %s:%d)\n",
738 HSIZE
, ENTRIES (Functions
)*2, __FILE__
, __LINE__
);
741 if (ENTRIES (Functions
) > 254)
743 /* Change 'char' to 'int' and remove this when we get to 256
745 fprintf(stderr
, "Error: function hash type too small (%d vs %ld at %s:%d)\n",
746 256, ENTRIES (Functions
), __FILE__
, __LINE__
);
750 for (i
=ENTRIES (Functions
)-1; i
>=0; i
--)
752 h
= hashfunc (Functions
[i
].Identifier
);
753 while (function_hash
[h
])
755 function_hash
[h
] = i
+ 1;
759 i
= hashfunc (Ident
);
762 /* We enforce the "hash table bigger than function table" rule,
763 so we know there will be at least one zero entry to find. */
764 if (!function_hash
[i
])
766 if (!strcasecmp (Ident
, Functions
[function_hash
[i
]-1].Identifier
))
767 return ((int) Functions
[function_hash
[i
]-1].ID
);
772 /* ---------------------------------------------------------------------------
773 * set new coordinates if in 'RECTANGLE' mode
774 * the cursor shape is also adjusted
777 AdjustAttachedBox (void)
779 if (Settings
.Mode
== ARC_MODE
)
781 Crosshair
.AttachedBox
.otherway
= gui
->shift_is_pressed ();
784 switch (Crosshair
.AttachedBox
.State
)
786 case STATE_SECOND
: /* one corner is selected */
788 /* update coordinates */
789 Crosshair
.AttachedBox
.Point2
.X
= Crosshair
.X
;
790 Crosshair
.AttachedBox
.Point2
.Y
= Crosshair
.Y
;
796 /* ---------------------------------------------------------------------------
797 * adjusts the objects which are to be created like attached lines...
800 AdjustAttachedObjects (void)
803 switch (Settings
.Mode
)
805 /* update at least an attached block (selection) */
808 if (Crosshair
.AttachedBox
.State
)
810 Crosshair
.AttachedBox
.Point2
.X
= Crosshair
.X
;
811 Crosshair
.AttachedBox
.Point2
.Y
= Crosshair
.Y
;
815 /* rectangle creation mode */
818 AdjustAttachedBox ();
821 /* polygon creation mode */
823 AdjustAttachedLine ();
825 /* line creation mode */
827 if (PCB
->RatDraw
|| PCB
->Clipping
== 0)
828 AdjustAttachedLine ();
830 AdjustTwoLine (PCB
->Clipping
- 1);
832 /* point insertion mode */
833 case INSERTPOINT_MODE
:
834 pnt
= AdjustInsertPoint ();
836 InsertedPoint
= *pnt
;
843 /* ---------------------------------------------------------------------------
844 * creates points of a line
850 void *ptr1
, *ptr2
, *ptr3
;
852 if (!Marked
.status
|| TEST_FLAG (LOCALREFFLAG
, PCB
))
853 SetLocalRef (Crosshair
.X
, Crosshair
.Y
, True
);
854 switch (Crosshair
.AttachedLine
.State
)
856 case STATE_FIRST
: /* first point */
857 if (PCB
->RatDraw
&& SearchScreen (Crosshair
.X
, Crosshair
.Y
,
858 PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr1
,
864 if (TEST_FLAG (AUTODRCFLAG
, PCB
) && Settings
.Mode
== LINE_MODE
)
866 type
= SearchScreen (Crosshair
.X
, Crosshair
.Y
,
867 PIN_TYPE
| PAD_TYPE
| VIA_TYPE
, &ptr1
, &ptr2
,
869 LookupConnection (Crosshair
.X
, Crosshair
.Y
, True
, TO_PCB (1),
872 if (type
== PIN_TYPE
|| type
== VIA_TYPE
)
874 Crosshair
.AttachedLine
.Point1
.X
=
875 Crosshair
.AttachedLine
.Point2
.X
= ((PinTypePtr
) ptr2
)->X
;
876 Crosshair
.AttachedLine
.Point1
.Y
=
877 Crosshair
.AttachedLine
.Point2
.Y
= ((PinTypePtr
) ptr2
)->Y
;
879 else if (type
== PAD_TYPE
)
881 PadTypePtr pad
= (PadTypePtr
) ptr2
;
883 d1
= SQUARE (Crosshair
.X
- pad
->Point1
.X
) +
884 SQUARE (Crosshair
.Y
- pad
->Point1
.Y
);
885 d2
= SQUARE (Crosshair
.X
- pad
->Point2
.X
) +
886 SQUARE (Crosshair
.Y
- pad
->Point2
.Y
);
889 Crosshair
.AttachedLine
.Point1
=
890 Crosshair
.AttachedLine
.Point2
= pad
->Point2
;
894 Crosshair
.AttachedLine
.Point1
=
895 Crosshair
.AttachedLine
.Point2
= pad
->Point1
;
900 Crosshair
.AttachedLine
.Point1
.X
=
901 Crosshair
.AttachedLine
.Point2
.X
= Crosshair
.X
;
902 Crosshair
.AttachedLine
.Point1
.Y
=
903 Crosshair
.AttachedLine
.Point2
.Y
= Crosshair
.Y
;
905 Crosshair
.AttachedLine
.State
= STATE_SECOND
;
909 /* fall through to third state too */
911 default: /* all following points */
912 Crosshair
.AttachedLine
.State
= STATE_THIRD
;
917 /* ---------------------------------------------------------------------------
918 * create first or second corner of a marked block
923 HideCrosshair (True
);
924 switch (Crosshair
.AttachedBox
.State
)
926 case STATE_FIRST
: /* setup first point */
927 Crosshair
.AttachedBox
.Point1
.X
=
928 Crosshair
.AttachedBox
.Point2
.X
= Crosshair
.X
;
929 Crosshair
.AttachedBox
.Point1
.Y
=
930 Crosshair
.AttachedBox
.Point2
.Y
= Crosshair
.Y
;
931 Crosshair
.AttachedBox
.State
= STATE_SECOND
;
934 case STATE_SECOND
: /* setup second point */
935 Crosshair
.AttachedBox
.State
= STATE_THIRD
;
938 RestoreCrosshair (True
);
942 /* ---------------------------------------------------------------------------
944 * does what's appropriate for the current mode setting. This normally
945 * means creation of an object at the current crosshair location.
947 * new created objects are added to the create undo list of course
952 void *ptr1
, *ptr2
, *ptr3
;
955 if (Settings
.RatWarn
)
957 switch (Settings
.Mode
)
965 /* do something after click time */
966 gui
->add_timer (click_cb
, CLICK_TIME
, hv
);
968 /* see if we clicked on something already selected
969 * (Note.Moving) or clicked on a MOVE_TYPE
972 for (test
= (SELECT_TYPES
| MOVE_TYPES
) & ~RATLINE_TYPE
;
975 type
= SearchScreen (Note
.X
, Note
.Y
, test
, &ptr1
, &ptr2
, &ptr3
);
976 if (!Note
.Hit
&& (type
& MOVE_TYPES
) &&
977 !TEST_FLAG (LOCKFLAG
, (PinTypePtr
) ptr2
))
984 if (!Note
.Moving
&& (type
& SELECT_TYPES
) &&
985 TEST_FLAG (SELECTEDFLAG
, (PinTypePtr
) ptr2
))
987 if ((Note
.Hit
&& Note
.Moving
) || type
== NO_TYPE
)
999 Message (_("You must turn via visibility on before\n"
1000 "you can place vias\n"));
1003 if ((via
= CreateNewVia (PCB
->Data
, Note
.X
, Note
.Y
,
1004 Settings
.ViaThickness
, 2 * Settings
.Keepaway
,
1005 0, Settings
.ViaDrillingHole
, NULL
,
1006 NoFlags ())) != NULL
)
1008 AddObjectToCreateUndoList (VIA_TYPE
, via
, via
, via
);
1009 IncrementUndoSerialNumber ();
1018 switch (Crosshair
.AttachedBox
.State
)
1021 Crosshair
.AttachedBox
.Point1
.X
=
1022 Crosshair
.AttachedBox
.Point2
.X
= Note
.X
;
1023 Crosshair
.AttachedBox
.Point1
.Y
=
1024 Crosshair
.AttachedBox
.Point2
.Y
= Note
.Y
;
1025 Crosshair
.AttachedBox
.State
= STATE_SECOND
;
1032 LocationType wx
, wy
;
1035 wx
= Note
.X
- Crosshair
.AttachedBox
.Point1
.X
;
1036 wy
= Note
.Y
- Crosshair
.AttachedBox
.Point1
.Y
;
1037 if (XOR (Crosshair
.AttachedBox
.otherway
, abs (wy
) > abs (wx
)))
1039 Crosshair
.AttachedBox
.Point2
.X
=
1040 Crosshair
.AttachedBox
.Point1
.X
+ abs (wy
) * SGNZ (wx
);
1041 sa
= (wx
>= 0) ? 0 : 180;
1043 if (abs (wy
) / 2 >= abs (wx
))
1044 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 45 : -45;
1047 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 90 : -90;
1051 Crosshair
.AttachedBox
.Point2
.Y
=
1052 Crosshair
.AttachedBox
.Point1
.Y
+ abs (wx
) * SGNZ (wy
);
1053 sa
= (wy
>= 0) ? -90 : 90;
1055 if (abs (wx
) / 2 >= abs (wy
))
1056 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -45 : 45;
1059 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -90 : 90;
1062 if (abs (wy
) > 0 && (arc
= CreateNewArcOnLayer (CURRENT
,
1084 bx
= GetArcEnds (arc
);
1085 Crosshair
.AttachedBox
.Point1
.X
=
1086 Crosshair
.AttachedBox
.Point2
.X
= bx
->X2
;
1087 Crosshair
.AttachedBox
.Point1
.Y
=
1088 Crosshair
.AttachedBox
.Point2
.Y
= bx
->Y2
;
1089 AddObjectToCreateUndoList (ARC_TYPE
, CURRENT
, arc
, arc
);
1090 IncrementUndoSerialNumber ();
1092 DrawArc (CURRENT
, arc
, 0);
1094 Crosshair
.AttachedBox
.State
= STATE_THIRD
;
1103 type
= SearchScreen (Note
.X
, Note
.Y
, LOCK_TYPES
, &ptr1
, &ptr2
, &ptr3
);
1104 if (type
== ELEMENT_TYPE
)
1106 ElementTypePtr element
= (ElementTypePtr
) ptr2
;
1108 TOGGLE_FLAG (LOCKFLAG
, element
);
1111 TOGGLE_FLAG (LOCKFLAG
, pin
);
1112 CLEAR_FLAG (SELECTEDFLAG
, pin
);
1117 TOGGLE_FLAG (LOCKFLAG
, pad
);
1118 CLEAR_FLAG (SELECTEDFLAG
, pad
);
1121 CLEAR_FLAG (SELECTEDFLAG
, element
);
1122 /* always re-draw it since I'm too lazy
1123 * to tell if a selected flag changed
1125 DrawElement (element
, 0);
1127 hid_actionl ("Report", "Object", NULL
);
1129 else if (type
!= NO_TYPE
)
1131 TextTypePtr thing
= (TextTypePtr
) ptr3
;
1132 TOGGLE_FLAG (LOCKFLAG
, thing
);
1133 if (TEST_FLAG (LOCKFLAG
, thing
)
1134 && TEST_FLAG (SELECTEDFLAG
, thing
))
1136 /* this is not un-doable since LOCK isn't */
1137 CLEAR_FLAG (SELECTEDFLAG
, thing
);
1138 DrawObject (type
, ptr1
, ptr2
, 0);
1141 hid_actionl ("Report", "Object", NULL
);
1149 SearchScreen (Note
.X
, Note
.Y
, PIN_TYPES
, &ptr1
, &ptr2
,
1151 && !TEST_FLAG (HOLEFLAG
, (PinTypePtr
) ptr3
))
1153 if (gui
->shift_is_pressed ())
1155 int tstyle
= GET_THERM (INDEXOFCURRENT
, (PinTypePtr
) ptr3
);
1159 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, tstyle
);
1161 else if (GET_THERM (INDEXOFCURRENT
, (PinTypePtr
) ptr3
))
1162 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, 0);
1164 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, PCB
->ThermStyle
);
1170 /* do update of position */
1172 if (Crosshair
.AttachedLine
.State
!= STATE_THIRD
)
1175 /* Remove anchor if clicking on start point;
1176 * this means we can't paint 0 length lines
1177 * which could be used for square SMD pads.
1178 * Instead use a very small delta, or change
1179 * the file after saving.
1181 if (Crosshair
.X
== Crosshair
.AttachedLine
.Point1
.X
1182 && Crosshair
.Y
== Crosshair
.AttachedLine
.Point1
.Y
)
1184 SetMode (LINE_MODE
);
1191 if ((line
= AddNet ()))
1194 AddObjectToCreateUndoList (RATLINE_TYPE
, line
, line
, line
);
1195 IncrementUndoSerialNumber ();
1197 Crosshair
.AttachedLine
.Point1
.X
=
1198 Crosshair
.AttachedLine
.Point2
.X
;
1199 Crosshair
.AttachedLine
.Point1
.Y
=
1200 Crosshair
.AttachedLine
.Point2
.Y
;
1206 /* create line if both ends are determined && length != 0 */
1211 && Crosshair
.AttachedLine
.Point1
.X
==
1212 Crosshair
.AttachedLine
.Point2
.X
1213 && Crosshair
.AttachedLine
.Point1
.Y
==
1214 Crosshair
.AttachedLine
.Point2
.Y
1215 && (Crosshair
.AttachedLine
.Point2
.X
!= Note
.X
1216 || Crosshair
.AttachedLine
.Point2
.Y
!= Note
.Y
))
1218 /* We will paint only the second line segment.
1219 Since we only check for vias on the first segment,
1220 swap them so we only paint the first segment. */
1221 Crosshair
.AttachedLine
.Point2
.X
= Note
.X
;
1222 Crosshair
.AttachedLine
.Point2
.Y
= Note
.Y
;
1225 if ((Crosshair
.AttachedLine
.Point1
.X
!=
1226 Crosshair
.AttachedLine
.Point2
.X
1227 || Crosshair
.AttachedLine
.Point1
.Y
!=
1228 Crosshair
.AttachedLine
.Point2
.Y
)
1230 CreateDrawnLineOnLayer (CURRENT
,
1231 Crosshair
.AttachedLine
.Point1
.X
,
1232 Crosshair
.AttachedLine
.Point1
.Y
,
1233 Crosshair
.AttachedLine
.Point2
.X
,
1234 Crosshair
.AttachedLine
.Point2
.Y
,
1235 Settings
.LineThickness
,
1236 2 * Settings
.Keepaway
,
1237 MakeFlags ((TEST_FLAG
1239 PCB
) ? FOUNDFLAG
: 0) |
1242 PCB
) ? CLEARLINEFLAG
:
1248 AddObjectToCreateUndoList (LINE_TYPE
, CURRENT
, line
, line
);
1249 DrawLine (CURRENT
, line
, 0);
1250 /* place a via if vias are visible, the layer is
1251 in a new group since the last line and there
1252 isn't a pin already here */
1253 if (PCB
->ViaOn
&& GetLayerGroupNumberByPointer (CURRENT
) !=
1254 GetLayerGroupNumberByPointer (lastLayer
) &&
1255 SearchObjectByLocation (PIN_TYPES
, &ptr1
, &ptr2
, &ptr3
,
1256 Crosshair
.AttachedLine
.Point1
.X
,
1257 Crosshair
.AttachedLine
.Point1
.Y
,
1258 Settings
.ViaThickness
/ 2) ==
1261 CreateNewVia (PCB
->Data
,
1262 Crosshair
.AttachedLine
.Point1
.X
,
1263 Crosshair
.AttachedLine
.Point1
.Y
,
1264 Settings
.ViaThickness
,
1265 2 * Settings
.Keepaway
, 0,
1266 Settings
.ViaDrillingHole
, NULL
,
1267 NoFlags ())) != NULL
)
1269 AddObjectToCreateUndoList (VIA_TYPE
, via
, via
, via
);
1272 /* copy the coordinates */
1273 Crosshair
.AttachedLine
.Point1
.X
=
1274 Crosshair
.AttachedLine
.Point2
.X
;
1275 Crosshair
.AttachedLine
.Point1
.Y
=
1276 Crosshair
.AttachedLine
.Point2
.Y
;
1277 IncrementUndoSerialNumber ();
1278 lastLayer
= CURRENT
;
1280 if (PCB
->Clipping
&& (Note
.X
!= Crosshair
.AttachedLine
.Point2
.X
1282 Crosshair
.AttachedLine
.Point2
.Y
)
1284 CreateDrawnLineOnLayer (CURRENT
,
1285 Crosshair
.AttachedLine
.Point2
.X
,
1286 Crosshair
.AttachedLine
.Point2
.Y
,
1288 Settings
.LineThickness
,
1289 2 * Settings
.Keepaway
,
1290 MakeFlags ((TEST_FLAG
1292 PCB
) ? FOUNDFLAG
: 0) |
1295 PCB
) ? CLEARLINEFLAG
:
1299 AddObjectToCreateUndoList (LINE_TYPE
, CURRENT
, line
, line
);
1300 IncrementUndoSerialNumber ();
1301 DrawLine (CURRENT
, line
, 0);
1302 /* move to new start point */
1303 Crosshair
.AttachedLine
.Point1
.X
= Note
.X
;
1304 Crosshair
.AttachedLine
.Point1
.Y
= Note
.Y
;
1305 Crosshair
.AttachedLine
.Point2
.X
= Note
.X
;
1306 Crosshair
.AttachedLine
.Point2
.Y
= Note
.Y
;
1307 if (TEST_FLAG (SWAPSTARTDIRFLAG
, PCB
))
1316 case RECTANGLE_MODE
:
1317 /* do update of position */
1320 /* create rectangle if both corners are determined
1321 * and width, height are != 0
1323 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
&&
1324 Crosshair
.AttachedBox
.Point1
.X
!= Crosshair
.AttachedBox
.Point2
.X
&&
1325 Crosshair
.AttachedBox
.Point1
.Y
!= Crosshair
.AttachedBox
.Point2
.Y
)
1327 PolygonTypePtr polygon
;
1329 if ((polygon
= CreateNewPolygonFromRectangle (CURRENT
,
1331 AttachedBox
.Point1
.X
,
1333 AttachedBox
.Point1
.Y
,
1335 AttachedBox
.Point2
.X
,
1337 AttachedBox
.Point2
.Y
,
1339 (CLEARPOLYFLAG
))) !=
1342 AddObjectToCreateUndoList (POLYGON_TYPE
, CURRENT
,
1344 IncrementUndoSerialNumber ();
1345 DrawPolygon (CURRENT
, polygon
, 0);
1349 /* reset state to 'first corner' */
1350 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
1358 if ((string
= gui
->prompt_for (_("Enter text:"), "")) != NULL
)
1363 if (GetLayerGroupNumberByNumber (INDEXOFCURRENT
) ==
1364 GetLayerGroupNumberByNumber (max_layer
+ SOLDER_LAYER
))
1365 flag
= ONSOLDERFLAG
;
1366 if ((text
= CreateNewText (CURRENT
, &PCB
->Font
, Note
.X
,
1367 Note
.Y
, 0, Settings
.TextScale
,
1368 string
, MakeFlags (flag
))) != NULL
)
1370 AddObjectToCreateUndoList (TEXT_TYPE
, CURRENT
, text
, text
);
1371 IncrementUndoSerialNumber ();
1372 DrawText (CURRENT
, text
, 0);
1376 /* free memory allocated by gui->prompt_for() */
1384 PointTypePtr points
= Crosshair
.AttachedPolygon
.Points
;
1385 Cardinal n
= Crosshair
.AttachedPolygon
.PointN
;
1387 /* do update of position; use the 'LINE_MODE' mechanism */
1390 /* check if this is the last point of a polygon */
1392 points
->X
== Crosshair
.AttachedLine
.Point2
.X
&&
1393 points
->Y
== Crosshair
.AttachedLine
.Point2
.Y
)
1395 CopyAttachedPolygonToLayer ();
1400 /* create new point if it's the first one or if it's
1401 * different to the last one
1404 points
[n
- 1].X
!= Crosshair
.AttachedLine
.Point2
.X
||
1405 points
[n
- 1].Y
!= Crosshair
.AttachedLine
.Point2
.Y
)
1407 CreateNewPointInPolygon (&Crosshair
.AttachedPolygon
,
1408 Crosshair
.AttachedLine
.Point2
.X
,
1409 Crosshair
.AttachedLine
.Point2
.Y
);
1411 /* copy the coordinates */
1412 Crosshair
.AttachedLine
.Point1
.X
= Crosshair
.AttachedLine
.Point2
.X
;
1413 Crosshair
.AttachedLine
.Point1
.Y
= Crosshair
.AttachedLine
.Point2
.Y
;
1418 case PASTEBUFFER_MODE
:
1420 TextType estr
[MAX_ELEMENTNAMES
];
1421 ElementTypePtr e
= 0;
1423 if (gui
->shift_is_pressed ())
1426 SearchScreen (Note
.X
, Note
.Y
, ELEMENT_TYPE
, &ptr1
, &ptr2
,
1428 if (type
== ELEMENT_TYPE
)
1430 e
= (ElementTypePtr
) ptr1
;
1433 memcpy (estr
, e
->Name
,
1434 MAX_ELEMENTNAMES
* sizeof (TextType
));
1435 memset (e
->Name
, 0, MAX_ELEMENTNAMES
* sizeof (TextType
));
1440 if (CopyPastebufferToLayout (Note
.X
, Note
.Y
))
1441 SetChangedFlag (True
);
1445 SearchScreen (Note
.X
, Note
.Y
, ELEMENT_TYPE
, &ptr1
, &ptr2
,
1447 if (type
== ELEMENT_TYPE
&& ptr1
)
1450 e
= (ElementTypePtr
) ptr1
;
1452 save_n
= NAME_INDEX (PCB
);
1454 for (i
= 0; i
< MAX_ELEMENTNAMES
; i
++)
1457 EraseElementName (e
);
1458 r_delete_entry (PCB
->Data
->name_tree
[i
],
1459 (BoxType
*) & (e
->Name
[i
]));
1460 memcpy (&(e
->Name
[i
]), &(estr
[i
]), sizeof (TextType
));
1461 e
->Name
[i
].Element
= e
;
1462 SetTextBoundingBox (&PCB
->Font
, &(e
->Name
[i
]));
1463 r_insert_entry (PCB
->Data
->name_tree
[i
],
1464 (BoxType
*) & (e
->Name
[i
]), 0);
1466 DrawElementName (e
, 0);
1475 SearchScreen (Note
.X
, Note
.Y
, REMOVE_TYPES
, &ptr1
, &ptr2
,
1478 if (TEST_FLAG (LOCKFLAG
, (LineTypePtr
) ptr2
))
1480 Message (_("Sorry, the object is locked\n"));
1483 if (type
== ELEMENT_TYPE
)
1485 RubberbandTypePtr ptr
;
1488 Crosshair
.AttachedObject
.RubberbandN
= 0;
1489 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
1490 ptr
= Crosshair
.AttachedObject
.Rubberband
;
1491 for (i
= 0; i
< Crosshair
.AttachedObject
.RubberbandN
; i
++)
1494 EraseRat ((RatTypePtr
) ptr
->Line
);
1495 MoveObjectToRemoveUndoList (RATLINE_TYPE
,
1496 ptr
->Line
, ptr
->Line
,
1501 RemoveObject (type
, ptr1
, ptr2
, ptr3
);
1502 IncrementUndoSerialNumber ();
1503 SetChangedFlag (True
);
1508 RotateScreenObject (Note
.X
, Note
.Y
,
1509 gui
->shift_is_pressed ()? (SWAP_IDENT
?
1511 : (SWAP_IDENT
? 3 : 1));
1514 /* both are almost the same */
1517 switch (Crosshair
.AttachedObject
.State
)
1519 /* first notify, lookup object */
1522 int types
= (Settings
.Mode
== COPY_MODE
) ?
1523 COPY_TYPES
: MOVE_TYPES
;
1525 Crosshair
.AttachedObject
.Type
=
1526 SearchScreen (Note
.X
, Note
.Y
, types
,
1527 &Crosshair
.AttachedObject
.Ptr1
,
1528 &Crosshair
.AttachedObject
.Ptr2
,
1529 &Crosshair
.AttachedObject
.Ptr3
);
1530 if (Crosshair
.AttachedObject
.Type
!= NO_TYPE
)
1532 if (Settings
.Mode
== MOVE_MODE
&&
1533 TEST_FLAG (LOCKFLAG
, (PinTypePtr
)
1534 Crosshair
.AttachedObject
.Ptr2
))
1536 Message (_("Sorry, the object is locked\n"));
1537 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1540 AttachForCopy (Note
.X
, Note
.Y
);
1545 /* second notify, move or copy object */
1547 if (Settings
.Mode
== COPY_MODE
)
1548 CopyObject (Crosshair
.AttachedObject
.Type
,
1549 Crosshair
.AttachedObject
.Ptr1
,
1550 Crosshair
.AttachedObject
.Ptr2
,
1551 Crosshair
.AttachedObject
.Ptr3
,
1552 Note
.X
- Crosshair
.AttachedObject
.X
,
1553 Note
.Y
- Crosshair
.AttachedObject
.Y
);
1556 MoveObjectAndRubberband (Crosshair
.AttachedObject
.Type
,
1557 Crosshair
.AttachedObject
.Ptr1
,
1558 Crosshair
.AttachedObject
.Ptr2
,
1559 Crosshair
.AttachedObject
.Ptr3
,
1560 Note
.X
- Crosshair
.AttachedObject
.X
,
1561 Note
.Y
- Crosshair
.AttachedObject
.Y
);
1562 SetLocalRef (0, 0, False
);
1564 SetChangedFlag (True
);
1566 /* reset identifiers */
1567 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1568 Crosshair
.AttachedObject
.State
= STATE_FIRST
;
1573 /* insert a point into a polygon/line/... */
1574 case INSERTPOINT_MODE
:
1575 switch (Crosshair
.AttachedObject
.State
)
1577 /* first notify, lookup object */
1579 Crosshair
.AttachedObject
.Type
=
1580 SearchScreen (Note
.X
, Note
.Y
, INSERT_TYPES
,
1581 &Crosshair
.AttachedObject
.Ptr1
,
1582 &Crosshair
.AttachedObject
.Ptr2
,
1583 &Crosshair
.AttachedObject
.Ptr3
);
1585 if (Crosshair
.AttachedObject
.Type
!= NO_TYPE
)
1587 if (TEST_FLAG (LOCKFLAG
, (PolygonTypePtr
)
1588 Crosshair
.AttachedObject
.Ptr2
))
1590 Message (_("Sorry, the object is locked\n"));
1591 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1596 /* get starting point of nearest segment */
1597 if (Crosshair
.AttachedObject
.Type
== POLYGON_TYPE
)
1600 (PolygonTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
1602 GetLowestDistancePolygonPoint (fake
.poly
, Note
.X
,
1604 fake
.line
.Point1
= fake
.poly
->Points
[polyIndex
];
1605 fake
.line
.Point2
= (polyIndex
) ?
1606 fake
.poly
->Points
[polyIndex
- 1]
1607 : fake
.poly
->Points
[fake
.poly
->PointN
- 1];
1608 Crosshair
.AttachedObject
.Ptr2
= &fake
.line
;
1611 Crosshair
.AttachedObject
.State
= STATE_SECOND
;
1612 InsertedPoint
= *AdjustInsertPoint ();
1617 /* second notify, insert new point into object */
1619 if (Crosshair
.AttachedObject
.Type
== POLYGON_TYPE
)
1620 InsertPointIntoObject (POLYGON_TYPE
,
1621 Crosshair
.AttachedObject
.Ptr1
, fake
.poly
,
1623 InsertedPoint
.X
, InsertedPoint
.Y
, False
);
1625 InsertPointIntoObject (Crosshair
.AttachedObject
.Type
,
1626 Crosshair
.AttachedObject
.Ptr1
,
1627 Crosshair
.AttachedObject
.Ptr2
,
1629 InsertedPoint
.X
, InsertedPoint
.Y
, False
);
1630 SetChangedFlag (True
);
1632 /* reset identifiers */
1633 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1634 Crosshair
.AttachedObject
.State
= STATE_FIRST
;
1642 /* --------------------------------------------------------------------------- */
1644 static const char atomic_syntax
[] = "Atomic(Save|Restore|Close|Block)";
1646 static const char atomic_help
[] = "Save or restore the undo serial number.";
1648 /* %start-doc actions Atomic
1650 This action allows making multiple-action bindings into an atomic
1651 operation that will be undone by a single Undo command. For example,
1652 to optimize rat lines, you'd delete the rats and re-add them. To
1653 group these into a single undo, you'd want the deletions and the
1654 additions to have the same undo serial number. So, you @code{Save},
1655 delete the rats, @code{Restore}, add the rats - using the same serial
1656 number as the deletes, then @code{Block}, which checks to see if the
1657 deletions or additions actually did anything. If not, the serial
1658 number is set to the saved number, as there's nothing to undo. If
1659 something did happen, the serial number is incremented so that these
1660 actions are counted as a single undo step.
1665 Saves the undo serial number.
1668 Returns it to the last saved number.
1671 Sets it to 1 greater than the last save.
1674 Does a Restore if there was nothing to undo, else does a Close.
1681 ActionAtomic (int argc
, char **argv
, int x
, int y
)
1686 switch (GetFunctionID (argv
[0]))
1689 SaveUndoSerialNumber ();
1692 RestoreUndoSerialNumber ();
1695 RestoreUndoSerialNumber ();
1696 IncrementUndoSerialNumber ();
1699 RestoreUndoSerialNumber ();
1701 IncrementUndoSerialNumber ();
1707 /* -------------------------------------------------------------------------- */
1709 static const char drc_syntax
[] = "DRC()";
1711 static const char drc_help
[] = "Invoke the DRC check.";
1713 /* %start-doc actions DRC
1715 Note that the design rule check uses the current board rule settings,
1716 not the current style settings.
1721 ActionDRCheck (int argc
, char **argv
, int x
, int y
)
1725 Message (_("Rules are minspace %d.%02d, minoverlap %d.%d "
1726 "minwidth %d.%02d, minsilk %d.%02d\n"
1727 "min drill %d.%02d, min annular ring %d.%02d\n"),
1728 (PCB
->Bloat
+ 1) / 100, (PCB
->Bloat
+ 1) % 100,
1729 PCB
->Shrink
/ 100, PCB
->Shrink
% 100,
1730 PCB
->minWid
/ 100, PCB
->minWid
% 100,
1731 PCB
->minSlk
/ 100, PCB
->minSlk
% 100,
1732 PCB
->minDrill
/ 100, PCB
->minDrill
% 100,
1733 PCB
->minRing
/ 100, PCB
->minRing
% 100);
1734 HideCrosshair (True
);
1737 Message (_("No DRC problems found.\n"));
1739 Message (_("Found %d design rule errors\n"), count
);
1740 RestoreCrosshair (True
);
1744 /* -------------------------------------------------------------------------- */
1746 static const char dumplibrary_syntax
[] = "DumpLibrary()";
1748 static const char dumplibrary_help
[] =
1749 "Display the entire contents of the libraries.";
1751 /* %start-doc actions DumpLibrary
1757 ActionDumpLibrary (int argc
, char **argv
, int x
, int y
)
1761 printf ("**** Do not count on this format. It will change ****\n\n");
1762 printf ("MenuN = %d\n", Library
.MenuN
);
1763 printf ("MenuMax = %d\n", Library
.MenuMax
);
1764 for (i
= 0; i
< Library
.MenuN
; i
++)
1766 printf ("Library #%d:\n", i
);
1767 printf (" EntryN = %d\n", Library
.Menu
[i
].EntryN
);
1768 printf (" EntryMax = %d\n", Library
.Menu
[i
].EntryMax
);
1769 printf (" Name = \"%s\"\n", UNKNOWN (Library
.Menu
[i
].Name
));
1770 printf (" directory = \"%s\"\n",
1771 UNKNOWN (Library
.Menu
[i
].directory
));
1772 printf (" Style = \"%s\"\n", UNKNOWN (Library
.Menu
[i
].Style
));
1773 printf (" flag = %d\n", Library
.Menu
[i
].flag
);
1775 for (j
= 0; j
< Library
.Menu
[i
].EntryN
; j
++)
1777 printf (" #%4d: ", j
);
1778 if (Library
.Menu
[i
].Entry
[j
].Template
== (char *) -1)
1780 printf ("newlib: \"%s\"\n",
1781 UNKNOWN (Library
.Menu
[i
].Entry
[j
].ListEntry
));
1785 printf ("\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"\n",
1786 UNKNOWN (Library
.Menu
[i
].Entry
[j
].ListEntry
),
1787 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Template
),
1788 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Package
),
1789 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Value
),
1790 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Description
));
1798 /* -------------------------------------------------------------------------- */
1800 static const char flip_syntax
[] = "Flip(Object|Selected|SelectedElements)";
1802 static const char flip_help
[] =
1803 "Flip an element to the opposite side of the board.";
1805 /* %start-doc actions Flip
1807 Note that the location of the element will be symmetric about the
1808 cursor location; i.e. if the part you are pointing at will still be at
1809 the same spot once the element is on the other side. When flipping
1810 multiple elements, this retains their positions relative to each
1811 other, not their absolute positions on the board.
1816 ActionFlip (int argc
, char **argv
, int x
, int y
)
1818 char *function
= ARG (0);
1819 ElementTypePtr element
;
1825 HideCrosshair (True
);
1826 switch (GetFunctionID (function
))
1829 if ((SearchScreen (x
, y
, ELEMENT_TYPE
,
1830 &ptrtmp
, &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
1832 element
= (ElementTypePtr
) ptrtmp
;
1833 ChangeElementSide (element
, 2 * Crosshair
.Y
- PCB
->MaxHeight
);
1834 IncrementUndoSerialNumber ();
1839 case F_SelectedElements
:
1840 ChangeSelectedElementSide ();
1846 RestoreCrosshair (True
);
1854 /* -------------------------------------------------------------------------- */
1856 static const char message_syntax
[] = "Message(message)";
1858 static const char message_help
[] = "Writes a message to the log window.";
1860 /* %start-doc actions Message
1862 This action displays a message to the log window. This action is primarily
1863 provided for use by other programs which may interface with PCB. If
1864 multiple arguments are given, each one is sent to the log window
1865 followed by a newline.
1870 ActionMessage (int argc
, char **argv
, int x
, int y
)
1877 for (i
= 0; i
< argc
; i
++)
1887 /* -------------------------------------------------------------------------- */
1889 static const char setthermal_syntax
[] =
1890 "SetThermal(Object|SelectedPins|SelectedVias|Selected, Style)";
1892 static const char setthermal_help
[] =
1893 "Set the thermal (on the current layer) of pins or vias to the given style.\n"
1894 "Style = 0 means no thermal.\n"
1895 "Style = 1 has diagonal fingers with sharp edges.\n"
1896 "Style = 2 has horizontal and vertical fingers with sharp edges.\n"
1897 "Style = 3 is a solid connection to the plane."
1898 "Style = 4 has diagonal fingers with rounded edges.\n"
1899 "Style = 5 has horizontal and vertical fingers with rounded edges.\n";
1901 /* %start-doc actions SetThermal
1903 This changes how/whether pins or vias connect to any rectangle or polygon
1904 on the current layer. The first argument can specify one object, or all
1905 selected pins, or all selected vias, or all selected pins and vias.
1906 The second argument specifies the style of connection.
1907 There are 5 possibilities:
1909 1 - 45 degree fingers with sharp edges,
1910 2 - horizontal & vertical fingers with sharp edges,
1911 3 - solid connection,
1912 4 - 45 degree fingers with rounded corners,
1913 5 - horizontal & vertical fingers with rounded corners.
1915 Pins and Vias may have thermals whether or not there is a polygon available
1916 to connect with. However, they will have no effect without the polygon.
1920 ActionSetThermal (int argc
, char **argv
, int x
, int y
)
1922 char *function
= ARG (0);
1923 char *style
= ARG (1);
1924 void *ptr1
, *ptr2
, *ptr3
;
1928 if (function
&& *function
&& style
&& *style
)
1932 kind
= GetValue (style
, NULL
, &absolute
);
1933 HideCrosshair (True
);
1935 switch (GetFunctionID (function
))
1939 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGETHERMAL_TYPES
,
1940 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
1942 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, kind
);
1943 IncrementUndoSerialNumber ();
1947 case F_SelectedPins
:
1948 ChangeSelectedThermals (PIN_TYPE
, kind
);
1950 case F_SelectedVias
:
1951 ChangeSelectedThermals (VIA_TYPE
, kind
);
1954 case F_SelectedElements
:
1955 ChangeSelectedThermals (CHANGETHERMAL_TYPES
, kind
);
1963 RestoreCrosshair (True
);
1971 /* ---------------------------------------------------------------------------
1972 * action routine to move the X pointer relative to the current position
1973 * syntax: MovePointer(deltax,deltay)
1976 ActionMovePointer (char *deltax
, char *deltay
)
1978 LocationType x
, y
, dx
, dy
;
1980 /* save old crosshair position */
1983 dx
= (LocationType
) (atoi (deltax
) * PCB
->Grid
);
1984 dy
= (LocationType
) (atoi (deltay
) * PCB
->Grid
);
1985 MoveCrosshairRelative (TO_SCREEN_SIGN_X (dx
), TO_SCREEN_SIGN_Y (dy
));
1986 FitCrosshairIntoGrid (Crosshair
.X
, Crosshair
.Y
);
1987 /* restore crosshair for erasure */
1990 HideCrosshair (False
);
1991 MoveCrosshairRelative (TO_SCREEN_SIGN_X (dx
), TO_SCREEN_SIGN_Y (dy
));
1992 /* update object position and cursor location */
1993 AdjustAttachedObjects ();
1994 RestoreCrosshair (False
);
1997 /* ---------------------------------------------------------------------------
1998 * !!! no action routine !!!
2000 * event handler to set the cursor according to the X pointer position
2001 * called from inside main.c
2004 EventMoveCrosshair (int ev_x
, int ev_y
)
2006 #ifdef HAVE_LIBSTROKE
2009 StrokeBox
.X2
= TO_PCB_X (ev_x
);
2010 StrokeBox
.Y2
= TO_PCB_Y (ev_y
);
2011 stroke_record (Event
->x
, ev_y
);
2014 #endif /* HAVE_LIBSTROKE */
2015 /* ignore events that are caused by ActionMovePointer */
2016 if (!IgnoreMotionEvents
)
2018 if (MoveCrosshairAbsolute (ev_x
, ev_y
))
2021 /* update object position and cursor location */
2022 AdjustAttachedObjects ();
2023 RestoreCrosshair (False
);
2027 IgnoreMotionEvents
= False
;
2030 /* --------------------------------------------------------------------------- */
2032 static const char setvalue_syntax
[] =
2033 "SetValue(Grid|Line|LineSize|Text|TextScale|ViaDrillingHole|Via|ViaSize, delta)";
2035 static const char setvalue_help
[] =
2036 "Change various board-wide values and sizes.";
2038 /* %start-doc actions SetValue
2042 @item ViaDrillingHole
2043 Changes the diameter of the drill for new vias.
2046 Sets the grid spacing.
2050 Changes the thickness of new lines.
2054 Changes the diameter of new vias.
2058 Changes the size of new text.
2065 ActionSetValue (int argc
, char **argv
, int x
, int y
)
2067 char *function
= ARG (0);
2068 char *val
= ARG (1);
2069 char *units
= ARG (2);
2070 Boolean r
; /* flag for 'relative' value */
2074 if (function
&& val
)
2076 HideCrosshair (True
);
2077 value
= GetValue (val
, units
, &r
);
2078 switch (GetFunctionID (function
))
2080 case F_ViaDrillingHole
:
2081 SetViaDrillingHole (r
? value
: value
+ Settings
.ViaDrillingHole
,
2083 hid_action ("RouteStylesChanged");
2089 if ((value
== (int) value
&& PCB
->Grid
== (int) PCB
->Grid
)
2090 || (value
!= (int) value
&& PCB
->Grid
!= (int) PCB
->Grid
))
2091 SetGrid (value
+ PCB
->Grid
, False
);
2094 ("Don't combine metric/English grids like that!\n"));
2097 SetGrid (value
, False
);
2102 SetLineSize (r
? value
: value
+ Settings
.LineThickness
);
2103 hid_action ("RouteStylesChanged");
2108 SetViaSize (r
? value
: value
+ Settings
.ViaThickness
, False
);
2109 hid_action ("RouteStylesChanged");
2115 SetTextScale (r
? value
: value
+ Settings
.TextScale
);
2121 RestoreCrosshair (True
);
2130 /* --------------------------------------------------------------------------- */
2132 static const char quit_syntax
[] = "Quit()";
2134 static const char quit_help
[] = "Quits the application.";
2136 /* %start-doc actions Quit
2138 If you have unsaved changes, you will be prompted to confirm before
2144 ActionQuit (int argc
, char **argv
, int x
, int y
)
2146 char *force
= ARG (0);
2147 if (force
&& strcasecmp (force
, "force") == 0)
2152 if (!PCB
->Changed
|| gui
->confirm_dialog (_("OK to lose data ?"), 0))
2157 /* --------------------------------------------------------------------------- */
2159 static const char connection_syntax
[] =
2160 "Connection(Find|ResetLinesAndPolygons|ResetPinsAndVias|Reset)";
2162 static const char connection_help
[] =
2163 "Searches connections of the object at the cursor position.";
2165 /* %start-doc actions Connection
2167 Connections found with this action will be highlighted in the
2168 ``connected-color'' color and will have the ``found'' flag set.
2173 The net under the cursor is ``found''.
2175 @item ResetLinesAndPolygons
2176 Any ``found'' lines and polygons are marked ``not found''.
2178 @item ResetPinsAndVias
2179 Any ``found'' pins and vias are marked ``not found''.
2182 All ``found'' objects are marked ``not found''.
2185 The net under the cursor is found and measured (the lengths of all
2186 line segments are added together)
2193 ActionConnection (int argc
, char **argv
, int x
, int y
)
2195 char *function
= ARG (0);
2198 HideCrosshair (True
);
2199 switch (GetFunctionID (function
))
2203 gui
->get_coords ("Click on a connection", &x
, &y
);
2204 LookupConnection (x
, y
, True
, PCB
->Grid
, FOUNDFLAG
);
2208 case F_ResetLinesAndPolygons
:
2209 ResetFoundLinesAndPolygons (True
);
2212 case F_ResetPinsViasAndPads
:
2213 ResetFoundPinsViasAndPads (True
);
2217 SaveUndoSerialNumber ();
2218 ResetFoundPinsViasAndPads (True
);
2219 RestoreUndoSerialNumber ();
2220 ResetFoundLinesAndPolygons (True
);
2223 RestoreCrosshair (True
);
2230 /* --------------------------------------------------------------------------- */
2232 static const char disperseelements_syntax
[] =
2233 "DisperseElements(All|Selected)";
2235 static const char disperseelements_help
[] = "Disperses elements.";
2237 /* %start-doc actions DisperseElements
2239 Normally this is used when starting a board, by selecting all elements
2240 and then dispersing them. This scatters the elements around the board
2241 so that you can pick individual ones, rather than have all the
2242 elements at the same 0,0 coordinate and thus impossible to choose
2250 ActionDisperseElements (int argc
, char **argv
, int x
, int y
)
2252 char *function
= ARG (0);
2253 long minx
, miny
, maxx
, maxy
, dx
, dy
;
2254 int all
= 0, bad
= 0;
2261 if (!function
|| !*function
)
2267 switch (GetFunctionID (function
))
2284 AFAIL (disperseelements
);
2288 ELEMENT_LOOP (PCB
->Data
);
2291 * If we want to disperse selected elements, maybe we need smarter
2292 * code here to avoid putting components on top of others which
2293 * are not selected. For now, I'm assuming that this is typically
2294 * going to be used either with a brand new design or a scratch
2295 * design holding some new components
2297 if (all
|| TEST_FLAG (SELECTEDFLAG
, element
))
2300 /* figure out how much to move the element */
2301 dx
= minx
- element
->BoundingBox
.X1
;
2303 /* snap to the grid */
2304 dx
-= (element
->MarkX
+ dx
) % (long) (PCB
->Grid
);
2307 * and add one grid size so we make sure we always space by GAP or
2310 dx
+= (long) (PCB
->Grid
);
2312 /* Figure out if this row has room. If not, start a new row */
2313 if (GAP
+ element
->BoundingBox
.X2
+ dx
> PCB
->MaxWidth
)
2319 /* figure out how much to move the element */
2320 dx
= minx
- element
->BoundingBox
.X1
;
2321 dy
= miny
- element
->BoundingBox
.Y1
;
2323 /* snap to the grid */
2324 dx
-= (element
->MarkX
+ dx
) % (long) (PCB
->Grid
);
2325 dx
+= (long) (PCB
->Grid
);
2326 dy
-= (element
->MarkY
+ dy
) % (long) (PCB
->Grid
);
2327 dy
+= (long) (PCB
->Grid
);
2329 /* move the element */
2330 MoveElementLowLevel (PCB
->Data
, element
, dx
, dy
);
2332 /* and add to the undo list so we can undo this operation */
2333 AddObjectToMoveUndoList (ELEMENT_TYPE
, NULL
, NULL
, element
, dx
, dy
);
2335 /* keep track of how tall this row is */
2336 minx
+= element
->BoundingBox
.X2
- element
->BoundingBox
.X1
+ GAP
;
2337 if (maxy
< element
->BoundingBox
.Y2
)
2339 maxy
= element
->BoundingBox
.Y2
;
2346 /* done with our action so increment the undo # */
2347 IncrementUndoSerialNumber ();
2349 ClearAndRedrawOutput ();
2350 SetChangedFlag (True
);
2357 /* --------------------------------------------------------------------------- */
2359 static const char display_syntax
[] =
2360 "Display(NameOnPCB|Description|Value)\n"
2361 "Display(Grid|Redraw)\n"
2362 "Display(CycleClip|Toggle45Degree|ToggleStartDirection)\n"
2363 "Display(ToggleGrid|ToggleRubberBandMode|ToggleUniqueNames)\n"
2364 "Display(ToggleMask|ToggleName|ToggleClearLine|ToggleSnapPin)\n"
2365 "Display(ToggleThindraw|ToggleThindrawPoly|ToggleOrthoMove|ToggleLocalRef)\n"
2366 "Display(ToggleCheckPlanes|ToggleShowDRC|ToggleAutoDRC)\n"
2367 "Display(ToggleLiveRoute|LockNames|OnlyNames)\n"
2368 "Display(Pinout|PinOrPadName)\n" "Display(Scroll, Direction)";
2370 static const char display_help
[] = "Several display-related actions.";
2372 /* %start-doc actions Display
2379 Specify whether all elements show their name, description, or value.
2382 Redraw the whole board.
2384 @item Toggle45Degree
2385 When clear, lines can be drawn at any angle. When set, lines are
2386 restricted to multiples of 45 degrees and requested lines may be
2387 broken up according to the clip setting.
2390 Changes the way lines are restricted to 45 degree increments. The
2391 various settings are: straight only, orthogonal then angled, and angled
2392 then orthogonal. If AllDirections is set, this action disables it.
2394 @item ToggleRubberBandMode
2395 If set, moving an object moves all the lines attached to it too.
2397 @item ToggleStartDirection
2398 If set, each time you set a point in a line, the Clip toggles between
2399 orth-angle and angle-ortho.
2401 @item ToggleUniqueNames
2402 If set, you will not be permitted to change the name of an element to
2403 match that of another element.
2406 If set, pin centers and pad end points are treated as additional grid
2407 points that the cursor can snap to.
2409 @item ToggleLocalRef
2410 If set, the mark is automatically set to the beginning of any move, so
2411 you can see the relative distance you've moved.
2413 @item ToggleThindraw
2414 If set, objects on the screen are drawn as outlines (lines are drawn
2415 as center-lines). This lets you see line endpoints hidden under pins,
2418 @item ToggleThindrawPoly
2419 If set, polygons on the screen are drawn as outlines.
2422 If set, pending objects (i.e. lines you're in the process of drawing)
2423 will be drawn with an outline showing how far away from other copper
2426 @item ToggleLiveRoute
2427 If set, the progress of the autorouter will be visible on the screen.
2430 If set, you will not be permitted to make connections which violate
2431 the current DRC and netlist settings.
2433 @item ToggleCheckPlanes
2434 If set, lines and arcs aren't drawn, which usually leaves just the
2435 polygons. If you also disable all but the layer you're interested in,
2436 this allows you to check for isolated regions.
2438 @item ToggleOrthoMove
2439 If set, the crosshair is only allowed to move orthogonally from its
2440 previous position. I.e. you can move an element or line up, down,
2441 left, or right, but not up+left or down+right.
2444 Selects whether the pinouts show the pin names or the pin numbers.
2447 Turns the solder mask on or off.
2449 @item ToggleClearLine
2450 When set, the clear-line flag causes new lines and arcs to have their
2451 ``clear polygons'' flag set, so they won't be electrically connected
2452 to any polygons they overlap.
2455 Resets the origin of the current grid to be wherever the mouse pointer
2456 is (not where the crosshair currently is). If you provide two numbers
2457 after this, the origin is set to that coordinate. The numbers are in
2458 PCB internal units, currently 1/100 mil.
2461 Toggles whether the grid is displayed or not.
2464 Causes the pinout of the element indicated by the cursor to be
2465 displayed, usually in a separate window.
2468 Toggles whether the names of pins, pads, or (yes) vias will be
2469 displayed. If the cursor is over an element, all of its pins and pads
2472 @item Step <direction> <amount> <units>
2473 Steps the crosshair in the given direction, with 1=down/left, 2=down,
2474 etc, according to the numeric keypad layout. If amount is not given,
2475 the crosshair steps along the grid.
2482 ActionDisplay (int argc
, char **argv
, int childX
, int childY
)
2484 char *function
, *str_dir
;
2491 if (function
&& (!str_dir
|| !*str_dir
))
2493 HideCrosshair (True
);
2494 switch (id
= GetFunctionID (function
))
2497 /* redraw layout with clearing the background */
2498 case F_ClearAndRedraw
:
2499 gui
->invalidate_all();
2502 /* redraw layout without clearing the background */
2508 area
.X2
= Output
.Width
;
2509 area
.Y2
= Output
.Height
;
2510 RedrawOutput (&area
);
2514 /* change the displayed name of elements */
2518 ELEMENT_LOOP (PCB
->Data
);
2520 EraseElementName (element
);
2523 CLEAR_FLAG (DESCRIPTIONFLAG
| NAMEONPCBFLAG
, PCB
);
2529 SET_FLAG (NAMEONPCBFLAG
, PCB
);
2532 SET_FLAG (DESCRIPTIONFLAG
, PCB
);
2535 ELEMENT_LOOP (PCB
->Data
);
2537 DrawElementName (element
, 0);
2543 /* toggle line-adjust flag */
2544 case F_ToggleAllDirections
:
2545 TOGGLE_FLAG (ALLDIRECTIONFLAG
, PCB
);
2546 AdjustAttachedObjects ();
2551 (ALLDIRECTIONFLAG
, PCB
)
2553 TOGGLE_FLAG (ALLDIRECTIONFLAG
, PCB
);
2557 PCB
->Clipping
= (PCB
->Clipping
+ 1) % 3;
2558 AdjustAttachedObjects ();
2561 case F_ToggleRubberBandMode
:
2562 TOGGLE_FLAG (RUBBERBANDFLAG
, PCB
);
2565 case F_ToggleStartDirection
:
2566 TOGGLE_FLAG (SWAPSTARTDIRFLAG
, PCB
);
2569 case F_ToggleUniqueNames
:
2570 TOGGLE_FLAG (UNIQUENAMEFLAG
, PCB
);
2573 case F_ToggleSnapPin
:
2574 TOGGLE_FLAG (SNAPPINFLAG
, PCB
);
2577 case F_ToggleLocalRef
:
2578 TOGGLE_FLAG (LOCALREFFLAG
, PCB
);
2581 case F_ToggleThindraw
:
2582 TOGGLE_FLAG (THINDRAWFLAG
, PCB
);
2583 ClearAndRedrawOutput ();
2586 case F_ToggleThindrawPoly
:
2587 TOGGLE_FLAG (THINDRAWPOLYFLAG
, PCB
);
2588 ClearAndRedrawOutput ();
2591 case F_ToggleLockNames
:
2592 TOGGLE_FLAG (LOCKNAMESFLAG
, PCB
);
2593 CLEAR_FLAG (ONLYNAMESFLAG
, PCB
);
2596 case F_ToggleOnlyNames
:
2597 TOGGLE_FLAG (ONLYNAMESFLAG
, PCB
);
2598 CLEAR_FLAG (LOCKNAMESFLAG
, PCB
);
2601 case F_ToggleShowDRC
:
2602 TOGGLE_FLAG (SHOWDRCFLAG
, PCB
);
2605 case F_ToggleLiveRoute
:
2606 TOGGLE_FLAG (LIVEROUTEFLAG
, PCB
);
2609 case F_ToggleAutoDRC
:
2610 TOGGLE_FLAG (AUTODRCFLAG
, PCB
);
2611 if (TEST_FLAG (AUTODRCFLAG
, PCB
) && Settings
.Mode
== LINE_MODE
)
2613 SaveUndoSerialNumber ();
2614 ResetFoundPinsViasAndPads (True
);
2615 RestoreUndoSerialNumber ();
2616 ResetFoundLinesAndPolygons (True
);
2617 if (Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
2618 LookupConnection (Crosshair
.AttachedLine
.Point1
.X
,
2619 Crosshair
.AttachedLine
.Point1
.Y
, True
, 1,
2624 case F_ToggleCheckPlanes
:
2625 TOGGLE_FLAG (CHECKPLANESFLAG
, PCB
);
2626 ClearAndRedrawOutput ();
2629 case F_ToggleOrthoMove
:
2630 TOGGLE_FLAG (ORTHOMOVEFLAG
, PCB
);
2634 TOGGLE_FLAG (SHOWNUMBERFLAG
, PCB
);
2639 TOGGLE_FLAG (SHOWMASKFLAG
, PCB
);
2643 case F_ToggleClearLine
:
2644 TOGGLE_FLAG (CLEARNEWFLAG
, PCB
);
2647 /* shift grid alignment */
2652 oldGrid
= PCB
->Grid
;
2654 if (MoveCrosshairAbsolute (childX
, childY
))
2655 RestoreCrosshair (False
); /* was hidden by MoveCrosshairAbs */
2656 SetGrid (oldGrid
, True
);
2660 /* toggle displaying of the grid */
2662 Settings
.DrawGrid
= !Settings
.DrawGrid
;
2666 /* display the pinout of an element */
2669 ElementTypePtr element
;
2673 (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
, &ptrtmp
,
2674 &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
2676 element
= (ElementTypePtr
) ptrtmp
;
2677 gui
->show_item (element
);
2682 /* toggle displaying of pin/pad/via names */
2683 case F_PinOrPadName
:
2685 void *ptr1
, *ptr2
, *ptr3
;
2687 switch (SearchScreen (Crosshair
.X
, Crosshair
.Y
,
2688 ELEMENT_TYPE
| PIN_TYPE
| PAD_TYPE
|
2689 VIA_TYPE
, (void **) &ptr1
, (void **) &ptr2
,
2693 PIN_LOOP ((ElementTypePtr
) ptr1
);
2695 if (TEST_FLAG (DISPLAYNAMEFLAG
, pin
))
2698 DrawPinName (pin
, 0);
2699 AddObjectToFlagUndoList (PIN_TYPE
, ptr1
, pin
, pin
);
2700 TOGGLE_FLAG (DISPLAYNAMEFLAG
, pin
);
2703 PAD_LOOP ((ElementTypePtr
) ptr1
);
2705 if (TEST_FLAG (DISPLAYNAMEFLAG
, pad
))
2708 DrawPadName (pad
, 0);
2709 AddObjectToFlagUndoList (PAD_TYPE
, ptr1
, pad
, pad
);
2710 TOGGLE_FLAG (DISPLAYNAMEFLAG
, pad
);
2713 SetChangedFlag (True
);
2714 IncrementUndoSerialNumber ();
2719 if (TEST_FLAG (DISPLAYNAMEFLAG
, (PinTypePtr
) ptr2
))
2720 ErasePinName ((PinTypePtr
) ptr2
);
2722 DrawPinName ((PinTypePtr
) ptr2
, 0);
2723 AddObjectToFlagUndoList (PIN_TYPE
, ptr1
, ptr2
, ptr3
);
2724 TOGGLE_FLAG (DISPLAYNAMEFLAG
, (PinTypePtr
) ptr2
);
2725 SetChangedFlag (True
);
2726 IncrementUndoSerialNumber ();
2731 if (TEST_FLAG (DISPLAYNAMEFLAG
, (PadTypePtr
) ptr2
))
2732 ErasePadName ((PadTypePtr
) ptr2
);
2734 DrawPadName ((PadTypePtr
) ptr2
, 0);
2735 AddObjectToFlagUndoList (PAD_TYPE
, ptr1
, ptr2
, ptr3
);
2736 TOGGLE_FLAG (DISPLAYNAMEFLAG
, (PadTypePtr
) ptr2
);
2737 SetChangedFlag (True
);
2738 IncrementUndoSerialNumber ();
2742 if (TEST_FLAG (DISPLAYNAMEFLAG
, (PinTypePtr
) ptr2
))
2743 EraseViaName ((PinTypePtr
) ptr2
);
2745 DrawViaName ((PinTypePtr
) ptr2
, 0);
2746 AddObjectToFlagUndoList (VIA_TYPE
, ptr1
, ptr2
, ptr3
);
2747 TOGGLE_FLAG (DISPLAYNAMEFLAG
, (PinTypePtr
) ptr2
);
2748 SetChangedFlag (True
);
2749 IncrementUndoSerialNumber ();
2758 RestoreCrosshair (True
);
2760 else if (function
&& str_dir
)
2762 switch (GetFunctionID (function
))
2768 PCB
->GridOffsetX
= atoi (argv
[1]);
2769 PCB
->GridOffsetY
= atoi (argv
[2]);
2770 if (Settings
.DrawGrid
)
2787 /* --------------------------------------------------------------------------- */
2789 static const char mode_syntax
[] =
2790 "Mode(Arc|Arrow|Copy|InsertPoint|Line|Lock|Move|None|PasteBuffer)\n"
2791 "Mode(Polygon|Rectangle|Remove|Rotate|Text|Thermal|Via)\n"
2792 "Mode(Notify|Release|Cancel|Stroke)\n" "Mode(Save|Restore)";
2794 static const char mode_help
[] = "Change or use the tool mode.";
2796 /* %start-doc actions Mode
2816 Select the indicated tool.
2819 Called when you press the mouse button, or move the mouse.
2822 Called when you release the mouse button.
2825 Cancels any pending tool activity, allowing you to restart elsewhere.
2826 For example, this allows you to start a new line rather than attach a
2827 line to the previous line.
2830 Similar to Cancel but calling this action a second time will return
2834 If your @code{pcb} was built with libstroke, this invokes the stroke
2835 input method. If not, this will restart a drawing mode if you were
2836 drawing, else it will select objects.
2839 Remembers the current tool.
2842 Restores the tool to the last saved tool.
2849 ActionMode (int argc
, char **argv
, int x
, int y
)
2851 char *function
= ARG (0);
2855 Note
.X
= Crosshair
.X
;
2856 Note
.Y
= Crosshair
.Y
;
2857 HideCrosshair (True
);
2858 switch (GetFunctionID (function
))
2864 SetMode (ARROW_MODE
);
2867 SetMode (COPY_MODE
);
2870 SetMode (INSERTPOINT_MODE
);
2873 SetMode (LINE_MODE
);
2876 SetMode (LOCK_MODE
);
2879 SetMode (MOVE_MODE
);
2886 int saved_mode
= Settings
.Mode
;
2888 SetMode (saved_mode
);
2893 switch (Settings
.Mode
)
2896 case PASTEBUFFER_MODE
:
2902 case INSERTPOINT_MODE
:
2903 case RUBBERBANDMOVE_MODE
:
2907 SetMode (ARROW_MODE
);
2911 if (Crosshair
.AttachedLine
.State
== STATE_FIRST
)
2912 SetMode (ARROW_MODE
);
2916 SetMode (LINE_MODE
);
2920 case RECTANGLE_MODE
:
2921 if (Crosshair
.AttachedBox
.State
== STATE_FIRST
)
2922 SetMode (ARROW_MODE
);
2926 SetMode (RECTANGLE_MODE
);
2931 if (Crosshair
.AttachedLine
.State
== STATE_FIRST
)
2932 SetMode (ARROW_MODE
);
2936 SetMode (POLYGON_MODE
);
2941 if (Crosshair
.AttachedBox
.State
== STATE_FIRST
)
2942 SetMode (ARROW_MODE
);
2963 SetMode (PASTEBUFFER_MODE
);
2966 SetMode (POLYGON_MODE
);
2968 #ifndef HAVE_LIBSTROKE
2981 SetMode (REMOVE_MODE
);
2984 SetMode (RECTANGLE_MODE
);
2987 SetMode (ROTATE_MODE
);
2990 #ifdef HAVE_LIBSTROKE
2992 StrokeBox
.X1
= Crosshair
.X
;
2993 StrokeBox
.Y1
= Crosshair
.Y
;
2996 /* Handle middle mouse button restarts of drawing mode. If not in
2997 | a drawing mode, middle mouse button will select objects.
2999 if (Settings
.Mode
== LINE_MODE
3000 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
3002 SetMode (LINE_MODE
);
3004 else if (Settings
.Mode
== ARC_MODE
3005 && Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
3007 else if (Settings
.Mode
== RECTANGLE_MODE
3008 && Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
3009 SetMode (RECTANGLE_MODE
);
3010 else if (Settings
.Mode
== POLYGON_MODE
3011 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
3012 SetMode (POLYGON_MODE
);
3017 SetMode (ARROW_MODE
);
3023 SetMode (TEXT_MODE
);
3026 SetMode (THERMAL_MODE
);
3032 case F_Restore
: /* restore the last saved mode */
3036 case F_Save
: /* save currently selected mode */
3040 RestoreCrosshair (True
);
3047 /* --------------------------------------------------------------------------- */
3049 static const char removeselected_syntax
[] = "RemoveSelected()";
3051 static const char removeselected_help
[] = "Removes any selected objects.";
3053 /* %start-doc actions RemoveSelected
3058 ActionRemoveSelected (int argc
, char **argv
, int x
, int y
)
3060 HideCrosshair (True
);
3061 if (RemoveSelected ())
3062 SetChangedFlag (True
);
3063 RestoreCrosshair (True
);
3067 /* --------------------------------------------------------------------------- */
3069 static const char renumber_syntax
[] = "Renumber()\n" "Renumber(filename)";
3071 static const char renumber_help
[] =
3072 "Renumber all elements. The changes will be recorded to filename\n"
3073 "for use in backannotating these changes to the schematic.";
3075 /* %start-doc actions Renumber
3080 ActionRenumber (int argc
, char **argv
, int x
, int y
)
3082 Boolean changed
= False
;
3083 ElementTypePtr
*element_list
;
3084 ElementTypePtr
*locked_element_list
;
3085 unsigned int i
, j
, k
, cnt
, lock_cnt
;
3091 size_t cnt_list_sz
= 100;
3097 char **was
, **is
, *pin
;
3098 unsigned int c_cnt
= 0;
3102 name
= gui
->prompt_for ("Renumber annotation file:", 0);
3106 if ((out
= fopen (name
, "r")))
3109 if (!gui
->confirm_dialog (_("File exists! Ok to overwrite?"), 0))
3112 if ((out
= fopen (name
, "w")) == NULL
)
3114 Message ("Could not open %s\n", name
);
3118 fprintf (out
, "*COMMENT* PCB Annotation File\n");
3119 fprintf (out
, "*FILEVERSION* 20061031\n");
3122 * Make a first pass through all of the elements and sort them out
3123 * by location on the board. While here we also collect a list of
3126 * We'll actually renumber things in the 2nd pass.
3128 element_list
= calloc (PCB
->Data
->ElementN
, sizeof (ElementTypePtr
));
3129 locked_element_list
= calloc (PCB
->Data
->ElementN
, sizeof (ElementTypePtr
));
3130 was
= calloc (PCB
->Data
->ElementN
, sizeof (char *));
3131 is
= calloc (PCB
->Data
->ElementN
, sizeof (char *));
3132 if (element_list
== NULL
|| locked_element_list
== NULL
|| was
== NULL
3135 fprintf (stderr
, "calloc() failed in %s\n", __FUNCTION__
);
3142 ELEMENT_LOOP (PCB
->Data
);
3144 if (TEST_FLAG (LOCKFLAG
, element
->Name
) || TEST_FLAG (LOCKFLAG
, element
))
3147 * add to the list of locked elements which we won't try to
3148 * renumber and whose reference designators are now reserved.
3151 "*WARN* Element \"%s\" at (%d,%d) is locked and will not be renumbered.\n",
3152 UNKNOWN (NAMEONPCB_NAME (element
)), element
->MarkX
,
3154 locked_element_list
[lock_cnt
] = element
;
3160 /* count of devices which will be renumbered */
3163 /* search for correct position in the list */
3165 while (element_list
[i
] && element
->MarkY
> element_list
[i
]->MarkY
)
3169 * We have found the position where we have the first element that
3170 * has the same Y value or a lower Y value. Now move forward if
3171 * needed through the X values
3173 while (element_list
[i
]
3174 && element
->MarkY
== element_list
[i
]->MarkY
3175 && element
->MarkX
> element_list
[i
]->MarkX
)
3178 for (j
= cnt
- 1; j
> i
; j
--)
3180 element_list
[j
] = element_list
[j
- 1];
3182 element_list
[i
] = element
;
3189 * Now that the elements are sorted by board position, we go through
3190 * and renumber them.
3194 * turn off the flag which requires unique names so it doesn't get
3195 * in our way. When we're done with the renumber we will have unique
3198 unique
= TEST_FLAG (UNIQUENAMEFLAG
, PCB
);
3199 CLEAR_FLAG (UNIQUENAMEFLAG
, PCB
);
3201 cnt_list
= calloc (cnt_list_sz
, sizeof (struct _cnt_list
));
3202 for (i
= 0; i
< cnt
; i
++)
3204 /* If there is no refdes, maybe just spit out a warning */
3205 if (NAMEONPCB_NAME (element_list
[i
]))
3207 /* figure out the prefix */
3208 tmps
= strdup (NAMEONPCB_NAME (element_list
[i
]));
3210 while (tmps
[j
] && (tmps
[j
] < '0' || tmps
[j
] > '9')
3215 /* check the counter for this prefix */
3217 cnt_list
[j
].name
&& (strcmp (cnt_list
[j
].name
, tmps
) != 0)
3218 && j
< cnt_list_sz
; j
++);
3220 /* grow the list if needed */
3221 if (j
== cnt_list_sz
)
3224 cnt_list
= realloc (cnt_list
, cnt_list_sz
);
3225 if (cnt_list
== NULL
)
3227 fprintf (stderr
, "realloc failed() in %s\n", __FUNCTION__
);
3230 /* zero out the memory that we added */
3231 for (tmpi
= j
; tmpi
< cnt_list_sz
; tmpi
++)
3233 cnt_list
[tmpi
].name
= NULL
;
3234 cnt_list
[tmpi
].cnt
= 0;
3239 * start a new counter if we don't have a counter for this
3242 if (!cnt_list
[j
].name
)
3244 cnt_list
[j
].name
= strdup (tmps
);
3245 cnt_list
[j
].cnt
= 0;
3249 * check to see if the new refdes is already used by a
3258 /* space for the prefix plus 1 digit plus the '\0' */
3259 sz
= strlen (cnt_list
[j
].name
) + 2;
3261 /* and 1 more per extra digit needed to hold the number */
3262 tmpi
= cnt_list
[j
].cnt
;
3268 tmps
= malloc (sz
* sizeof (char));
3269 sprintf (tmps
, "%s%d", cnt_list
[j
].name
, cnt_list
[j
].cnt
);
3272 * now compare to the list of reserved (by locked
3275 for (k
= 0; k
< lock_cnt
; k
++)
3278 (UNKNOWN (NAMEONPCB_NAME (locked_element_list
[k
])),
3289 if (strcmp (tmps
, NAMEONPCB_NAME (element_list
[i
])) != 0)
3291 fprintf (out
, "*RENAME* \"%s\" \"%s\"\n",
3292 NAMEONPCB_NAME (element_list
[i
]), tmps
);
3294 /* add this rename to our table of renames so we can update the netlist */
3295 was
[c_cnt
] = strdup (NAMEONPCB_NAME (element_list
[i
]));
3296 is
[c_cnt
] = strdup (tmps
);
3299 AddObjectToChangeNameUndoList (ELEMENT_TYPE
, NULL
, NULL
,
3301 NAMEONPCB_NAME (element_list
3304 ChangeObjectName (ELEMENT_TYPE
, element_list
[i
], NULL
, NULL
,
3308 /* we don't free tmps in this case because it is used */
3315 fprintf (out
, "*WARN* Element at (%d,%d) has no name.\n",
3316 element_list
[i
]->MarkX
, element_list
[i
]->MarkY
);
3323 /* restore the unique flag setting */
3325 SET_FLAG (UNIQUENAMEFLAG
, PCB
);
3330 /* update the netlist */
3331 AddNetlistLibToUndoList (&(PCB
->NetlistLib
));
3333 /* iterate over each net */
3334 for (i
= 0; i
< PCB
->NetlistLib
.MenuN
; i
++)
3337 /* iterate over each pin on the net */
3338 for (j
= 0; j
< PCB
->NetlistLib
.Menu
[i
].EntryN
; j
++)
3341 /* figure out the pin number part from strings like U3-21 */
3342 tmps
= strdup (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
);
3343 for (k
= 0; tmps
[k
] && tmps
[k
] != '-'; k
++);
3347 /* iterate over the list of changed reference designators */
3348 for (k
= 0; k
< c_cnt
; k
++)
3351 * if the pin needs to change, change it and quit
3352 * searching in the list.
3354 if (strcmp (tmps
, was
[k
]) == 0)
3356 free (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
);
3357 PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
=
3358 malloc ((strlen (is
[k
]) + strlen (pin
) +
3359 2) * sizeof (char));
3360 sprintf (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
,
3361 "%s-%s", is
[k
], pin
);
3369 for (k
= 0; k
< c_cnt
; k
++)
3375 hid_action ("NetlistChanged");
3376 IncrementUndoSerialNumber ();
3377 SetChangedFlag (True
);
3380 free (locked_element_list
);
3381 free (element_list
);
3387 /* --------------------------------------------------------------------------- */
3389 static const char ripup_syntax
[] = "RipUp(All|Selected|Element)";
3391 static const char ripup_help
[] =
3392 "Ripup auto-routed tracks, or convert an element to parts.";
3394 /* %start-doc actions RipUp
3399 Removes all lines and vias which were created by the autorouter.
3402 Removes all selected lines and vias which were created by the
3406 Converts the element under the cursor to parts (vias and lines). Note
3407 that this uses the highest numbered paste buffer.
3414 ActionRipUp (int argc
, char **argv
, int x
, int y
)
3416 char *function
= ARG (0);
3417 Boolean changed
= False
;
3421 HideCrosshair (True
);
3422 switch (GetFunctionID (function
))
3425 ALLLINE_LOOP (PCB
->Data
);
3427 if (TEST_FLAG (AUTOFLAG
, line
) && !TEST_FLAG (LOCKFLAG
, line
))
3429 RemoveObject (LINE_TYPE
, layer
, line
, line
);
3434 VIA_LOOP (PCB
->Data
);
3436 if (TEST_FLAG (AUTOFLAG
, via
) && !TEST_FLAG (LOCKFLAG
, via
))
3438 RemoveObject (VIA_TYPE
, via
, via
, via
);
3446 IncrementUndoSerialNumber ();
3447 SetChangedFlag (True
);
3451 VISIBLELINE_LOOP (PCB
->Data
);
3453 if (TEST_FLAGS (AUTOFLAG
| SELECTEDFLAG
, line
)
3454 && !TEST_FLAG (LOCKFLAG
, line
))
3456 RemoveObject (LINE_TYPE
, layer
, line
, line
);
3462 VIA_LOOP (PCB
->Data
);
3464 if (TEST_FLAGS (AUTOFLAG
| SELECTEDFLAG
, via
)
3465 && !TEST_FLAG (LOCKFLAG
, via
))
3467 RemoveObject (VIA_TYPE
, via
, via
, via
);
3474 IncrementUndoSerialNumber ();
3475 SetChangedFlag (True
);
3480 void *ptr1
, *ptr2
, *ptr3
;
3482 if (SearchScreen (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
,
3483 &ptr1
, &ptr2
, &ptr3
) != NO_TYPE
)
3485 Note
.Buffer
= Settings
.BufferNumber
;
3486 SetBufferNumber (MAX_BUFFER
- 1);
3487 ClearBuffer (PASTEBUFFER
);
3488 CopyObjectToBuffer (PASTEBUFFER
->Data
, PCB
->Data
,
3489 ELEMENT_TYPE
, ptr1
, ptr2
, ptr3
);
3490 SmashBufferElement (PASTEBUFFER
);
3493 SaveUndoSerialNumber ();
3494 EraseObject (ELEMENT_TYPE
, ptr1
, ptr1
);
3495 MoveObjectToRemoveUndoList (ELEMENT_TYPE
, ptr1
, ptr2
, ptr3
);
3496 RestoreUndoSerialNumber ();
3497 CopyPastebufferToLayout (0, 0);
3498 SetBufferNumber (Note
.Buffer
);
3499 SetChangedFlag (True
);
3504 RestoreCrosshair (True
);
3509 /* --------------------------------------------------------------------------- */
3511 static const char addrats_syntax
[] = "AddRats(AllRats|SelectedRats|Close)";
3513 static const char addrats_help
[] = "Add one or more rat lines to the board.";
3515 /* %start-doc actions AddRats
3520 Create rat lines for all loaded nets that aren't already connected on
3524 Similarly, but only add rat lines for nets connected to selected pins
3528 Selects the shortest unselected rat on the board.
3535 ActionAddRats (int argc
, char **argv
, int x
, int y
)
3537 char *function
= ARG (0);
3543 HideCrosshair (True
);
3544 switch (GetFunctionID (function
))
3547 if (AddAllRats (False
, NULL
))
3548 SetChangedFlag (True
);
3550 case F_SelectedRats
:
3552 if (AddAllRats (True
, NULL
))
3553 SetChangedFlag (True
);
3556 small
= SQUARE (MAX_COORD
);
3558 RAT_LOOP (PCB
->Data
);
3560 if (TEST_FLAG (SELECTEDFLAG
, line
))
3562 len
= SQUARE (line
->Point1
.X
- line
->Point2
.X
) +
3563 SQUARE (line
->Point1
.Y
- line
->Point2
.Y
);
3573 AddObjectToFlagUndoList (RATLINE_TYPE
, shorty
, shorty
, shorty
);
3574 SET_FLAG (SELECTEDFLAG
, shorty
);
3575 DrawRat (shorty
, 0);
3577 CenterDisplay ((shorty
->Point2
.X
+ shorty
->Point1
.X
) / 2,
3578 (shorty
->Point2
.Y
+ shorty
->Point1
.Y
) / 2,
3583 RestoreCrosshair (True
);
3588 /* --------------------------------------------------------------------------- */
3590 static const char deleterats_syntax
[] =
3591 "DeleteRats(AllRats|Selected|SelectedRats)";
3593 static const char deleterats_help
[] = "Delete rat lines.";
3595 /* %start-doc actions DeleteRats
3600 ActionDeleteRats (int argc
, char **argv
, int x
, int y
)
3602 char *function
= ARG (0);
3605 HideCrosshair (True
);
3606 switch (GetFunctionID (function
))
3609 if (DeleteRats (False
))
3610 SetChangedFlag (True
);
3612 case F_SelectedRats
:
3614 if (DeleteRats (True
))
3615 SetChangedFlag (True
);
3618 RestoreCrosshair (True
);
3623 /* --------------------------------------------------------------------------- */
3625 static const char autoplace_syntax
[] = "AutoPlaceSelected()";
3627 static const char autoplace_help
[] = "Auto-place selected components.";
3629 /* %start-doc actions AutoPlaceSelected
3631 Attempts to re-arrange the selected components such that the nets
3632 connecting them are minimized. Note that you cannot undo this.
3637 ActionAutoPlaceSelected (int argc
, char **argv
, int x
, int y
)
3640 if (gui
->confirm_dialog (_("Auto-placement can NOT be undone.\n"
3641 "Do you want to continue anyway?\n"), 0))
3643 HideCrosshair (True
);
3644 if (AutoPlaceSelected ())
3645 SetChangedFlag (True
);
3646 RestoreCrosshair (True
);
3651 /* --------------------------------------------------------------------------- */
3653 static const char autoroute_syntax
[] = "AutoRoute(AllRats|SelectedRats)";
3655 static const char autoroute_help
[] = "Auto-route some or all rat lines.";
3657 /* %start-doc actions AutoRoute
3662 Attempt to autoroute all rats.
3665 Attempt to autoroute the selected rats.
3669 Before autorouting, it's important to set up a few things. First,
3670 make sure any layers you aren't using are disabled, else the
3671 autorouter may use them. Next, make sure the current line and via
3672 styles are set accordingly. Last, make sure "new lines clear
3673 polygons" is set, in case you eventually want to add a copper pour.
3675 Autorouting takes a while. During this time, the program may not be
3681 ActionAutoRoute (int argc
, char **argv
, int x
, int y
)
3683 char *function
= ARG (0);
3685 if (function
) /* one parameter */
3687 HideCrosshair (True
);
3688 switch (GetFunctionID (function
))
3691 if (AutoRoute (False
))
3692 SetChangedFlag (True
);
3694 case F_SelectedRats
:
3696 if (AutoRoute (True
))
3697 SetChangedFlag (True
);
3700 RestoreCrosshair (True
);
3705 /* --------------------------------------------------------------------------- */
3707 static const char markcrosshair_syntax
[] =
3708 "MarkCrosshair()\n" "MarkCrosshair(Center)";
3710 static const char markcrosshair_help
[] = "Set/Reset the Crosshair mark";
3712 /* %start-doc actions MarkCrosshair
3714 The ``mark'' is a small X-shaped target on the display which is
3715 treated like a second origin (the normal origin is the upper let
3716 corner of the board). The GUI will display a second set of
3717 coordinates for this mark, which tells you how far you are from it.
3719 If no argument is given, the mark is toggled - disabled if it was
3720 enabled, or enabled at the current cursor position of disabled. If
3721 the @code{Center} argument is given, the mark is moved to the current
3727 ActionMarkCrosshair (int argc
, char **argv
, int x
, int y
)
3729 char *function
= ARG (0);
3730 if (!function
|| !*function
)
3735 Marked
.status
= False
;
3739 Marked
.status
= True
;
3740 Marked
.X
= Crosshair
.X
;
3741 Marked
.Y
= Crosshair
.Y
;
3745 else if (GetFunctionID (function
) == F_Center
)
3748 Marked
.status
= True
;
3749 Marked
.X
= Crosshair
.X
;
3750 Marked
.Y
= Crosshair
.Y
;
3756 /* --------------------------------------------------------------------------- */
3758 static const char changesize_syntax
[] =
3759 "ChangeSize(Object, delta)\n"
3760 "ChangeSize(SelectedObjects|Selected, delta)\n"
3761 "ChangeSize(SelectedLines|SelectedPins|SelectedVias, delta)\n"
3762 "ChangeSize(SelectedPads|SelectedTexts|SelectedNames, delta)\n"
3763 "ChangeSize(SelectedElements, delta)";
3765 static const char changesize_help
[] = "Changes the size of objects.";
3767 /* %start-doc actions ChangeSize
3769 For lines and arcs, this changes the width. For pins and vias, this
3770 changes the overall diameter of the copper annulus. For pads, this
3771 changes the width and, indirectly, the length. For texts and names,
3772 this changes the scaling factor. For elements, this changes the width
3773 of the silk layer lines and arcs for this element.
3778 ActionChangeSize (int argc
, char **argv
, int x
, int y
)
3780 char *function
= ARG (0);
3781 char *delta
= ARG (1);
3782 char *units
= ARG (2);
3783 Boolean r
; /* indicates if absolute size is given */
3786 if (function
&& delta
)
3788 value
= GetValue (delta
, units
, &r
);
3789 HideCrosshair (True
);
3790 switch (GetFunctionID (function
))
3795 void *ptr1
, *ptr2
, *ptr3
;
3798 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGESIZE_TYPES
,
3799 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
3800 if (TEST_FLAG (LOCKFLAG
, (PinTypePtr
) ptr2
))
3801 Message (_("Sorry, the object is locked\n"));
3802 if (ChangeObjectSize (type
, ptr1
, ptr2
, ptr3
, value
, r
))
3803 SetChangedFlag (True
);
3807 case F_SelectedVias
:
3808 if (ChangeSelectedSize (VIA_TYPE
, value
, r
))
3809 SetChangedFlag (True
);
3812 case F_SelectedPins
:
3813 if (ChangeSelectedSize (PIN_TYPE
, value
, r
))
3814 SetChangedFlag (True
);
3817 case F_SelectedPads
:
3818 if (ChangeSelectedSize (PAD_TYPE
, value
, r
))
3819 SetChangedFlag (True
);
3822 case F_SelectedArcs
:
3823 if (ChangeSelectedSize (ARC_TYPE
, value
, r
))
3824 SetChangedFlag (True
);
3827 case F_SelectedLines
:
3828 if (ChangeSelectedSize (LINE_TYPE
, value
, r
))
3829 SetChangedFlag (True
);
3832 case F_SelectedTexts
:
3833 if (ChangeSelectedSize (TEXT_TYPE
, value
, r
))
3834 SetChangedFlag (True
);
3837 case F_SelectedNames
:
3838 if (ChangeSelectedSize (ELEMENTNAME_TYPE
, value
, r
))
3839 SetChangedFlag (True
);
3842 case F_SelectedElements
:
3843 if (ChangeSelectedSize (ELEMENT_TYPE
, value
, r
))
3844 SetChangedFlag (True
);
3848 case F_SelectedObjects
:
3849 if (ChangeSelectedSize (CHANGESIZE_TYPES
, value
, r
))
3850 SetChangedFlag (True
);
3853 RestoreCrosshair (True
);
3858 /* --------------------------------------------------------------------------- */
3860 static const char changedrillsize_syntax
[] =
3861 "ChangeDrillSize(Object, delta)\n"
3862 "ChangeDrillSize(SelectedPins|SelectedVias|Selected|SelectedObjects, delta)";
3864 static const char changedrillsize_help
[] =
3865 "Changes the drilling hole size of objects.";
3867 /* %start-doc actions ChangeDrillSize
3872 ActionChange2ndSize (int argc
, char **argv
, int x
, int y
)
3874 char *function
= ARG (0);
3875 char *delta
= ARG (1);
3876 char *units
= ARG (2);
3880 if (function
&& delta
)
3882 value
= GetValue (delta
, units
, &r
);
3883 HideCrosshair (True
);
3884 switch (GetFunctionID (function
))
3889 void *ptr1
, *ptr2
, *ptr3
;
3891 gui
->get_coords ("Select an Object", &x
, &y
);
3893 SearchScreen (x
, y
, CHANGE2NDSIZE_TYPES
,
3894 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
3895 if (ChangeObject2ndSize
3896 (type
, ptr1
, ptr2
, ptr3
, value
, r
, True
))
3897 SetChangedFlag (True
);
3901 case F_SelectedVias
:
3902 if (ChangeSelected2ndSize (VIA_TYPE
, value
, r
))
3903 SetChangedFlag (True
);
3906 case F_SelectedPins
:
3907 if (ChangeSelected2ndSize (PIN_TYPE
, value
, r
))
3908 SetChangedFlag (True
);
3911 case F_SelectedObjects
:
3912 if (ChangeSelected2ndSize (PIN_TYPES
, value
, r
))
3913 SetChangedFlag (True
);
3916 RestoreCrosshair (True
);
3921 /* --------------------------------------------------------------------------- */
3923 static const char changeclearsize_syntax
[] =
3924 "ChangeClearSize(Object, delta)\n"
3925 "ChangeClearSize(SelectedPins|SelectedPads|SelectedVias, delta)\n"
3926 "ChangeClearSize(SelectedLines|SelectedArcs, delta\n"
3927 "ChangeClearSize(Selected|SelectedObjects, delta)";
3929 static const char changeclearsize_help
[] =
3930 "Changes the clearance size of objects.";
3932 /* %start-doc actions ChangeClearSize
3934 If the solder mask is currently showing, this action changes the
3935 solder mask clearance. If the mask is not showing, this action
3936 changes the polygon clearance.
3941 ActionChangeClearSize (int argc
, char **argv
, int x
, int y
)
3943 char *function
= ARG (0);
3944 char *delta
= ARG (1);
3945 char *units
= ARG (2);
3949 if (function
&& delta
)
3951 value
= 2 * GetValue (delta
, units
, &r
);
3952 HideCrosshair (True
);
3953 switch (GetFunctionID (function
))
3958 void *ptr1
, *ptr2
, *ptr3
;
3960 gui
->get_coords ("Select and Object", &x
, &y
);
3963 CHANGECLEARSIZE_TYPES
, &ptr1
, &ptr2
,
3965 if (ChangeObjectClearSize (type
, ptr1
, ptr2
, ptr3
, value
, r
))
3966 SetChangedFlag (True
);
3969 case F_SelectedVias
:
3970 if (ChangeSelectedClearSize (VIA_TYPE
, value
, r
))
3971 SetChangedFlag (True
);
3973 case F_SelectedPads
:
3974 if (ChangeSelectedClearSize (PAD_TYPE
, value
, r
))
3975 SetChangedFlag (True
);
3977 case F_SelectedPins
:
3978 if (ChangeSelectedClearSize (PIN_TYPE
, value
, r
))
3979 SetChangedFlag (True
);
3981 case F_SelectedLines
:
3982 if (ChangeSelectedClearSize (LINE_TYPE
, value
, r
))
3983 SetChangedFlag (True
);
3985 case F_SelectedArcs
:
3986 if (ChangeSelectedClearSize (ARC_TYPE
, value
, r
))
3987 SetChangedFlag (True
);
3990 case F_SelectedObjects
:
3991 if (ChangeSelectedClearSize (CHANGECLEARSIZE_TYPES
, value
, r
))
3992 SetChangedFlag (True
);
3995 RestoreCrosshair (True
);
4000 /* --------------------------------------------------------------------------- */
4002 static const char minmaskgap_syntax
[] =
4003 "MinMaskGap(delta)\n" "MinMaskGap(Selected, delta)";
4005 static const char minmaskgap_help
[] =
4006 "Ensures the mask is a minimum distance from pins and pads.";
4008 /* %start-doc actions MinMaskGap
4010 Checks all specified pins and/or pads, and increases the mask if
4011 needed to ensure a minimum distance between the pin or pad edge and
4017 ActionMinMaskGap (int argc
, char **argv
, int x
, int y
)
4019 char *function
= ARG (0);
4020 char *delta
= ARG (1);
4021 char *units
= ARG (2);
4028 if (strcasecmp (function
, "Selected") == 0)
4029 flags
= SELECTEDFLAG
;
4036 value
= 2 * GetValue (delta
, units
, &r
);
4038 HideCrosshair (True
);
4039 SaveUndoSerialNumber ();
4040 ELEMENT_LOOP (PCB
->Data
);
4044 if (!TEST_FLAGS (flags
, pin
))
4046 if (pin
->Mask
< pin
->Thickness
+ value
)
4048 ChangeObjectMaskSize (PIN_TYPE
, element
, pin
, 0,
4049 pin
->Thickness
+ value
, 1);
4050 RestoreUndoSerialNumber ();
4056 if (!TEST_FLAGS (flags
, pad
))
4058 if (pad
->Mask
< pad
->Thickness
+ value
)
4060 ChangeObjectMaskSize (PAD_TYPE
, element
, pad
, 0,
4061 pad
->Thickness
+ value
, 1);
4062 RestoreUndoSerialNumber ();
4068 VIA_LOOP (PCB
->Data
);
4070 if (!TEST_FLAGS (flags
, via
))
4072 if (via
->Mask
&& via
->Mask
< via
->Thickness
+ value
)
4074 ChangeObjectMaskSize (VIA_TYPE
, via
, 0, 0, via
->Thickness
+ value
, 1);
4075 RestoreUndoSerialNumber ();
4079 RestoreUndoSerialNumber ();
4080 IncrementUndoSerialNumber ();
4084 /* --------------------------------------------------------------------------- */
4086 static const char changepinname_syntax
[] =
4087 "ChangePinName(ElementName,PinNumber,PinName)";
4089 static const char changepinname_help
[] =
4090 "Sets the name of a specific pin on a specific element.";
4092 /* %start-doc actions ChangePinName
4094 This can be especially useful for annotating pin names from a
4095 schematic to the layout without requiring knowledge of the pcb file
4099 ChangePinName(U3, 7, VCC)
4105 ActionChangePinName (int argc
, char **argv
, int x
, int y
)
4108 char *refdes
, *pinnum
, *pinname
;
4112 AFAIL (changepinname
);
4119 ELEMENT_LOOP (PCB
->Data
);
4121 if (NSTRCMP (refdes
, NAMEONPCB_NAME (element
)) == 0)
4125 if (NSTRCMP (pinnum
, pin
->Number
) == 0)
4127 AddObjectToChangeNameUndoList (PIN_TYPE
, NULL
, NULL
,
4130 * Note: we can't free() pin->Name first because
4131 * it is used in the undo list
4133 pin
->Name
= strdup (pinname
);
4134 SetChangedFlag (True
);
4142 if (NSTRCMP (pinnum
, pad
->Number
) == 0)
4144 AddObjectToChangeNameUndoList (PAD_TYPE
, NULL
, NULL
,
4147 * Note: we can't free() pad->Name first because
4148 * it is used in the undo list
4150 pad
->Name
= strdup (pinname
);
4151 SetChangedFlag (True
);
4160 * done with our action so increment the undo # if we actually
4165 IncrementUndoSerialNumber ();
4166 gui
->invalidate_all ();
4172 /* --------------------------------------------------------------------------- */
4174 static const char changename_syntax
[] =
4175 "ChangeName(Object)\n" "ChangeName(Layout|Layer)";
4177 static const char changename_help
[] = "Sets the name of objects.";
4179 /* %start-doc actions ChangeName
4184 Changes the name of the element under the cursor.
4187 Changes the name of the layout. This is printed on the fab drawings.
4190 Changes the name of the currently active layer.
4197 ActionChangeName (int argc
, char **argv
, int x
, int y
)
4199 char *function
= ARG (0);
4204 HideCrosshair (True
);
4205 switch (GetFunctionID (function
))
4207 /* change the name of an object */
4211 void *ptr1
, *ptr2
, *ptr3
;
4213 gui
->get_coords ("Select an Object", &x
, &y
);
4215 SearchScreen (x
, y
, CHANGENAME_TYPES
,
4216 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4218 SaveUndoSerialNumber ();
4219 if (QueryInputAndChangeObjectName (type
, ptr1
, ptr2
, ptr3
))
4221 SetChangedFlag (True
);
4222 if (type
== ELEMENT_TYPE
)
4224 RubberbandTypePtr ptr
;
4227 RestoreUndoSerialNumber ();
4228 Crosshair
.AttachedObject
.RubberbandN
= 0;
4229 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
4230 ptr
= Crosshair
.AttachedObject
.Rubberband
;
4231 for (i
= 0; i
< Crosshair
.AttachedObject
.RubberbandN
;
4235 EraseRat ((RatTypePtr
) ptr
->Line
);
4236 MoveObjectToRemoveUndoList (RATLINE_TYPE
,
4237 ptr
->Line
, ptr
->Line
,
4240 IncrementUndoSerialNumber ();
4248 /* change the layout's name */
4251 gui
->prompt_for (_("Enter the layout name:"), EMPTY (PCB
->Name
));
4252 if (name
&& ChangeLayoutName (name
)) /* XXX memory leak */
4253 SetChangedFlag (True
);
4256 /* change the name of the active layer */
4258 name
= gui
->prompt_for (_("Enter the layer name:"),
4259 EMPTY (CURRENT
->Name
));
4260 if (name
&& ChangeLayerName (CURRENT
, name
)) /* XXX memory leak */
4261 SetChangedFlag (True
);
4264 RestoreCrosshair (True
);
4270 /* --------------------------------------------------------------------------- */
4272 static const char morphpolygon_syntax
[] = "MorphPolygon(Object|Selected)";
4274 static const char morphpolygon_help
[] =
4275 "Converts dead polygon islands into separate polygons.";
4277 /* %start-doc actions MorphPolygon
4279 If a polygon is divided into unconnected "islands", you can use
4280 this command to convert the otherwise disappeared islands into
4281 separate polygons. Be sure the cursor is over a portion of the
4282 polygon that remains visible. Very small islands that may flake
4283 off are automatically deleted.
4288 ActionMorphPolygon (int argc
, char **argv
, int x
, int y
)
4290 char *function
= ARG (0);
4293 HideCrosshair (True
);
4294 switch (GetFunctionID (function
))
4299 void *ptr1
, *ptr2
, *ptr3
;
4301 gui
->get_coords ("Select an Object", &x
, &y
);
4302 if ((type
= SearchScreen (x
, y
, POLYGON_TYPE
,
4303 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4305 MorphPolygon ((LayerType
*) ptr1
, (PolygonType
*) ptr3
);
4307 IncrementUndoSerialNumber ();
4312 case F_SelectedObjects
:
4313 ALLPOLYGON_LOOP (PCB
->Data
);
4315 if (TEST_FLAG (SELECTEDFLAG
, polygon
))
4316 MorphPolygon (layer
, polygon
);
4320 IncrementUndoSerialNumber ();
4327 /* --------------------------------------------------------------------------- */
4329 static const char togglehidename_syntax
[] =
4330 "ToggleHideName(Object|SelectedElements)";
4332 static const char togglehidename_help
[] =
4333 "Toggles the visibility of element names.";
4335 /* %start-doc actions ToggleHideName
4337 If names are hidden you won't see them on the screen and they will not
4338 appear on the silk layer when you print the layout.
4343 ActionToggleHideName (int argc
, char **argv
, int x
, int y
)
4345 char *function
= ARG (0);
4346 if (function
&& PCB
->ElementOn
)
4348 HideCrosshair (True
);
4349 switch (GetFunctionID (function
))
4354 void *ptr1
, *ptr2
, *ptr3
;
4356 gui
->get_coords ("Select an Object", &x
, &y
);
4357 if ((type
= SearchScreen (x
, y
, ELEMENT_TYPE
,
4358 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4360 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr3
);
4361 EraseElementName ((ElementTypePtr
) ptr2
);
4362 TOGGLE_FLAG (HIDENAMEFLAG
, (ElementTypePtr
) ptr2
);
4363 DrawElementName ((ElementTypePtr
) ptr2
, 0);
4365 IncrementUndoSerialNumber ();
4369 case F_SelectedElements
:
4372 Boolean changed
= False
;
4373 ELEMENT_LOOP (PCB
->Data
);
4375 if ((TEST_FLAG (SELECTEDFLAG
, element
) ||
4376 TEST_FLAG (SELECTEDFLAG
,
4377 &NAMEONPCB_TEXT (element
)))
4378 && (FRONT (element
) || PCB
->InvisibleObjectsOn
))
4380 AddObjectToFlagUndoList (ELEMENT_TYPE
, element
,
4382 EraseElementName (element
);
4383 TOGGLE_FLAG (HIDENAMEFLAG
, element
);
4384 DrawElementName (element
, 0);
4392 IncrementUndoSerialNumber ();
4396 RestoreCrosshair (True
);
4401 /* --------------------------------------------------------------------------- */
4403 static const char changejoin_syntax
[] =
4404 "ChangeJoin(ToggleObject|SelectedLines|SelectedArcs|Selected)";
4406 static const char changejoin_help
[] =
4407 "Changes the join (clearance through polygons) of objects.";
4409 /* %start-doc actions ChangeJoin
4411 The join flag determines whether a line or arc, drawn to intersect a
4412 polygon, electrically connects to the polygon or not. When joined,
4413 the line/arc is simply drawn over the polygon, making an electrical
4414 connection. When not joined, a gap is drawn between the line and the
4415 polygon, insulating them from each other.
4420 ActionChangeJoin (int argc
, char **argv
, int x
, int y
)
4422 char *function
= ARG (0);
4425 HideCrosshair (True
);
4426 switch (GetFunctionID (function
))
4428 case F_ToggleObject
:
4432 void *ptr1
, *ptr2
, *ptr3
;
4434 gui
->get_coords ("Select an Object", &x
, &y
);
4436 SearchScreen (x
, y
, CHANGEJOIN_TYPES
,
4437 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4438 if (ChangeObjectJoin (type
, ptr1
, ptr2
, ptr3
))
4439 SetChangedFlag (True
);
4443 case F_SelectedLines
:
4444 if (ChangeSelectedJoin (LINE_TYPE
))
4445 SetChangedFlag (True
);
4448 case F_SelectedArcs
:
4449 if (ChangeSelectedJoin (ARC_TYPE
))
4450 SetChangedFlag (True
);
4454 case F_SelectedObjects
:
4455 if (ChangeSelectedJoin (CHANGEJOIN_TYPES
))
4456 SetChangedFlag (True
);
4459 RestoreCrosshair (True
);
4464 /* --------------------------------------------------------------------------- */
4466 static const char changesquare_syntax
[] =
4467 "ChangeSquare(ToggleObject)\n"
4468 "ChangeSquare(SelectedElements|SelectedPins)\n"
4469 "ChangeSquare(Selected|SelectedObjects)";
4471 static const char changesquare_help
[] =
4472 "Changes the square flag of pins and pads.";
4474 /* %start-doc actions ChangeSquare
4476 Note that @code{Pins} means both pins and pads.
4483 ActionChangeSquare (int argc
, char **argv
, int x
, int y
)
4485 char *function
= ARG (0);
4488 HideCrosshair (True
);
4489 switch (GetFunctionID (function
))
4491 case F_ToggleObject
:
4495 void *ptr1
, *ptr2
, *ptr3
;
4497 gui
->get_coords ("Select an Object", &x
, &y
);
4499 SearchScreen (x
, y
, CHANGESQUARE_TYPES
,
4500 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4501 if (ChangeObjectSquare (type
, ptr1
, ptr2
, ptr3
))
4502 SetChangedFlag (True
);
4506 case F_SelectedElements
:
4507 if (ChangeSelectedSquare (ELEMENT_TYPE
))
4508 SetChangedFlag (True
);
4511 case F_SelectedPins
:
4512 if (ChangeSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4513 SetChangedFlag (True
);
4517 case F_SelectedObjects
:
4518 if (ChangeSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4519 SetChangedFlag (True
);
4522 RestoreCrosshair (True
);
4527 /* --------------------------------------------------------------------------- */
4529 static const char setsquare_syntax
[] =
4530 "SetSquare(ToggleObject|SelectedElements|SelectedPins)";
4532 static const char setsquare_help
[] = "sets the square-flag of objects.";
4534 /* %start-doc actions SetSquare
4536 Note that @code{Pins} means pins and pads.
4543 ActionSetSquare (int argc
, char **argv
, int x
, int y
)
4545 char *function
= ARG (0);
4546 if (function
&& *function
)
4548 /* HideCrosshair (True); */
4549 switch (GetFunctionID (function
))
4551 case F_ToggleObject
:
4555 void *ptr1
, *ptr2
, *ptr3
;
4557 gui
->get_coords ("Select an object", &x
, &y
);
4559 SearchScreen (x
, y
, CHANGESQUARE_TYPES
,
4560 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4561 if (SetObjectSquare (type
, ptr1
, ptr2
, ptr3
))
4562 SetChangedFlag (True
);
4566 case F_SelectedElements
:
4567 if (SetSelectedSquare (ELEMENT_TYPE
))
4568 SetChangedFlag (True
);
4571 case F_SelectedPins
:
4572 if (SetSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4573 SetChangedFlag (True
);
4577 case F_SelectedObjects
:
4578 if (SetSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4579 SetChangedFlag (True
);
4582 /* RestoreCrosshair (True); */
4587 /* --------------------------------------------------------------------------- */
4589 static const char clearsquare_syntax
[] =
4590 "ClearSquare(ToggleObject|SelectedElements|SelectedPins)";
4592 static const char clearsquare_help
[] =
4593 "Clears the square-flag of pins and pads.";
4595 /* %start-doc actions ClearSquare
4597 Note that @code{Pins} means pins and pads.
4604 ActionClearSquare (int argc
, char **argv
, int x
, int y
)
4606 char *function
= ARG (0);
4607 if (function
&& *function
)
4609 /* HideCrosshair (True); */
4610 switch (GetFunctionID (function
))
4612 case F_ToggleObject
:
4616 void *ptr1
, *ptr2
, *ptr3
;
4618 gui
->get_coords ("Select an Object", &x
, &y
);
4620 SearchScreen (x
, y
, CHANGESQUARE_TYPES
,
4621 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4622 if (ClrObjectSquare (type
, ptr1
, ptr2
, ptr3
))
4623 SetChangedFlag (True
);
4627 case F_SelectedElements
:
4628 if (ClrSelectedSquare (ELEMENT_TYPE
))
4629 SetChangedFlag (True
);
4632 case F_SelectedPins
:
4633 if (ClrSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4634 SetChangedFlag (True
);
4638 case F_SelectedObjects
:
4639 if (ClrSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4640 SetChangedFlag (True
);
4643 /* RestoreCrosshair (True); */
4648 /* --------------------------------------------------------------------------- */
4650 static const char changeoctagon_syntax
[] =
4651 "ChangeOctagon(Object|ToggleObject|SelectedObjects|Selected)\n"
4652 "ChangeOctagon(SelectedElements|SelectedPins|SelectedVias)";
4654 static const char changeoctagon_help
[] =
4655 "Changes the octagon-flag of pins and vias.";
4657 /* %start-doc actions ChangeOctagon
4664 ActionChangeOctagon (int argc
, char **argv
, int x
, int y
)
4666 char *function
= ARG (0);
4669 /* HideCrosshair (True); */
4670 switch (GetFunctionID (function
))
4672 case F_ToggleObject
:
4676 void *ptr1
, *ptr2
, *ptr3
;
4678 gui
->get_coords ("Select an Object", &x
, &y
);
4680 SearchScreen (x
, y
, CHANGEOCTAGON_TYPES
,
4681 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4682 if (ChangeObjectOctagon (type
, ptr1
, ptr2
, ptr3
))
4683 SetChangedFlag (True
);
4687 case F_SelectedElements
:
4688 if (ChangeSelectedOctagon (ELEMENT_TYPE
))
4689 SetChangedFlag (True
);
4692 case F_SelectedPins
:
4693 if (ChangeSelectedOctagon (PIN_TYPE
))
4694 SetChangedFlag (True
);
4697 case F_SelectedVias
:
4698 if (ChangeSelectedOctagon (VIA_TYPE
))
4699 SetChangedFlag (True
);
4703 case F_SelectedObjects
:
4704 if (ChangeSelectedOctagon (PIN_TYPES
))
4705 SetChangedFlag (True
);
4708 /* RestoreCrosshair (True); */
4713 /* --------------------------------------------------------------------------- */
4715 static const char setoctagon_syntax
[] =
4716 "SetOctagon(Object|ToggleObject|SelectedElements|Selected)";
4718 static const char setoctagon_help
[] = "Sets the octagon-flag of objects.";
4720 /* %start-doc actions SetOctagon
4727 ActionSetOctagon (int argc
, char **argv
, int x
, int y
)
4729 char *function
= ARG (0);
4732 /* HideCrosshair (True); */
4733 switch (GetFunctionID (function
))
4735 case F_ToggleObject
:
4739 void *ptr1
, *ptr2
, *ptr3
;
4741 gui
->get_coords ("Select an object", &x
, &y
);
4743 SearchScreen (x
, y
, CHANGEOCTAGON_TYPES
,
4744 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4745 if (SetObjectOctagon (type
, ptr1
, ptr2
, ptr3
))
4746 SetChangedFlag (True
);
4750 case F_SelectedElements
:
4751 if (SetSelectedOctagon (ELEMENT_TYPE
))
4752 SetChangedFlag (True
);
4755 case F_SelectedPins
:
4756 if (SetSelectedOctagon (PIN_TYPE
))
4757 SetChangedFlag (True
);
4760 case F_SelectedVias
:
4761 if (SetSelectedOctagon (VIA_TYPE
))
4762 SetChangedFlag (True
);
4766 case F_SelectedObjects
:
4767 if (SetSelectedOctagon (PIN_TYPES
))
4768 SetChangedFlag (True
);
4771 /* RestoreCrosshair (True); */
4776 /* --------------------------------------------------------------------------- */
4778 static const char clearoctagon_syntax
[] =
4779 "ClearOctagon(ToggleObject|Object|SelectedObjects|Selected)\n"
4780 "ClearOctagon(SelectedElements|SelectedPins|SelectedVias)";
4782 static const char clearoctagon_help
[] =
4783 "Clears the octagon-flag of pins and vias.";
4785 /* %start-doc actions ClearOctagon
4792 ActionClearOctagon (int argc
, char **argv
, int x
, int y
)
4794 char *function
= ARG (0);
4797 /* HideCrosshair (True); */
4798 switch (GetFunctionID (function
))
4800 case F_ToggleObject
:
4804 void *ptr1
, *ptr2
, *ptr3
;
4806 gui
->get_coords ("Select an Object", &x
, &y
);
4808 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGEOCTAGON_TYPES
,
4809 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4810 if (ClrObjectOctagon (type
, ptr1
, ptr2
, ptr3
))
4811 SetChangedFlag (True
);
4815 case F_SelectedElements
:
4816 if (ClrSelectedOctagon (ELEMENT_TYPE
))
4817 SetChangedFlag (True
);
4820 case F_SelectedPins
:
4821 if (ClrSelectedOctagon (PIN_TYPE
))
4822 SetChangedFlag (True
);
4825 case F_SelectedVias
:
4826 if (ClrSelectedOctagon (VIA_TYPE
))
4827 SetChangedFlag (True
);
4831 case F_SelectedObjects
:
4832 if (ClrSelectedOctagon (PIN_TYPES
))
4833 SetChangedFlag (True
);
4836 /* RestoreCrosshair (True); */
4841 /* --------------------------------------------------------------------------- */
4843 static const char changehold_syntax
[] =
4844 "ChangeHole(ToggleObject|Object|SelectedVias|Selected)";
4846 static const char changehold_help
[] = "Changes the hole flag of objects.";
4848 /* %start-doc actions ChangeHole
4850 The "hole flag" of a via determines whether the via is a
4851 plated-through hole (not set), or an unplated hole (set).
4856 ActionChangeHole (int argc
, char **argv
, int x
, int y
)
4858 char *function
= ARG (0);
4861 /* HideCrosshair (True); */
4862 switch (GetFunctionID (function
))
4864 case F_ToggleObject
:
4868 void *ptr1
, *ptr2
, *ptr3
;
4870 gui
->get_coords ("Select an Object", &x
, &y
);
4871 if ((type
= SearchScreen (x
, y
, VIA_TYPE
,
4872 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
4873 && ChangeHole ((PinTypePtr
) ptr3
))
4874 IncrementUndoSerialNumber ();
4878 case F_SelectedVias
:
4880 if (ChangeSelectedHole ())
4881 SetChangedFlag (True
);
4884 /* RestoreCrosshair (True); */
4889 /* --------------------------------------------------------------------------- */
4891 static const char changepaste_syntax
[] =
4892 "ChangePaste(ToggleObject|Object|SelectedPads|Selected)";
4894 static const char changepaste_help
[] = "Changes the no paste flag of objects.";
4896 /* %start-doc actions ChangePaste
4898 The "no paste flag" of a pad determines whether the solderpaste
4899 stencil will have an opening for the pad (no set) or if there wil be
4900 no solderpaste on the pad (set). This is used for things such as
4906 ActionChangePaste (int argc
, char **argv
, int x
, int y
)
4908 char *function
= ARG (0);
4911 /* HideCrosshair (True); */
4912 switch (GetFunctionID (function
))
4914 case F_ToggleObject
:
4918 void *ptr1
, *ptr2
, *ptr3
;
4920 gui
->get_coords ("Select an Object", &x
, &y
);
4921 if ((type
= SearchScreen (x
, y
, PAD_TYPE
,
4922 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
4923 && ChangePaste ((PadTypePtr
) ptr3
))
4924 IncrementUndoSerialNumber ();
4928 case F_SelectedPads
:
4930 if (ChangeSelectedPaste ())
4931 SetChangedFlag (True
);
4934 /* RestoreCrosshair (True); */
4939 /* --------------------------------------------------------------------------- */
4941 static const char select_syntax
[] =
4942 "Select(ToggleObject)\n"
4943 "Select(All|Block|Connection)\n"
4944 "Select(ElementByName|ObjectByName|PadByName|PinByName)\n"
4945 "Select(ElementByName|ObjectByName|PadByName|PinByName, Name)\n"
4946 "Select(TextByName|ViaByName)\n"
4947 "Select(TextByName|ViaByName, Name)\n" "Select(Convert)";
4949 static const char select_help
[] = "Toggles or sets the selection";
4951 /* %start-doc actions Select
4962 These all rely on having a regular expression parser built into
4963 @code{pcb}. If the name is not specified then the user is prompted
4964 for a pattern, and all objects that match the pattern and are of the
4965 type specified are selected.
4969 Selects the object under the cursor.
4972 Selects all objects in a rectangle indicated by the cursor.
4975 Selects all objects on the board.
4978 Selects all connections with the ``found'' flag set.
4981 Converts the selected objects to an element. This uses the highest
4982 numbered paste buffer.
4989 ActionSelect (int argc
, char **argv
, int x
, int y
)
4991 char *function
= ARG (0);
4995 HideCrosshair (True
);
4996 switch (GetFunctionID (function
))
4998 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
5000 /* select objects by their names */
5001 case F_ElementByName
:
5002 type
= ELEMENT_TYPE
;
5004 case F_ObjectByName
:
5022 char *pattern
= ARG (1);
5026 gui
->prompt_for (_("Enter pattern:"), "")) != NULL
)
5028 if (SelectObjectByName (type
, pattern
, True
))
5029 SetChangedFlag (True
);
5035 #endif /* defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) */
5037 /* select a single object */
5038 case F_ToggleObject
:
5040 if (SelectObject ())
5041 SetChangedFlag (True
);
5044 /* all objects in block */
5049 box
.X1
= MIN (Crosshair
.AttachedBox
.Point1
.X
,
5050 Crosshair
.AttachedBox
.Point2
.X
);
5051 box
.Y1
= MIN (Crosshair
.AttachedBox
.Point1
.Y
,
5052 Crosshair
.AttachedBox
.Point2
.Y
);
5053 box
.X2
= MAX (Crosshair
.AttachedBox
.Point1
.X
,
5054 Crosshair
.AttachedBox
.Point2
.X
);
5055 box
.Y2
= MAX (Crosshair
.AttachedBox
.Point1
.Y
,
5056 Crosshair
.AttachedBox
.Point2
.Y
);
5058 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
&&
5059 SelectBlock (&box
, True
))
5061 SetChangedFlag (True
);
5062 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
5067 /* select all visible objects */
5072 box
.X1
= -MAX_COORD
;
5073 box
.Y1
= -MAX_COORD
;
5076 if (SelectBlock (&box
, True
))
5077 SetChangedFlag (True
);
5081 /* all found connections */
5083 if (SelectConnection (True
))
5085 IncrementUndoSerialNumber ();
5086 SetChangedFlag (True
);
5093 Note
.Buffer
= Settings
.BufferNumber
;
5094 SetBufferNumber (MAX_BUFFER
- 1);
5095 ClearBuffer (PASTEBUFFER
);
5096 gui
->get_coords ("Select the Element's Mark Location", &x
, &y
);
5097 x
= GRIDFIT_X (x
, PCB
->Grid
);
5098 y
= GRIDFIT_Y (y
, PCB
->Grid
);
5099 AddSelectedToBuffer (PASTEBUFFER
, x
, y
, True
);
5100 SaveUndoSerialNumber ();
5102 ConvertBufferToElement (PASTEBUFFER
);
5103 RestoreUndoSerialNumber ();
5104 CopyPastebufferToLayout (x
, y
);
5105 SetBufferNumber (Note
.Buffer
);
5110 RestoreCrosshair (True
);
5114 RestoreCrosshair (True
);
5119 /* FLAG(have_regex,FlagHaveRegex,0) */
5121 FlagHaveRegex (int parm
)
5123 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
5130 /* --------------------------------------------------------------------------- */
5132 static const char unselect_syntax
[] =
5133 "Unselect(All|Block|Connection)\n"
5134 "Unselect(ElementByName|ObjectByName|PadByName|PinByName)\n"
5135 "Unselect(ElementByName|ObjectByName|PadByName|PinByName, Name)\n"
5136 "Unselect(TextByName|ViaByName)\n" "Unselect(TextByName|ViaByName, Name)\n";
5138 static const char unselect_help
[] =
5139 "unselects the object at the pointer location or the specified objects";
5141 /* %start-doc actions Unselect
5146 Unselect all objects.
5149 Unselect all objects in a rectangle given by the cursor.
5152 Unselect all connections with the ``found'' flag set.
5161 These all rely on having a regular expression parser built into
5162 @code{pcb}. If the name is not specified then the user is prompted
5163 for a pattern, and all objects that match the pattern and are of the
5164 type specified are unselected.
5172 ActionUnselect (int argc
, char **argv
, int x
, int y
)
5174 char *function
= ARG (0);
5178 HideCrosshair (True
);
5179 switch (GetFunctionID (function
))
5181 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
5183 /* select objects by their names */
5184 case F_ElementByName
:
5185 type
= ELEMENT_TYPE
;
5187 case F_ObjectByName
:
5205 char *pattern
= ARG (1);
5209 gui
->prompt_for (_("Enter pattern:"), "")) != NULL
)
5211 if (SelectObjectByName (type
, pattern
, False
))
5212 SetChangedFlag (True
);
5218 #endif /* defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) */
5220 /* all objects in block */
5225 box
.X1
= MIN (Crosshair
.AttachedBox
.Point1
.X
,
5226 Crosshair
.AttachedBox
.Point2
.X
);
5227 box
.Y1
= MIN (Crosshair
.AttachedBox
.Point1
.Y
,
5228 Crosshair
.AttachedBox
.Point2
.Y
);
5229 box
.X2
= MAX (Crosshair
.AttachedBox
.Point1
.X
,
5230 Crosshair
.AttachedBox
.Point2
.X
);
5231 box
.Y2
= MAX (Crosshair
.AttachedBox
.Point1
.Y
,
5232 Crosshair
.AttachedBox
.Point2
.Y
);
5234 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
&&
5235 SelectBlock (&box
, False
))
5237 SetChangedFlag (True
);
5238 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
5243 /* unselect all visible objects */
5248 box
.X1
= -MAX_COORD
;
5249 box
.Y1
= -MAX_COORD
;
5252 if (SelectBlock (&box
, False
))
5253 SetChangedFlag (True
);
5257 /* all found connections */
5259 if (SelectConnection (False
))
5261 IncrementUndoSerialNumber ();
5262 SetChangedFlag (True
);
5267 RestoreCrosshair (True
);
5272 RestoreCrosshair (True
);
5277 /* --------------------------------------------------------------------------- */
5279 static const char saveto_syntax
[] =
5280 "SaveTo(Layout|LayoutAs,filename)\n"
5281 "SaveTo(AllConnections|AllUnusedPins|ElementConnections,filename)";
5283 static const char saveto_help
[] = "Saves data to a file.";
5285 /* %start-doc actions SaveTo
5290 Saves the current layout.
5293 Saves the current layout, and remembers the filename used.
5295 @item AllConnections
5296 Save all connections to a file.
5299 List all unused pins to a file.
5301 @item ElementConnections
5302 Save connections to the element at the cursor to a file.
5309 ActionSaveTo (int argc
, char **argv
, int x
, int y
)
5319 if (strcasecmp (function
, "LayoutAs") == 0)
5321 MYFREE (PCB
->Filename
);
5322 PCB
->Filename
= MyStrdup (name
, __FUNCTION__
);
5323 function
= "Layout";
5325 if (strcasecmp (function
, "Layout") == 0)
5327 SavePCB (PCB
->Filename
);
5331 if (strcasecmp (function
, "AllConnections") == 0)
5335 if ((fp
= CheckAndOpenFile (name
, True
, False
, &result
, NULL
)) != NULL
)
5337 LookupConnectionsToAllElements (fp
);
5339 SetChangedFlag (True
);
5344 if (strcasecmp (function
, "AllUnusedPins") == 0)
5348 if ((fp
= CheckAndOpenFile (name
, True
, False
, &result
, NULL
)) != NULL
)
5350 LookupUnusedPins (fp
);
5352 SetChangedFlag (True
);
5357 if (strcasecmp (function
, "ElementConnections") == 0)
5359 ElementTypePtr element
;
5364 if ((SearchScreen (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
,
5365 &ptrtmp
, &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
5367 element
= (ElementTypePtr
) ptrtmp
;
5369 CheckAndOpenFile (name
, True
, False
, &result
, NULL
)) != NULL
)
5371 LookupElementConnections (element
, fp
);
5373 SetChangedFlag (True
);
5382 /* --------------------------------------------------------------------------- */
5384 static const char savesettings_syntax
[] =
5385 "SaveSettings()\n" "SaveSettings(local)";
5387 static const char savesettings_help
[] = "Saves settings.";
5389 /* %start-doc actions SaveSettings
5391 If you pass no arguments, the settings are stored in
5392 @code{$HOME/.pcb/settings}. If you pass the word @code{local} they're
5393 saved in @code{./pcb.settings}.
5398 ActionSaveSettings (int argc
, char **argv
, int x
, int y
)
5400 int locally
= argc
> 0 ? (strncasecmp (argv
[0], "local", 5) == 0) : 0;
5401 hid_save_settings (locally
);
5405 /* --------------------------------------------------------------------------- */
5407 static const char loadfrom_syntax
[] =
5408 "LoadFrom(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert,filename)";
5410 static const char loadfrom_help
[] = "Load layout data from a file.";
5412 /* %start-doc actions LoadFrom
5414 This action assumes you know what the filename is. The various GUIs
5415 should have a similar @code{Load} action where the filename is
5416 optional, and will provide their own file selection mechanism to let
5417 you choose the file name.
5422 Loads an entire PCB layout, replacing the current one.
5424 @item LayoutToBuffer
5425 Loads an entire PCB layout to the paste buffer.
5427 @item ElementToBuffer
5428 Loads the given element file into the paste buffer. Element files
5429 contain only a single @code{Element} definition, such as the
5430 ``newlib'' library uses.
5433 Loads a new netlist, replacing any current netlist.
5436 Re-loads the current layout from its disk file, reverting any changes
5444 ActionLoadFrom (int argc
, char **argv
, int x
, int y
)
5456 HideCrosshair (True
);
5458 if (strcasecmp (function
, "ElementToBuffer") == 0)
5460 if (LoadElementToBuffer (PASTEBUFFER
, name
, True
))
5461 SetMode (PASTEBUFFER_MODE
);
5464 else if (strcasecmp (function
, "LayoutToBuffer") == 0)
5466 if (LoadLayoutToBuffer (PASTEBUFFER
, name
))
5467 SetMode (PASTEBUFFER_MODE
);
5470 else if (strcasecmp (function
, "Layout") == 0)
5472 if (!PCB
->Changed
||
5473 gui
->confirm_dialog (_("OK to override layout data?"), 0))
5477 else if (strcasecmp (function
, "Netlist") == 0)
5479 if (PCB
->Netlistname
)
5480 SaveFree (PCB
->Netlistname
);
5481 PCB
->Netlistname
= StripWhiteSpaceAndDup (name
);
5482 FreeLibraryMemory (&PCB
->NetlistLib
);
5483 if (!ReadNetlist (PCB
->Netlistname
))
5484 hid_action ("NetlistChanged");
5486 else if (strcasecmp (function
, "Revert") == 0 && PCB
->Filename
5488 || gui
->confirm_dialog (_("OK to override changes?"), 0)))
5490 strcpy (fname
, PCB
->Filename
); /*Calling LoadPCB(PCB->Filename) changes the content of PCB->Filename. */
5494 RestoreCrosshair (True
);
5498 /* --------------------------------------------------------------------------- */
5500 static const char new_syntax
[] = "New([name])";
5502 static const char new_help
[] = "Starts a new layout.";
5504 /* %start-doc actions New
5506 If a name is not given, one is prompted for.
5511 ActionNew (int argc
, char **argv
, int x
, int y
)
5513 char *name
= ARG (0);
5515 HideCrosshair (True
);
5516 if (!PCB
->Changed
|| gui
->confirm_dialog (_("OK to clear layout data?"), 0))
5519 name
= MyStrdup (name
, "ActionNew");
5521 name
= gui
->prompt_for (_("Enter the layout name:"), "");
5525 /* do emergency saving
5526 * clear the old struct and allocate memory for the new one
5528 if (PCB
->Changed
&& Settings
.SaveInTMP
)
5531 PCB
= CreateNewPCB (True
);
5532 PCB
->Data
->LayerN
= DEF_LAYER
;
5533 CreateNewPCBPost (PCB
, 1);
5535 /* setup the new name and reset some values to default */
5536 PCB
->Name
= name
; /* XXX memory leak */
5538 ResetStackAndVisibility ();
5539 CreateDefaultFont ();
5540 SetCrosshairRange (0, 0, PCB
->MaxWidth
, PCB
->MaxHeight
);
5541 CenterDisplay (PCB
->MaxWidth
/ 2, PCB
->MaxHeight
/ 2, False
);
5542 ClearAndRedrawOutput ();
5544 hid_action ("PCBChanged");
5547 RestoreCrosshair (True
);
5551 /* ---------------------------------------------------------------------------
5552 * no operation, just for testing purposes
5553 * syntax: Bell(volume)
5556 ActionBell (char *volume
)
5561 /* --------------------------------------------------------------------------- */
5563 static const char pastebuffer_syntax
[] =
5564 "PasteBuffer(AddSelected|Clear|1..MAX_BUFFER)\n"
5565 "PasteBuffer(Rotate, 1..3)\n"
5566 "PasteBuffer(Convert|Save|Restore|Mirror)\n"
5567 "PasteBuffer(ToLayout, X, Y, units)";
5569 static const char pastebuffer_help
[] =
5570 "Various operations on the paste buffer.";
5572 /* %start-doc actions PasteBuffer
5574 There are a number of paste buffers; the actual limit is a
5575 compile-time constant @code{MAX_BUFFER} in @file{globalconst.h}. It
5576 is currently @code{5}. One of these is the ``current'' paste buffer,
5577 often referred to as ``the'' paste buffer.
5582 Copies the selected objects to the current paste buffer.
5585 Remove all objects from the current paste buffer.
5588 Convert the current paste buffer to an element. Vias are converted to
5589 pins, lines are converted to pads.
5592 Convert any elements in the paste buffer back to vias and lines.
5595 Flip all objects in the paste buffer vertically (up/down flip). To mirror
5596 horizontally, combine this with rotations.
5599 Rotates the current buffer. The number to pass is 1..3, where 1 means
5600 90 degrees counter clockwise, 2 means 180 degrees, and 3 means 90
5601 degrees clockwise (270 CCW).
5604 Saves any elements in the current buffer to the indicated file.
5607 Pastes any elements in the current buffer to the indicated X, Y
5608 coordinates in the layout. The @code{X} and @code{Y} are treated like
5609 @code{delta} is for many other objects. For each, if it's prefixed by
5610 @code{+} or @code{-}, then that amount is relative to the last
5611 location. Otherwise, it's absolute. Units can be
5612 @code{mil} or @code{mm}; if unspecified, units are PCB's internal
5613 units, currently 1/100 mil.
5617 Selects the given buffer to be the current paste buffer.
5624 ActionPasteBuffer (int argc
, char **argv
, int x
, int y
)
5626 char *function
= argc
? argv
[0] : "";
5627 char *sbufnum
= argc
> 1 ? argv
[1] : "";
5630 HideCrosshair (True
);
5633 switch (GetFunctionID (function
))
5635 /* clear contents of paste buffer */
5637 ClearBuffer (PASTEBUFFER
);
5640 /* copies objects to paste buffer */
5642 AddSelectedToBuffer (PASTEBUFFER
, 0, 0, False
);
5645 /* converts buffer contents into an element */
5647 ConvertBufferToElement (PASTEBUFFER
);
5650 /* break up element for editing */
5652 SmashBufferElement (PASTEBUFFER
);
5657 MirrorBuffer (PASTEBUFFER
);
5663 RotateBuffer (PASTEBUFFER
, (BYTE
) atoi (sbufnum
));
5664 SetCrosshairRangeToBuffer ();
5669 if (PASTEBUFFER
->Data
->ElementN
== 0)
5671 Message (_("Buffer has no elements!\n"));
5675 name
= gui
->prompt_for ("Save as:", 0);
5682 if ((exist
= fopen (name
, "r")))
5686 confirm_dialog (_("File exists! Ok to overwrite?"), 0))
5687 SaveBufferElements (name
);
5690 SaveBufferElements (name
);
5696 static int oldx
= 0, oldy
= 0;
5704 else if (argc
== 3 || argc
== 4)
5706 x
= GetValue (ARG (1), ARG (3), &r
);
5709 y
= GetValue (ARG (2), ARG (3), &r
);
5715 RestoreCrosshair (True
);
5716 AFAIL (pastebuffer
);
5721 if (CopyPastebufferToLayout (x
, y
))
5722 SetChangedFlag (True
);
5729 int number
= atoi (function
);
5731 /* correct number */
5733 SetBufferNumber (number
- 1);
5738 RestoreCrosshair (True
);
5742 /* --------------------------------------------------------------------------- */
5744 static const char undo_syntax
[] = "Undo()\n" "Undo(ClearList)";
5746 static const char undo_help
[] = "Undo recent changes.";
5748 /* %start-doc actions Undo
5750 The unlimited undo feature of @code{Pcb} allows you to recover from
5751 most operations that materially affect you work. Calling
5752 @code{Undo()} without any parameter recovers from the last (non-undo)
5753 operation. @code{ClearList} is used to release the allocated
5754 memory. @code{ClearList} is called whenever a new layout is started or
5755 loaded. See also @code{Redo} and @code{Atomic}.
5757 Note that undo groups operations by serial number; changes with the
5758 same serial number will be undone (or redone) as a group. See
5764 ActionUndo (int argc
, char **argv
, int x
, int y
)
5766 char *function
= ARG (0);
5767 if (!function
|| !*function
)
5769 /* don't allow undo in the middle of an operation */
5770 if (Crosshair
.AttachedObject
.State
!= STATE_FIRST
)
5772 if (Crosshair
.AttachedBox
.State
!= STATE_FIRST
5773 && Settings
.Mode
!= ARC_MODE
)
5775 /* undo the last operation */
5777 HideCrosshair (True
);
5778 if (Settings
.Mode
== POLYGON_MODE
&& Crosshair
.AttachedPolygon
.PointN
)
5780 GoToPreviousPoint ();
5781 RestoreCrosshair (True
);
5784 /* move anchor point if undoing during line creation */
5785 if (Settings
.Mode
== LINE_MODE
)
5787 if (Crosshair
.AttachedLine
.State
== STATE_SECOND
)
5789 if (TEST_FLAG (AUTODRCFLAG
, PCB
))
5790 Undo (True
); /* undo the connection find */
5791 Crosshair
.AttachedLine
.State
= STATE_FIRST
;
5792 SetLocalRef (0, 0, False
);
5793 RestoreCrosshair (True
);
5796 if (Crosshair
.AttachedLine
.State
== STATE_THIRD
)
5799 void *ptr1
, *ptr3
, *ptrtmp
;
5801 /* this search is guaranteed to succeed */
5802 SearchObjectByLocation (LINE_TYPE
| RATLINE_TYPE
, &ptr1
,
5804 Crosshair
.AttachedLine
.Point1
.X
,
5805 Crosshair
.AttachedLine
.Point1
.Y
, 0);
5806 ptr2
= (LineTypePtr
) ptrtmp
;
5808 /* save both ends of line */
5809 Crosshair
.AttachedLine
.Point2
.X
= ptr2
->Point1
.X
;
5810 Crosshair
.AttachedLine
.Point2
.Y
= ptr2
->Point1
.Y
;
5811 if ((type
= Undo (True
)))
5812 SetChangedFlag (True
);
5813 /* check that the undo was of the right type */
5814 if ((type
& UNDO_CREATE
) == 0)
5816 /* wrong undo type, restore anchor points */
5817 Crosshair
.AttachedLine
.Point2
.X
=
5818 Crosshair
.AttachedLine
.Point1
.X
;
5819 Crosshair
.AttachedLine
.Point2
.Y
=
5820 Crosshair
.AttachedLine
.Point1
.Y
;
5821 RestoreCrosshair (True
);
5824 /* move to new anchor */
5825 Crosshair
.AttachedLine
.Point1
.X
=
5826 Crosshair
.AttachedLine
.Point2
.X
;
5827 Crosshair
.AttachedLine
.Point1
.Y
=
5828 Crosshair
.AttachedLine
.Point2
.Y
;
5829 /* check if an intermediate point was removed */
5830 if (type
& UNDO_REMOVE
)
5832 /* this search should find the restored line */
5833 SearchObjectByLocation (LINE_TYPE
| RATLINE_TYPE
, &ptr1
,
5836 Crosshair
.AttachedLine
.Point2
.X
,
5837 Crosshair
.AttachedLine
.Point2
.Y
, 0);
5838 ptr2
= (LineTypePtr
) ptrtmp
;
5839 Crosshair
.AttachedLine
.Point1
.X
=
5840 Crosshair
.AttachedLine
.Point2
.X
= ptr2
->Point2
.X
;
5841 Crosshair
.AttachedLine
.Point1
.Y
=
5842 Crosshair
.AttachedLine
.Point2
.Y
= ptr2
->Point2
.Y
;
5844 FitCrosshairIntoGrid (Crosshair
.X
, Crosshair
.Y
);
5845 AdjustAttachedObjects ();
5846 if (--addedLines
== 0)
5848 Crosshair
.AttachedLine
.State
= STATE_SECOND
;
5849 lastLayer
= CURRENT
;
5853 /* this search is guaranteed to succeed too */
5854 SearchObjectByLocation (LINE_TYPE
| RATLINE_TYPE
, &ptr1
,
5857 Crosshair
.AttachedLine
.Point1
.X
,
5858 Crosshair
.AttachedLine
.Point1
.Y
, 0);
5859 ptr2
= (LineTypePtr
) ptrtmp
;
5860 lastLayer
= (LayerTypePtr
) ptr1
;
5862 RestoreCrosshair (True
);
5866 if (Settings
.Mode
== ARC_MODE
)
5868 if (Crosshair
.AttachedBox
.State
== STATE_SECOND
)
5870 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
5871 RestoreCrosshair (True
);
5874 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
)
5876 void *ptr1
, *ptr2
, *ptr3
;
5878 /* guaranteed to succeed */
5879 SearchObjectByLocation (ARC_TYPE
, &ptr1
, &ptr2
, &ptr3
,
5880 Crosshair
.AttachedBox
.Point1
.X
,
5881 Crosshair
.AttachedBox
.Point1
.Y
, 0);
5882 bx
= GetArcEnds ((ArcTypePtr
) ptr2
);
5883 Crosshair
.AttachedBox
.Point1
.X
=
5884 Crosshair
.AttachedBox
.Point2
.X
= bx
->X1
;
5885 Crosshair
.AttachedBox
.Point1
.Y
=
5886 Crosshair
.AttachedBox
.Point2
.Y
= bx
->Y1
;
5887 AdjustAttachedObjects ();
5888 if (--addedLines
== 0)
5889 Crosshair
.AttachedBox
.State
= STATE_SECOND
;
5892 /* undo the last destructive operation */
5894 SetChangedFlag (True
);
5898 switch (GetFunctionID (function
))
5900 /* clear 'undo objects' list */
5902 ClearUndoList (False
);
5906 RestoreCrosshair (True
);
5910 /* --------------------------------------------------------------------------- */
5912 static const char redo_syntax
[] = "Redo()";
5914 static const char redo_help
[] = "Redo recent \"undo\" operations.";
5916 /* %start-doc actions Redo
5918 This routine allows you to recover from the last undo command. You
5919 might want to do this if you thought that undo was going to revert
5920 something other than what it actually did (in case you are confused
5921 about which operations are un-doable), or if you have been backing up
5922 through a long undo list and over-shoot your stopping point. Any
5923 change that is made since the undo in question will trim the redo
5924 list. For example if you add ten lines, then undo three of them you
5925 could use redo to put them back, but if you move a line on the board
5926 before performing the redo, you will lose the ability to "redo" the
5927 three "undone" lines.
5932 ActionRedo (int argc
, char **argv
, int x
, int y
)
5934 if ((Settings
.Mode
== POLYGON_MODE
&&
5935 Crosshair
.AttachedPolygon
.PointN
) ||
5936 Crosshair
.AttachedLine
.State
== STATE_SECOND
)
5938 HideCrosshair (True
);
5941 SetChangedFlag (True
);
5942 if (Settings
.Mode
== LINE_MODE
&&
5943 Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
5945 LineTypePtr line
= &CURRENT
->Line
[CURRENT
->LineN
- 1];
5946 Crosshair
.AttachedLine
.Point1
.X
=
5947 Crosshair
.AttachedLine
.Point2
.X
= line
->Point2
.X
;
5948 Crosshair
.AttachedLine
.Point1
.Y
=
5949 Crosshair
.AttachedLine
.Point2
.Y
= line
->Point2
.Y
;
5953 RestoreCrosshair (True
);
5957 /* --------------------------------------------------------------------------- */
5959 static const char polygon_syntax
[] = "Polygon(Close|PreviousPoint)";
5961 static const char polygon_help
[] = "Some polygon related stuff.";
5963 /* %start-doc actions Polygon
5965 Polygons need a special action routine to make life easier.
5970 Creates the final segment of the polygon. This may fail if clipping
5971 to 45 degree lines is switched on, in which case a warning is issued.
5974 Resets the newly entered corner to the previous one. The Undo action
5975 will call Polygon(PreviousPoint) when appropriate to do so.
5982 ActionPolygon (int argc
, char **argv
, int x
, int y
)
5984 char *function
= ARG (0);
5985 if (function
&& Settings
.Mode
== POLYGON_MODE
)
5987 HideCrosshair (True
);
5988 switch (GetFunctionID (function
))
5990 /* close open polygon if possible */
5995 /* go back to the previous point */
5996 case F_PreviousPoint
:
5997 GoToPreviousPoint ();
6000 RestoreCrosshair (True
);
6005 /* --------------------------------------------------------------------------- */
6007 static const char routestyle_syntax
[] = "RouteStyle(1|2|3|4)";
6009 static const char routestyle_help
[] =
6010 "Copies the indicated routing style into the current sizes.";
6012 /* %start-doc actions RouteStyle
6017 ActionRouteStyle (int argc
, char **argv
, int x
, int y
)
6019 char *str
= ARG (0);
6020 RouteStyleType
*rts
;
6025 number
= atoi (str
);
6026 if (number
> 0 && number
<= NUM_STYLES
)
6028 rts
= &PCB
->RouteStyle
[number
- 1];
6029 SetLineSize (rts
->Thick
);
6030 SetViaSize (rts
->Diameter
, True
);
6031 SetViaDrillingHole (rts
->Hole
, True
);
6032 SetKeepawayWidth (rts
->Keepaway
);
6039 /* --------------------------------------------------------------------------- */
6041 static const char moveobject_syntax
[] = "MoveObject(X,Y,dim)";
6043 static const char moveobject_help
[] = "Moves the object under the crosshair.";
6045 /* %start-doc actions MoveObject
6047 The @code{X} and @code{Y} are treated like @code{delta} is for many
6048 other objects. For each, if it's prefixed by @code{+} or @code{-},
6049 then that amount is relative. Otherwise, it's absolute. Units can be
6050 @code{mil} or @code{mm}; if unspecified, units are PCB's internal
6051 units, currently 1/100 mil.
6056 ActionMoveObject (int argc
, char **argv
, int x
, int y
)
6058 char *x_str
= ARG (0);
6059 char *y_str
= ARG (1);
6060 char *units
= ARG (2);
6061 LocationType nx
, ny
;
6063 void *ptr1
, *ptr2
, *ptr3
;
6066 ny
= GetValue (y_str
, units
, &r1
);
6067 nx
= GetValue (x_str
, units
, &r2
);
6069 type
= SearchScreen (x
, y
, MOVE_TYPES
, &ptr1
, &ptr2
, &ptr3
);
6070 if (type
== NO_TYPE
)
6072 Message (_("Nothing found under crosshair\n"));
6079 Crosshair
.AttachedObject
.RubberbandN
= 0;
6080 if (TEST_FLAG (RUBBERBANDFLAG
, PCB
))
6081 LookupRubberbandLines (type
, ptr1
, ptr2
, ptr3
);
6082 if (type
== ELEMENT_TYPE
)
6083 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
6084 MoveObjectAndRubberband (type
, ptr1
, ptr2
, ptr3
, nx
, ny
);
6085 SetChangedFlag (True
);
6089 /* --------------------------------------------------------------------------- */
6091 static const char movetocurrentlayer_syntax
[] =
6092 "MoveToCurrentLayer(Object|SelectedObjects)";
6094 static const char movetocurrentlayer_help
[] =
6095 "Moves objects to the current layer.";
6097 /* %start-doc actions MoveToCurrentLayer
6099 Note that moving an element from a component layer to a solder layer,
6100 or from solder to component, won't automatically flip it. Use the
6101 @code{Flip()} action to do that.
6106 ActionMoveToCurrentLayer (int argc
, char **argv
, int x
, int y
)
6108 char *function
= ARG (0);
6111 HideCrosshair (True
);
6112 switch (GetFunctionID (function
))
6117 void *ptr1
, *ptr2
, *ptr3
;
6119 gui
->get_coords ("Select an Object", &x
, &y
);
6121 SearchScreen (x
, y
, MOVETOLAYER_TYPES
,
6122 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
6123 if (MoveObjectToLayer (type
, ptr1
, ptr2
, ptr3
, CURRENT
, False
))
6124 SetChangedFlag (True
);
6128 case F_SelectedObjects
:
6130 if (MoveSelectedObjectsToLayer (CURRENT
))
6131 SetChangedFlag (True
);
6134 RestoreCrosshair (True
);
6140 static const char setsame_syntax
[] = "SetSame()";
6142 static const char setsame_help
[] =
6143 "Sets current layer and sizes to match indicated item.";
6145 /* %start-doc actions SetSame
6147 When invoked over any line, arc, polygon, or via, this changes the
6148 current layer to be the layer that item is on, and changes the current
6149 sizes (thickness, keepaway, drill, etc) according to that item.
6154 ActionSetSame (int argc
, char **argv
, int x
, int y
)
6156 void *ptr1
, *ptr2
, *ptr3
;
6158 LayerTypePtr layer
= CURRENT
;
6160 type
= SearchScreen (x
, y
, CLONE_TYPES
, &ptr1
, &ptr2
, &ptr3
);
6161 /* set layer current and size from line or arc */
6165 HideCrosshair (True
);
6166 Settings
.LineThickness
= ((LineTypePtr
) ptr2
)->Thickness
;
6167 Settings
.Keepaway
= ((LineTypePtr
) ptr2
)->Clearance
/ 2;
6168 layer
= (LayerTypePtr
) ptr1
;
6169 if (Settings
.Mode
!= LINE_MODE
)
6170 SetMode (LINE_MODE
);
6171 RestoreCrosshair (True
);
6172 hid_action ("RouteStyleChanged");
6176 HideCrosshair (True
);
6177 Settings
.LineThickness
= ((ArcTypePtr
) ptr2
)->Thickness
;
6178 Settings
.Keepaway
= ((ArcTypePtr
) ptr2
)->Clearance
/ 2;
6179 layer
= (LayerTypePtr
) ptr1
;
6180 if (Settings
.Mode
!= ARC_MODE
)
6182 RestoreCrosshair (True
);
6183 hid_action ("RouteStyleChanged");
6187 layer
= (LayerTypePtr
) ptr1
;
6191 HideCrosshair (True
);
6192 Settings
.ViaThickness
= ((PinTypePtr
) ptr2
)->Thickness
;
6193 Settings
.ViaDrillingHole
= ((PinTypePtr
) ptr2
)->DrillingHole
;
6194 Settings
.Keepaway
= ((PinTypePtr
) ptr2
)->Clearance
/ 2;
6195 if (Settings
.Mode
!= VIA_MODE
)
6197 RestoreCrosshair (True
);
6198 hid_action ("RouteStyleChanged");
6204 if (layer
!= CURRENT
)
6206 ChangeGroupVisibility (GetLayerNumber (PCB
->Data
, layer
), True
, True
);
6207 ClearAndRedrawOutput ();
6213 /* --------------------------------------------------------------------------- */
6215 static const char setflag_syntax
[] =
6216 "SetFlag(Object|Selected|SelectedObjects, flag)\n"
6217 "SetFlag(SelectedLines|SelectedPins|SelectedVias, flag)\n"
6218 "SetFlag(SelectedPads|SelectedTexts|SelectedNames, flag)\n"
6219 "SetFlag(SelectedElements, flag)\n"
6220 "flag = square | octagon | thermal | join";
6222 static const char setflag_help
[] = "Sets flags on objects.";
6224 /* %start-doc actions SetFlag
6226 Turns the given flag on, regardless of its previous setting. See
6230 SetFlag(SelectedPins,thermal)
6236 ActionSetFlag (int argc
, char **argv
, int x
, int y
)
6238 char *function
= ARG (0);
6239 char *flag
= ARG (1);
6240 ChangeFlag (function
, flag
, 1, "SetFlag");
6244 /* --------------------------------------------------------------------------- */
6246 static const char clrflag_syntax
[] =
6247 "ClrFlag(Object|Selected|SelectedObjects, flag)\n"
6248 "ClrFlag(SelectedLines|SelectedPins|SelectedVias, flag)\n"
6249 "ClrFlag(SelectedPads|SelectedTexts|SelectedNames, flag)\n"
6250 "ClrFlag(SelectedElements, flag)\n"
6251 "flag = square | octagon | thermal | join";
6253 static const char clrflag_help
[] = "Clears flags on objects.";
6255 /* %start-doc actions ClrFlag
6257 Turns the given flag off, regardless of its previous setting. See
6261 ClrFlag(SelectedLines,join)
6267 ActionClrFlag (int argc
, char **argv
, int x
, int y
)
6269 char *function
= ARG (0);
6270 char *flag
= ARG (1);
6271 ChangeFlag (function
, flag
, 0, "ClrFlag");
6275 /* --------------------------------------------------------------------------- */
6277 static const char changeflag_syntax
[] =
6278 "ChangeFlag(Object|Selected|SelectedObjects, flag, value)\n"
6279 "ChangeFlag(SelectedLines|SelectedPins|SelectedVias, flag, value)\n"
6280 "ChangeFlag(SelectedPads|SelectedTexts|SelectedNames, flag, value)\n"
6281 "ChangeFlag(SelectedElements, flag, value)\n"
6282 "flag = square | octagon | thermal | join\n" "value = 0 | 1";
6284 static const char changeflag_help
[] = "Sets or clears flags on objects.";
6286 /* %start-doc actions ChangeFlag
6288 Toggles the given flag on the indicated object(s). The flag may be
6289 one of the flags listed above (square, octagon, thermal, join). The
6290 value may be the number 0 or 1. If the value is 0, the flag is
6291 cleared. If the value is 1, the flag is set.
6296 ActionChangeFlag (int argc
, char **argv
, int x
, int y
)
6298 char *function
= ARG (0);
6299 char *flag
= ARG (1);
6300 int value
= argc
> 2 ? atoi (argv
[2]) : -1;
6301 if (value
!= 0 && value
!= 1)
6304 ChangeFlag (function
, flag
, value
, "ChangeFlag");
6310 ChangeFlag (char *what
, char *flag_name
, int value
, char *cmd_name
)
6312 Boolean (*set_object
) (int, void *, void *, void *);
6313 Boolean (*set_selected
) (int);
6315 if (NSTRCMP (flag_name
, "square") == 0)
6317 set_object
= value
? SetObjectSquare
: ClrObjectSquare
;
6318 set_selected
= value
? SetSelectedSquare
: ClrSelectedSquare
;
6320 else if (NSTRCMP (flag_name
, "octagon") == 0)
6322 set_object
= value
? SetObjectOctagon
: ClrObjectOctagon
;
6323 set_selected
= value
? SetSelectedOctagon
: ClrSelectedOctagon
;
6325 else if (NSTRCMP (flag_name
, "join") == 0)
6327 /* Note: these are backwards, because the flag is "clear" but
6328 the command is "join". */
6329 set_object
= value
? ClrObjectJoin
: SetObjectJoin
;
6330 set_selected
= value
? ClrSelectedJoin
: SetSelectedJoin
;
6334 Message (_("%s(): Flag \"%s\" is not valid\n"), cmd_name
, flag_name
);
6338 HideCrosshair (True
);
6339 switch (GetFunctionID (what
))
6344 void *ptr1
, *ptr2
, *ptr3
;
6347 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGESIZE_TYPES
,
6348 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
6349 if (TEST_FLAG (LOCKFLAG
, (PinTypePtr
) ptr2
))
6350 Message (_("Sorry, the object is locked\n"));
6351 if (set_object (type
, ptr1
, ptr2
, ptr3
))
6352 SetChangedFlag (True
);
6356 case F_SelectedVias
:
6357 if (set_selected (VIA_TYPE
))
6358 SetChangedFlag (True
);
6361 case F_SelectedPins
:
6362 if (set_selected (PIN_TYPE
))
6363 SetChangedFlag (True
);
6366 case F_SelectedPads
:
6367 if (set_selected (PAD_TYPE
))
6368 SetChangedFlag (True
);
6371 case F_SelectedLines
:
6372 if (set_selected (LINE_TYPE
))
6373 SetChangedFlag (True
);
6376 case F_SelectedTexts
:
6377 if (set_selected (TEXT_TYPE
))
6378 SetChangedFlag (True
);
6381 case F_SelectedNames
:
6382 if (set_selected (ELEMENTNAME_TYPE
))
6383 SetChangedFlag (True
);
6386 case F_SelectedElements
:
6387 if (set_selected (ELEMENT_TYPE
))
6388 SetChangedFlag (True
);
6392 case F_SelectedObjects
:
6393 if (set_selected (CHANGESIZE_TYPES
))
6394 SetChangedFlag (True
);
6397 RestoreCrosshair (True
);
6401 /* --------------------------------------------------------------------------- */
6403 static const char executefile_syntax
[] = "ExecuteFile(filename)";
6405 static const char executefile_help
[] = "Run actions from the given file.";
6407 /* %start-doc actions ExecuteFile
6409 Lines starting with @code{#} are ignored.
6414 ActionExecuteFile (int argc
, char **argv
, int x
, int y
)
6423 AFAIL (executefile
);
6427 if ((fp
= fopen (fname
, "r")) == NULL
)
6429 fprintf (stderr
, "Could not open actions file \"%s\".\n", fname
);
6433 while (fgets (line
, sizeof (line
), fp
) != NULL
)
6438 /* eat the trailing newline */
6439 while (*sp
&& *sp
!= '\r' && *sp
!= '\n')
6443 /* eat leading spaces and tabs */
6445 while (*sp
&& (*sp
== ' ' || *sp
== '\t'))
6449 * if we have anything left and its not a comment line
6453 if (*sp
&& *sp
!= '#')
6455 Message ("%s : line %-3d : \"%s\"\n", fname
, n
, sp
);
6456 hid_parse_actions (sp
, 0);
6464 /* --------------------------------------------------------------------------- */
6467 ActionPSCalib (int argc
, char **argv
, int x
, int y
)
6469 HID
*ps
= hid_find_exporter ("ps");
6470 ps
->calibrate (0.0,0.0);
6474 /* --------------------------------------------------------------------------- */
6476 HID_Action action_action_list
[] = {
6477 {"AddRats", 0, ActionAddRats
,
6478 addrats_help
, addrats_syntax
}
6480 {"Atomic", 0, ActionAtomic
,
6481 atomic_help
, atomic_syntax
}
6483 {"AutoPlaceSelected", 0, ActionAutoPlaceSelected
,
6484 autoplace_help
, autoplace_syntax
}
6486 {"AutoRoute", 0, ActionAutoRoute
,
6487 autoroute_help
, autoroute_syntax
}
6489 {"ChangeClearSize", 0, ActionChangeClearSize
,
6490 changeclearsize_help
, changeclearsize_syntax
}
6492 {"ChangeDrillSize", 0, ActionChange2ndSize
,
6493 changedrillsize_help
, changedrillsize_syntax
}
6495 {"ChangeHole", 0, ActionChangeHole
,
6496 changehold_help
, changehold_syntax
}
6498 {"ChangeJoin", 0, ActionChangeJoin
,
6499 changejoin_help
, changejoin_syntax
}
6501 {"ChangeName", 0, ActionChangeName
,
6502 changename_help
, changename_syntax
}
6504 {"ChangePaste", 0, ActionChangePaste
,
6505 changepaste_help
, changepaste_syntax
}
6507 {"ChangePinName", 0, ActionChangePinName
,
6508 changepinname_help
, changepinname_syntax
}
6510 {"ChangeSize", 0, ActionChangeSize
,
6511 changesize_help
, changesize_syntax
}
6513 {"ChangeSquare", 0, ActionChangeSquare
,
6514 changesquare_help
, changesquare_syntax
}
6516 {"ChangeOctagon", 0, ActionChangeOctagon
,
6517 changeoctagon_help
, changeoctagon_syntax
}
6519 {"ClearSquare", 0, ActionClearSquare
,
6520 clearsquare_help
, clearsquare_syntax
}
6522 {"ClearOctagon", 0, ActionClearOctagon
,
6523 clearoctagon_help
, clearoctagon_syntax
}
6525 {"Connection", 0, ActionConnection
,
6526 connection_help
, connection_syntax
}
6528 {"DeleteRats", 0, ActionDeleteRats
,
6529 deleterats_help
, deleterats_syntax
}
6531 {"DisperseElements", 0, ActionDisperseElements
,
6532 disperseelements_help
, disperseelements_syntax
}
6534 {"Display", 0, ActionDisplay
,
6535 display_help
, display_syntax
}
6537 {"DRC", 0, ActionDRCheck
,
6538 drc_help
, drc_syntax
}
6540 {"DumpLibrary", 0, ActionDumpLibrary
,
6541 dumplibrary_help
, dumplibrary_syntax
}
6543 {"ExecuteFile", 0, ActionExecuteFile
,
6544 executefile_help
, executefile_syntax
}
6546 {"Flip", "Click on Object or Flip Point", ActionFlip
,
6547 flip_help
, flip_syntax
}
6549 {"LoadFrom", 0, ActionLoadFrom
,
6550 loadfrom_help
, loadfrom_syntax
}
6552 {"MarkCrosshair", 0, ActionMarkCrosshair
,
6553 markcrosshair_help
, markcrosshair_syntax
}
6555 {"Message", 0, ActionMessage
,
6556 message_help
, message_syntax
}
6558 {"MinMaskGap", 0, ActionMinMaskGap
,
6559 minmaskgap_help
, minmaskgap_syntax
}
6561 {"Mode", 0, ActionMode
,
6562 mode_help
, mode_syntax
}
6564 {"MorphPolygon", 0, ActionMorphPolygon
,
6565 morphpolygon_help
, morphpolygon_syntax
}
6567 {"PasteBuffer", 0, ActionPasteBuffer
,
6568 pastebuffer_help
, pastebuffer_syntax
}
6570 {"Quit", 0, ActionQuit
,
6571 quit_help
, quit_syntax
}
6573 {"RemoveSelected", 0, ActionRemoveSelected
,
6574 removeselected_help
, removeselected_syntax
}
6576 {"Renumber", 0, ActionRenumber
,
6577 renumber_help
, renumber_syntax
}
6579 {"RipUp", 0, ActionRipUp
,
6580 ripup_help
, ripup_syntax
}
6582 {"Select", 0, ActionSelect
,
6583 select_help
, select_syntax
}
6585 {"Unselect", 0, ActionUnselect
,
6586 unselect_help
, unselect_syntax
}
6588 {"SaveSettings", 0, ActionSaveSettings
,
6589 savesettings_help
, savesettings_syntax
}
6591 {"SaveTo", 0, ActionSaveTo
,
6592 saveto_help
, saveto_syntax
}
6594 {"SetSquare", 0, ActionSetSquare
,
6595 setsquare_help
, setsquare_syntax
}
6597 {"SetOctagon", 0, ActionSetOctagon
,
6598 setoctagon_help
, setoctagon_syntax
}
6600 {"SetThermal", 0, ActionSetThermal
,
6601 setthermal_help
, setthermal_syntax
}
6603 {"SetValue", 0, ActionSetValue
,
6604 setvalue_help
, setvalue_syntax
}
6606 {"ToggleHideName", 0, ActionToggleHideName
,
6607 togglehidename_help
, togglehidename_syntax
}
6609 {"Undo", 0, ActionUndo
,
6610 undo_help
, undo_syntax
}
6612 {"Redo", 0, ActionRedo
,
6613 redo_help
, redo_syntax
}
6615 {"SetSame", "Select item to use attributes from", ActionSetSame
,
6616 setsame_help
, setsame_syntax
}
6618 {"SetFlag", 0, ActionSetFlag
,
6619 setflag_help
, setflag_syntax
}
6621 {"ClrFlag", 0, ActionClrFlag
,
6622 clrflag_help
, clrflag_syntax
}
6624 {"ChangeFlag", 0, ActionChangeFlag
,
6625 changeflag_help
, changeflag_syntax
}
6627 {"Polygon", 0, ActionPolygon
,
6628 polygon_help
, polygon_syntax
}
6630 {"RouteStyle", 0, ActionRouteStyle
,
6631 routestyle_help
, routestyle_syntax
}
6633 {"MoveObject", "Select an Object", ActionMoveObject
,
6634 moveobject_help
, moveobject_syntax
}
6636 {"MoveToCurrentLayer", 0, ActionMoveToCurrentLayer
,
6637 movetocurrentlayer_help
, movetocurrentlayer_syntax
}
6639 {"New", 0, ActionNew
,
6640 new_help
, new_syntax
}
6642 {"pscalib", 0, ActionPSCalib
}
6646 REGISTER_ACTIONS (action_action_list
)