1 /* 15 Oct 2008 Ineiev: add CycleCrosshair action */
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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"
60 /*#include "print.h"*/
65 #include "rubberband.h"
76 #ifdef HAVE_LIBDMALLOC
80 /* for fork() and friends */
85 #ifdef HAVE_SYS_WAIT_H
89 /* ---------------------------------------------------------------------------
119 F_ElementConnections
,
158 F_ResetLinesAndPolygons
,
159 F_ResetPinsViasAndPads
,
181 F_ToggleAllDirections
,
192 F_ToggleRubberBandMode
,
193 F_ToggleStartDirection
,
198 F_ToggleThindrawPoly
,
212 typedef struct /* used to identify subfunctions */
217 FunctionType
, *FunctionTypePtr
;
219 /* --------------------------------------------------------------------------- */
221 /* %start-doc actions 00delta
223 Many actions take a @code{delta} parameter as the last parameter,
224 which is an amount to change something. That @code{delta} may include
225 units, as an additional parameter, such as @code{Action(Object,5,mm)}.
226 If no units are specified, the default is PCB's native units
227 (currently 1/100 mil). Also, if the delta is prefixed by @code{+} or
228 @code{-}, the size is increased or decreased by that amount.
229 Otherwise, the size size is set to the given amount.
233 Action(Object,+0.5,mm)
237 Actions which take a @code{delta} parameter which do not accept all
238 these options will specify what they do take.
242 /* %start-doc actions 00objects
244 Many actions act on indicated objects on the board. They will have
245 parameters like @code{ToggleObject} or @code{SelectedVias} to indicate
246 what group of objects they act on. Unless otherwise specified, these
247 parameters are defined as follows:
253 Affects the object under the mouse pointer. If this action is invoked
254 from a menu or script, the user will be prompted to click on an
255 object, which is then the object affected.
258 @itemx SelectedObjects
260 Affects all objects which are currently selected. At least, all
261 selected objects for which the given action makes sense.
265 @itemx Selected@var{Type}
267 Affects all objects which are both selected and of the @var{Type} specified.
273 /* %start-doc actions 00macros
277 Pins, pads, and vias can have various shapes. All may be round. Pins
278 and pads may be square (obviously "square" pads are usually
279 rectangular). Pins and vias may be octagonal. When you change a
280 shape flag of an element, you actually change all of its pins and
283 Note that the square flag takes precedence over the octagon flag,
284 thus, if both the square and octagon flags are set, the object is
285 square. When the square flag is cleared, the pins and pads will be
286 either round or, if the octagon flag is set, octagonal.
292 /* ---------------------------------------------------------------------------
293 * some local identifiers
295 static PointType InsertedPoint
;
296 static LayerTypePtr lastLayer
;
310 Boolean Moving
; /* selected type clicked on */
311 int Hit
; /* move type clicked on */
318 static int defer_updates
= 0;
319 static int defer_needs_update
= 0;
321 static Cardinal polyIndex
= 0;
322 static Boolean IgnoreMotionEvents
= False
;
323 static Boolean saved_mode
= False
;
324 #ifdef HAVE_LIBSTROKE
325 static Boolean mid_stroke
= False
;
326 static BoxType StrokeBox
;
328 static FunctionType Functions
[] = {
329 {"AddSelected", F_AddSelected
},
331 {"AllConnections", F_AllConnections
},
332 {"AllRats", F_AllRats
},
333 {"AllUnusedPins", F_AllUnusedPins
},
337 {"Description", F_Description
},
338 {"Cancel", F_Cancel
},
339 {"Center", F_Center
},
341 {"ClearAndRedraw", F_ClearAndRedraw
},
342 {"ClearList", F_ClearList
},
344 {"Connection", F_Connection
},
345 {"Convert", F_Convert
},
347 {"CycleClip", F_CycleClip
},
348 {"CycleCrosshair", F_CycleCrosshair
},
349 {"DeleteRats", F_DeleteRats
},
351 {"DrillReport", F_DrillReport
},
352 {"Element", F_Element
},
353 {"ElementByName", F_ElementByName
},
354 {"ElementConnections", F_ElementConnections
},
355 {"ElementToBuffer", F_ElementToBuffer
},
356 {"Escape", F_Escape
},
358 {"FlipElement", F_FlipElement
},
359 {"FoundPins", F_FoundPins
},
361 {"InsertPoint", F_InsertPoint
},
363 {"Layout", F_Layout
},
364 {"LayoutAs", F_LayoutAs
},
365 {"LayoutToBuffer", F_LayoutToBuffer
},
367 {"LineSize", F_LineSize
},
369 {"Mirror", F_Mirror
},
371 {"NameOnPCB", F_NameOnPCB
},
372 {"Netlist", F_Netlist
},
374 {"Notify", F_Notify
},
375 {"Object", F_Object
},
376 {"ObjectByName", F_ObjectByName
},
377 {"PasteBuffer", F_PasteBuffer
},
378 {"PadByName", F_PadByName
},
379 {"PinByName", F_PinByName
},
380 {"PinOrPadName", F_PinOrPadName
},
381 {"Pinout", F_Pinout
},
382 {"Polygon", F_Polygon
},
383 {"PreviousPoint", F_PreviousPoint
},
384 {"RatsNest", F_RatsNest
},
385 {"Rectangle", F_Rectangle
},
386 {"Redraw", F_Redraw
},
387 {"Release", F_Release
},
388 {"Remove", F_Remove
},
389 {"RemoveSelected", F_RemoveSelected
},
390 {"Report", F_Report
},
392 {"ResetLinesAndPolygons", F_ResetLinesAndPolygons
},
393 {"ResetPinsViasAndPads", F_ResetPinsViasAndPads
},
394 {"Restore", F_Restore
},
395 {"Revert", F_Revert
},
396 {"Rotate", F_Rotate
},
398 {"Scroll", F_Scroll
},
399 {"Selected", F_Selected
},
400 {"SelectedArcs", F_SelectedArcs
},
401 {"SelectedElements", F_SelectedElements
},
402 {"SelectedLines", F_SelectedLines
},
403 {"SelectedNames", F_SelectedNames
},
404 {"SelectedObjects", F_SelectedObjects
},
405 {"SelectedPins", F_SelectedPins
},
406 {"SelectedPads", F_SelectedPads
},
407 {"SelectedRats", F_SelectedRats
},
408 {"SelectedTexts", F_SelectedTexts
},
409 {"SelectedVias", F_SelectedVias
},
410 {"Stroke", F_Stroke
},
412 {"TextByName", F_TextByName
},
413 {"TextScale", F_TextScale
},
414 {"Thermal", F_Thermal
},
415 {"ToLayout", F_ToLayout
},
416 {"Toggle45Degree", F_ToggleAllDirections
},
417 {"ToggleClearLine", F_ToggleClearLine
},
418 {"ToggleFullPoly", F_ToggleFullPoly
},
419 {"ToggleGrid", F_ToggleGrid
},
420 {"ToggleMask", F_ToggleMask
},
421 {"ToggleName", F_ToggleName
},
422 {"ToggleObject", F_ToggleObject
},
423 {"ToggleRubberBandMode", F_ToggleRubberBandMode
},
424 {"ToggleStartDirection", F_ToggleStartDirection
},
425 {"ToggleSnapPin", F_ToggleSnapPin
},
426 {"ToggleThindraw", F_ToggleThindraw
},
427 {"ToggleThindrawPoly", F_ToggleThindrawPoly
},
428 {"ToggleLockNames", F_ToggleLockNames
},
429 {"ToggleOnlyNames", F_ToggleOnlyNames
},
430 {"ToggleHideNames", F_ToggleHideNames
},
431 {"ToggleCheckPlanes", F_ToggleCheckPlanes
},
432 {"ToggleLocalRef", F_ToggleLocalRef
},
433 {"ToggleOrthoMove", F_ToggleOrthoMove
},
434 {"ToggleShowDRC", F_ToggleShowDRC
},
435 {"ToggleLiveRoute", F_ToggleLiveRoute
},
436 {"ToggleAutoDRC", F_ToggleAutoDRC
},
437 {"ToggleUniqueNames", F_ToggleUniqueNames
},
440 {"ViaByName", F_ViaByName
},
441 {"ViaSize", F_ViaSize
},
442 {"ViaDrillingHole", F_ViaDrillingHole
},
446 /* ---------------------------------------------------------------------------
447 * some local routines
449 static int GetFunctionID (String
);
450 static void AdjustAttachedBox (void);
451 static void NotifyLine (void);
452 static void NotifyBlock (void);
453 static void NotifyMode (void);
454 static void ClearWarnings (void);
455 #ifdef HAVE_LIBSTROKE
456 static void FinishStroke (void);
457 extern void stroke_init (void);
458 extern void stroke_record (int x
, int y
);
459 extern int stroke_trans (char *s
);
461 static void ChangeFlag (char *, char *, int, char *);
463 #define ARG(n) (argc > (n) ? argv[n] : 0)
465 #ifdef HAVE_LIBSTROKE
467 /* ---------------------------------------------------------------------------
468 * FinishStroke - try to recognize the stroke sent
476 void *ptr1
, *ptr2
, *ptr3
;
479 if (stroke_trans (msg
))
485 if (Settings
.Mode
== LINE_MODE
)
495 RotateScreenObject (StrokeBox
.X1
, StrokeBox
.Y1
, SWAP_IDENT
? 1 : 3);
501 RotateScreenObject (StrokeBox
.X1
, StrokeBox
.Y1
, SWAP_IDENT
? 3 : 1);
507 SetMode (ARROW_MODE
);
532 SetZoom (1000); /* special zoom extents */
544 LocationType x
= (StrokeBox
.X1
+ StrokeBox
.X2
) / 2;
545 LocationType y
= (StrokeBox
.Y1
+ StrokeBox
.Y2
) / 2;
549 log (fabs (StrokeBox
.X2
- StrokeBox
.X1
) / Output
.Width
) /
554 log (fabs (StrokeBox
.Y2
- StrokeBox
.Y1
) / Output
.Height
) /
558 CenterDisplay (x
, y
, False
);
563 Message ("Unknown stroke %s\n", msg
);
572 /* ---------------------------------------------------------------------------
573 * Clear warning color from pins/pads
578 Settings
.RatWarn
= False
;
579 ALLPIN_LOOP (PCB
->Data
);
581 if (TEST_FLAG (WARNFLAG
, pin
))
583 CLEAR_FLAG (WARNFLAG
, pin
);
588 ALLPAD_LOOP (PCB
->Data
);
590 if (TEST_FLAG (WARNFLAG
, pad
))
592 CLEAR_FLAG (WARNFLAG
, pad
);
606 if (Note
.Moving
&& !gui
->shift_is_pressed ())
608 HideCrosshair (True
);
609 Note
.Buffer
= Settings
.BufferNumber
;
610 SetBufferNumber (MAX_BUFFER
- 1);
611 ClearBuffer (PASTEBUFFER
);
612 AddSelectedToBuffer (PASTEBUFFER
, Note
.X
, Note
.Y
, True
);
613 SaveUndoSerialNumber ();
617 SetMode (PASTEBUFFER_MODE
);
618 RestoreCrosshair (True
);
620 else if (Note
.Hit
&& !gui
->shift_is_pressed ())
622 HideCrosshair (True
);
625 SetMode (gui
->control_is_pressed ()? COPY_MODE
: MOVE_MODE
);
626 Crosshair
.AttachedObject
.Ptr1
= Note
.ptr1
;
627 Crosshair
.AttachedObject
.Ptr2
= Note
.ptr2
;
628 Crosshair
.AttachedObject
.Ptr3
= Note
.ptr3
;
629 Crosshair
.AttachedObject
.Type
= Note
.Hit
;
630 AttachForCopy (Note
.X
, Note
.Y
);
631 RestoreCrosshair (True
);
639 HideCrosshair (True
);
640 SaveUndoSerialNumber ();
645 /* unselect first if shift key not down */
646 if (!gui
->shift_is_pressed () && SelectBlock (&box
, False
))
647 SetChangedFlag (True
);
649 Crosshair
.AttachedBox
.Point1
.X
= Note
.X
;
650 Crosshair
.AttachedBox
.Point1
.Y
= Note
.Y
;
651 RestoreCrosshair (True
);
670 Note
.Click
= False
; /* inhibit timer action */
671 SaveUndoSerialNumber ();
672 /* unselect first if shift key not down */
673 if (!gui
->shift_is_pressed ())
675 if (SelectBlock (&box
, False
))
676 SetChangedFlag (True
);
684 RestoreUndoSerialNumber ();
686 SetChangedFlag (True
);
690 else if (Note
.Moving
)
692 RestoreUndoSerialNumber ();
694 ClearBuffer (PASTEBUFFER
);
695 SetBufferNumber (Note
.Buffer
);
704 else if (Settings
.Mode
== ARROW_MODE
)
706 box
.X1
= MIN (Crosshair
.AttachedBox
.Point1
.X
,
707 Crosshair
.AttachedBox
.Point2
.X
);
708 box
.Y1
= MIN (Crosshair
.AttachedBox
.Point1
.Y
,
709 Crosshair
.AttachedBox
.Point2
.Y
);
710 box
.X2
= MAX (Crosshair
.AttachedBox
.Point1
.X
,
711 Crosshair
.AttachedBox
.Point2
.X
);
712 box
.Y2
= MAX (Crosshair
.AttachedBox
.Point1
.Y
,
713 Crosshair
.AttachedBox
.Point2
.Y
);
714 RestoreUndoSerialNumber ();
715 if (SelectBlock (&box
, True
))
716 SetChangedFlag (True
);
718 IncrementUndoSerialNumber ();
719 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
726 /* ---------------------------------------------------------------------------
727 * get function ID of passed string
730 static char function_hash
[HSIZE
];
731 static int hash_initted
= 0;
740 i
= (i
* 13) ^ (unsigned char)tolower((int) *s
);
743 i
= (unsigned int)i
% HSIZE
;
748 GetFunctionID (String Ident
)
758 if (HSIZE
< ENTRIES (Functions
) * 2)
760 fprintf(stderr
, "Error: function hash size too small (%d vs %lu at %s:%d)\n",
761 HSIZE
, (unsigned long) ENTRIES (Functions
)*2, __FILE__
, __LINE__
);
764 if (ENTRIES (Functions
) > 254)
766 /* Change 'char' to 'int' and remove this when we get to 256
768 fprintf(stderr
, "Error: function hash type too small (%d vs %lu at %s:%d)\n",
769 256, (unsigned long) ENTRIES (Functions
), __FILE__
, __LINE__
);
773 for (i
=ENTRIES (Functions
)-1; i
>=0; i
--)
775 h
= hashfunc (Functions
[i
].Identifier
);
776 while (function_hash
[h
])
778 function_hash
[h
] = i
+ 1;
782 i
= hashfunc (Ident
);
785 /* We enforce the "hash table bigger than function table" rule,
786 so we know there will be at least one zero entry to find. */
787 if (!function_hash
[i
])
789 if (!strcasecmp (Ident
, Functions
[function_hash
[i
]-1].Identifier
))
790 return ((int) Functions
[function_hash
[i
]-1].ID
);
795 /* ---------------------------------------------------------------------------
796 * set new coordinates if in 'RECTANGLE' mode
797 * the cursor shape is also adjusted
800 AdjustAttachedBox (void)
802 if (Settings
.Mode
== ARC_MODE
)
804 Crosshair
.AttachedBox
.otherway
= gui
->shift_is_pressed ();
807 switch (Crosshair
.AttachedBox
.State
)
809 case STATE_SECOND
: /* one corner is selected */
811 /* update coordinates */
812 Crosshair
.AttachedBox
.Point2
.X
= Crosshair
.X
;
813 Crosshair
.AttachedBox
.Point2
.Y
= Crosshair
.Y
;
819 /* ---------------------------------------------------------------------------
820 * adjusts the objects which are to be created like attached lines...
823 AdjustAttachedObjects (void)
826 switch (Settings
.Mode
)
828 /* update at least an attached block (selection) */
831 if (Crosshair
.AttachedBox
.State
)
833 Crosshair
.AttachedBox
.Point2
.X
= Crosshair
.X
;
834 Crosshair
.AttachedBox
.Point2
.Y
= Crosshair
.Y
;
838 /* rectangle creation mode */
841 AdjustAttachedBox ();
844 /* polygon creation mode */
846 AdjustAttachedLine ();
848 /* line creation mode */
850 if (PCB
->RatDraw
|| PCB
->Clipping
== 0)
851 AdjustAttachedLine ();
853 AdjustTwoLine (PCB
->Clipping
- 1);
855 /* point insertion mode */
856 case INSERTPOINT_MODE
:
857 pnt
= AdjustInsertPoint ();
859 InsertedPoint
= *pnt
;
866 /* ---------------------------------------------------------------------------
867 * creates points of a line
873 void *ptr1
, *ptr2
, *ptr3
;
875 if (!Marked
.status
|| TEST_FLAG (LOCALREFFLAG
, PCB
))
876 SetLocalRef (Crosshair
.X
, Crosshair
.Y
, True
);
877 switch (Crosshair
.AttachedLine
.State
)
879 case STATE_FIRST
: /* first point */
880 if (PCB
->RatDraw
&& SearchScreen (Crosshair
.X
, Crosshair
.Y
,
881 PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr1
,
887 if (TEST_FLAG (AUTODRCFLAG
, PCB
) && Settings
.Mode
== LINE_MODE
)
889 type
= SearchScreen (Crosshair
.X
, Crosshair
.Y
,
890 PIN_TYPE
| PAD_TYPE
| VIA_TYPE
, &ptr1
, &ptr2
,
892 LookupConnection (Crosshair
.X
, Crosshair
.Y
, True
, TO_PCB (1),
895 if (type
== PIN_TYPE
|| type
== VIA_TYPE
)
897 Crosshair
.AttachedLine
.Point1
.X
=
898 Crosshair
.AttachedLine
.Point2
.X
= ((PinTypePtr
) ptr2
)->X
;
899 Crosshair
.AttachedLine
.Point1
.Y
=
900 Crosshair
.AttachedLine
.Point2
.Y
= ((PinTypePtr
) ptr2
)->Y
;
902 else if (type
== PAD_TYPE
)
904 PadTypePtr pad
= (PadTypePtr
) ptr2
;
906 d1
= SQUARE (Crosshair
.X
- pad
->Point1
.X
) +
907 SQUARE (Crosshair
.Y
- pad
->Point1
.Y
);
908 d2
= SQUARE (Crosshair
.X
- pad
->Point2
.X
) +
909 SQUARE (Crosshair
.Y
- pad
->Point2
.Y
);
912 Crosshair
.AttachedLine
.Point1
=
913 Crosshair
.AttachedLine
.Point2
= pad
->Point2
;
917 Crosshair
.AttachedLine
.Point1
=
918 Crosshair
.AttachedLine
.Point2
= pad
->Point1
;
923 Crosshair
.AttachedLine
.Point1
.X
=
924 Crosshair
.AttachedLine
.Point2
.X
= Crosshair
.X
;
925 Crosshair
.AttachedLine
.Point1
.Y
=
926 Crosshair
.AttachedLine
.Point2
.Y
= Crosshair
.Y
;
928 Crosshair
.AttachedLine
.State
= STATE_SECOND
;
932 /* fall through to third state too */
934 default: /* all following points */
935 Crosshair
.AttachedLine
.State
= STATE_THIRD
;
940 /* ---------------------------------------------------------------------------
941 * create first or second corner of a marked block
946 HideCrosshair (True
);
947 switch (Crosshair
.AttachedBox
.State
)
949 case STATE_FIRST
: /* setup first point */
950 Crosshair
.AttachedBox
.Point1
.X
=
951 Crosshair
.AttachedBox
.Point2
.X
= Crosshair
.X
;
952 Crosshair
.AttachedBox
.Point1
.Y
=
953 Crosshair
.AttachedBox
.Point2
.Y
= Crosshair
.Y
;
954 Crosshair
.AttachedBox
.State
= STATE_SECOND
;
957 case STATE_SECOND
: /* setup second point */
958 Crosshair
.AttachedBox
.State
= STATE_THIRD
;
961 RestoreCrosshair (True
);
965 /* ---------------------------------------------------------------------------
967 * does what's appropriate for the current mode setting. This normally
968 * means creation of an object at the current crosshair location.
970 * new created objects are added to the create undo list of course
975 void *ptr1
, *ptr2
, *ptr3
;
978 if (Settings
.RatWarn
)
980 switch (Settings
.Mode
)
988 /* do something after click time */
989 gui
->add_timer (click_cb
, CLICK_TIME
, hv
);
991 /* see if we clicked on something already selected
992 * (Note.Moving) or clicked on a MOVE_TYPE
995 for (test
= (SELECT_TYPES
| MOVE_TYPES
) & ~RATLINE_TYPE
;
998 type
= SearchScreen (Note
.X
, Note
.Y
, test
, &ptr1
, &ptr2
, &ptr3
);
999 if (!Note
.Hit
&& (type
& MOVE_TYPES
) &&
1000 !TEST_FLAG (LOCKFLAG
, (PinTypePtr
) ptr2
))
1007 if (!Note
.Moving
&& (type
& SELECT_TYPES
) &&
1008 TEST_FLAG (SELECTEDFLAG
, (PinTypePtr
) ptr2
))
1010 if ((Note
.Hit
&& Note
.Moving
) || type
== NO_TYPE
)
1022 Message (_("You must turn via visibility on before\n"
1023 "you can place vias\n"));
1026 if ((via
= CreateNewVia (PCB
->Data
, Note
.X
, Note
.Y
,
1027 Settings
.ViaThickness
, 2 * Settings
.Keepaway
,
1028 0, Settings
.ViaDrillingHole
, NULL
,
1029 NoFlags ())) != NULL
)
1031 AddObjectToCreateUndoList (VIA_TYPE
, via
, via
, via
);
1032 if (gui
->shift_is_pressed ())
1033 ChangeObjectThermal (VIA_TYPE
, via
, via
, via
, PCB
->ThermStyle
);
1034 IncrementUndoSerialNumber ();
1043 switch (Crosshair
.AttachedBox
.State
)
1046 Crosshair
.AttachedBox
.Point1
.X
=
1047 Crosshair
.AttachedBox
.Point2
.X
= Note
.X
;
1048 Crosshair
.AttachedBox
.Point1
.Y
=
1049 Crosshair
.AttachedBox
.Point2
.Y
= Note
.Y
;
1050 Crosshair
.AttachedBox
.State
= STATE_SECOND
;
1057 LocationType wx
, wy
;
1060 wx
= Note
.X
- Crosshair
.AttachedBox
.Point1
.X
;
1061 wy
= Note
.Y
- Crosshair
.AttachedBox
.Point1
.Y
;
1062 if (XOR (Crosshair
.AttachedBox
.otherway
, abs (wy
) > abs (wx
)))
1064 Crosshair
.AttachedBox
.Point2
.X
=
1065 Crosshair
.AttachedBox
.Point1
.X
+ abs (wy
) * SGNZ (wx
);
1066 sa
= (wx
>= 0) ? 0 : 180;
1068 if (abs (wy
) / 2 >= abs (wx
))
1069 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 45 : -45;
1072 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 90 : -90;
1076 Crosshair
.AttachedBox
.Point2
.Y
=
1077 Crosshair
.AttachedBox
.Point1
.Y
+ abs (wx
) * SGNZ (wy
);
1078 sa
= (wy
>= 0) ? -90 : 90;
1080 if (abs (wx
) / 2 >= abs (wy
))
1081 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -45 : 45;
1084 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -90 : 90;
1087 if (abs (wy
) > 0 && (arc
= CreateNewArcOnLayer (CURRENT
,
1111 bx
= GetArcEnds (arc
);
1112 Crosshair
.AttachedBox
.Point1
.X
=
1113 Crosshair
.AttachedBox
.Point2
.X
= bx
->X2
;
1114 Crosshair
.AttachedBox
.Point1
.Y
=
1115 Crosshair
.AttachedBox
.Point2
.Y
= bx
->Y2
;
1116 AddObjectToCreateUndoList (ARC_TYPE
, CURRENT
, arc
, arc
);
1117 IncrementUndoSerialNumber ();
1119 DrawArc (CURRENT
, arc
, 0);
1121 Crosshair
.AttachedBox
.State
= STATE_THIRD
;
1130 type
= SearchScreen (Note
.X
, Note
.Y
, LOCK_TYPES
, &ptr1
, &ptr2
, &ptr3
);
1131 if (type
== ELEMENT_TYPE
)
1133 ElementTypePtr element
= (ElementTypePtr
) ptr2
;
1135 TOGGLE_FLAG (LOCKFLAG
, element
);
1138 TOGGLE_FLAG (LOCKFLAG
, pin
);
1139 CLEAR_FLAG (SELECTEDFLAG
, pin
);
1144 TOGGLE_FLAG (LOCKFLAG
, pad
);
1145 CLEAR_FLAG (SELECTEDFLAG
, pad
);
1148 CLEAR_FLAG (SELECTEDFLAG
, element
);
1149 /* always re-draw it since I'm too lazy
1150 * to tell if a selected flag changed
1152 DrawElement (element
, 0);
1154 hid_actionl ("Report", "Object", NULL
);
1156 else if (type
!= NO_TYPE
)
1158 TextTypePtr thing
= (TextTypePtr
) ptr3
;
1159 TOGGLE_FLAG (LOCKFLAG
, thing
);
1160 if (TEST_FLAG (LOCKFLAG
, thing
)
1161 && TEST_FLAG (SELECTEDFLAG
, thing
))
1163 /* this is not un-doable since LOCK isn't */
1164 CLEAR_FLAG (SELECTEDFLAG
, thing
);
1165 DrawObject (type
, ptr1
, ptr2
, 0);
1168 hid_actionl ("Report", "Object", NULL
);
1176 SearchScreen (Note
.X
, Note
.Y
, PIN_TYPES
, &ptr1
, &ptr2
,
1178 && !TEST_FLAG (HOLEFLAG
, (PinTypePtr
) ptr3
))
1180 if (gui
->shift_is_pressed ())
1182 int tstyle
= GET_THERM (INDEXOFCURRENT
, (PinTypePtr
) ptr3
);
1186 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, tstyle
);
1188 else if (GET_THERM (INDEXOFCURRENT
, (PinTypePtr
) ptr3
))
1189 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, 0);
1191 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, PCB
->ThermStyle
);
1197 /* do update of position */
1199 if (Crosshair
.AttachedLine
.State
!= STATE_THIRD
)
1202 /* Remove anchor if clicking on start point;
1203 * this means we can't paint 0 length lines
1204 * which could be used for square SMD pads.
1205 * Instead use a very small delta, or change
1206 * the file after saving.
1208 if (Crosshair
.X
== Crosshair
.AttachedLine
.Point1
.X
1209 && Crosshair
.Y
== Crosshair
.AttachedLine
.Point1
.Y
)
1211 SetMode (LINE_MODE
);
1218 if ((line
= AddNet ()))
1221 AddObjectToCreateUndoList (RATLINE_TYPE
, line
, line
, line
);
1222 IncrementUndoSerialNumber ();
1224 Crosshair
.AttachedLine
.Point1
.X
=
1225 Crosshair
.AttachedLine
.Point2
.X
;
1226 Crosshair
.AttachedLine
.Point1
.Y
=
1227 Crosshair
.AttachedLine
.Point2
.Y
;
1233 /* create line if both ends are determined && length != 0 */
1238 && Crosshair
.AttachedLine
.Point1
.X
==
1239 Crosshair
.AttachedLine
.Point2
.X
1240 && Crosshair
.AttachedLine
.Point1
.Y
==
1241 Crosshair
.AttachedLine
.Point2
.Y
1242 && (Crosshair
.AttachedLine
.Point2
.X
!= Note
.X
1243 || Crosshair
.AttachedLine
.Point2
.Y
!= Note
.Y
))
1245 /* We will only need to paint the second line segment.
1246 Since we only check for vias on the first segment,
1247 swap them so the non-empty segment is the first segment. */
1248 Crosshair
.AttachedLine
.Point2
.X
= Note
.X
;
1249 Crosshair
.AttachedLine
.Point2
.Y
= Note
.Y
;
1252 if ((Crosshair
.AttachedLine
.Point1
.X
!=
1253 Crosshair
.AttachedLine
.Point2
.X
1254 || Crosshair
.AttachedLine
.Point1
.Y
!=
1255 Crosshair
.AttachedLine
.Point2
.Y
)
1257 CreateDrawnLineOnLayer (CURRENT
,
1258 Crosshair
.AttachedLine
.Point1
.X
,
1259 Crosshair
.AttachedLine
.Point1
.Y
,
1260 Crosshair
.AttachedLine
.Point2
.X
,
1261 Crosshair
.AttachedLine
.Point2
.Y
,
1262 Settings
.LineThickness
,
1263 2 * Settings
.Keepaway
,
1264 MakeFlags ((TEST_FLAG
1266 PCB
) ? FOUNDFLAG
: 0) |
1269 PCB
) ? CLEARLINEFLAG
:
1275 AddObjectToCreateUndoList (LINE_TYPE
, CURRENT
, line
, line
);
1276 DrawLine (CURRENT
, line
, 0);
1277 /* place a via if vias are visible, the layer is
1278 in a new group since the last line and there
1279 isn't a pin already here */
1280 if (PCB
->ViaOn
&& GetLayerGroupNumberByPointer (CURRENT
) !=
1281 GetLayerGroupNumberByPointer (lastLayer
) &&
1282 SearchObjectByLocation (PIN_TYPES
, &ptr1
, &ptr2
, &ptr3
,
1283 Crosshair
.AttachedLine
.Point1
.X
,
1284 Crosshair
.AttachedLine
.Point1
.Y
,
1285 Settings
.ViaThickness
/ 2) ==
1288 CreateNewVia (PCB
->Data
,
1289 Crosshair
.AttachedLine
.Point1
.X
,
1290 Crosshair
.AttachedLine
.Point1
.Y
,
1291 Settings
.ViaThickness
,
1292 2 * Settings
.Keepaway
, 0,
1293 Settings
.ViaDrillingHole
, NULL
,
1294 NoFlags ())) != NULL
)
1296 AddObjectToCreateUndoList (VIA_TYPE
, via
, via
, via
);
1299 /* copy the coordinates */
1300 Crosshair
.AttachedLine
.Point1
.X
=
1301 Crosshair
.AttachedLine
.Point2
.X
;
1302 Crosshair
.AttachedLine
.Point1
.Y
=
1303 Crosshair
.AttachedLine
.Point2
.Y
;
1304 IncrementUndoSerialNumber ();
1305 lastLayer
= CURRENT
;
1307 if (PCB
->Clipping
&& (Note
.X
!= Crosshair
.AttachedLine
.Point2
.X
1309 Crosshair
.AttachedLine
.Point2
.Y
)
1311 CreateDrawnLineOnLayer (CURRENT
,
1312 Crosshair
.AttachedLine
.Point2
.X
,
1313 Crosshair
.AttachedLine
.Point2
.Y
,
1315 Settings
.LineThickness
,
1316 2 * Settings
.Keepaway
,
1317 MakeFlags ((TEST_FLAG
1319 PCB
) ? FOUNDFLAG
: 0) |
1322 PCB
) ? CLEARLINEFLAG
:
1326 AddObjectToCreateUndoList (LINE_TYPE
, CURRENT
, line
, line
);
1327 IncrementUndoSerialNumber ();
1328 DrawLine (CURRENT
, line
, 0);
1329 /* move to new start point */
1330 Crosshair
.AttachedLine
.Point1
.X
= Note
.X
;
1331 Crosshair
.AttachedLine
.Point1
.Y
= Note
.Y
;
1332 Crosshair
.AttachedLine
.Point2
.X
= Note
.X
;
1333 Crosshair
.AttachedLine
.Point2
.Y
= Note
.Y
;
1334 if (TEST_FLAG (SWAPSTARTDIRFLAG
, PCB
))
1343 case RECTANGLE_MODE
:
1344 /* do update of position */
1347 /* create rectangle if both corners are determined
1348 * and width, height are != 0
1350 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
&&
1351 Crosshair
.AttachedBox
.Point1
.X
!= Crosshair
.AttachedBox
.Point2
.X
&&
1352 Crosshair
.AttachedBox
.Point1
.Y
!= Crosshair
.AttachedBox
.Point2
.Y
)
1354 PolygonTypePtr polygon
;
1356 int flags
= CLEARPOLYFLAG
;
1357 if (TEST_FLAG (NEWFULLPOLYFLAG
, PCB
))
1358 flags
|= FULLPOLYFLAG
;
1359 if ((polygon
= CreateNewPolygonFromRectangle (CURRENT
,
1361 AttachedBox
.Point1
.X
,
1363 AttachedBox
.Point1
.Y
,
1365 AttachedBox
.Point2
.X
,
1367 AttachedBox
.Point2
.Y
,
1372 AddObjectToCreateUndoList (POLYGON_TYPE
, CURRENT
,
1374 IncrementUndoSerialNumber ();
1375 DrawPolygon (CURRENT
, polygon
, 0);
1379 /* reset state to 'first corner' */
1380 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
1388 if ((string
= gui
->prompt_for (_("Enter text:"), "")) != NULL
)
1390 if (strlen(string
) > 0)
1395 if (GetLayerGroupNumberByNumber (INDEXOFCURRENT
) ==
1396 GetLayerGroupNumberByNumber (max_layer
+ SOLDER_LAYER
))
1397 flag
= ONSOLDERFLAG
;
1398 if ((text
= CreateNewText (CURRENT
, &PCB
->Font
, Note
.X
,
1399 Note
.Y
, 0, Settings
.TextScale
,
1400 string
, MakeFlags (flag
))) != NULL
)
1402 AddObjectToCreateUndoList (TEXT_TYPE
, CURRENT
, text
, text
);
1403 IncrementUndoSerialNumber ();
1404 DrawText (CURRENT
, text
, 0);
1409 /* free memory allocated by gui->prompt_for() */
1417 PointTypePtr points
= Crosshair
.AttachedPolygon
.Points
;
1418 Cardinal n
= Crosshair
.AttachedPolygon
.PointN
;
1420 /* do update of position; use the 'LINE_MODE' mechanism */
1423 /* check if this is the last point of a polygon */
1425 points
->X
== Crosshair
.AttachedLine
.Point2
.X
&&
1426 points
->Y
== Crosshair
.AttachedLine
.Point2
.Y
)
1428 CopyAttachedPolygonToLayer ();
1433 /* create new point if it's the first one or if it's
1434 * different to the last one
1437 points
[n
- 1].X
!= Crosshair
.AttachedLine
.Point2
.X
||
1438 points
[n
- 1].Y
!= Crosshair
.AttachedLine
.Point2
.Y
)
1440 CreateNewPointInPolygon (&Crosshair
.AttachedPolygon
,
1441 Crosshair
.AttachedLine
.Point2
.X
,
1442 Crosshair
.AttachedLine
.Point2
.Y
);
1444 /* copy the coordinates */
1445 Crosshair
.AttachedLine
.Point1
.X
= Crosshair
.AttachedLine
.Point2
.X
;
1446 Crosshair
.AttachedLine
.Point1
.Y
= Crosshair
.AttachedLine
.Point2
.Y
;
1451 case PASTEBUFFER_MODE
:
1453 TextType estr
[MAX_ELEMENTNAMES
];
1454 ElementTypePtr e
= 0;
1456 if (gui
->shift_is_pressed ())
1459 SearchScreen (Note
.X
, Note
.Y
, ELEMENT_TYPE
, &ptr1
, &ptr2
,
1461 if (type
== ELEMENT_TYPE
)
1463 e
= (ElementTypePtr
) ptr1
;
1468 memcpy (estr
, e
->Name
,
1469 MAX_ELEMENTNAMES
* sizeof (TextType
));
1470 for (i
= 0; i
< MAX_ELEMENTNAMES
; ++i
)
1471 estr
[i
].TextString
= estr
[i
].TextString
? strdup(estr
[i
].TextString
) : NULL
;
1476 if (CopyPastebufferToLayout (Note
.X
, Note
.Y
))
1477 SetChangedFlag (True
);
1481 SearchScreen (Note
.X
, Note
.Y
, ELEMENT_TYPE
, &ptr1
, &ptr2
,
1483 if (type
== ELEMENT_TYPE
&& ptr1
)
1486 e
= (ElementTypePtr
) ptr1
;
1488 save_n
= NAME_INDEX (PCB
);
1490 for (i
= 0; i
< MAX_ELEMENTNAMES
; i
++)
1493 EraseElementName (e
);
1494 r_delete_entry (PCB
->Data
->name_tree
[i
],
1495 (BoxType
*) & (e
->Name
[i
]));
1496 memcpy (&(e
->Name
[i
]), &(estr
[i
]), sizeof (TextType
));
1497 e
->Name
[i
].Element
= e
;
1498 SetTextBoundingBox (&PCB
->Font
, &(e
->Name
[i
]));
1499 r_insert_entry (PCB
->Data
->name_tree
[i
],
1500 (BoxType
*) & (e
->Name
[i
]), 0);
1502 DrawElementName (e
, 0);
1511 SearchScreen (Note
.X
, Note
.Y
, REMOVE_TYPES
, &ptr1
, &ptr2
,
1514 if (TEST_FLAG (LOCKFLAG
, (LineTypePtr
) ptr2
))
1516 Message (_("Sorry, the object is locked\n"));
1519 if (type
== ELEMENT_TYPE
)
1521 RubberbandTypePtr ptr
;
1524 Crosshair
.AttachedObject
.RubberbandN
= 0;
1525 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
1526 ptr
= Crosshair
.AttachedObject
.Rubberband
;
1527 for (i
= 0; i
< Crosshair
.AttachedObject
.RubberbandN
; i
++)
1530 EraseRat ((RatTypePtr
) ptr
->Line
);
1531 if (TEST_FLAG (RUBBERENDFLAG
, ptr
->Line
))
1532 MoveObjectToRemoveUndoList (RATLINE_TYPE
,
1533 ptr
->Line
, ptr
->Line
,
1536 TOGGLE_FLAG (RUBBERENDFLAG
, ptr
->Line
); /* only remove line once */
1540 RemoveObject (type
, ptr1
, ptr2
, ptr3
);
1541 IncrementUndoSerialNumber ();
1542 SetChangedFlag (True
);
1547 RotateScreenObject (Note
.X
, Note
.Y
,
1548 gui
->shift_is_pressed ()? (SWAP_IDENT
?
1550 : (SWAP_IDENT
? 3 : 1));
1553 /* both are almost the same */
1556 switch (Crosshair
.AttachedObject
.State
)
1558 /* first notify, lookup object */
1561 int types
= (Settings
.Mode
== COPY_MODE
) ?
1562 COPY_TYPES
: MOVE_TYPES
;
1564 Crosshair
.AttachedObject
.Type
=
1565 SearchScreen (Note
.X
, Note
.Y
, types
,
1566 &Crosshair
.AttachedObject
.Ptr1
,
1567 &Crosshair
.AttachedObject
.Ptr2
,
1568 &Crosshair
.AttachedObject
.Ptr3
);
1569 if (Crosshair
.AttachedObject
.Type
!= NO_TYPE
)
1571 if (Settings
.Mode
== MOVE_MODE
&&
1572 TEST_FLAG (LOCKFLAG
, (PinTypePtr
)
1573 Crosshair
.AttachedObject
.Ptr2
))
1575 Message (_("Sorry, the object is locked\n"));
1576 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1579 AttachForCopy (Note
.X
, Note
.Y
);
1584 /* second notify, move or copy object */
1586 if (Settings
.Mode
== COPY_MODE
)
1587 CopyObject (Crosshair
.AttachedObject
.Type
,
1588 Crosshair
.AttachedObject
.Ptr1
,
1589 Crosshair
.AttachedObject
.Ptr2
,
1590 Crosshair
.AttachedObject
.Ptr3
,
1591 Note
.X
- Crosshair
.AttachedObject
.X
,
1592 Note
.Y
- Crosshair
.AttachedObject
.Y
);
1595 MoveObjectAndRubberband (Crosshair
.AttachedObject
.Type
,
1596 Crosshair
.AttachedObject
.Ptr1
,
1597 Crosshair
.AttachedObject
.Ptr2
,
1598 Crosshair
.AttachedObject
.Ptr3
,
1599 Note
.X
- Crosshair
.AttachedObject
.X
,
1600 Note
.Y
- Crosshair
.AttachedObject
.Y
);
1601 SetLocalRef (0, 0, False
);
1603 SetChangedFlag (True
);
1605 /* reset identifiers */
1606 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1607 Crosshair
.AttachedObject
.State
= STATE_FIRST
;
1612 /* insert a point into a polygon/line/... */
1613 case INSERTPOINT_MODE
:
1614 switch (Crosshair
.AttachedObject
.State
)
1616 /* first notify, lookup object */
1618 Crosshair
.AttachedObject
.Type
=
1619 SearchScreen (Note
.X
, Note
.Y
, INSERT_TYPES
,
1620 &Crosshair
.AttachedObject
.Ptr1
,
1621 &Crosshair
.AttachedObject
.Ptr2
,
1622 &Crosshair
.AttachedObject
.Ptr3
);
1624 if (Crosshair
.AttachedObject
.Type
!= NO_TYPE
)
1626 if (TEST_FLAG (LOCKFLAG
, (PolygonTypePtr
)
1627 Crosshair
.AttachedObject
.Ptr2
))
1629 Message (_("Sorry, the object is locked\n"));
1630 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1635 /* get starting point of nearest segment */
1636 if (Crosshair
.AttachedObject
.Type
== POLYGON_TYPE
)
1639 (PolygonTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
1641 GetLowestDistancePolygonPoint (fake
.poly
, Note
.X
,
1643 fake
.line
.Point1
= fake
.poly
->Points
[polyIndex
];
1644 fake
.line
.Point2
= (polyIndex
) ?
1645 fake
.poly
->Points
[polyIndex
- 1]
1646 : fake
.poly
->Points
[fake
.poly
->PointN
- 1];
1647 Crosshair
.AttachedObject
.Ptr2
= &fake
.line
;
1650 Crosshair
.AttachedObject
.State
= STATE_SECOND
;
1651 InsertedPoint
= *AdjustInsertPoint ();
1656 /* second notify, insert new point into object */
1658 if (Crosshair
.AttachedObject
.Type
== POLYGON_TYPE
)
1659 InsertPointIntoObject (POLYGON_TYPE
,
1660 Crosshair
.AttachedObject
.Ptr1
, fake
.poly
,
1662 InsertedPoint
.X
, InsertedPoint
.Y
, False
);
1664 InsertPointIntoObject (Crosshair
.AttachedObject
.Type
,
1665 Crosshair
.AttachedObject
.Ptr1
,
1666 Crosshair
.AttachedObject
.Ptr2
,
1668 InsertedPoint
.X
, InsertedPoint
.Y
, False
);
1669 SetChangedFlag (True
);
1671 /* reset identifiers */
1672 Crosshair
.AttachedObject
.Type
= NO_TYPE
;
1673 Crosshair
.AttachedObject
.State
= STATE_FIRST
;
1681 /* --------------------------------------------------------------------------- */
1683 static const char atomic_syntax
[] = "Atomic(Save|Restore|Close|Block)";
1685 static const char atomic_help
[] = "Save or restore the undo serial number.";
1687 /* %start-doc actions Atomic
1689 This action allows making multiple-action bindings into an atomic
1690 operation that will be undone by a single Undo command. For example,
1691 to optimize rat lines, you'd delete the rats and re-add them. To
1692 group these into a single undo, you'd want the deletions and the
1693 additions to have the same undo serial number. So, you @code{Save},
1694 delete the rats, @code{Restore}, add the rats - using the same serial
1695 number as the deletes, then @code{Block}, which checks to see if the
1696 deletions or additions actually did anything. If not, the serial
1697 number is set to the saved number, as there's nothing to undo. If
1698 something did happen, the serial number is incremented so that these
1699 actions are counted as a single undo step.
1704 Saves the undo serial number.
1707 Returns it to the last saved number.
1710 Sets it to 1 greater than the last save.
1713 Does a Restore if there was nothing to undo, else does a Close.
1720 ActionAtomic (int argc
, char **argv
, int x
, int y
)
1725 switch (GetFunctionID (argv
[0]))
1728 SaveUndoSerialNumber ();
1731 RestoreUndoSerialNumber ();
1734 RestoreUndoSerialNumber ();
1735 IncrementUndoSerialNumber ();
1738 RestoreUndoSerialNumber ();
1740 IncrementUndoSerialNumber ();
1746 /* -------------------------------------------------------------------------- */
1748 static const char drc_syntax
[] = "DRC()";
1750 static const char drc_help
[] = "Invoke the DRC check.";
1752 /* %start-doc actions DRC
1754 Note that the design rule check uses the current board rule settings,
1755 not the current style settings.
1760 ActionDRCheck (int argc
, char **argv
, int x
, int y
)
1764 if (gui
->drc_gui
== NULL
|| gui
->drc_gui
->log_drc_overview
)
1766 Message (_("Rules are minspace %d.%02d, minoverlap %d.%d "
1767 "minwidth %d.%02d, minsilk %d.%02d\n"
1768 "min drill %d.%02d, min annular ring %d.%02d\n"),
1769 (PCB
->Bloat
+ 1) / 100, (PCB
->Bloat
+ 1) % 100,
1770 PCB
->Shrink
/ 100, PCB
->Shrink
% 100,
1771 PCB
->minWid
/ 100, PCB
->minWid
% 100,
1772 PCB
->minSlk
/ 100, PCB
->minSlk
% 100,
1773 PCB
->minDrill
/ 100, PCB
->minDrill
% 100,
1774 PCB
->minRing
/ 100, PCB
->minRing
% 100);
1776 HideCrosshair (True
);
1778 if (gui
->drc_gui
== NULL
|| gui
->drc_gui
->log_drc_overview
)
1781 Message (_("No DRC problems found.\n"));
1783 Message (_("Found %d design rule errors.\n"), count
);
1785 Message (_("Aborted DRC after %d design rule errors.\n"), -count
);
1787 RestoreCrosshair (True
);
1791 /* -------------------------------------------------------------------------- */
1793 static const char dumplibrary_syntax
[] = "DumpLibrary()";
1795 static const char dumplibrary_help
[] =
1796 "Display the entire contents of the libraries.";
1798 /* %start-doc actions DumpLibrary
1804 ActionDumpLibrary (int argc
, char **argv
, int x
, int y
)
1808 printf ("**** Do not count on this format. It will change ****\n\n");
1809 printf ("MenuN = %d\n", Library
.MenuN
);
1810 printf ("MenuMax = %d\n", Library
.MenuMax
);
1811 for (i
= 0; i
< Library
.MenuN
; i
++)
1813 printf ("Library #%d:\n", i
);
1814 printf (" EntryN = %d\n", Library
.Menu
[i
].EntryN
);
1815 printf (" EntryMax = %d\n", Library
.Menu
[i
].EntryMax
);
1816 printf (" Name = \"%s\"\n", UNKNOWN (Library
.Menu
[i
].Name
));
1817 printf (" directory = \"%s\"\n",
1818 UNKNOWN (Library
.Menu
[i
].directory
));
1819 printf (" Style = \"%s\"\n", UNKNOWN (Library
.Menu
[i
].Style
));
1820 printf (" flag = %d\n", Library
.Menu
[i
].flag
);
1822 for (j
= 0; j
< Library
.Menu
[i
].EntryN
; j
++)
1824 printf (" #%4d: ", j
);
1825 if (Library
.Menu
[i
].Entry
[j
].Template
== (char *) -1)
1827 printf ("newlib: \"%s\"\n",
1828 UNKNOWN (Library
.Menu
[i
].Entry
[j
].ListEntry
));
1832 printf ("\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"\n",
1833 UNKNOWN (Library
.Menu
[i
].Entry
[j
].ListEntry
),
1834 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Template
),
1835 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Package
),
1836 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Value
),
1837 UNKNOWN (Library
.Menu
[i
].Entry
[j
].Description
));
1845 /* -------------------------------------------------------------------------- */
1847 static const char flip_syntax
[] = "Flip(Object|Selected|SelectedElements)";
1849 static const char flip_help
[] =
1850 "Flip an element to the opposite side of the board.";
1852 /* %start-doc actions Flip
1854 Note that the location of the element will be symmetric about the
1855 cursor location; i.e. if the part you are pointing at will still be at
1856 the same spot once the element is on the other side. When flipping
1857 multiple elements, this retains their positions relative to each
1858 other, not their absolute positions on the board.
1863 ActionFlip (int argc
, char **argv
, int x
, int y
)
1865 char *function
= ARG (0);
1866 ElementTypePtr element
;
1872 HideCrosshair (True
);
1873 switch (GetFunctionID (function
))
1876 if ((SearchScreen (x
, y
, ELEMENT_TYPE
,
1877 &ptrtmp
, &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
1879 element
= (ElementTypePtr
) ptrtmp
;
1880 ChangeElementSide (element
, 2 * Crosshair
.Y
- PCB
->MaxHeight
);
1881 IncrementUndoSerialNumber ();
1886 case F_SelectedElements
:
1887 ChangeSelectedElementSide ();
1893 RestoreCrosshair (True
);
1901 /* -------------------------------------------------------------------------- */
1903 static const char message_syntax
[] = "Message(message)";
1905 static const char message_help
[] = "Writes a message to the log window.";
1907 /* %start-doc actions Message
1909 This action displays a message to the log window. This action is primarily
1910 provided for use by other programs which may interface with PCB. If
1911 multiple arguments are given, each one is sent to the log window
1912 followed by a newline.
1917 ActionMessage (int argc
, char **argv
, int x
, int y
)
1924 for (i
= 0; i
< argc
; i
++)
1934 /* -------------------------------------------------------------------------- */
1936 static const char setthermal_syntax
[] =
1937 "SetThermal(Object|SelectedPins|SelectedVias|Selected, Style)";
1939 static const char setthermal_help
[] =
1940 "Set the thermal (on the current layer) of pins or vias to the given style.\n"
1941 "Style = 0 means no thermal.\n"
1942 "Style = 1 has diagonal fingers with sharp edges.\n"
1943 "Style = 2 has horizontal and vertical fingers with sharp edges.\n"
1944 "Style = 3 is a solid connection to the plane."
1945 "Style = 4 has diagonal fingers with rounded edges.\n"
1946 "Style = 5 has horizontal and vertical fingers with rounded edges.\n";
1948 /* %start-doc actions SetThermal
1950 This changes how/whether pins or vias connect to any rectangle or polygon
1951 on the current layer. The first argument can specify one object, or all
1952 selected pins, or all selected vias, or all selected pins and vias.
1953 The second argument specifies the style of connection.
1954 There are 5 possibilities:
1956 1 - 45 degree fingers with sharp edges,
1957 2 - horizontal & vertical fingers with sharp edges,
1958 3 - solid connection,
1959 4 - 45 degree fingers with rounded corners,
1960 5 - horizontal & vertical fingers with rounded corners.
1962 Pins and Vias may have thermals whether or not there is a polygon available
1963 to connect with. However, they will have no effect without the polygon.
1967 ActionSetThermal (int argc
, char **argv
, int x
, int y
)
1969 char *function
= ARG (0);
1970 char *style
= ARG (1);
1971 void *ptr1
, *ptr2
, *ptr3
;
1975 if (function
&& *function
&& style
&& *style
)
1979 kind
= GetValue (style
, NULL
, &absolute
);
1980 HideCrosshair (True
);
1982 switch (GetFunctionID (function
))
1986 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGETHERMAL_TYPES
,
1987 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
1989 ChangeObjectThermal (type
, ptr1
, ptr2
, ptr3
, kind
);
1990 IncrementUndoSerialNumber ();
1994 case F_SelectedPins
:
1995 ChangeSelectedThermals (PIN_TYPE
, kind
);
1997 case F_SelectedVias
:
1998 ChangeSelectedThermals (VIA_TYPE
, kind
);
2001 case F_SelectedElements
:
2002 ChangeSelectedThermals (CHANGETHERMAL_TYPES
, kind
);
2010 RestoreCrosshair (True
);
2018 /* ---------------------------------------------------------------------------
2019 * action routine to move the X pointer relative to the current position
2020 * syntax: MovePointer(deltax,deltay)
2023 ActionMovePointer (char *deltax
, char *deltay
)
2025 LocationType x
, y
, dx
, dy
;
2027 /* save old crosshair position */
2030 dx
= (LocationType
) (atoi (deltax
) * PCB
->Grid
);
2031 dy
= (LocationType
) (atoi (deltay
) * PCB
->Grid
);
2032 MoveCrosshairRelative (TO_SCREEN_SIGN_X (dx
), TO_SCREEN_SIGN_Y (dy
));
2033 FitCrosshairIntoGrid (Crosshair
.X
, Crosshair
.Y
);
2034 /* restore crosshair for erasure */
2037 HideCrosshair (False
);
2038 MoveCrosshairRelative (TO_SCREEN_SIGN_X (dx
), TO_SCREEN_SIGN_Y (dy
));
2039 /* update object position and cursor location */
2040 AdjustAttachedObjects ();
2041 RestoreCrosshair (False
);
2044 /* ---------------------------------------------------------------------------
2045 * !!! no action routine !!!
2047 * event handler to set the cursor according to the X pointer position
2048 * called from inside main.c
2051 EventMoveCrosshair (int ev_x
, int ev_y
)
2053 #ifdef HAVE_LIBSTROKE
2056 StrokeBox
.X2
= TO_PCB_X (ev_x
);
2057 StrokeBox
.Y2
= TO_PCB_Y (ev_y
);
2058 stroke_record (Event
->x
, ev_y
);
2061 #endif /* HAVE_LIBSTROKE */
2062 /* ignore events that are caused by ActionMovePointer */
2063 if (!IgnoreMotionEvents
)
2065 if (MoveCrosshairAbsolute (ev_x
, ev_y
))
2068 /* update object position and cursor location */
2069 AdjustAttachedObjects ();
2070 RestoreCrosshair (False
);
2074 IgnoreMotionEvents
= False
;
2077 /* --------------------------------------------------------------------------- */
2079 static const char setvalue_syntax
[] =
2080 "SetValue(Grid|Line|LineSize|Text|TextScale|ViaDrillingHole|Via|ViaSize, delta)";
2082 static const char setvalue_help
[] =
2083 "Change various board-wide values and sizes.";
2085 /* %start-doc actions SetValue
2089 @item ViaDrillingHole
2090 Changes the diameter of the drill for new vias.
2093 Sets the grid spacing.
2097 Changes the thickness of new lines.
2101 Changes the diameter of new vias.
2105 Changes the size of new text.
2112 ActionSetValue (int argc
, char **argv
, int x
, int y
)
2114 char *function
= ARG (0);
2115 char *val
= ARG (1);
2116 char *units
= ARG (2);
2117 Boolean r
; /* flag for 'relative' value */
2121 if (function
&& val
)
2123 HideCrosshair (True
);
2124 value
= GetValue (val
, units
, &r
);
2125 switch (GetFunctionID (function
))
2127 case F_ViaDrillingHole
:
2128 SetViaDrillingHole (r
? value
: value
+ Settings
.ViaDrillingHole
,
2130 hid_action ("RouteStylesChanged");
2136 if ((value
== (int) value
&& PCB
->Grid
== (int) PCB
->Grid
)
2137 || (value
!= (int) value
&& PCB
->Grid
!= (int) PCB
->Grid
)
2141 * On the way down short against the minimum
2144 if ((value
+ PCB
->Grid
) < 1)
2146 else if (PCB
->Grid
== 1)
2147 SetGrid ( value
, False
);
2149 SetGrid (value
+ PCB
->Grid
, False
);
2154 ("Don't combine metric/English grids like that!\n"));
2157 SetGrid (value
, False
);
2162 SetLineSize (r
? value
: value
+ Settings
.LineThickness
);
2163 hid_action ("RouteStylesChanged");
2168 SetViaSize (r
? value
: value
+ Settings
.ViaThickness
, False
);
2169 hid_action ("RouteStylesChanged");
2175 SetTextScale (r
? value
: value
+ Settings
.TextScale
);
2181 RestoreCrosshair (True
);
2190 /* --------------------------------------------------------------------------- */
2192 static const char quit_syntax
[] = "Quit()";
2194 static const char quit_help
[] = "Quits the application after confirming.";
2196 /* %start-doc actions Quit
2198 If you have unsaved changes, you will be prompted to confirm (or
2199 save) before quitting.
2204 ActionQuit (int argc
, char **argv
, int x
, int y
)
2206 char *force
= ARG (0);
2207 if (force
&& strcasecmp (force
, "force") == 0)
2212 if (!PCB
->Changed
|| gui
->close_confirm_dialog () == HID_CLOSE_CONFIRM_OK
)
2217 /* --------------------------------------------------------------------------- */
2219 static const char connection_syntax
[] =
2220 "Connection(Find|ResetLinesAndPolygons|ResetPinsAndVias|Reset)";
2222 static const char connection_help
[] =
2223 "Searches connections of the object at the cursor position.";
2225 /* %start-doc actions Connection
2227 Connections found with this action will be highlighted in the
2228 ``connected-color'' color and will have the ``found'' flag set.
2233 The net under the cursor is ``found''.
2235 @item ResetLinesAndPolygons
2236 Any ``found'' lines and polygons are marked ``not found''.
2238 @item ResetPinsAndVias
2239 Any ``found'' pins and vias are marked ``not found''.
2242 All ``found'' objects are marked ``not found''.
2245 The net under the cursor is found and measured (the lengths of all
2246 line segments are added together)
2253 ActionConnection (int argc
, char **argv
, int x
, int y
)
2255 char *function
= ARG (0);
2258 HideCrosshair (True
);
2259 switch (GetFunctionID (function
))
2263 gui
->get_coords ("Click on a connection", &x
, &y
);
2264 LookupConnection (x
, y
, True
, 1, FOUNDFLAG
);
2268 case F_ResetLinesAndPolygons
:
2269 ResetFoundLinesAndPolygons (True
);
2272 case F_ResetPinsViasAndPads
:
2273 ResetFoundPinsViasAndPads (True
);
2277 SaveUndoSerialNumber ();
2278 ResetFoundPinsViasAndPads (True
);
2279 RestoreUndoSerialNumber ();
2280 ResetFoundLinesAndPolygons (True
);
2283 RestoreCrosshair (True
);
2290 /* --------------------------------------------------------------------------- */
2292 static const char disperseelements_syntax
[] =
2293 "DisperseElements(All|Selected)";
2295 static const char disperseelements_help
[] = "Disperses elements.";
2297 /* %start-doc actions DisperseElements
2299 Normally this is used when starting a board, by selecting all elements
2300 and then dispersing them. This scatters the elements around the board
2301 so that you can pick individual ones, rather than have all the
2302 elements at the same 0,0 coordinate and thus impossible to choose
2310 ActionDisperseElements (int argc
, char **argv
, int x
, int y
)
2312 char *function
= ARG (0);
2313 long minx
, miny
, maxx
, maxy
, dx
, dy
;
2314 int all
= 0, bad
= 0;
2321 if (!function
|| !*function
)
2327 switch (GetFunctionID (function
))
2344 AFAIL (disperseelements
);
2348 ELEMENT_LOOP (PCB
->Data
);
2351 * If we want to disperse selected elements, maybe we need smarter
2352 * code here to avoid putting components on top of others which
2353 * are not selected. For now, I'm assuming that this is typically
2354 * going to be used either with a brand new design or a scratch
2355 * design holding some new components
2357 if (!TEST_FLAG (LOCKFLAG
, element
) && (all
|| TEST_FLAG (SELECTEDFLAG
, element
)))
2360 /* figure out how much to move the element */
2361 dx
= minx
- element
->BoundingBox
.X1
;
2363 /* snap to the grid */
2364 dx
-= (element
->MarkX
+ dx
) % (long) (PCB
->Grid
);
2367 * and add one grid size so we make sure we always space by GAP or
2370 dx
+= (long) (PCB
->Grid
);
2372 /* Figure out if this row has room. If not, start a new row */
2373 if (GAP
+ element
->BoundingBox
.X2
+ dx
> PCB
->MaxWidth
)
2379 /* figure out how much to move the element */
2380 dx
= minx
- element
->BoundingBox
.X1
;
2381 dy
= miny
- element
->BoundingBox
.Y1
;
2383 /* snap to the grid */
2384 dx
-= (element
->MarkX
+ dx
) % (long) (PCB
->Grid
);
2385 dx
+= (long) (PCB
->Grid
);
2386 dy
-= (element
->MarkY
+ dy
) % (long) (PCB
->Grid
);
2387 dy
+= (long) (PCB
->Grid
);
2389 /* move the element */
2390 MoveElementLowLevel (PCB
->Data
, element
, dx
, dy
);
2392 /* and add to the undo list so we can undo this operation */
2393 AddObjectToMoveUndoList (ELEMENT_TYPE
, NULL
, NULL
, element
, dx
, dy
);
2395 /* keep track of how tall this row is */
2396 minx
+= element
->BoundingBox
.X2
- element
->BoundingBox
.X1
+ GAP
;
2397 if (maxy
< element
->BoundingBox
.Y2
)
2399 maxy
= element
->BoundingBox
.Y2
;
2406 /* done with our action so increment the undo # */
2407 IncrementUndoSerialNumber ();
2409 ClearAndRedrawOutput ();
2410 SetChangedFlag (True
);
2417 /* --------------------------------------------------------------------------- */
2419 static const char display_syntax
[] =
2420 "Display(NameOnPCB|Description|Value)\n"
2421 "Display(Grid|Redraw)\n"
2422 "Display(CycleClip|CycleCrosshair|Toggle45Degree|ToggleStartDirection)\n"
2423 "Display(ToggleGrid|ToggleRubberBandMode|ToggleUniqueNames)\n"
2424 "Display(ToggleMask|ToggleName|ToggleClearLine|ToggleFullPoly|ToggleSnapPin)\n"
2425 "Display(ToggleThindraw|ToggleThindrawPoly|ToggleOrthoMove|ToggleLocalRef)\n"
2426 "Display(ToggleCheckPlanes|ToggleShowDRC|ToggleAutoDRC)\n"
2427 "Display(ToggleLiveRoute|LockNames|OnlyNames)\n"
2428 "Display(Pinout|PinOrPadName)\n" "Display(Scroll, Direction)";
2430 static const char display_help
[] = "Several display-related actions.";
2432 /* %start-doc actions Display
2439 Specify whether all elements show their name, description, or value.
2442 Redraw the whole board.
2444 @item Toggle45Degree
2445 When clear, lines can be drawn at any angle. When set, lines are
2446 restricted to multiples of 45 degrees and requested lines may be
2447 broken up according to the clip setting.
2450 Changes the way lines are restricted to 45 degree increments. The
2451 various settings are: straight only, orthogonal then angled, and angled
2452 then orthogonal. If AllDirections is set, this action disables it.
2454 @item CycleCrosshair
2455 Changes crosshair drawing. Crosshair may accept form of 4-ray,
2456 8-ray and 12-ray cross.
2458 @item ToggleRubberBandMode
2459 If set, moving an object moves all the lines attached to it too.
2461 @item ToggleStartDirection
2462 If set, each time you set a point in a line, the Clip toggles between
2463 orth-angle and angle-ortho.
2465 @item ToggleUniqueNames
2466 If set, you will not be permitted to change the name of an element to
2467 match that of another element.
2470 If set, pin centers and pad end points are treated as additional grid
2471 points that the cursor can snap to.
2473 @item ToggleLocalRef
2474 If set, the mark is automatically set to the beginning of any move, so
2475 you can see the relative distance you've moved.
2477 @item ToggleThindraw
2478 If set, objects on the screen are drawn as outlines (lines are drawn
2479 as center-lines). This lets you see line endpoints hidden under pins,
2482 @item ToggleThindrawPoly
2483 If set, polygons on the screen are drawn as outlines.
2486 If set, pending objects (i.e. lines you're in the process of drawing)
2487 will be drawn with an outline showing how far away from other copper
2490 @item ToggleLiveRoute
2491 If set, the progress of the autorouter will be visible on the screen.
2494 If set, you will not be permitted to make connections which violate
2495 the current DRC and netlist settings.
2497 @item ToggleCheckPlanes
2498 If set, lines and arcs aren't drawn, which usually leaves just the
2499 polygons. If you also disable all but the layer you're interested in,
2500 this allows you to check for isolated regions.
2502 @item ToggleOrthoMove
2503 If set, the crosshair is only allowed to move orthogonally from its
2504 previous position. I.e. you can move an element or line up, down,
2505 left, or right, but not up+left or down+right.
2508 Selects whether the pinouts show the pin names or the pin numbers.
2511 Turns the solder mask on or off.
2513 @item ToggleClearLine
2514 When set, the clear-line flag causes new lines and arcs to have their
2515 ``clear polygons'' flag set, so they won't be electrically connected
2516 to any polygons they overlap.
2518 @item ToggleFullPoly
2519 When set, the full-poly flag causes new polygons to have their
2520 ``full polygon'' flag set, so all parts of them will be displayed
2521 instead of only the biggest one.
2524 Resets the origin of the current grid to be wherever the mouse pointer
2525 is (not where the crosshair currently is). If you provide two numbers
2526 after this, the origin is set to that coordinate. The numbers are in
2527 PCB internal units, currently 1/100 mil.
2530 Toggles whether the grid is displayed or not.
2533 Causes the pinout of the element indicated by the cursor to be
2534 displayed, usually in a separate window.
2537 Toggles whether the names of pins, pads, or (yes) vias will be
2538 displayed. If the cursor is over an element, all of its pins and pads
2541 @item Step <direction> <amount> <units>
2542 Steps the crosshair in the given direction, with 1=down/left, 2=down,
2543 etc, according to the numeric keypad layout. If amount is not given,
2544 the crosshair steps along the grid.
2551 ActionDisplay (int argc
, char **argv
, int childX
, int childY
)
2553 char *function
, *str_dir
;
2560 if (function
&& (!str_dir
|| !*str_dir
))
2562 HideCrosshair (True
);
2563 switch (id
= GetFunctionID (function
))
2566 /* redraw layout with clearing the background */
2567 case F_ClearAndRedraw
:
2568 gui
->invalidate_all();
2571 /* redraw layout without clearing the background */
2577 area
.X2
= Output
.Width
;
2578 area
.Y2
= Output
.Height
;
2579 RedrawOutput (&area
);
2583 /* change the displayed name of elements */
2587 ELEMENT_LOOP (PCB
->Data
);
2589 EraseElementName (element
);
2592 CLEAR_FLAG (DESCRIPTIONFLAG
| NAMEONPCBFLAG
, PCB
);
2598 SET_FLAG (NAMEONPCBFLAG
, PCB
);
2601 SET_FLAG (DESCRIPTIONFLAG
, PCB
);
2604 ELEMENT_LOOP (PCB
->Data
);
2606 DrawElementName (element
, 0);
2612 /* toggle line-adjust flag */
2613 case F_ToggleAllDirections
:
2614 TOGGLE_FLAG (ALLDIRECTIONFLAG
, PCB
);
2615 AdjustAttachedObjects ();
2620 (ALLDIRECTIONFLAG
, PCB
)
2622 TOGGLE_FLAG (ALLDIRECTIONFLAG
, PCB
);
2626 PCB
->Clipping
= (PCB
->Clipping
+ 1) % 3;
2627 AdjustAttachedObjects ();
2630 case F_CycleCrosshair
:
2632 if (Crosshair_Shapes_Number
== Crosshair
.shape
)
2633 Crosshair
.shape
= Basic_Crosshair_Shape
;
2636 case F_ToggleRubberBandMode
:
2637 TOGGLE_FLAG (RUBBERBANDFLAG
, PCB
);
2640 case F_ToggleStartDirection
:
2641 TOGGLE_FLAG (SWAPSTARTDIRFLAG
, PCB
);
2644 case F_ToggleUniqueNames
:
2645 TOGGLE_FLAG (UNIQUENAMEFLAG
, PCB
);
2648 case F_ToggleSnapPin
:
2649 TOGGLE_FLAG (SNAPPINFLAG
, PCB
);
2652 case F_ToggleLocalRef
:
2653 TOGGLE_FLAG (LOCALREFFLAG
, PCB
);
2656 case F_ToggleThindraw
:
2657 TOGGLE_FLAG (THINDRAWFLAG
, PCB
);
2658 ClearAndRedrawOutput ();
2661 case F_ToggleThindrawPoly
:
2662 TOGGLE_FLAG (THINDRAWPOLYFLAG
, PCB
);
2663 ClearAndRedrawOutput ();
2666 case F_ToggleLockNames
:
2667 TOGGLE_FLAG (LOCKNAMESFLAG
, PCB
);
2668 CLEAR_FLAG (ONLYNAMESFLAG
, PCB
);
2671 case F_ToggleOnlyNames
:
2672 TOGGLE_FLAG (ONLYNAMESFLAG
, PCB
);
2673 CLEAR_FLAG (LOCKNAMESFLAG
, PCB
);
2676 case F_ToggleHideNames
:
2677 TOGGLE_FLAG (HIDENAMESFLAG
, PCB
);
2678 ClearAndRedrawOutput ();
2681 case F_ToggleShowDRC
:
2682 TOGGLE_FLAG (SHOWDRCFLAG
, PCB
);
2685 case F_ToggleLiveRoute
:
2686 TOGGLE_FLAG (LIVEROUTEFLAG
, PCB
);
2689 case F_ToggleAutoDRC
:
2690 TOGGLE_FLAG (AUTODRCFLAG
, PCB
);
2691 if (TEST_FLAG (AUTODRCFLAG
, PCB
) && Settings
.Mode
== LINE_MODE
)
2693 SaveUndoSerialNumber ();
2694 ResetFoundPinsViasAndPads (True
);
2695 RestoreUndoSerialNumber ();
2696 ResetFoundLinesAndPolygons (True
);
2697 if (Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
2698 LookupConnection (Crosshair
.AttachedLine
.Point1
.X
,
2699 Crosshair
.AttachedLine
.Point1
.Y
, True
, 1,
2704 case F_ToggleCheckPlanes
:
2705 TOGGLE_FLAG (CHECKPLANESFLAG
, PCB
);
2706 ClearAndRedrawOutput ();
2709 case F_ToggleOrthoMove
:
2710 TOGGLE_FLAG (ORTHOMOVEFLAG
, PCB
);
2714 TOGGLE_FLAG (SHOWNUMBERFLAG
, PCB
);
2719 TOGGLE_FLAG (SHOWMASKFLAG
, PCB
);
2723 case F_ToggleClearLine
:
2724 TOGGLE_FLAG (CLEARNEWFLAG
, PCB
);
2727 case F_ToggleFullPoly
:
2728 TOGGLE_FLAG (NEWFULLPOLYFLAG
, PCB
);
2731 /* shift grid alignment */
2736 oldGrid
= PCB
->Grid
;
2738 if (MoveCrosshairAbsolute (childX
, childY
))
2739 RestoreCrosshair (False
); /* was hidden by MoveCrosshairAbs */
2740 SetGrid (oldGrid
, True
);
2744 /* toggle displaying of the grid */
2746 Settings
.DrawGrid
= !Settings
.DrawGrid
;
2750 /* display the pinout of an element */
2753 ElementTypePtr element
;
2757 gui
->get_coords ("Click on an element", &x
, &y
);
2759 (x
, y
, ELEMENT_TYPE
, &ptrtmp
,
2760 &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
2762 element
= (ElementTypePtr
) ptrtmp
;
2763 gui
->show_item (element
);
2768 /* toggle displaying of pin/pad/via names */
2769 case F_PinOrPadName
:
2771 void *ptr1
, *ptr2
, *ptr3
;
2773 switch (SearchScreen (Crosshair
.X
, Crosshair
.Y
,
2774 ELEMENT_TYPE
| PIN_TYPE
| PAD_TYPE
|
2775 VIA_TYPE
, (void **) &ptr1
, (void **) &ptr2
,
2779 PIN_LOOP ((ElementTypePtr
) ptr1
);
2781 if (TEST_FLAG (DISPLAYNAMEFLAG
, pin
))
2784 DrawPinName (pin
, 0);
2785 AddObjectToFlagUndoList (PIN_TYPE
, ptr1
, pin
, pin
);
2786 TOGGLE_FLAG (DISPLAYNAMEFLAG
, pin
);
2789 PAD_LOOP ((ElementTypePtr
) ptr1
);
2791 if (TEST_FLAG (DISPLAYNAMEFLAG
, pad
))
2794 DrawPadName (pad
, 0);
2795 AddObjectToFlagUndoList (PAD_TYPE
, ptr1
, pad
, pad
);
2796 TOGGLE_FLAG (DISPLAYNAMEFLAG
, pad
);
2799 SetChangedFlag (True
);
2800 IncrementUndoSerialNumber ();
2805 if (TEST_FLAG (DISPLAYNAMEFLAG
, (PinTypePtr
) ptr2
))
2806 ErasePinName ((PinTypePtr
) ptr2
);
2808 DrawPinName ((PinTypePtr
) ptr2
, 0);
2809 AddObjectToFlagUndoList (PIN_TYPE
, ptr1
, ptr2
, ptr3
);
2810 TOGGLE_FLAG (DISPLAYNAMEFLAG
, (PinTypePtr
) ptr2
);
2811 SetChangedFlag (True
);
2812 IncrementUndoSerialNumber ();
2817 if (TEST_FLAG (DISPLAYNAMEFLAG
, (PadTypePtr
) ptr2
))
2818 ErasePadName ((PadTypePtr
) ptr2
);
2820 DrawPadName ((PadTypePtr
) ptr2
, 0);
2821 AddObjectToFlagUndoList (PAD_TYPE
, ptr1
, ptr2
, ptr3
);
2822 TOGGLE_FLAG (DISPLAYNAMEFLAG
, (PadTypePtr
) ptr2
);
2823 SetChangedFlag (True
);
2824 IncrementUndoSerialNumber ();
2828 if (TEST_FLAG (DISPLAYNAMEFLAG
, (PinTypePtr
) ptr2
))
2829 EraseViaName ((PinTypePtr
) ptr2
);
2831 DrawViaName ((PinTypePtr
) ptr2
, 0);
2832 AddObjectToFlagUndoList (VIA_TYPE
, ptr1
, ptr2
, ptr3
);
2833 TOGGLE_FLAG (DISPLAYNAMEFLAG
, (PinTypePtr
) ptr2
);
2834 SetChangedFlag (True
);
2835 IncrementUndoSerialNumber ();
2844 RestoreCrosshair (True
);
2846 else if (function
&& str_dir
)
2848 switch (GetFunctionID (function
))
2854 PCB
->GridOffsetX
= atoi (argv
[1]);
2855 PCB
->GridOffsetY
= atoi (argv
[2]);
2856 if (Settings
.DrawGrid
)
2873 /* --------------------------------------------------------------------------- */
2875 static const char mode_syntax
[] =
2876 "Mode(Arc|Arrow|Copy|InsertPoint|Line|Lock|Move|None|PasteBuffer)\n"
2877 "Mode(Polygon|Rectangle|Remove|Rotate|Text|Thermal|Via)\n"
2878 "Mode(Notify|Release|Cancel|Stroke)\n" "Mode(Save|Restore)";
2880 static const char mode_help
[] = "Change or use the tool mode.";
2882 /* %start-doc actions Mode
2902 Select the indicated tool.
2905 Called when you press the mouse button, or move the mouse.
2908 Called when you release the mouse button.
2911 Cancels any pending tool activity, allowing you to restart elsewhere.
2912 For example, this allows you to start a new line rather than attach a
2913 line to the previous line.
2916 Similar to Cancel but calling this action a second time will return
2920 If your @code{pcb} was built with libstroke, this invokes the stroke
2921 input method. If not, this will restart a drawing mode if you were
2922 drawing, else it will select objects.
2925 Remembers the current tool.
2928 Restores the tool to the last saved tool.
2935 ActionMode (int argc
, char **argv
, int x
, int y
)
2937 char *function
= ARG (0);
2941 Note
.X
= Crosshair
.X
;
2942 Note
.Y
= Crosshair
.Y
;
2943 HideCrosshair (True
);
2944 switch (GetFunctionID (function
))
2950 SetMode (ARROW_MODE
);
2953 SetMode (COPY_MODE
);
2956 SetMode (INSERTPOINT_MODE
);
2959 SetMode (LINE_MODE
);
2962 SetMode (LOCK_MODE
);
2965 SetMode (MOVE_MODE
);
2972 int saved_mode
= Settings
.Mode
;
2974 SetMode (saved_mode
);
2979 switch (Settings
.Mode
)
2982 case PASTEBUFFER_MODE
:
2988 case INSERTPOINT_MODE
:
2989 case RUBBERBANDMOVE_MODE
:
2993 SetMode (ARROW_MODE
);
2997 if (Crosshair
.AttachedLine
.State
== STATE_FIRST
)
2998 SetMode (ARROW_MODE
);
3002 SetMode (LINE_MODE
);
3006 case RECTANGLE_MODE
:
3007 if (Crosshair
.AttachedBox
.State
== STATE_FIRST
)
3008 SetMode (ARROW_MODE
);
3012 SetMode (RECTANGLE_MODE
);
3017 if (Crosshair
.AttachedLine
.State
== STATE_FIRST
)
3018 SetMode (ARROW_MODE
);
3022 SetMode (POLYGON_MODE
);
3027 if (Crosshair
.AttachedBox
.State
== STATE_FIRST
)
3028 SetMode (ARROW_MODE
);
3049 SetMode (PASTEBUFFER_MODE
);
3052 SetMode (POLYGON_MODE
);
3054 #ifndef HAVE_LIBSTROKE
3067 SetMode (REMOVE_MODE
);
3070 SetMode (RECTANGLE_MODE
);
3073 SetMode (ROTATE_MODE
);
3076 #ifdef HAVE_LIBSTROKE
3078 StrokeBox
.X1
= Crosshair
.X
;
3079 StrokeBox
.Y1
= Crosshair
.Y
;
3082 /* Handle middle mouse button restarts of drawing mode. If not in
3083 | a drawing mode, middle mouse button will select objects.
3085 if (Settings
.Mode
== LINE_MODE
3086 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
3088 SetMode (LINE_MODE
);
3090 else if (Settings
.Mode
== ARC_MODE
3091 && Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
3093 else if (Settings
.Mode
== RECTANGLE_MODE
3094 && Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
3095 SetMode (RECTANGLE_MODE
);
3096 else if (Settings
.Mode
== POLYGON_MODE
3097 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
3098 SetMode (POLYGON_MODE
);
3103 SetMode (ARROW_MODE
);
3109 SetMode (TEXT_MODE
);
3112 SetMode (THERMAL_MODE
);
3118 case F_Restore
: /* restore the last saved mode */
3122 case F_Save
: /* save currently selected mode */
3126 RestoreCrosshair (True
);
3133 /* --------------------------------------------------------------------------- */
3135 static const char removeselected_syntax
[] = "RemoveSelected()";
3137 static const char removeselected_help
[] = "Removes any selected objects.";
3139 /* %start-doc actions RemoveSelected
3144 ActionRemoveSelected (int argc
, char **argv
, int x
, int y
)
3146 HideCrosshair (True
);
3147 if (RemoveSelected ())
3148 SetChangedFlag (True
);
3149 RestoreCrosshair (True
);
3153 /* --------------------------------------------------------------------------- */
3155 static const char renumber_syntax
[] = "Renumber()\n" "Renumber(filename)";
3157 static const char renumber_help
[] =
3158 "Renumber all elements. The changes will be recorded to filename\n"
3159 "for use in backannotating these changes to the schematic.";
3161 /* %start-doc actions Renumber
3166 ActionRenumber (int argc
, char **argv
, int x
, int y
)
3168 Boolean changed
= False
;
3169 ElementTypePtr
*element_list
;
3170 ElementTypePtr
*locked_element_list
;
3171 unsigned int i
, j
, k
, cnt
, lock_cnt
;
3177 static char * default_file
= NULL
;
3178 size_t cnt_list_sz
= 100;
3184 char **was
, **is
, *pin
;
3185 unsigned int c_cnt
= 0;
3192 * We deal with the case where name already exists in this
3193 * function so the GUI doesn't need to deal with it
3195 name
= gui
->fileselect (_("Save Renumber Annotation File As ..."),
3196 _("Choose a file to record the renumbering to.\n"
3197 "This file may be used to back annotate the\n"
3198 "change to the schematics.\n"),
3199 default_file
, ".eco", "eco",
3209 free (default_file
);
3210 default_file
= NULL
;
3215 default_file
= strdup (name
);
3218 if ((out
= fopen (name
, "r")))
3221 if (!gui
->confirm_dialog (_("File exists! Ok to overwrite?"), 0))
3223 if (free_name
&& name
)
3229 if ((out
= fopen (name
, "w")) == NULL
)
3231 Message ("Could not open %s\n", name
);
3232 if (free_name
&& name
)
3237 if (free_name
&& name
)
3240 fprintf (out
, "*COMMENT* PCB Annotation File\n");
3241 fprintf (out
, "*FILEVERSION* 20061031\n");
3244 * Make a first pass through all of the elements and sort them out
3245 * by location on the board. While here we also collect a list of
3248 * We'll actually renumber things in the 2nd pass.
3250 element_list
= calloc (PCB
->Data
->ElementN
, sizeof (ElementTypePtr
));
3251 locked_element_list
= calloc (PCB
->Data
->ElementN
, sizeof (ElementTypePtr
));
3252 was
= calloc (PCB
->Data
->ElementN
, sizeof (char *));
3253 is
= calloc (PCB
->Data
->ElementN
, sizeof (char *));
3254 if (element_list
== NULL
|| locked_element_list
== NULL
|| was
== NULL
3257 fprintf (stderr
, "calloc() failed in %s\n", __FUNCTION__
);
3264 ELEMENT_LOOP (PCB
->Data
);
3266 if (TEST_FLAG (LOCKFLAG
, element
->Name
) || TEST_FLAG (LOCKFLAG
, element
))
3269 * add to the list of locked elements which we won't try to
3270 * renumber and whose reference designators are now reserved.
3273 "*WARN* Element \"%s\" at (%d,%d) is locked and will not be renumbered.\n",
3274 UNKNOWN (NAMEONPCB_NAME (element
)), element
->MarkX
,
3276 locked_element_list
[lock_cnt
] = element
;
3282 /* count of devices which will be renumbered */
3285 /* search for correct position in the list */
3287 while (element_list
[i
] && element
->MarkY
> element_list
[i
]->MarkY
)
3291 * We have found the position where we have the first element that
3292 * has the same Y value or a lower Y value. Now move forward if
3293 * needed through the X values
3295 while (element_list
[i
]
3296 && element
->MarkY
== element_list
[i
]->MarkY
3297 && element
->MarkX
> element_list
[i
]->MarkX
)
3300 for (j
= cnt
- 1; j
> i
; j
--)
3302 element_list
[j
] = element_list
[j
- 1];
3304 element_list
[i
] = element
;
3311 * Now that the elements are sorted by board position, we go through
3312 * and renumber them.
3316 * turn off the flag which requires unique names so it doesn't get
3317 * in our way. When we're done with the renumber we will have unique
3320 unique
= TEST_FLAG (UNIQUENAMEFLAG
, PCB
);
3321 CLEAR_FLAG (UNIQUENAMEFLAG
, PCB
);
3323 cnt_list
= calloc (cnt_list_sz
, sizeof (struct _cnt_list
));
3324 for (i
= 0; i
< cnt
; i
++)
3326 /* If there is no refdes, maybe just spit out a warning */
3327 if (NAMEONPCB_NAME (element_list
[i
]))
3329 /* figure out the prefix */
3330 tmps
= strdup (NAMEONPCB_NAME (element_list
[i
]));
3332 while (tmps
[j
] && (tmps
[j
] < '0' || tmps
[j
] > '9')
3337 /* check the counter for this prefix */
3339 cnt_list
[j
].name
&& (strcmp (cnt_list
[j
].name
, tmps
) != 0)
3340 && j
< cnt_list_sz
; j
++);
3342 /* grow the list if needed */
3343 if (j
== cnt_list_sz
)
3346 cnt_list
= realloc (cnt_list
, cnt_list_sz
);
3347 if (cnt_list
== NULL
)
3349 fprintf (stderr
, "realloc failed() in %s\n", __FUNCTION__
);
3352 /* zero out the memory that we added */
3353 for (tmpi
= j
; tmpi
< cnt_list_sz
; tmpi
++)
3355 cnt_list
[tmpi
].name
= NULL
;
3356 cnt_list
[tmpi
].cnt
= 0;
3361 * start a new counter if we don't have a counter for this
3364 if (!cnt_list
[j
].name
)
3366 cnt_list
[j
].name
= strdup (tmps
);
3367 cnt_list
[j
].cnt
= 0;
3371 * check to see if the new refdes is already used by a
3380 /* space for the prefix plus 1 digit plus the '\0' */
3381 sz
= strlen (cnt_list
[j
].name
) + 2;
3383 /* and 1 more per extra digit needed to hold the number */
3384 tmpi
= cnt_list
[j
].cnt
;
3390 tmps
= malloc (sz
* sizeof (char));
3391 sprintf (tmps
, "%s%d", cnt_list
[j
].name
, cnt_list
[j
].cnt
);
3394 * now compare to the list of reserved (by locked
3397 for (k
= 0; k
< lock_cnt
; k
++)
3400 (UNKNOWN (NAMEONPCB_NAME (locked_element_list
[k
])),
3411 if (strcmp (tmps
, NAMEONPCB_NAME (element_list
[i
])) != 0)
3413 fprintf (out
, "*RENAME* \"%s\" \"%s\"\n",
3414 NAMEONPCB_NAME (element_list
[i
]), tmps
);
3416 /* add this rename to our table of renames so we can update the netlist */
3417 was
[c_cnt
] = strdup (NAMEONPCB_NAME (element_list
[i
]));
3418 is
[c_cnt
] = strdup (tmps
);
3421 AddObjectToChangeNameUndoList (ELEMENT_TYPE
, NULL
, NULL
,
3423 NAMEONPCB_NAME (element_list
3426 ChangeObjectName (ELEMENT_TYPE
, element_list
[i
], NULL
, NULL
,
3430 /* we don't free tmps in this case because it is used */
3437 fprintf (out
, "*WARN* Element at (%d,%d) has no name.\n",
3438 element_list
[i
]->MarkX
, element_list
[i
]->MarkY
);
3445 /* restore the unique flag setting */
3447 SET_FLAG (UNIQUENAMEFLAG
, PCB
);
3452 /* update the netlist */
3453 AddNetlistLibToUndoList (&(PCB
->NetlistLib
));
3455 /* iterate over each net */
3456 for (i
= 0; i
< PCB
->NetlistLib
.MenuN
; i
++)
3459 /* iterate over each pin on the net */
3460 for (j
= 0; j
< PCB
->NetlistLib
.Menu
[i
].EntryN
; j
++)
3463 /* figure out the pin number part from strings like U3-21 */
3464 tmps
= strdup (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
);
3465 for (k
= 0; tmps
[k
] && tmps
[k
] != '-'; k
++);
3469 /* iterate over the list of changed reference designators */
3470 for (k
= 0; k
< c_cnt
; k
++)
3473 * if the pin needs to change, change it and quit
3474 * searching in the list.
3476 if (strcmp (tmps
, was
[k
]) == 0)
3478 free (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
);
3479 PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
=
3480 malloc ((strlen (is
[k
]) + strlen (pin
) +
3481 2) * sizeof (char));
3482 sprintf (PCB
->NetlistLib
.Menu
[i
].Entry
[j
].ListEntry
,
3483 "%s-%s", is
[k
], pin
);
3491 for (k
= 0; k
< c_cnt
; k
++)
3498 IncrementUndoSerialNumber ();
3499 SetChangedFlag (True
);
3502 free (locked_element_list
);
3503 free (element_list
);
3509 /* --------------------------------------------------------------------------- */
3511 static const char ripup_syntax
[] = "RipUp(All|Selected|Element)";
3513 static const char ripup_help
[] =
3514 "Ripup auto-routed tracks, or convert an element to parts.";
3516 /* %start-doc actions RipUp
3521 Removes all lines and vias which were created by the autorouter.
3524 Removes all selected lines and vias which were created by the
3528 Converts the element under the cursor to parts (vias and lines). Note
3529 that this uses the highest numbered paste buffer.
3536 ActionRipUp (int argc
, char **argv
, int x
, int y
)
3538 char *function
= ARG (0);
3539 Boolean changed
= False
;
3543 HideCrosshair (True
);
3544 switch (GetFunctionID (function
))
3547 ALLLINE_LOOP (PCB
->Data
);
3549 if (TEST_FLAG (AUTOFLAG
, line
) && !TEST_FLAG (LOCKFLAG
, line
))
3551 RemoveObject (LINE_TYPE
, layer
, line
, line
);
3556 VIA_LOOP (PCB
->Data
);
3558 if (TEST_FLAG (AUTOFLAG
, via
) && !TEST_FLAG (LOCKFLAG
, via
))
3560 RemoveObject (VIA_TYPE
, via
, via
, via
);
3568 IncrementUndoSerialNumber ();
3569 SetChangedFlag (True
);
3573 VISIBLELINE_LOOP (PCB
->Data
);
3575 if (TEST_FLAGS (AUTOFLAG
| SELECTEDFLAG
, line
)
3576 && !TEST_FLAG (LOCKFLAG
, line
))
3578 RemoveObject (LINE_TYPE
, layer
, line
, line
);
3584 VIA_LOOP (PCB
->Data
);
3586 if (TEST_FLAGS (AUTOFLAG
| SELECTEDFLAG
, via
)
3587 && !TEST_FLAG (LOCKFLAG
, via
))
3589 RemoveObject (VIA_TYPE
, via
, via
, via
);
3596 IncrementUndoSerialNumber ();
3597 SetChangedFlag (True
);
3602 void *ptr1
, *ptr2
, *ptr3
;
3604 if (SearchScreen (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
,
3605 &ptr1
, &ptr2
, &ptr3
) != NO_TYPE
)
3607 Note
.Buffer
= Settings
.BufferNumber
;
3608 SetBufferNumber (MAX_BUFFER
- 1);
3609 ClearBuffer (PASTEBUFFER
);
3610 CopyObjectToBuffer (PASTEBUFFER
->Data
, PCB
->Data
,
3611 ELEMENT_TYPE
, ptr1
, ptr2
, ptr3
);
3612 SmashBufferElement (PASTEBUFFER
);
3615 SaveUndoSerialNumber ();
3616 EraseObject (ELEMENT_TYPE
, ptr1
, ptr1
);
3617 MoveObjectToRemoveUndoList (ELEMENT_TYPE
, ptr1
, ptr2
, ptr3
);
3618 RestoreUndoSerialNumber ();
3619 CopyPastebufferToLayout (0, 0);
3620 SetBufferNumber (Note
.Buffer
);
3621 SetChangedFlag (True
);
3626 RestoreCrosshair (True
);
3631 /* --------------------------------------------------------------------------- */
3633 static const char addrats_syntax
[] = "AddRats(AllRats|SelectedRats|Close)";
3635 static const char addrats_help
[] = "Add one or more rat lines to the board.";
3637 /* %start-doc actions AddRats
3642 Create rat lines for all loaded nets that aren't already connected on
3646 Similarly, but only add rat lines for nets connected to selected pins
3650 Selects the shortest unselected rat on the board.
3657 ActionAddRats (int argc
, char **argv
, int x
, int y
)
3659 char *function
= ARG (0);
3665 if (Settings
.RatWarn
)
3667 HideCrosshair (True
);
3668 switch (GetFunctionID (function
))
3671 if (AddAllRats (False
, NULL
))
3672 SetChangedFlag (True
);
3674 case F_SelectedRats
:
3676 if (AddAllRats (True
, NULL
))
3677 SetChangedFlag (True
);
3680 small
= SQUARE (MAX_COORD
);
3682 RAT_LOOP (PCB
->Data
);
3684 if (TEST_FLAG (SELECTEDFLAG
, line
))
3686 len
= SQUARE (line
->Point1
.X
- line
->Point2
.X
) +
3687 SQUARE (line
->Point1
.Y
- line
->Point2
.Y
);
3697 AddObjectToFlagUndoList (RATLINE_TYPE
, shorty
, shorty
, shorty
);
3698 SET_FLAG (SELECTEDFLAG
, shorty
);
3699 DrawRat (shorty
, 0);
3701 CenterDisplay ((shorty
->Point2
.X
+ shorty
->Point1
.X
) / 2,
3702 (shorty
->Point2
.Y
+ shorty
->Point1
.Y
) / 2,
3707 RestoreCrosshair (True
);
3712 /* --------------------------------------------------------------------------- */
3714 static const char delete_syntax
[] =
3715 "Delete(Object|Selected)\n"
3716 "Delete(AllRats|SelectedRats)"
3719 static const char delete_help
[] = "Delete stuff.";
3721 /* %start-doc actions Delete
3726 ActionDelete (int argc
, char **argv
, int x
, int y
)
3728 char *function
= ARG (0);
3729 int id
= GetFunctionID (function
);
3731 Note
.X
= Crosshair
.X
;
3732 Note
.Y
= Crosshair
.Y
;
3734 if (id
== -1) /* no arg */
3736 if (RemoveSelected() == False
)
3740 HideCrosshair (True
);
3745 SetMode(REMOVE_MODE
);
3753 if (DeleteRats (False
))
3754 SetChangedFlag (True
);
3756 case F_SelectedRats
:
3757 if (DeleteRats (True
))
3758 SetChangedFlag (True
);
3762 RestoreCrosshair (True
);
3766 /* --------------------------------------------------------------------------- */
3768 static const char deleterats_syntax
[] =
3769 "DeleteRats(AllRats|Selected|SelectedRats)";
3771 static const char deleterats_help
[] = "Delete rat lines.";
3773 /* %start-doc actions DeleteRats
3778 ActionDeleteRats (int argc
, char **argv
, int x
, int y
)
3780 char *function
= ARG (0);
3783 if (Settings
.RatWarn
)
3785 HideCrosshair (True
);
3786 switch (GetFunctionID (function
))
3789 if (DeleteRats (False
))
3790 SetChangedFlag (True
);
3792 case F_SelectedRats
:
3794 if (DeleteRats (True
))
3795 SetChangedFlag (True
);
3798 RestoreCrosshair (True
);
3803 /* --------------------------------------------------------------------------- */
3805 static const char autoplace_syntax
[] = "AutoPlaceSelected()";
3807 static const char autoplace_help
[] = "Auto-place selected components.";
3809 /* %start-doc actions AutoPlaceSelected
3811 Attempts to re-arrange the selected components such that the nets
3812 connecting them are minimized. Note that you cannot undo this.
3817 ActionAutoPlaceSelected (int argc
, char **argv
, int x
, int y
)
3820 if (gui
->confirm_dialog (_("Auto-placement can NOT be undone.\n"
3821 "Do you want to continue anyway?\n"), 0))
3823 HideCrosshair (True
);
3824 if (AutoPlaceSelected ())
3825 SetChangedFlag (True
);
3826 RestoreCrosshair (True
);
3831 /* --------------------------------------------------------------------------- */
3833 static const char autoroute_syntax
[] = "AutoRoute(AllRats|SelectedRats)";
3835 static const char autoroute_help
[] = "Auto-route some or all rat lines.";
3837 /* %start-doc actions AutoRoute
3842 Attempt to autoroute all rats.
3845 Attempt to autoroute the selected rats.
3849 Before autorouting, it's important to set up a few things. First,
3850 make sure any layers you aren't using are disabled, else the
3851 autorouter may use them. Next, make sure the current line and via
3852 styles are set accordingly. Last, make sure "new lines clear
3853 polygons" is set, in case you eventually want to add a copper pour.
3855 Autorouting takes a while. During this time, the program may not be
3861 ActionAutoRoute (int argc
, char **argv
, int x
, int y
)
3863 char *function
= ARG (0);
3865 if (function
) /* one parameter */
3867 HideCrosshair (True
);
3868 switch (GetFunctionID (function
))
3871 if (AutoRoute (False
))
3872 SetChangedFlag (True
);
3874 case F_SelectedRats
:
3876 if (AutoRoute (True
))
3877 SetChangedFlag (True
);
3880 RestoreCrosshair (True
);
3885 /* --------------------------------------------------------------------------- */
3887 static const char markcrosshair_syntax
[] =
3888 "MarkCrosshair()\n" "MarkCrosshair(Center)";
3890 static const char markcrosshair_help
[] = "Set/Reset the Crosshair mark";
3892 /* %start-doc actions MarkCrosshair
3894 The ``mark'' is a small X-shaped target on the display which is
3895 treated like a second origin (the normal origin is the upper let
3896 corner of the board). The GUI will display a second set of
3897 coordinates for this mark, which tells you how far you are from it.
3899 If no argument is given, the mark is toggled - disabled if it was
3900 enabled, or enabled at the current cursor position of disabled. If
3901 the @code{Center} argument is given, the mark is moved to the current
3907 ActionMarkCrosshair (int argc
, char **argv
, int x
, int y
)
3909 char *function
= ARG (0);
3910 if (!function
|| !*function
)
3915 Marked
.status
= False
;
3919 Marked
.status
= True
;
3920 Marked
.X
= Crosshair
.X
;
3921 Marked
.Y
= Crosshair
.Y
;
3925 else if (GetFunctionID (function
) == F_Center
)
3928 Marked
.status
= True
;
3929 Marked
.X
= Crosshair
.X
;
3930 Marked
.Y
= Crosshair
.Y
;
3936 /* --------------------------------------------------------------------------- */
3938 static const char changesize_syntax
[] =
3939 "ChangeSize(Object, delta)\n"
3940 "ChangeSize(SelectedObjects|Selected, delta)\n"
3941 "ChangeSize(SelectedLines|SelectedPins|SelectedVias, delta)\n"
3942 "ChangeSize(SelectedPads|SelectedTexts|SelectedNames, delta)\n"
3943 "ChangeSize(SelectedElements, delta)";
3945 static const char changesize_help
[] = "Changes the size of objects.";
3947 /* %start-doc actions ChangeSize
3949 For lines and arcs, this changes the width. For pins and vias, this
3950 changes the overall diameter of the copper annulus. For pads, this
3951 changes the width and, indirectly, the length. For texts and names,
3952 this changes the scaling factor. For elements, this changes the width
3953 of the silk layer lines and arcs for this element.
3958 ActionChangeSize (int argc
, char **argv
, int x
, int y
)
3960 char *function
= ARG (0);
3961 char *delta
= ARG (1);
3962 char *units
= ARG (2);
3963 Boolean r
; /* indicates if absolute size is given */
3966 if (function
&& delta
)
3968 value
= GetValue (delta
, units
, &r
);
3969 HideCrosshair (True
);
3970 switch (GetFunctionID (function
))
3975 void *ptr1
, *ptr2
, *ptr3
;
3978 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGESIZE_TYPES
,
3979 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
3980 if (TEST_FLAG (LOCKFLAG
, (PinTypePtr
) ptr2
))
3981 Message (_("Sorry, the object is locked\n"));
3982 if (ChangeObjectSize (type
, ptr1
, ptr2
, ptr3
, value
, r
))
3983 SetChangedFlag (True
);
3987 case F_SelectedVias
:
3988 if (ChangeSelectedSize (VIA_TYPE
, value
, r
))
3989 SetChangedFlag (True
);
3992 case F_SelectedPins
:
3993 if (ChangeSelectedSize (PIN_TYPE
, value
, r
))
3994 SetChangedFlag (True
);
3997 case F_SelectedPads
:
3998 if (ChangeSelectedSize (PAD_TYPE
, value
, r
))
3999 SetChangedFlag (True
);
4002 case F_SelectedArcs
:
4003 if (ChangeSelectedSize (ARC_TYPE
, value
, r
))
4004 SetChangedFlag (True
);
4007 case F_SelectedLines
:
4008 if (ChangeSelectedSize (LINE_TYPE
, value
, r
))
4009 SetChangedFlag (True
);
4012 case F_SelectedTexts
:
4013 if (ChangeSelectedSize (TEXT_TYPE
, value
, r
))
4014 SetChangedFlag (True
);
4017 case F_SelectedNames
:
4018 if (ChangeSelectedSize (ELEMENTNAME_TYPE
, value
, r
))
4019 SetChangedFlag (True
);
4022 case F_SelectedElements
:
4023 if (ChangeSelectedSize (ELEMENT_TYPE
, value
, r
))
4024 SetChangedFlag (True
);
4028 case F_SelectedObjects
:
4029 if (ChangeSelectedSize (CHANGESIZE_TYPES
, value
, r
))
4030 SetChangedFlag (True
);
4033 RestoreCrosshair (True
);
4038 /* --------------------------------------------------------------------------- */
4040 static const char changedrillsize_syntax
[] =
4041 "ChangeDrillSize(Object, delta)\n"
4042 "ChangeDrillSize(SelectedPins|SelectedVias|Selected|SelectedObjects, delta)";
4044 static const char changedrillsize_help
[] =
4045 "Changes the drilling hole size of objects.";
4047 /* %start-doc actions ChangeDrillSize
4052 ActionChange2ndSize (int argc
, char **argv
, int x
, int y
)
4054 char *function
= ARG (0);
4055 char *delta
= ARG (1);
4056 char *units
= ARG (2);
4060 if (function
&& delta
)
4062 value
= GetValue (delta
, units
, &r
);
4063 HideCrosshair (True
);
4064 switch (GetFunctionID (function
))
4069 void *ptr1
, *ptr2
, *ptr3
;
4071 gui
->get_coords ("Select an Object", &x
, &y
);
4073 SearchScreen (x
, y
, CHANGE2NDSIZE_TYPES
,
4074 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4075 if (ChangeObject2ndSize
4076 (type
, ptr1
, ptr2
, ptr3
, value
, r
, True
))
4077 SetChangedFlag (True
);
4081 case F_SelectedVias
:
4082 if (ChangeSelected2ndSize (VIA_TYPE
, value
, r
))
4083 SetChangedFlag (True
);
4086 case F_SelectedPins
:
4087 if (ChangeSelected2ndSize (PIN_TYPE
, value
, r
))
4088 SetChangedFlag (True
);
4091 case F_SelectedObjects
:
4092 if (ChangeSelected2ndSize (PIN_TYPES
, value
, r
))
4093 SetChangedFlag (True
);
4096 RestoreCrosshair (True
);
4101 /* --------------------------------------------------------------------------- */
4103 static const char changeclearsize_syntax
[] =
4104 "ChangeClearSize(Object, delta)\n"
4105 "ChangeClearSize(SelectedPins|SelectedPads|SelectedVias, delta)\n"
4106 "ChangeClearSize(SelectedLines|SelectedArcs, delta\n"
4107 "ChangeClearSize(Selected|SelectedObjects, delta)";
4109 static const char changeclearsize_help
[] =
4110 "Changes the clearance size of objects.";
4112 /* %start-doc actions ChangeClearSize
4114 If the solder mask is currently showing, this action changes the
4115 solder mask clearance. If the mask is not showing, this action
4116 changes the polygon clearance.
4121 ActionChangeClearSize (int argc
, char **argv
, int x
, int y
)
4123 char *function
= ARG (0);
4124 char *delta
= ARG (1);
4125 char *units
= ARG (2);
4129 if (function
&& delta
)
4131 value
= 2 * GetValue (delta
, units
, &r
);
4132 HideCrosshair (True
);
4133 switch (GetFunctionID (function
))
4138 void *ptr1
, *ptr2
, *ptr3
;
4140 gui
->get_coords ("Select an Object", &x
, &y
);
4143 CHANGECLEARSIZE_TYPES
, &ptr1
, &ptr2
,
4145 if (ChangeObjectClearSize (type
, ptr1
, ptr2
, ptr3
, value
, r
))
4146 SetChangedFlag (True
);
4149 case F_SelectedVias
:
4150 if (ChangeSelectedClearSize (VIA_TYPE
, value
, r
))
4151 SetChangedFlag (True
);
4153 case F_SelectedPads
:
4154 if (ChangeSelectedClearSize (PAD_TYPE
, value
, r
))
4155 SetChangedFlag (True
);
4157 case F_SelectedPins
:
4158 if (ChangeSelectedClearSize (PIN_TYPE
, value
, r
))
4159 SetChangedFlag (True
);
4161 case F_SelectedLines
:
4162 if (ChangeSelectedClearSize (LINE_TYPE
, value
, r
))
4163 SetChangedFlag (True
);
4165 case F_SelectedArcs
:
4166 if (ChangeSelectedClearSize (ARC_TYPE
, value
, r
))
4167 SetChangedFlag (True
);
4170 case F_SelectedObjects
:
4171 if (ChangeSelectedClearSize (CHANGECLEARSIZE_TYPES
, value
, r
))
4172 SetChangedFlag (True
);
4175 RestoreCrosshair (True
);
4180 /* --------------------------------------------------------------------------- */
4182 static const char minmaskgap_syntax
[] =
4183 "MinMaskGap(delta)\n" "MinMaskGap(Selected, delta)";
4185 static const char minmaskgap_help
[] =
4186 "Ensures the mask is a minimum distance from pins and pads.";
4188 /* %start-doc actions MinMaskGap
4190 Checks all specified pins and/or pads, and increases the mask if
4191 needed to ensure a minimum distance between the pin or pad edge and
4197 ActionMinMaskGap (int argc
, char **argv
, int x
, int y
)
4199 char *function
= ARG (0);
4200 char *delta
= ARG (1);
4201 char *units
= ARG (2);
4208 if (strcasecmp (function
, "Selected") == 0)
4209 flags
= SELECTEDFLAG
;
4216 value
= 2 * GetValue (delta
, units
, &r
);
4218 HideCrosshair (True
);
4219 SaveUndoSerialNumber ();
4220 ELEMENT_LOOP (PCB
->Data
);
4224 if (!TEST_FLAGS (flags
, pin
))
4226 if (pin
->Mask
< pin
->Thickness
+ value
)
4228 ChangeObjectMaskSize (PIN_TYPE
, element
, pin
, 0,
4229 pin
->Thickness
+ value
, 1);
4230 RestoreUndoSerialNumber ();
4236 if (!TEST_FLAGS (flags
, pad
))
4238 if (pad
->Mask
< pad
->Thickness
+ value
)
4240 ChangeObjectMaskSize (PAD_TYPE
, element
, pad
, 0,
4241 pad
->Thickness
+ value
, 1);
4242 RestoreUndoSerialNumber ();
4248 VIA_LOOP (PCB
->Data
);
4250 if (!TEST_FLAGS (flags
, via
))
4252 if (via
->Mask
&& via
->Mask
< via
->Thickness
+ value
)
4254 ChangeObjectMaskSize (VIA_TYPE
, via
, 0, 0, via
->Thickness
+ value
, 1);
4255 RestoreUndoSerialNumber ();
4259 RestoreUndoSerialNumber ();
4260 IncrementUndoSerialNumber ();
4264 /* --------------------------------------------------------------------------- */
4266 static const char mincleargap_syntax
[] =
4267 "MinClearGap(delta)\n" "MinClearGap(Selected, delta)";
4269 static const char mincleargap_help
[] =
4270 "Ensures that polygons are a minimum distance from objects.";
4272 /* %start-doc actions MinClearGap
4274 Checks all specified objects, and increases the polygon clearance if
4275 needed to ensure a minimum distance between their edges and the
4281 ActionMinClearGap (int argc
, char **argv
, int x
, int y
)
4283 char *function
= ARG (0);
4284 char *delta
= ARG (1);
4285 char *units
= ARG (2);
4292 if (strcasecmp (function
, "Selected") == 0)
4293 flags
= SELECTEDFLAG
;
4300 value
= 2 * GetValue (delta
, units
, &r
);
4302 HideCrosshair (True
);
4303 SaveUndoSerialNumber ();
4304 ELEMENT_LOOP (PCB
->Data
);
4308 if (!TEST_FLAGS (flags
, pin
))
4310 if (pin
->Clearance
< value
)
4312 ChangeObjectClearSize (PIN_TYPE
, element
, pin
, 0,
4314 RestoreUndoSerialNumber ();
4320 if (!TEST_FLAGS (flags
, pad
))
4322 if (pad
->Clearance
< value
)
4324 ChangeObjectClearSize (PAD_TYPE
, element
, pad
, 0,
4326 RestoreUndoSerialNumber ();
4332 VIA_LOOP (PCB
->Data
);
4334 if (!TEST_FLAGS (flags
, via
))
4336 if (via
->Clearance
< value
)
4338 ChangeObjectClearSize (VIA_TYPE
, via
, 0, 0, value
, 1);
4339 RestoreUndoSerialNumber ();
4343 ALLLINE_LOOP (PCB
->Data
);
4345 if (!TEST_FLAGS (flags
, line
))
4347 if (line
->Clearance
< value
)
4349 ChangeObjectClearSize (LINE_TYPE
, layer
, line
, 0, value
, 1);
4350 RestoreUndoSerialNumber ();
4354 ALLARC_LOOP (PCB
->Data
);
4356 if (!TEST_FLAGS (flags
, arc
))
4358 if (arc
->Clearance
< value
)
4360 ChangeObjectClearSize (ARC_TYPE
, layer
, arc
, 0, value
, 1);
4361 RestoreUndoSerialNumber ();
4365 RestoreUndoSerialNumber ();
4366 IncrementUndoSerialNumber ();
4370 /* --------------------------------------------------------------------------- */
4372 static const char changepinname_syntax
[] =
4373 "ChangePinName(ElementName,PinNumber,PinName)";
4375 static const char changepinname_help
[] =
4376 "Sets the name of a specific pin on a specific element.";
4378 /* %start-doc actions ChangePinName
4380 This can be especially useful for annotating pin names from a
4381 schematic to the layout without requiring knowledge of the pcb file
4385 ChangePinName(U3, 7, VCC)
4391 ActionChangePinName (int argc
, char **argv
, int x
, int y
)
4394 char *refdes
, *pinnum
, *pinname
;
4398 AFAIL (changepinname
);
4405 ELEMENT_LOOP (PCB
->Data
);
4407 if (NSTRCMP (refdes
, NAMEONPCB_NAME (element
)) == 0)
4411 if (NSTRCMP (pinnum
, pin
->Number
) == 0)
4413 AddObjectToChangeNameUndoList (PIN_TYPE
, NULL
, NULL
,
4416 * Note: we can't free() pin->Name first because
4417 * it is used in the undo list
4419 pin
->Name
= strdup (pinname
);
4420 SetChangedFlag (True
);
4428 if (NSTRCMP (pinnum
, pad
->Number
) == 0)
4430 AddObjectToChangeNameUndoList (PAD_TYPE
, NULL
, NULL
,
4433 * Note: we can't free() pad->Name first because
4434 * it is used in the undo list
4436 pad
->Name
= strdup (pinname
);
4437 SetChangedFlag (True
);
4446 * done with our action so increment the undo # if we actually
4452 defer_needs_update
= 1;
4455 IncrementUndoSerialNumber ();
4456 gui
->invalidate_all ();
4463 /* --------------------------------------------------------------------------- */
4465 static const char changename_syntax
[] =
4466 "ChangeName(Object)\n" "ChangeName(Layout|Layer)";
4468 static const char changename_help
[] = "Sets the name of objects.";
4470 /* %start-doc actions ChangeName
4475 Changes the name of the element under the cursor.
4478 Changes the name of the layout. This is printed on the fab drawings.
4481 Changes the name of the currently active layer.
4488 ActionChangeName (int argc
, char **argv
, int x
, int y
)
4490 char *function
= ARG (0);
4495 HideCrosshair (True
);
4496 switch (GetFunctionID (function
))
4498 /* change the name of an object */
4502 void *ptr1
, *ptr2
, *ptr3
;
4504 gui
->get_coords ("Select an Object", &x
, &y
);
4506 SearchScreen (x
, y
, CHANGENAME_TYPES
,
4507 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4509 SaveUndoSerialNumber ();
4510 if (QueryInputAndChangeObjectName (type
, ptr1
, ptr2
, ptr3
))
4512 SetChangedFlag (True
);
4513 if (type
== ELEMENT_TYPE
)
4515 RubberbandTypePtr ptr
;
4518 RestoreUndoSerialNumber ();
4519 Crosshair
.AttachedObject
.RubberbandN
= 0;
4520 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
4521 ptr
= Crosshair
.AttachedObject
.Rubberband
;
4522 for (i
= 0; i
< Crosshair
.AttachedObject
.RubberbandN
;
4526 EraseRat ((RatTypePtr
) ptr
->Line
);
4527 MoveObjectToRemoveUndoList (RATLINE_TYPE
,
4528 ptr
->Line
, ptr
->Line
,
4531 IncrementUndoSerialNumber ();
4539 /* change the layout's name */
4542 gui
->prompt_for (_("Enter the layout name:"), EMPTY (PCB
->Name
));
4543 if (name
&& ChangeLayoutName (name
)) /* XXX memory leak */
4544 SetChangedFlag (True
);
4547 /* change the name of the active layer */
4549 name
= gui
->prompt_for (_("Enter the layer name:"),
4550 EMPTY (CURRENT
->Name
));
4551 if (name
&& ChangeLayerName (CURRENT
, name
)) /* XXX memory leak */
4552 SetChangedFlag (True
);
4555 RestoreCrosshair (True
);
4561 /* --------------------------------------------------------------------------- */
4563 static const char morphpolygon_syntax
[] = "MorphPolygon(Object|Selected)";
4565 static const char morphpolygon_help
[] =
4566 "Converts dead polygon islands into separate polygons.";
4568 /* %start-doc actions MorphPolygon
4570 If a polygon is divided into unconnected "islands", you can use
4571 this command to convert the otherwise disappeared islands into
4572 separate polygons. Be sure the cursor is over a portion of the
4573 polygon that remains visible. Very small islands that may flake
4574 off are automatically deleted.
4579 ActionMorphPolygon (int argc
, char **argv
, int x
, int y
)
4581 char *function
= ARG (0);
4584 HideCrosshair (True
);
4585 switch (GetFunctionID (function
))
4590 void *ptr1
, *ptr2
, *ptr3
;
4592 gui
->get_coords ("Select an Object", &x
, &y
);
4593 if ((type
= SearchScreen (x
, y
, POLYGON_TYPE
,
4594 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4596 MorphPolygon ((LayerType
*) ptr1
, (PolygonType
*) ptr3
);
4598 IncrementUndoSerialNumber ();
4603 case F_SelectedObjects
:
4604 ALLPOLYGON_LOOP (PCB
->Data
);
4606 if (TEST_FLAG (SELECTEDFLAG
, polygon
))
4607 MorphPolygon (layer
, polygon
);
4611 IncrementUndoSerialNumber ();
4618 /* --------------------------------------------------------------------------- */
4620 static const char togglehidename_syntax
[] =
4621 "ToggleHideName(Object|SelectedElements)";
4623 static const char togglehidename_help
[] =
4624 "Toggles the visibility of element names.";
4626 /* %start-doc actions ToggleHideName
4628 If names are hidden you won't see them on the screen and they will not
4629 appear on the silk layer when you print the layout.
4634 ActionToggleHideName (int argc
, char **argv
, int x
, int y
)
4636 char *function
= ARG (0);
4637 if (function
&& PCB
->ElementOn
)
4639 HideCrosshair (True
);
4640 switch (GetFunctionID (function
))
4645 void *ptr1
, *ptr2
, *ptr3
;
4647 gui
->get_coords ("Select an Object", &x
, &y
);
4648 if ((type
= SearchScreen (x
, y
, ELEMENT_TYPE
,
4649 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4651 AddObjectToFlagUndoList (type
, ptr1
, ptr2
, ptr3
);
4652 EraseElementName ((ElementTypePtr
) ptr2
);
4653 TOGGLE_FLAG (HIDENAMEFLAG
, (ElementTypePtr
) ptr2
);
4654 DrawElementName ((ElementTypePtr
) ptr2
, 0);
4656 IncrementUndoSerialNumber ();
4660 case F_SelectedElements
:
4663 Boolean changed
= False
;
4664 ELEMENT_LOOP (PCB
->Data
);
4666 if ((TEST_FLAG (SELECTEDFLAG
, element
) ||
4667 TEST_FLAG (SELECTEDFLAG
,
4668 &NAMEONPCB_TEXT (element
)))
4669 && (FRONT (element
) || PCB
->InvisibleObjectsOn
))
4671 AddObjectToFlagUndoList (ELEMENT_TYPE
, element
,
4673 EraseElementName (element
);
4674 TOGGLE_FLAG (HIDENAMEFLAG
, element
);
4675 DrawElementName (element
, 0);
4683 IncrementUndoSerialNumber ();
4687 RestoreCrosshair (True
);
4692 /* --------------------------------------------------------------------------- */
4694 static const char changejoin_syntax
[] =
4695 "ChangeJoin(ToggleObject|SelectedLines|SelectedArcs|Selected)";
4697 static const char changejoin_help
[] =
4698 "Changes the join (clearance through polygons) of objects.";
4700 /* %start-doc actions ChangeJoin
4702 The join flag determines whether a line or arc, drawn to intersect a
4703 polygon, electrically connects to the polygon or not. When joined,
4704 the line/arc is simply drawn over the polygon, making an electrical
4705 connection. When not joined, a gap is drawn between the line and the
4706 polygon, insulating them from each other.
4711 ActionChangeJoin (int argc
, char **argv
, int x
, int y
)
4713 char *function
= ARG (0);
4716 HideCrosshair (True
);
4717 switch (GetFunctionID (function
))
4719 case F_ToggleObject
:
4723 void *ptr1
, *ptr2
, *ptr3
;
4725 gui
->get_coords ("Select an Object", &x
, &y
);
4727 SearchScreen (x
, y
, CHANGEJOIN_TYPES
,
4728 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4729 if (ChangeObjectJoin (type
, ptr1
, ptr2
, ptr3
))
4730 SetChangedFlag (True
);
4734 case F_SelectedLines
:
4735 if (ChangeSelectedJoin (LINE_TYPE
))
4736 SetChangedFlag (True
);
4739 case F_SelectedArcs
:
4740 if (ChangeSelectedJoin (ARC_TYPE
))
4741 SetChangedFlag (True
);
4745 case F_SelectedObjects
:
4746 if (ChangeSelectedJoin (CHANGEJOIN_TYPES
))
4747 SetChangedFlag (True
);
4750 RestoreCrosshair (True
);
4755 /* --------------------------------------------------------------------------- */
4757 static const char changesquare_syntax
[] =
4758 "ChangeSquare(ToggleObject)\n"
4759 "ChangeSquare(SelectedElements|SelectedPins)\n"
4760 "ChangeSquare(Selected|SelectedObjects)";
4762 static const char changesquare_help
[] =
4763 "Changes the square flag of pins and pads.";
4765 /* %start-doc actions ChangeSquare
4767 Note that @code{Pins} means both pins and pads.
4774 ActionChangeSquare (int argc
, char **argv
, int x
, int y
)
4776 char *function
= ARG (0);
4779 HideCrosshair (True
);
4780 switch (GetFunctionID (function
))
4782 case F_ToggleObject
:
4786 void *ptr1
, *ptr2
, *ptr3
;
4788 gui
->get_coords ("Select an Object", &x
, &y
);
4790 SearchScreen (x
, y
, CHANGESQUARE_TYPES
,
4791 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4792 if (ChangeObjectSquare (type
, ptr1
, ptr2
, ptr3
))
4793 SetChangedFlag (True
);
4797 case F_SelectedElements
:
4798 if (ChangeSelectedSquare (ELEMENT_TYPE
))
4799 SetChangedFlag (True
);
4802 case F_SelectedPins
:
4803 if (ChangeSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4804 SetChangedFlag (True
);
4808 case F_SelectedObjects
:
4809 if (ChangeSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4810 SetChangedFlag (True
);
4813 RestoreCrosshair (True
);
4818 /* --------------------------------------------------------------------------- */
4820 static const char setsquare_syntax
[] =
4821 "SetSquare(ToggleObject|SelectedElements|SelectedPins)";
4823 static const char setsquare_help
[] = "sets the square-flag of objects.";
4825 /* %start-doc actions SetSquare
4827 Note that @code{Pins} means pins and pads.
4834 ActionSetSquare (int argc
, char **argv
, int x
, int y
)
4836 char *function
= ARG (0);
4837 if (function
&& *function
)
4839 /* HideCrosshair (True); */
4840 switch (GetFunctionID (function
))
4842 case F_ToggleObject
:
4846 void *ptr1
, *ptr2
, *ptr3
;
4848 gui
->get_coords ("Select an object", &x
, &y
);
4850 SearchScreen (x
, y
, CHANGESQUARE_TYPES
,
4851 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4852 if (SetObjectSquare (type
, ptr1
, ptr2
, ptr3
))
4853 SetChangedFlag (True
);
4857 case F_SelectedElements
:
4858 if (SetSelectedSquare (ELEMENT_TYPE
))
4859 SetChangedFlag (True
);
4862 case F_SelectedPins
:
4863 if (SetSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4864 SetChangedFlag (True
);
4868 case F_SelectedObjects
:
4869 if (SetSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4870 SetChangedFlag (True
);
4873 /* RestoreCrosshair (True); */
4878 /* --------------------------------------------------------------------------- */
4880 static const char clearsquare_syntax
[] =
4881 "ClearSquare(ToggleObject|SelectedElements|SelectedPins)";
4883 static const char clearsquare_help
[] =
4884 "Clears the square-flag of pins and pads.";
4886 /* %start-doc actions ClearSquare
4888 Note that @code{Pins} means pins and pads.
4895 ActionClearSquare (int argc
, char **argv
, int x
, int y
)
4897 char *function
= ARG (0);
4898 if (function
&& *function
)
4900 /* HideCrosshair (True); */
4901 switch (GetFunctionID (function
))
4903 case F_ToggleObject
:
4907 void *ptr1
, *ptr2
, *ptr3
;
4909 gui
->get_coords ("Select an Object", &x
, &y
);
4911 SearchScreen (x
, y
, CHANGESQUARE_TYPES
,
4912 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4913 if (ClrObjectSquare (type
, ptr1
, ptr2
, ptr3
))
4914 SetChangedFlag (True
);
4918 case F_SelectedElements
:
4919 if (ClrSelectedSquare (ELEMENT_TYPE
))
4920 SetChangedFlag (True
);
4923 case F_SelectedPins
:
4924 if (ClrSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4925 SetChangedFlag (True
);
4929 case F_SelectedObjects
:
4930 if (ClrSelectedSquare (PIN_TYPE
| PAD_TYPE
))
4931 SetChangedFlag (True
);
4934 /* RestoreCrosshair (True); */
4939 /* --------------------------------------------------------------------------- */
4941 static const char changeoctagon_syntax
[] =
4942 "ChangeOctagon(Object|ToggleObject|SelectedObjects|Selected)\n"
4943 "ChangeOctagon(SelectedElements|SelectedPins|SelectedVias)";
4945 static const char changeoctagon_help
[] =
4946 "Changes the octagon-flag of pins and vias.";
4948 /* %start-doc actions ChangeOctagon
4955 ActionChangeOctagon (int argc
, char **argv
, int x
, int y
)
4957 char *function
= ARG (0);
4960 /* HideCrosshair (True); */
4961 switch (GetFunctionID (function
))
4963 case F_ToggleObject
:
4967 void *ptr1
, *ptr2
, *ptr3
;
4969 gui
->get_coords ("Select an Object", &x
, &y
);
4971 SearchScreen (x
, y
, CHANGEOCTAGON_TYPES
,
4972 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
4973 if (ChangeObjectOctagon (type
, ptr1
, ptr2
, ptr3
))
4974 SetChangedFlag (True
);
4978 case F_SelectedElements
:
4979 if (ChangeSelectedOctagon (ELEMENT_TYPE
))
4980 SetChangedFlag (True
);
4983 case F_SelectedPins
:
4984 if (ChangeSelectedOctagon (PIN_TYPE
))
4985 SetChangedFlag (True
);
4988 case F_SelectedVias
:
4989 if (ChangeSelectedOctagon (VIA_TYPE
))
4990 SetChangedFlag (True
);
4994 case F_SelectedObjects
:
4995 if (ChangeSelectedOctagon (PIN_TYPES
))
4996 SetChangedFlag (True
);
4999 /* RestoreCrosshair (True); */
5004 /* --------------------------------------------------------------------------- */
5006 static const char setoctagon_syntax
[] =
5007 "SetOctagon(Object|ToggleObject|SelectedElements|Selected)";
5009 static const char setoctagon_help
[] = "Sets the octagon-flag of objects.";
5011 /* %start-doc actions SetOctagon
5018 ActionSetOctagon (int argc
, char **argv
, int x
, int y
)
5020 char *function
= ARG (0);
5023 /* HideCrosshair (True); */
5024 switch (GetFunctionID (function
))
5026 case F_ToggleObject
:
5030 void *ptr1
, *ptr2
, *ptr3
;
5032 gui
->get_coords ("Select an object", &x
, &y
);
5034 SearchScreen (x
, y
, CHANGEOCTAGON_TYPES
,
5035 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
5036 if (SetObjectOctagon (type
, ptr1
, ptr2
, ptr3
))
5037 SetChangedFlag (True
);
5041 case F_SelectedElements
:
5042 if (SetSelectedOctagon (ELEMENT_TYPE
))
5043 SetChangedFlag (True
);
5046 case F_SelectedPins
:
5047 if (SetSelectedOctagon (PIN_TYPE
))
5048 SetChangedFlag (True
);
5051 case F_SelectedVias
:
5052 if (SetSelectedOctagon (VIA_TYPE
))
5053 SetChangedFlag (True
);
5057 case F_SelectedObjects
:
5058 if (SetSelectedOctagon (PIN_TYPES
))
5059 SetChangedFlag (True
);
5062 /* RestoreCrosshair (True); */
5067 /* --------------------------------------------------------------------------- */
5069 static const char clearoctagon_syntax
[] =
5070 "ClearOctagon(ToggleObject|Object|SelectedObjects|Selected)\n"
5071 "ClearOctagon(SelectedElements|SelectedPins|SelectedVias)";
5073 static const char clearoctagon_help
[] =
5074 "Clears the octagon-flag of pins and vias.";
5076 /* %start-doc actions ClearOctagon
5083 ActionClearOctagon (int argc
, char **argv
, int x
, int y
)
5085 char *function
= ARG (0);
5088 /* HideCrosshair (True); */
5089 switch (GetFunctionID (function
))
5091 case F_ToggleObject
:
5095 void *ptr1
, *ptr2
, *ptr3
;
5097 gui
->get_coords ("Select an Object", &x
, &y
);
5099 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGEOCTAGON_TYPES
,
5100 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
5101 if (ClrObjectOctagon (type
, ptr1
, ptr2
, ptr3
))
5102 SetChangedFlag (True
);
5106 case F_SelectedElements
:
5107 if (ClrSelectedOctagon (ELEMENT_TYPE
))
5108 SetChangedFlag (True
);
5111 case F_SelectedPins
:
5112 if (ClrSelectedOctagon (PIN_TYPE
))
5113 SetChangedFlag (True
);
5116 case F_SelectedVias
:
5117 if (ClrSelectedOctagon (VIA_TYPE
))
5118 SetChangedFlag (True
);
5122 case F_SelectedObjects
:
5123 if (ClrSelectedOctagon (PIN_TYPES
))
5124 SetChangedFlag (True
);
5127 /* RestoreCrosshair (True); */
5132 /* --------------------------------------------------------------------------- */
5134 static const char changehold_syntax
[] =
5135 "ChangeHole(ToggleObject|Object|SelectedVias|Selected)";
5137 static const char changehold_help
[] = "Changes the hole flag of objects.";
5139 /* %start-doc actions ChangeHole
5141 The "hole flag" of a via determines whether the via is a
5142 plated-through hole (not set), or an unplated hole (set).
5147 ActionChangeHole (int argc
, char **argv
, int x
, int y
)
5149 char *function
= ARG (0);
5152 /* HideCrosshair (True); */
5153 switch (GetFunctionID (function
))
5155 case F_ToggleObject
:
5159 void *ptr1
, *ptr2
, *ptr3
;
5161 gui
->get_coords ("Select an Object", &x
, &y
);
5162 if ((type
= SearchScreen (x
, y
, VIA_TYPE
,
5163 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
5164 && ChangeHole ((PinTypePtr
) ptr3
))
5165 IncrementUndoSerialNumber ();
5169 case F_SelectedVias
:
5171 if (ChangeSelectedHole ())
5172 SetChangedFlag (True
);
5175 /* RestoreCrosshair (True); */
5180 /* --------------------------------------------------------------------------- */
5182 static const char changepaste_syntax
[] =
5183 "ChangePaste(ToggleObject|Object|SelectedPads|Selected)";
5185 static const char changepaste_help
[] = "Changes the no paste flag of objects.";
5187 /* %start-doc actions ChangePaste
5189 The "no paste flag" of a pad determines whether the solderpaste
5190 stencil will have an opening for the pad (no set) or if there wil be
5191 no solderpaste on the pad (set). This is used for things such as
5197 ActionChangePaste (int argc
, char **argv
, int x
, int y
)
5199 char *function
= ARG (0);
5202 /* HideCrosshair (True); */
5203 switch (GetFunctionID (function
))
5205 case F_ToggleObject
:
5209 void *ptr1
, *ptr2
, *ptr3
;
5211 gui
->get_coords ("Select an Object", &x
, &y
);
5212 if ((type
= SearchScreen (x
, y
, PAD_TYPE
,
5213 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
5214 && ChangePaste ((PadTypePtr
) ptr3
))
5215 IncrementUndoSerialNumber ();
5219 case F_SelectedPads
:
5221 if (ChangeSelectedPaste ())
5222 SetChangedFlag (True
);
5225 /* RestoreCrosshair (True); */
5230 /* --------------------------------------------------------------------------- */
5232 static const char select_syntax
[] =
5233 "Select(ToggleObject)\n"
5234 "Select(All|Block|Connection)\n"
5235 "Select(ElementByName|ObjectByName|PadByName|PinByName)\n"
5236 "Select(ElementByName|ObjectByName|PadByName|PinByName, Name)\n"
5237 "Select(TextByName|ViaByName)\n"
5238 "Select(TextByName|ViaByName, Name)\n" "Select(Convert)";
5240 static const char select_help
[] = "Toggles or sets the selection";
5242 /* %start-doc actions Select
5253 These all rely on having a regular expression parser built into
5254 @code{pcb}. If the name is not specified then the user is prompted
5255 for a pattern, and all objects that match the pattern and are of the
5256 type specified are selected.
5260 Selects the object under the cursor.
5263 Selects all objects in a rectangle indicated by the cursor.
5266 Selects all objects on the board.
5269 Selects all connections with the ``found'' flag set.
5272 Converts the selected objects to an element. This uses the highest
5273 numbered paste buffer.
5280 ActionSelect (int argc
, char **argv
, int x
, int y
)
5282 char *function
= ARG (0);
5286 HideCrosshair (True
);
5287 switch (GetFunctionID (function
))
5289 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
5291 /* select objects by their names */
5292 case F_ElementByName
:
5293 type
= ELEMENT_TYPE
;
5295 case F_ObjectByName
:
5313 char *pattern
= ARG (1);
5317 gui
->prompt_for (_("Enter pattern:"), "")) != NULL
)
5319 if (SelectObjectByName (type
, pattern
, True
))
5320 SetChangedFlag (True
);
5326 #endif /* defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) */
5328 /* select a single object */
5329 case F_ToggleObject
:
5331 if (SelectObject ())
5332 SetChangedFlag (True
);
5335 /* all objects in block */
5340 box
.X1
= MIN (Crosshair
.AttachedBox
.Point1
.X
,
5341 Crosshair
.AttachedBox
.Point2
.X
);
5342 box
.Y1
= MIN (Crosshair
.AttachedBox
.Point1
.Y
,
5343 Crosshair
.AttachedBox
.Point2
.Y
);
5344 box
.X2
= MAX (Crosshair
.AttachedBox
.Point1
.X
,
5345 Crosshair
.AttachedBox
.Point2
.X
);
5346 box
.Y2
= MAX (Crosshair
.AttachedBox
.Point1
.Y
,
5347 Crosshair
.AttachedBox
.Point2
.Y
);
5349 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
&&
5350 SelectBlock (&box
, True
))
5352 SetChangedFlag (True
);
5353 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
5358 /* select all visible objects */
5363 box
.X1
= -MAX_COORD
;
5364 box
.Y1
= -MAX_COORD
;
5367 if (SelectBlock (&box
, True
))
5368 SetChangedFlag (True
);
5372 /* all found connections */
5374 if (SelectConnection (True
))
5376 IncrementUndoSerialNumber ();
5377 SetChangedFlag (True
);
5384 Note
.Buffer
= Settings
.BufferNumber
;
5385 SetBufferNumber (MAX_BUFFER
- 1);
5386 ClearBuffer (PASTEBUFFER
);
5387 gui
->get_coords ("Select the Element's Mark Location", &x
, &y
);
5388 x
= GRIDFIT_X (x
, PCB
->Grid
);
5389 y
= GRIDFIT_Y (y
, PCB
->Grid
);
5390 AddSelectedToBuffer (PASTEBUFFER
, x
, y
, True
);
5391 SaveUndoSerialNumber ();
5393 ConvertBufferToElement (PASTEBUFFER
);
5394 RestoreUndoSerialNumber ();
5395 CopyPastebufferToLayout (x
, y
);
5396 SetBufferNumber (Note
.Buffer
);
5401 RestoreCrosshair (True
);
5405 RestoreCrosshair (True
);
5410 /* FLAG(have_regex,FlagHaveRegex,0) */
5412 FlagHaveRegex (int parm
)
5414 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
5421 /* --------------------------------------------------------------------------- */
5423 static const char unselect_syntax
[] =
5424 "Unselect(All|Block|Connection)\n"
5425 "Unselect(ElementByName|ObjectByName|PadByName|PinByName)\n"
5426 "Unselect(ElementByName|ObjectByName|PadByName|PinByName, Name)\n"
5427 "Unselect(TextByName|ViaByName)\n" "Unselect(TextByName|ViaByName, Name)\n";
5429 static const char unselect_help
[] =
5430 "unselects the object at the pointer location or the specified objects";
5432 /* %start-doc actions Unselect
5437 Unselect all objects.
5440 Unselect all objects in a rectangle given by the cursor.
5443 Unselect all connections with the ``found'' flag set.
5452 These all rely on having a regular expression parser built into
5453 @code{pcb}. If the name is not specified then the user is prompted
5454 for a pattern, and all objects that match the pattern and are of the
5455 type specified are unselected.
5463 ActionUnselect (int argc
, char **argv
, int x
, int y
)
5465 char *function
= ARG (0);
5469 HideCrosshair (True
);
5470 switch (GetFunctionID (function
))
5472 #if defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP)
5474 /* select objects by their names */
5475 case F_ElementByName
:
5476 type
= ELEMENT_TYPE
;
5478 case F_ObjectByName
:
5496 char *pattern
= ARG (1);
5500 gui
->prompt_for (_("Enter pattern:"), "")) != NULL
)
5502 if (SelectObjectByName (type
, pattern
, False
))
5503 SetChangedFlag (True
);
5509 #endif /* defined(HAVE_REGCOMP) || defined(HAVE_RE_COMP) */
5511 /* all objects in block */
5516 box
.X1
= MIN (Crosshair
.AttachedBox
.Point1
.X
,
5517 Crosshair
.AttachedBox
.Point2
.X
);
5518 box
.Y1
= MIN (Crosshair
.AttachedBox
.Point1
.Y
,
5519 Crosshair
.AttachedBox
.Point2
.Y
);
5520 box
.X2
= MAX (Crosshair
.AttachedBox
.Point1
.X
,
5521 Crosshair
.AttachedBox
.Point2
.X
);
5522 box
.Y2
= MAX (Crosshair
.AttachedBox
.Point1
.Y
,
5523 Crosshair
.AttachedBox
.Point2
.Y
);
5525 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
&&
5526 SelectBlock (&box
, False
))
5528 SetChangedFlag (True
);
5529 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
5534 /* unselect all visible objects */
5539 box
.X1
= -MAX_COORD
;
5540 box
.Y1
= -MAX_COORD
;
5543 if (SelectBlock (&box
, False
))
5544 SetChangedFlag (True
);
5548 /* all found connections */
5550 if (SelectConnection (False
))
5552 IncrementUndoSerialNumber ();
5553 SetChangedFlag (True
);
5558 RestoreCrosshair (True
);
5563 RestoreCrosshair (True
);
5568 /* --------------------------------------------------------------------------- */
5570 static const char saveto_syntax
[] =
5571 "SaveTo(Layout|LayoutAs,filename)\n"
5572 "SaveTo(AllConnections|AllUnusedPins|ElementConnections,filename)\n"
5573 "SaveTo(PasteBuffer,filename)";
5575 static const char saveto_help
[] = "Saves data to a file.";
5577 /* %start-doc actions SaveTo
5582 Saves the current layout.
5585 Saves the current layout, and remembers the filename used.
5587 @item AllConnections
5588 Save all connections to a file.
5591 List all unused pins to a file.
5593 @item ElementConnections
5594 Save connections to the element at the cursor to a file.
5597 Save the content of the active Buffer to a file. This is the graphical way to create a footprint.
5604 ActionSaveTo (int argc
, char **argv
, int x
, int y
)
5612 if (strcasecmp (function
, "Layout") == 0)
5614 SavePCB (PCB
->Filename
);
5621 if (strcasecmp (function
, "LayoutAs") == 0)
5623 MYFREE (PCB
->Filename
);
5624 PCB
->Filename
= MyStrdup (name
, __FUNCTION__
);
5625 SavePCB (PCB
->Filename
);
5629 if (strcasecmp (function
, "AllConnections") == 0)
5633 if ((fp
= CheckAndOpenFile (name
, True
, False
, &result
, NULL
)) != NULL
)
5635 LookupConnectionsToAllElements (fp
);
5637 SetChangedFlag (True
);
5642 if (strcasecmp (function
, "AllUnusedPins") == 0)
5646 if ((fp
= CheckAndOpenFile (name
, True
, False
, &result
, NULL
)) != NULL
)
5648 LookupUnusedPins (fp
);
5650 SetChangedFlag (True
);
5655 if (strcasecmp (function
, "ElementConnections") == 0)
5657 ElementTypePtr element
;
5662 if ((SearchScreen (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
,
5663 &ptrtmp
, &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
5665 element
= (ElementTypePtr
) ptrtmp
;
5667 CheckAndOpenFile (name
, True
, False
, &result
, NULL
)) != NULL
)
5669 LookupElementConnections (element
, fp
);
5671 SetChangedFlag (True
);
5677 if (strcasecmp (function
, "PasteBuffer") == 0)
5679 return SaveBufferElements (name
);
5685 /* --------------------------------------------------------------------------- */
5687 static const char savesettings_syntax
[] =
5688 "SaveSettings()\n" "SaveSettings(local)";
5690 static const char savesettings_help
[] = "Saves settings.";
5692 /* %start-doc actions SaveSettings
5694 If you pass no arguments, the settings are stored in
5695 @code{$HOME/.pcb/settings}. If you pass the word @code{local} they're
5696 saved in @code{./pcb.settings}.
5701 ActionSaveSettings (int argc
, char **argv
, int x
, int y
)
5703 int locally
= argc
> 0 ? (strncasecmp (argv
[0], "local", 5) == 0) : 0;
5704 hid_save_settings (locally
);
5708 /* --------------------------------------------------------------------------- */
5710 static const char loadfrom_syntax
[] =
5711 "LoadFrom(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert,filename)";
5713 static const char loadfrom_help
[] = "Load layout data from a file.";
5715 /* %start-doc actions LoadFrom
5717 This action assumes you know what the filename is. The various GUIs
5718 should have a similar @code{Load} action where the filename is
5719 optional, and will provide their own file selection mechanism to let
5720 you choose the file name.
5725 Loads an entire PCB layout, replacing the current one.
5727 @item LayoutToBuffer
5728 Loads an entire PCB layout to the paste buffer.
5730 @item ElementToBuffer
5731 Loads the given element file into the paste buffer. Element files
5732 contain only a single @code{Element} definition, such as the
5733 ``newlib'' library uses.
5736 Loads a new netlist, replacing any current netlist.
5739 Re-loads the current layout from its disk file, reverting any changes
5747 ActionLoadFrom (int argc
, char **argv
, int x
, int y
)
5759 HideCrosshair (True
);
5761 if (strcasecmp (function
, "ElementToBuffer") == 0)
5763 if (LoadElementToBuffer (PASTEBUFFER
, name
, True
))
5764 SetMode (PASTEBUFFER_MODE
);
5767 else if (strcasecmp (function
, "LayoutToBuffer") == 0)
5769 if (LoadLayoutToBuffer (PASTEBUFFER
, name
))
5770 SetMode (PASTEBUFFER_MODE
);
5773 else if (strcasecmp (function
, "Layout") == 0)
5775 if (!PCB
->Changed
||
5776 gui
->confirm_dialog (_("OK to override layout data?"), 0))
5780 else if (strcasecmp (function
, "Netlist") == 0)
5782 if (PCB
->Netlistname
)
5783 SaveFree (PCB
->Netlistname
);
5784 PCB
->Netlistname
= StripWhiteSpaceAndDup (name
);
5785 FreeLibraryMemory (&PCB
->NetlistLib
);
5786 if (!ImportNetlist (PCB
->Netlistname
))
5789 else if (strcasecmp (function
, "Revert") == 0 && PCB
->Filename
5791 || gui
->confirm_dialog (_("OK to override changes?"), 0)))
5793 strcpy (fname
, PCB
->Filename
); /*Calling LoadPCB(PCB->Filename) changes the content of PCB->Filename. */
5797 RestoreCrosshair (True
);
5801 /* --------------------------------------------------------------------------- */
5803 static const char new_syntax
[] = "New([name])";
5805 static const char new_help
[] = "Starts a new layout.";
5807 /* %start-doc actions New
5809 If a name is not given, one is prompted for.
5814 ActionNew (int argc
, char **argv
, int x
, int y
)
5816 char *name
= ARG (0);
5818 HideCrosshair (True
);
5819 if (!PCB
->Changed
|| gui
->confirm_dialog (_("OK to clear layout data?"), 0))
5822 name
= MyStrdup (name
, "ActionNew");
5824 name
= gui
->prompt_for (_("Enter the layout name:"), "");
5828 RestoreCrosshair(True
);
5832 /* do emergency saving
5833 * clear the old struct and allocate memory for the new one
5835 if (PCB
->Changed
&& Settings
.SaveInTMP
)
5838 PCB
= CreateNewPCB (True
);
5839 PCB
->Data
->LayerN
= DEF_LAYER
;
5840 CreateNewPCBPost (PCB
, 1);
5842 /* setup the new name and reset some values to default */
5843 PCB
->Name
= name
; /* XXX memory leak */
5845 ResetStackAndVisibility ();
5846 CreateDefaultFont ();
5847 SetCrosshairRange (0, 0, PCB
->MaxWidth
, PCB
->MaxHeight
);
5848 CenterDisplay (PCB
->MaxWidth
/ 2, PCB
->MaxHeight
/ 2, False
);
5849 ClearAndRedrawOutput ();
5851 hid_action ("PCBChanged");
5852 RestoreCrosshair(True
);
5855 RestoreCrosshair (True
);
5859 /* ---------------------------------------------------------------------------
5860 * no operation, just for testing purposes
5861 * syntax: Bell(volume)
5864 ActionBell (char *volume
)
5869 /* --------------------------------------------------------------------------- */
5871 static const char pastebuffer_syntax
[] =
5872 "PasteBuffer(AddSelected|Clear|1..MAX_BUFFER)\n"
5873 "PasteBuffer(Rotate, 1..3)\n"
5874 "PasteBuffer(Convert|Save|Restore|Mirror)\n"
5875 "PasteBuffer(ToLayout, X, Y, units)";
5877 static const char pastebuffer_help
[] =
5878 "Various operations on the paste buffer.";
5880 /* %start-doc actions PasteBuffer
5882 There are a number of paste buffers; the actual limit is a
5883 compile-time constant @code{MAX_BUFFER} in @file{globalconst.h}. It
5884 is currently @code{5}. One of these is the ``current'' paste buffer,
5885 often referred to as ``the'' paste buffer.
5890 Copies the selected objects to the current paste buffer.
5893 Remove all objects from the current paste buffer.
5896 Convert the current paste buffer to an element. Vias are converted to
5897 pins, lines are converted to pads.
5900 Convert any elements in the paste buffer back to vias and lines.
5903 Flip all objects in the paste buffer vertically (up/down flip). To mirror
5904 horizontally, combine this with rotations.
5907 Rotates the current buffer. The number to pass is 1..3, where 1 means
5908 90 degrees counter clockwise, 2 means 180 degrees, and 3 means 90
5909 degrees clockwise (270 CCW).
5912 Saves any elements in the current buffer to the indicated file.
5915 Pastes any elements in the current buffer to the indicated X, Y
5916 coordinates in the layout. The @code{X} and @code{Y} are treated like
5917 @code{delta} is for many other objects. For each, if it's prefixed by
5918 @code{+} or @code{-}, then that amount is relative to the last
5919 location. Otherwise, it's absolute. Units can be
5920 @code{mil} or @code{mm}; if unspecified, units are PCB's internal
5921 units, currently 1/100 mil.
5925 Selects the given buffer to be the current paste buffer.
5932 ActionPasteBuffer (int argc
, char **argv
, int x
, int y
)
5934 char *function
= argc
? argv
[0] : "";
5935 char *sbufnum
= argc
> 1 ? argv
[1] : "";
5937 static char *default_file
= NULL
;
5940 HideCrosshair (True
);
5943 switch (GetFunctionID (function
))
5945 /* clear contents of paste buffer */
5947 ClearBuffer (PASTEBUFFER
);
5950 /* copies objects to paste buffer */
5952 AddSelectedToBuffer (PASTEBUFFER
, 0, 0, False
);
5955 /* converts buffer contents into an element */
5957 ConvertBufferToElement (PASTEBUFFER
);
5960 /* break up element for editing */
5962 SmashBufferElement (PASTEBUFFER
);
5967 MirrorBuffer (PASTEBUFFER
);
5973 RotateBuffer (PASTEBUFFER
, (BYTE
) atoi (sbufnum
));
5974 SetCrosshairRangeToBuffer ();
5979 if (PASTEBUFFER
->Data
->ElementN
== 0)
5981 Message (_("Buffer has no elements!\n"));
5987 name
= gui
->fileselect (_("Save Paste Buffer As ..."),
5988 _("Choose a file to save the contents of the\n"
5989 "paste buffer to.\n"),
5990 default_file
, ".fp", "footprint",
5995 free (default_file
);
5996 default_file
= NULL
;
6000 default_file
= strdup (name
);
6011 if ((exist
= fopen (name
, "r")))
6015 confirm_dialog (_("File exists! Ok to overwrite?"), 0))
6016 SaveBufferElements (name
);
6019 SaveBufferElements (name
);
6021 if (free_name
&& name
)
6028 static int oldx
= 0, oldy
= 0;
6036 else if (argc
== 3 || argc
== 4)
6038 x
= GetValue (ARG (1), ARG (3), &r
);
6041 y
= GetValue (ARG (2), ARG (3), &r
);
6047 RestoreCrosshair (True
);
6048 AFAIL (pastebuffer
);
6053 if (CopyPastebufferToLayout (x
, y
))
6054 SetChangedFlag (True
);
6061 int number
= atoi (function
);
6063 /* correct number */
6065 SetBufferNumber (number
- 1);
6070 RestoreCrosshair (True
);
6074 /* --------------------------------------------------------------------------- */
6076 static const char undo_syntax
[] = "Undo()\n" "Undo(ClearList)";
6078 static const char undo_help
[] = "Undo recent changes.";
6080 /* %start-doc actions Undo
6082 The unlimited undo feature of @code{Pcb} allows you to recover from
6083 most operations that materially affect you work. Calling
6084 @code{Undo()} without any parameter recovers from the last (non-undo)
6085 operation. @code{ClearList} is used to release the allocated
6086 memory. @code{ClearList} is called whenever a new layout is started or
6087 loaded. See also @code{Redo} and @code{Atomic}.
6089 Note that undo groups operations by serial number; changes with the
6090 same serial number will be undone (or redone) as a group. See
6096 ActionUndo (int argc
, char **argv
, int x
, int y
)
6098 char *function
= ARG (0);
6099 if (!function
|| !*function
)
6101 /* don't allow undo in the middle of an operation */
6102 if (Crosshair
.AttachedObject
.State
!= STATE_FIRST
)
6104 if (Crosshair
.AttachedBox
.State
!= STATE_FIRST
6105 && Settings
.Mode
!= ARC_MODE
)
6107 /* undo the last operation */
6109 HideCrosshair (True
);
6110 if (Settings
.Mode
== POLYGON_MODE
&& Crosshair
.AttachedPolygon
.PointN
)
6112 GoToPreviousPoint ();
6113 RestoreCrosshair (True
);
6116 /* move anchor point if undoing during line creation */
6117 if (Settings
.Mode
== LINE_MODE
)
6119 if (Crosshair
.AttachedLine
.State
== STATE_SECOND
)
6121 if (TEST_FLAG (AUTODRCFLAG
, PCB
))
6122 Undo (True
); /* undo the connection find */
6123 Crosshair
.AttachedLine
.State
= STATE_FIRST
;
6124 SetLocalRef (0, 0, False
);
6125 RestoreCrosshair (True
);
6128 if (Crosshair
.AttachedLine
.State
== STATE_THIRD
)
6131 void *ptr1
, *ptr3
, *ptrtmp
;
6133 /* this search is guaranteed to succeed */
6134 SearchObjectByLocation (LINE_TYPE
| RATLINE_TYPE
, &ptr1
,
6136 Crosshair
.AttachedLine
.Point1
.X
,
6137 Crosshair
.AttachedLine
.Point1
.Y
, 0);
6138 ptr2
= (LineTypePtr
) ptrtmp
;
6140 /* save both ends of line */
6141 Crosshair
.AttachedLine
.Point2
.X
= ptr2
->Point1
.X
;
6142 Crosshair
.AttachedLine
.Point2
.Y
= ptr2
->Point1
.Y
;
6143 if ((type
= Undo (True
)))
6144 SetChangedFlag (True
);
6145 /* check that the undo was of the right type */
6146 if ((type
& UNDO_CREATE
) == 0)
6148 /* wrong undo type, restore anchor points */
6149 Crosshair
.AttachedLine
.Point2
.X
=
6150 Crosshair
.AttachedLine
.Point1
.X
;
6151 Crosshair
.AttachedLine
.Point2
.Y
=
6152 Crosshair
.AttachedLine
.Point1
.Y
;
6153 RestoreCrosshair (True
);
6156 /* move to new anchor */
6157 Crosshair
.AttachedLine
.Point1
.X
=
6158 Crosshair
.AttachedLine
.Point2
.X
;
6159 Crosshair
.AttachedLine
.Point1
.Y
=
6160 Crosshair
.AttachedLine
.Point2
.Y
;
6161 /* check if an intermediate point was removed */
6162 if (type
& UNDO_REMOVE
)
6164 /* this search should find the restored line */
6165 SearchObjectByLocation (LINE_TYPE
| RATLINE_TYPE
, &ptr1
,
6168 Crosshair
.AttachedLine
.Point2
.X
,
6169 Crosshair
.AttachedLine
.Point2
.Y
, 0);
6170 ptr2
= (LineTypePtr
) ptrtmp
;
6171 if (TEST_FLAG (AUTODRCFLAG
, PCB
))
6173 /* undo loses FOUNDFLAG */
6174 SET_FLAG(FOUNDFLAG
, ptr2
);
6175 DrawLine (CURRENT
, ptr2
, 0);
6177 Crosshair
.AttachedLine
.Point1
.X
=
6178 Crosshair
.AttachedLine
.Point2
.X
= ptr2
->Point2
.X
;
6179 Crosshair
.AttachedLine
.Point1
.Y
=
6180 Crosshair
.AttachedLine
.Point2
.Y
= ptr2
->Point2
.Y
;
6182 FitCrosshairIntoGrid (Crosshair
.X
, Crosshair
.Y
);
6183 AdjustAttachedObjects ();
6184 if (--addedLines
== 0)
6186 Crosshair
.AttachedLine
.State
= STATE_SECOND
;
6187 lastLayer
= CURRENT
;
6191 /* this search is guaranteed to succeed too */
6192 SearchObjectByLocation (LINE_TYPE
| RATLINE_TYPE
, &ptr1
,
6195 Crosshair
.AttachedLine
.Point1
.X
,
6196 Crosshair
.AttachedLine
.Point1
.Y
, 0);
6197 ptr2
= (LineTypePtr
) ptrtmp
;
6198 lastLayer
= (LayerTypePtr
) ptr1
;
6200 RestoreCrosshair (True
);
6204 if (Settings
.Mode
== ARC_MODE
)
6206 if (Crosshair
.AttachedBox
.State
== STATE_SECOND
)
6208 Crosshair
.AttachedBox
.State
= STATE_FIRST
;
6209 RestoreCrosshair (True
);
6212 if (Crosshair
.AttachedBox
.State
== STATE_THIRD
)
6214 void *ptr1
, *ptr2
, *ptr3
;
6216 /* guaranteed to succeed */
6217 SearchObjectByLocation (ARC_TYPE
, &ptr1
, &ptr2
, &ptr3
,
6218 Crosshair
.AttachedBox
.Point1
.X
,
6219 Crosshair
.AttachedBox
.Point1
.Y
, 0);
6220 bx
= GetArcEnds ((ArcTypePtr
) ptr2
);
6221 Crosshair
.AttachedBox
.Point1
.X
=
6222 Crosshair
.AttachedBox
.Point2
.X
= bx
->X1
;
6223 Crosshair
.AttachedBox
.Point1
.Y
=
6224 Crosshair
.AttachedBox
.Point2
.Y
= bx
->Y1
;
6225 AdjustAttachedObjects ();
6226 if (--addedLines
== 0)
6227 Crosshair
.AttachedBox
.State
= STATE_SECOND
;
6230 /* undo the last destructive operation */
6232 SetChangedFlag (True
);
6236 switch (GetFunctionID (function
))
6238 /* clear 'undo objects' list */
6240 ClearUndoList (False
);
6244 RestoreCrosshair (True
);
6248 /* --------------------------------------------------------------------------- */
6250 static const char redo_syntax
[] = "Redo()";
6252 static const char redo_help
[] = "Redo recent \"undo\" operations.";
6254 /* %start-doc actions Redo
6256 This routine allows you to recover from the last undo command. You
6257 might want to do this if you thought that undo was going to revert
6258 something other than what it actually did (in case you are confused
6259 about which operations are un-doable), or if you have been backing up
6260 through a long undo list and over-shoot your stopping point. Any
6261 change that is made since the undo in question will trim the redo
6262 list. For example if you add ten lines, then undo three of them you
6263 could use redo to put them back, but if you move a line on the board
6264 before performing the redo, you will lose the ability to "redo" the
6265 three "undone" lines.
6270 ActionRedo (int argc
, char **argv
, int x
, int y
)
6272 if ((Settings
.Mode
== POLYGON_MODE
&&
6273 Crosshair
.AttachedPolygon
.PointN
) ||
6274 Crosshair
.AttachedLine
.State
== STATE_SECOND
)
6276 HideCrosshair (True
);
6279 SetChangedFlag (True
);
6280 if (Settings
.Mode
== LINE_MODE
&&
6281 Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
6283 LineTypePtr line
= &CURRENT
->Line
[CURRENT
->LineN
- 1];
6284 Crosshair
.AttachedLine
.Point1
.X
=
6285 Crosshair
.AttachedLine
.Point2
.X
= line
->Point2
.X
;
6286 Crosshair
.AttachedLine
.Point1
.Y
=
6287 Crosshair
.AttachedLine
.Point2
.Y
= line
->Point2
.Y
;
6291 RestoreCrosshair (True
);
6295 /* --------------------------------------------------------------------------- */
6297 static const char polygon_syntax
[] = "Polygon(Close|PreviousPoint)";
6299 static const char polygon_help
[] = "Some polygon related stuff.";
6301 /* %start-doc actions Polygon
6303 Polygons need a special action routine to make life easier.
6308 Creates the final segment of the polygon. This may fail if clipping
6309 to 45 degree lines is switched on, in which case a warning is issued.
6312 Resets the newly entered corner to the previous one. The Undo action
6313 will call Polygon(PreviousPoint) when appropriate to do so.
6320 ActionPolygon (int argc
, char **argv
, int x
, int y
)
6322 char *function
= ARG (0);
6323 if (function
&& Settings
.Mode
== POLYGON_MODE
)
6325 HideCrosshair (True
);
6326 switch (GetFunctionID (function
))
6328 /* close open polygon if possible */
6333 /* go back to the previous point */
6334 case F_PreviousPoint
:
6335 GoToPreviousPoint ();
6338 RestoreCrosshair (True
);
6343 /* --------------------------------------------------------------------------- */
6345 static const char routestyle_syntax
[] = "RouteStyle(1|2|3|4)";
6347 static const char routestyle_help
[] =
6348 "Copies the indicated routing style into the current sizes.";
6350 /* %start-doc actions RouteStyle
6355 ActionRouteStyle (int argc
, char **argv
, int x
, int y
)
6357 char *str
= ARG (0);
6358 RouteStyleType
*rts
;
6363 number
= atoi (str
);
6364 if (number
> 0 && number
<= NUM_STYLES
)
6366 rts
= &PCB
->RouteStyle
[number
- 1];
6367 SetLineSize (rts
->Thick
);
6368 SetViaSize (rts
->Diameter
, True
);
6369 SetViaDrillingHole (rts
->Hole
, True
);
6370 SetKeepawayWidth (rts
->Keepaway
);
6371 hid_action("RouteStylesChanged");
6378 /* --------------------------------------------------------------------------- */
6380 static const char moveobject_syntax
[] = "MoveObject(X,Y,dim)";
6382 static const char moveobject_help
[] = "Moves the object under the crosshair.";
6384 /* %start-doc actions MoveObject
6386 The @code{X} and @code{Y} are treated like @code{delta} is for many
6387 other objects. For each, if it's prefixed by @code{+} or @code{-},
6388 then that amount is relative. Otherwise, it's absolute. Units can be
6389 @code{mil} or @code{mm}; if unspecified, units are PCB's internal
6390 units, currently 1/100 mil.
6395 ActionMoveObject (int argc
, char **argv
, int x
, int y
)
6397 char *x_str
= ARG (0);
6398 char *y_str
= ARG (1);
6399 char *units
= ARG (2);
6400 LocationType nx
, ny
;
6402 void *ptr1
, *ptr2
, *ptr3
;
6405 ny
= GetValue (y_str
, units
, &r1
);
6406 nx
= GetValue (x_str
, units
, &r2
);
6408 type
= SearchScreen (x
, y
, MOVE_TYPES
, &ptr1
, &ptr2
, &ptr3
);
6409 if (type
== NO_TYPE
)
6411 Message (_("Nothing found under crosshair\n"));
6418 Crosshair
.AttachedObject
.RubberbandN
= 0;
6419 if (TEST_FLAG (RUBBERBANDFLAG
, PCB
))
6420 LookupRubberbandLines (type
, ptr1
, ptr2
, ptr3
);
6421 if (type
== ELEMENT_TYPE
)
6422 LookupRatLines (type
, ptr1
, ptr2
, ptr3
);
6423 MoveObjectAndRubberband (type
, ptr1
, ptr2
, ptr3
, nx
, ny
);
6424 SetChangedFlag (True
);
6428 /* --------------------------------------------------------------------------- */
6430 static const char movetocurrentlayer_syntax
[] =
6431 "MoveToCurrentLayer(Object|SelectedObjects)";
6433 static const char movetocurrentlayer_help
[] =
6434 "Moves objects to the current layer.";
6436 /* %start-doc actions MoveToCurrentLayer
6438 Note that moving an element from a component layer to a solder layer,
6439 or from solder to component, won't automatically flip it. Use the
6440 @code{Flip()} action to do that.
6445 ActionMoveToCurrentLayer (int argc
, char **argv
, int x
, int y
)
6447 char *function
= ARG (0);
6450 HideCrosshair (True
);
6451 switch (GetFunctionID (function
))
6456 void *ptr1
, *ptr2
, *ptr3
;
6458 gui
->get_coords ("Select an Object", &x
, &y
);
6460 SearchScreen (x
, y
, MOVETOLAYER_TYPES
,
6461 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
6462 if (MoveObjectToLayer (type
, ptr1
, ptr2
, ptr3
, CURRENT
, False
))
6463 SetChangedFlag (True
);
6467 case F_SelectedObjects
:
6469 if (MoveSelectedObjectsToLayer (CURRENT
))
6470 SetChangedFlag (True
);
6473 RestoreCrosshair (True
);
6479 static const char setsame_syntax
[] = "SetSame()";
6481 static const char setsame_help
[] =
6482 "Sets current layer and sizes to match indicated item.";
6484 /* %start-doc actions SetSame
6486 When invoked over any line, arc, polygon, or via, this changes the
6487 current layer to be the layer that item is on, and changes the current
6488 sizes (thickness, keepaway, drill, etc) according to that item.
6493 ActionSetSame (int argc
, char **argv
, int x
, int y
)
6495 void *ptr1
, *ptr2
, *ptr3
;
6497 LayerTypePtr layer
= CURRENT
;
6499 type
= SearchScreen (x
, y
, CLONE_TYPES
, &ptr1
, &ptr2
, &ptr3
);
6500 /* set layer current and size from line or arc */
6504 HideCrosshair (True
);
6505 Settings
.LineThickness
= ((LineTypePtr
) ptr2
)->Thickness
;
6506 Settings
.Keepaway
= ((LineTypePtr
) ptr2
)->Clearance
/ 2;
6507 layer
= (LayerTypePtr
) ptr1
;
6508 if (Settings
.Mode
!= LINE_MODE
)
6509 SetMode (LINE_MODE
);
6510 RestoreCrosshair (True
);
6511 hid_action ("RouteStylesChanged");
6515 HideCrosshair (True
);
6516 Settings
.LineThickness
= ((ArcTypePtr
) ptr2
)->Thickness
;
6517 Settings
.Keepaway
= ((ArcTypePtr
) ptr2
)->Clearance
/ 2;
6518 layer
= (LayerTypePtr
) ptr1
;
6519 if (Settings
.Mode
!= ARC_MODE
)
6521 RestoreCrosshair (True
);
6522 hid_action ("RouteStylesChanged");
6526 layer
= (LayerTypePtr
) ptr1
;
6530 HideCrosshair (True
);
6531 Settings
.ViaThickness
= ((PinTypePtr
) ptr2
)->Thickness
;
6532 Settings
.ViaDrillingHole
= ((PinTypePtr
) ptr2
)->DrillingHole
;
6533 Settings
.Keepaway
= ((PinTypePtr
) ptr2
)->Clearance
/ 2;
6534 if (Settings
.Mode
!= VIA_MODE
)
6536 RestoreCrosshair (True
);
6537 hid_action ("RouteStylesChanged");
6543 if (layer
!= CURRENT
)
6545 ChangeGroupVisibility (GetLayerNumber (PCB
->Data
, layer
), True
, True
);
6546 ClearAndRedrawOutput ();
6552 /* --------------------------------------------------------------------------- */
6554 static const char setflag_syntax
[] =
6555 "SetFlag(Object|Selected|SelectedObjects, flag)\n"
6556 "SetFlag(SelectedLines|SelectedPins|SelectedVias, flag)\n"
6557 "SetFlag(SelectedPads|SelectedTexts|SelectedNames, flag)\n"
6558 "SetFlag(SelectedElements, flag)\n"
6559 "flag = square | octagon | thermal | join";
6561 static const char setflag_help
[] = "Sets flags on objects.";
6563 /* %start-doc actions SetFlag
6565 Turns the given flag on, regardless of its previous setting. See
6569 SetFlag(SelectedPins,thermal)
6575 ActionSetFlag (int argc
, char **argv
, int x
, int y
)
6577 char *function
= ARG (0);
6578 char *flag
= ARG (1);
6579 ChangeFlag (function
, flag
, 1, "SetFlag");
6583 /* --------------------------------------------------------------------------- */
6585 static const char clrflag_syntax
[] =
6586 "ClrFlag(Object|Selected|SelectedObjects, flag)\n"
6587 "ClrFlag(SelectedLines|SelectedPins|SelectedVias, flag)\n"
6588 "ClrFlag(SelectedPads|SelectedTexts|SelectedNames, flag)\n"
6589 "ClrFlag(SelectedElements, flag)\n"
6590 "flag = square | octagon | thermal | join";
6592 static const char clrflag_help
[] = "Clears flags on objects.";
6594 /* %start-doc actions ClrFlag
6596 Turns the given flag off, regardless of its previous setting. See
6600 ClrFlag(SelectedLines,join)
6606 ActionClrFlag (int argc
, char **argv
, int x
, int y
)
6608 char *function
= ARG (0);
6609 char *flag
= ARG (1);
6610 ChangeFlag (function
, flag
, 0, "ClrFlag");
6614 /* --------------------------------------------------------------------------- */
6616 static const char changeflag_syntax
[] =
6617 "ChangeFlag(Object|Selected|SelectedObjects, flag, value)\n"
6618 "ChangeFlag(SelectedLines|SelectedPins|SelectedVias, flag, value)\n"
6619 "ChangeFlag(SelectedPads|SelectedTexts|SelectedNames, flag, value)\n"
6620 "ChangeFlag(SelectedElements, flag, value)\n"
6621 "flag = square | octagon | thermal | join\n" "value = 0 | 1";
6623 static const char changeflag_help
[] = "Sets or clears flags on objects.";
6625 /* %start-doc actions ChangeFlag
6627 Toggles the given flag on the indicated object(s). The flag may be
6628 one of the flags listed above (square, octagon, thermal, join). The
6629 value may be the number 0 or 1. If the value is 0, the flag is
6630 cleared. If the value is 1, the flag is set.
6635 ActionChangeFlag (int argc
, char **argv
, int x
, int y
)
6637 char *function
= ARG (0);
6638 char *flag
= ARG (1);
6639 int value
= argc
> 2 ? atoi (argv
[2]) : -1;
6640 if (value
!= 0 && value
!= 1)
6643 ChangeFlag (function
, flag
, value
, "ChangeFlag");
6649 ChangeFlag (char *what
, char *flag_name
, int value
, char *cmd_name
)
6651 Boolean (*set_object
) (int, void *, void *, void *);
6652 Boolean (*set_selected
) (int);
6654 if (NSTRCMP (flag_name
, "square") == 0)
6656 set_object
= value
? SetObjectSquare
: ClrObjectSquare
;
6657 set_selected
= value
? SetSelectedSquare
: ClrSelectedSquare
;
6659 else if (NSTRCMP (flag_name
, "octagon") == 0)
6661 set_object
= value
? SetObjectOctagon
: ClrObjectOctagon
;
6662 set_selected
= value
? SetSelectedOctagon
: ClrSelectedOctagon
;
6664 else if (NSTRCMP (flag_name
, "join") == 0)
6666 /* Note: these are backwards, because the flag is "clear" but
6667 the command is "join". */
6668 set_object
= value
? ClrObjectJoin
: SetObjectJoin
;
6669 set_selected
= value
? ClrSelectedJoin
: SetSelectedJoin
;
6673 Message (_("%s(): Flag \"%s\" is not valid\n"), cmd_name
, flag_name
);
6677 HideCrosshair (True
);
6678 switch (GetFunctionID (what
))
6683 void *ptr1
, *ptr2
, *ptr3
;
6686 SearchScreen (Crosshair
.X
, Crosshair
.Y
, CHANGESIZE_TYPES
,
6687 &ptr1
, &ptr2
, &ptr3
)) != NO_TYPE
)
6688 if (TEST_FLAG (LOCKFLAG
, (PinTypePtr
) ptr2
))
6689 Message (_("Sorry, the object is locked\n"));
6690 if (set_object (type
, ptr1
, ptr2
, ptr3
))
6691 SetChangedFlag (True
);
6695 case F_SelectedVias
:
6696 if (set_selected (VIA_TYPE
))
6697 SetChangedFlag (True
);
6700 case F_SelectedPins
:
6701 if (set_selected (PIN_TYPE
))
6702 SetChangedFlag (True
);
6705 case F_SelectedPads
:
6706 if (set_selected (PAD_TYPE
))
6707 SetChangedFlag (True
);
6710 case F_SelectedLines
:
6711 if (set_selected (LINE_TYPE
))
6712 SetChangedFlag (True
);
6715 case F_SelectedTexts
:
6716 if (set_selected (TEXT_TYPE
))
6717 SetChangedFlag (True
);
6720 case F_SelectedNames
:
6721 if (set_selected (ELEMENTNAME_TYPE
))
6722 SetChangedFlag (True
);
6725 case F_SelectedElements
:
6726 if (set_selected (ELEMENT_TYPE
))
6727 SetChangedFlag (True
);
6731 case F_SelectedObjects
:
6732 if (set_selected (CHANGESIZE_TYPES
))
6733 SetChangedFlag (True
);
6736 RestoreCrosshair (True
);
6740 /* --------------------------------------------------------------------------- */
6742 static const char executefile_syntax
[] = "ExecuteFile(filename)";
6744 static const char executefile_help
[] = "Run actions from the given file.";
6746 /* %start-doc actions ExecuteFile
6748 Lines starting with @code{#} are ignored.
6753 ActionExecuteFile (int argc
, char **argv
, int x
, int y
)
6762 AFAIL (executefile
);
6766 if ((fp
= fopen (fname
, "r")) == NULL
)
6768 fprintf (stderr
, "Could not open actions file \"%s\".\n", fname
);
6773 defer_needs_update
= 0;
6774 while (fgets (line
, sizeof (line
), fp
) != NULL
)
6779 /* eat the trailing newline */
6780 while (*sp
&& *sp
!= '\r' && *sp
!= '\n')
6784 /* eat leading spaces and tabs */
6786 while (*sp
&& (*sp
== ' ' || *sp
== '\t'))
6790 * if we have anything left and its not a comment line
6794 if (*sp
&& *sp
!= '#')
6796 /*Message ("%s : line %-3d : \"%s\"\n", fname, n, sp);*/
6797 hid_parse_actions (sp
, 0);
6802 if (defer_needs_update
)
6804 IncrementUndoSerialNumber ();
6805 gui
->invalidate_all ();
6811 /* --------------------------------------------------------------------------- */
6814 ActionPSCalib (int argc
, char **argv
, int x
, int y
)
6816 HID
*ps
= hid_find_exporter ("ps");
6817 ps
->calibrate (0.0,0.0);
6821 /* --------------------------------------------------------------------------- */
6823 static ElementType
*element_cache
= NULL
;
6825 static ElementType
*
6826 find_element_by_refdes (char *refdes
)
6829 && NAMEONPCB_NAME(element_cache
)
6830 && strcmp (NAMEONPCB_NAME(element_cache
), refdes
) == 0)
6831 return element_cache
;
6833 ELEMENT_LOOP (PCB
->Data
);
6835 if (NAMEONPCB_NAME(element
)
6836 && strcmp (NAMEONPCB_NAME(element
), refdes
) == 0)
6838 element_cache
= element
;
6839 return element_cache
;
6846 static AttributeType
*
6847 lookup_attr (AttributeListTypePtr list
, const char *name
)
6850 for (i
=0; i
<list
->Number
; i
++)
6851 if (strcmp (list
->List
[i
].name
, name
) == 0)
6852 return & list
->List
[i
];
6857 delete_attr (AttributeListTypePtr list
, AttributeType
*attr
)
6859 int idx
= attr
- list
->List
;
6860 if (idx
< 0 || idx
>= list
->Number
)
6862 if (list
->Number
- idx
> 1)
6863 memmove (attr
, attr
+1, (list
->Number
- idx
- 1) * sizeof(AttributeType
));
6867 static const char elementlist_syntax
[] = "ElementList(Start|Done|Need,<refdes>,<footprint>,<value>)";
6869 static const char elementlist_help
[] = "Adds the given element if it doesn't already exist.";
6871 /* %start-doc actions elementlist
6876 Indicates the start of an element list; call this before any Need
6880 Searches the board for an element with a matching refdes.
6882 If found, the value and footprint are updated.
6884 If not found, a new element is created with the given footprint and value.
6887 Compares the list of elements needed since the most recent
6888 @code{start} with the list of elements actually on the board. Any
6889 elements that weren't listed are selected, so that the user may delete
6897 ActionElementList (int argc
, char **argv
, int x
, int y
)
6899 ElementType
*e
= NULL
;
6900 char *refdes
, *value
, *footprint
, *old
;
6902 char *function
= argv
[0];
6904 if (strcasecmp (function
, "start") == 0)
6906 ELEMENT_LOOP (PCB
->Data
);
6908 CLEAR_FLAG (FOUNDFLAG
, element
);
6911 element_cache
= NULL
;
6915 if (strcasecmp (function
, "done") == 0)
6917 ELEMENT_LOOP (PCB
->Data
);
6919 if (TEST_FLAG (FOUNDFLAG
, element
))
6921 CLEAR_FLAG (FOUNDFLAG
, element
);
6923 else if (! EMPTY_STRING_P (NAMEONPCB_NAME (element
)))
6925 /* Unnamed elements should remain untouched */
6926 SET_FLAG (SELECTEDFLAG
, element
);
6933 if (strcasecmp (function
, "need") != 0)
6934 AFAIL (elementlist
);
6937 AFAIL (elementlist
);
6946 args
[0] = footprint
;
6950 e
= find_element_by_refdes (refdes
);
6954 /* Not on board, need to add it. */
6955 if (LoadFootprint(argc
, args
, x
, y
))
6957 if (CopyPastebufferToLayout (0, 0))
6958 SetChangedFlag (True
);
6961 else if (e
&& strcmp (DESCRIPTION_NAME(e
), footprint
) != 0)
6964 LocationType mx
, my
;
6967 /* Different footprint, we need to swap them out. */
6968 if (LoadFootprint(argc
, args
, x
, y
))
6971 er
= ElementOrientation (e
);
6972 pe
= & PASTEBUFFER
->Data
->Element
[0];
6973 pr
= ElementOrientation (pe
);
6979 RotateElementLowLevel (PASTEBUFFER
->Data
, pe
, pe
->MarkX
, pe
->MarkY
, (er
-pr
+4)%4);
6981 for (i
=0; i
<MAX_ELEMENTNAMES
; i
++)
6983 pe
->Name
[i
].X
= e
->Name
[i
].X
- mx
;
6984 pe
->Name
[i
].Y
= e
->Name
[i
].Y
- my
;
6985 pe
->Name
[i
].Direction
= e
->Name
[i
].Direction
;
6986 pe
->Name
[i
].Scale
= e
->Name
[i
].Scale
;
6991 if (CopyPastebufferToLayout (mx
, my
))
6992 SetChangedFlag (True
);
6995 e
= find_element_by_refdes (refdes
);
6997 old
= ChangeElementText (PCB
, PCB
->Data
, e
, NAMEONPCB_INDEX
, strdup (refdes
));
7000 old
= ChangeElementText (PCB
, PCB
->Data
, e
, VALUE_INDEX
, strdup (value
));
7004 SET_FLAG (FOUNDFLAG
, e
);
7009 static const char elementsetattr_syntax
[] = "ElementSetAttr(refdes,name[,value])";
7011 static const char elementsetattr_help
[] = "Sets or clears an element-specific attribute";
7013 /* %start-doc actions elementsetattr
7015 If a value is specified, the named attribute is added (if not already
7016 present) or changed (if it is) to the given value. If the value is
7017 not specified, the given attribute is removed if present.
7022 ActionElementSetAttr (int argc
, char **argv
, int x
, int y
)
7024 ElementType
*e
= NULL
;
7025 char *refdes
, *name
, *value
;
7026 AttributeType
*attr
;
7030 AFAIL (changepinname
);
7037 ELEMENT_LOOP (PCB
->Data
);
7039 if (NSTRCMP (refdes
, NAMEONPCB_NAME (element
)) == 0)
7049 Message("Cannot change attribute of %s - element not found", refdes
);
7053 attr
= lookup_attr (&e
->Attributes
, name
);
7057 MYFREE (attr
->value
);
7058 attr
->value
= MyStrdup (value
, "ElementSetAttr");
7060 if (attr
&& ! value
)
7062 delete_attr (& e
->Attributes
, attr
);
7066 CreateNewAttribute (& e
->Attributes
, name
, value
);
7072 static const char execcommand_syntax
[] = "ExecCommand(command)";
7074 static const char execcommand_help
[] = "Runs a command";
7076 /* %start-doc actions execcommand
7078 Runs the given command, which is a system executable.
7083 ActionExecCommand (int argc
, char **argv
, int x
, int y
)
7089 AFAIL (execcommand
);
7094 if (system (command
))
7099 static const char import_syntax
[] =
7101 "Import([gnetlist|make[,source,source,...]])\n";
7103 static const char import_help
[] = "Import schematics";
7105 /* %start-doc actions import
7107 Imports element and netlist data from the schematics (or some other
7108 source). The first parameter, which is optional, is the mode. If not
7109 specified, the @code{import::mode} attribute in the PCB is used.
7110 @code{gnetlist} means gnetlist is used to obtain the information from
7111 the schematics. @code{make} invokes @code{make}, assuming the user
7112 has a @code{Makefile} in the current directory. The @code{Makefile}
7113 will be invoked with the following variables set:
7118 The name of the .pcb file
7121 A space-separated list of source files
7124 The name of the file in which to put the command script, which may
7125 contain any @pcb{} actions. By default, this is a temporary file
7126 selected by @pcb{}, but if you specify an @code{import::outfile}
7127 attribute, that file name is used instead (and not automatically
7128 deleted afterwards).
7132 The target specified to be built is the first of these that apply:
7137 The target specified by an @code{import::target} attribute.
7140 The output file specified by an @code{import::outfile} attribute.
7143 If nothing else is specified, the target is @code{pcb_import}.
7147 If you specify an @code{import::makefile} attribute, then "-f <that
7148 file>" will be added to the command line.
7150 If you specify the mode, you may also specify the source files
7151 (schematics). If you do not specify any, the list of schematics is
7152 obtained by reading the @code{import::src@var{N}} attributes (like
7153 @code{import::src0}, @code{import::src1}, etc).
7155 For compatibility with future extensions to the import file format,
7156 the generated file @emph{must not} start with the two characters
7159 If a temporary file is needed the @code{TMPDIR} environment variable
7160 is used to select its location.
7162 Note that the programs @code{gnetlist} and @code{make} may be
7163 overridden by the user via the @code{make-program} and @code{gnetlist}
7164 @code{pcb} settings (i.e. in @code{~/.pcb/settings} or on the command
7170 pcb_spawnvp (char **argv
)
7177 Message("Cannot fork!");
7183 execvp (argv
[0], argv
);
7196 * Creates a new temporary file name. Hopefully the operating system
7197 * provides a mkdtemp() function to securily create a temporary
7198 * directory with mode 0700. If so then that directory is created and
7199 * the returned string is made up of the directory plus the name
7200 * variable. For example:
7202 * tempfile_name_new ("myfile") might return
7203 * "/var/tmp/pcb.123456/myfile".
7205 * If mkdtemp() is not available then 'name' is ignored and the
7206 * insecure tmpnam() function is used.
7208 * Files/names created with tempfile_name_new() should be unlinked
7209 * with tempfile_unlink to make sure the temporary directory is also
7210 * removed when mkdtemp() is used.
7213 tempfile_name_new (char * name
)
7215 char *tmpfile
= NULL
;
7217 char *tmpdir
, *mytmpdir
;
7221 assert ( name
!= NULL
);
7224 #define TEMPLATE "pcb.XXXXXXXX"
7227 tmpdir
= getenv ("TMPDIR");
7229 /* FIXME -- what about win32? */
7230 if (tmpdir
== NULL
) {
7234 mytmpdir
= (char *) malloc (sizeof(char) *
7239 if (mytmpdir
== NULL
) {
7240 fprintf (stderr
, "%s(): malloc failed()\n", __FUNCTION__
);
7245 (void)strcat (mytmpdir
, tmpdir
);
7246 (void)strcat (mytmpdir
, PCB_DIR_SEPARATOR_S
);
7247 (void)strcat (mytmpdir
, TEMPLATE
);
7248 if (mkdtemp (mytmpdir
) == NULL
) {
7249 fprintf (stderr
, "%s(): mkdtemp (\"%s\") failed\n", __FUNCTION__
, mytmpdir
);
7255 len
= strlen (mytmpdir
) + /* the temp directory name */
7256 1 + /* the directory sep. */
7257 strlen (name
) + /* the file name */
7258 1 /* the \0 termination */
7261 tmpfile
= (char *) malloc (sizeof (char) * len
);
7264 (void)strcat (tmpfile
, mytmpdir
);
7265 (void)strcat (tmpfile
, PCB_DIR_SEPARATOR_S
);
7266 (void)strcat (tmpfile
, name
);
7272 * tmpnam() uses a static buffer so strdup() the result right away
7273 * in case someone decides to create multiple temp names.
7275 tmpfile
= strdup (tmpnam (NULL
));
7282 * Unlink a temporary file. If we have mkdtemp() then our temp file
7283 * lives in a temporary directory and we need to remove that directory
7287 tempfile_unlink (char * name
)
7296 /* it is possible that the file was never created so it is OK if the
7299 /* now figure out the directory name to remove */
7300 e
= strlen (name
) - 1;
7301 while (e
> 0 && name
[e
] != PCB_DIR_SEPARATOR_C
) {e
--;}
7303 dname
= strdup (name
);
7307 * at this point, e *should* point to the end of the directory part
7308 * but lets make sure.
7311 rc2
= rmdir (dname
);
7317 fprintf (stderr
, "%s(): Unable to determine temp directory name from the temp file\n",
7319 fprintf (stderr
, "%s(): \"%s\"\n",
7320 __FUNCTION__
, name
);
7324 /* name was allocated with malloc */
7329 * FIXME - should also return -1 if the temp file exists and was not
7340 fprintf (stderr
, "Failed to unlink \"%s\"\n", name
);
7352 ActionImport (int argc
, char **argv
, int x
, int y
)
7355 char **sources
= NULL
;
7360 mode
= AttributeGet (PCB
, "import::mode");
7367 nsources
= argc
- 1;
7378 sprintf(sname
, "import::src%d", nsources
);
7379 src
= AttributeGet (PCB
, sname
);
7384 sources
= (char **) malloc ((nsources
+ 1) * sizeof (char *));
7388 sprintf(sname
, "import::src%d", nsources
);
7389 src
= AttributeGet (PCB
, sname
);
7390 sources
[nsources
] = src
;
7397 /* Replace .pcb with .sch and hope for the best. */
7398 char *pcbname
= PCB
->Filename
;
7400 char *dot
, *slash
, *bslash
;
7404 Message ("Please save your PCB first, so that it has a\n"
7405 "file name, or manually add an import::src0 attribute with\n"
7406 "the name of the schematic to import from.");
7410 schname
= (char *) malloc (strlen(pcbname
) + 5);
7411 strcpy (schname
, pcbname
);
7412 dot
= strchr (schname
, '.');
7413 slash
= strchr (schname
, '/');
7414 bslash
= strchr (schname
, '\\');
7415 if (dot
&& slash
&& dot
< slash
)
7417 if (dot
&& bslash
&& dot
< bslash
)
7421 strcat (schname
, ".sch");
7423 sources
= (char **) malloc (2 * sizeof (char *));
7424 sources
[0] = schname
;
7429 if (strcasecmp (mode
, "gnetlist") == 0)
7431 char *tmpfile
= tempfile_name_new ("gnetlist_output");
7435 if (tmpfile
== NULL
) {
7436 Message ("Could not create temp file");
7440 cmd
= (char **) malloc ((6 + nsources
) * sizeof (char *));
7441 cmd
[0] = Settings
.GnetlistProgram
;
7446 for (i
=0; i
<nsources
; i
++)
7447 cmd
[5+i
] = sources
[i
];
7448 cmd
[5+nsources
] = NULL
;
7450 if (pcb_spawnvp (cmd
))
7458 ActionExecuteFile (1, cmd
, 0, 0);
7461 tempfile_unlink (tmpfile
);
7463 else if (strcasecmp (mode
, "make") == 0)
7465 int must_free_tmpfile
= 0;
7471 char *user_outfile
= NULL
;
7472 char *user_makefile
= NULL
;
7473 char *user_target
= NULL
;
7476 user_outfile
= AttributeGet (PCB
, "import::outfile");
7477 user_makefile
= AttributeGet (PCB
, "import::makefile");
7478 user_target
= AttributeGet (PCB
, "import::target");
7479 if (user_outfile
&& !user_target
)
7480 user_target
= user_outfile
;
7483 tmpfile
= user_outfile
;
7486 tmpfile
= tempfile_name_new ("gnetlist_output");
7487 if (tmpfile
== NULL
) {
7488 Message ("Could not create temp file");
7491 must_free_tmpfile
= 1;
7494 srclen
= sizeof("SRCLIST=") + 2;
7495 for (i
=0; i
<nsources
; i
++)
7496 srclen
+= strlen (sources
[i
]) + 2;
7497 srclist
= (char *) malloc (srclen
);
7498 strcpy (srclist
, "SRCLIST=");
7499 for (i
=0; i
<nsources
; i
++)
7502 strcat (srclist
, " ");
7503 strcat (srclist
, sources
[i
]);
7506 cmd
[0] = Settings
.MakeProgram
;
7508 cmd
[2] = Concat ("PCB=", PCB
->Filename
, NULL
);
7510 cmd
[4] = Concat ("OUT=", tmpfile
, NULL
);
7515 cmd
[i
++] = user_makefile
;
7517 cmd
[i
++] = user_target
? user_target
: "pcb_import";
7520 if (pcb_spawnvp (cmd
))
7522 if (must_free_tmpfile
)
7532 ActionExecuteFile (1, cmd
, 0, 0);
7537 if (must_free_tmpfile
)
7538 tempfile_unlink (tmpfile
);
7542 Message ("Unknown import mode: %s\n", mode
);
7547 AddAllRats (False
, NULL
);
7552 /* ------------------------------------------------------------ */
7554 static const char attributes_syntax
[] =
7555 "Attributes(Layout|Layer|Element)\n"
7556 "Attributes(Layer,layername)";
7558 static const char attributes_help
[] =
7559 "Let the user edit the attributes of the layout, current or given\n"
7560 "layer, or selected element.";
7562 /* %start-doc actions Attributes
7564 This just pops up a dialog letting the user edit the attributes of the
7565 pcb, an element, or a layer.
7571 ActionAttributes (int argc
, char **argv
, int x
, int y
)
7573 char *function
= ARG (0);
7574 char *layername
= ARG (1);
7580 if (!gui
->edit_attributes
)
7582 Message ("This GUI doesn't support Attribute Editing\n");
7586 switch (GetFunctionID (function
))
7590 gui
->edit_attributes("Layout Attributes", &(PCB
->Attributes
));
7596 LayerType
*layer
= CURRENT
;
7601 for (i
=0; i
<max_layer
; i
++)
7602 if (strcmp (PCB
->Data
->Layer
[i
].Name
, layername
) == 0)
7604 layer
= & (PCB
->Data
->Layer
[i
]);
7609 Message ("No layer named %s\n", layername
);
7613 buf
= (char *) malloc (strlen (layer
->Name
) + strlen ("Layer X Attributes"));
7614 sprintf (buf
, "Layer %s Attributes", layer
->Name
);
7615 gui
->edit_attributes(buf
, &(layer
->Attributes
));
7623 ElementType
*e
= NULL
;
7624 ELEMENT_LOOP (PCB
->Data
);
7626 if (TEST_FLAG (SELECTEDFLAG
, element
))
7635 Message ("Too many elements selected\n");
7641 gui
->get_coords ("Click on an element", &x
, &y
);
7643 (x
, y
, ELEMENT_TYPE
, &ptrtmp
,
7644 &ptrtmp
, &ptrtmp
)) != NO_TYPE
)
7645 e
= (ElementTypePtr
) ptrtmp
;
7648 Message ("No element found there\n");
7653 buf
= (char *) malloc (strlen (NAMEONPCB_NAME(e
)) + strlen ("Element X Attributes"));
7654 sprintf(buf
, "Element %s Attributes", NAMEONPCB_NAME(e
));
7655 gui
->edit_attributes(buf
, &(e
->Attributes
));
7667 /* --------------------------------------------------------------------------- */
7669 HID_Action action_action_list
[] = {
7670 {"AddRats", 0, ActionAddRats
,
7671 addrats_help
, addrats_syntax
}
7673 {"Attributes", 0, ActionAttributes
,
7674 attributes_help
, attributes_syntax
}
7676 {"Atomic", 0, ActionAtomic
,
7677 atomic_help
, atomic_syntax
}
7679 {"AutoPlaceSelected", 0, ActionAutoPlaceSelected
,
7680 autoplace_help
, autoplace_syntax
}
7682 {"AutoRoute", 0, ActionAutoRoute
,
7683 autoroute_help
, autoroute_syntax
}
7685 {"ChangeClearSize", 0, ActionChangeClearSize
,
7686 changeclearsize_help
, changeclearsize_syntax
}
7688 {"ChangeDrillSize", 0, ActionChange2ndSize
,
7689 changedrillsize_help
, changedrillsize_syntax
}
7691 {"ChangeHole", 0, ActionChangeHole
,
7692 changehold_help
, changehold_syntax
}
7694 {"ChangeJoin", 0, ActionChangeJoin
,
7695 changejoin_help
, changejoin_syntax
}
7697 {"ChangeName", 0, ActionChangeName
,
7698 changename_help
, changename_syntax
}
7700 {"ChangePaste", 0, ActionChangePaste
,
7701 changepaste_help
, changepaste_syntax
}
7703 {"ChangePinName", 0, ActionChangePinName
,
7704 changepinname_help
, changepinname_syntax
}
7706 {"ChangeSize", 0, ActionChangeSize
,
7707 changesize_help
, changesize_syntax
}
7709 {"ChangeSquare", 0, ActionChangeSquare
,
7710 changesquare_help
, changesquare_syntax
}
7712 {"ChangeOctagon", 0, ActionChangeOctagon
,
7713 changeoctagon_help
, changeoctagon_syntax
}
7715 {"ClearSquare", 0, ActionClearSquare
,
7716 clearsquare_help
, clearsquare_syntax
}
7718 {"ClearOctagon", 0, ActionClearOctagon
,
7719 clearoctagon_help
, clearoctagon_syntax
}
7721 {"Connection", 0, ActionConnection
,
7722 connection_help
, connection_syntax
}
7724 {"Delete", 0, ActionDelete
,
7725 delete_help
, delete_syntax
}
7727 {"DeleteRats", 0, ActionDeleteRats
,
7728 deleterats_help
, deleterats_syntax
}
7730 {"DisperseElements", 0, ActionDisperseElements
,
7731 disperseelements_help
, disperseelements_syntax
}
7733 {"Display", 0, ActionDisplay
,
7734 display_help
, display_syntax
}
7736 {"DRC", 0, ActionDRCheck
,
7737 drc_help
, drc_syntax
}
7739 {"DumpLibrary", 0, ActionDumpLibrary
,
7740 dumplibrary_help
, dumplibrary_syntax
}
7742 {"ExecuteFile", 0, ActionExecuteFile
,
7743 executefile_help
, executefile_syntax
}
7745 {"Flip", "Click on Object or Flip Point", ActionFlip
,
7746 flip_help
, flip_syntax
}
7748 {"LoadFrom", 0, ActionLoadFrom
,
7749 loadfrom_help
, loadfrom_syntax
}
7751 {"MarkCrosshair", 0, ActionMarkCrosshair
,
7752 markcrosshair_help
, markcrosshair_syntax
}
7754 {"Message", 0, ActionMessage
,
7755 message_help
, message_syntax
}
7757 {"MinMaskGap", 0, ActionMinMaskGap
,
7758 minmaskgap_help
, minmaskgap_syntax
}
7760 {"MinClearGap", 0, ActionMinClearGap
,
7761 mincleargap_help
, mincleargap_syntax
}
7763 {"Mode", 0, ActionMode
,
7764 mode_help
, mode_syntax
}
7766 {"MorphPolygon", 0, ActionMorphPolygon
,
7767 morphpolygon_help
, morphpolygon_syntax
}
7769 {"PasteBuffer", 0, ActionPasteBuffer
,
7770 pastebuffer_help
, pastebuffer_syntax
}
7772 {"Quit", 0, ActionQuit
,
7773 quit_help
, quit_syntax
}
7775 {"RemoveSelected", 0, ActionRemoveSelected
,
7776 removeselected_help
, removeselected_syntax
}
7778 {"Renumber", 0, ActionRenumber
,
7779 renumber_help
, renumber_syntax
}
7781 {"RipUp", 0, ActionRipUp
,
7782 ripup_help
, ripup_syntax
}
7784 {"Select", 0, ActionSelect
,
7785 select_help
, select_syntax
}
7787 {"Unselect", 0, ActionUnselect
,
7788 unselect_help
, unselect_syntax
}
7790 {"SaveSettings", 0, ActionSaveSettings
,
7791 savesettings_help
, savesettings_syntax
}
7793 {"SaveTo", 0, ActionSaveTo
,
7794 saveto_help
, saveto_syntax
}
7796 {"SetSquare", 0, ActionSetSquare
,
7797 setsquare_help
, setsquare_syntax
}
7799 {"SetOctagon", 0, ActionSetOctagon
,
7800 setoctagon_help
, setoctagon_syntax
}
7802 {"SetThermal", 0, ActionSetThermal
,
7803 setthermal_help
, setthermal_syntax
}
7805 {"SetValue", 0, ActionSetValue
,
7806 setvalue_help
, setvalue_syntax
}
7808 {"ToggleHideName", 0, ActionToggleHideName
,
7809 togglehidename_help
, togglehidename_syntax
}
7811 {"Undo", 0, ActionUndo
,
7812 undo_help
, undo_syntax
}
7814 {"Redo", 0, ActionRedo
,
7815 redo_help
, redo_syntax
}
7817 {"SetSame", "Select item to use attributes from", ActionSetSame
,
7818 setsame_help
, setsame_syntax
}
7820 {"SetFlag", 0, ActionSetFlag
,
7821 setflag_help
, setflag_syntax
}
7823 {"ClrFlag", 0, ActionClrFlag
,
7824 clrflag_help
, clrflag_syntax
}
7826 {"ChangeFlag", 0, ActionChangeFlag
,
7827 changeflag_help
, changeflag_syntax
}
7829 {"Polygon", 0, ActionPolygon
,
7830 polygon_help
, polygon_syntax
}
7832 {"RouteStyle", 0, ActionRouteStyle
,
7833 routestyle_help
, routestyle_syntax
}
7835 {"MoveObject", "Select an Object", ActionMoveObject
,
7836 moveobject_help
, moveobject_syntax
}
7838 {"MoveToCurrentLayer", 0, ActionMoveToCurrentLayer
,
7839 movetocurrentlayer_help
, movetocurrentlayer_syntax
}
7841 {"New", 0, ActionNew
,
7842 new_help
, new_syntax
}
7844 {"pscalib", 0, ActionPSCalib
}
7846 {"ElementList", 0, ActionElementList
,
7847 elementlist_help
, elementlist_syntax
}
7849 {"ElementSetAttr", 0, ActionElementSetAttr
,
7850 elementsetattr_help
, elementsetattr_syntax
}
7852 {"ExecCommand", 0, ActionExecCommand
,
7853 execcommand_help
, execcommand_syntax
}
7855 {"Import", 0, ActionImport
,
7856 import_help
, import_syntax
}
7860 REGISTER_ACTIONS (action_action_list
)