6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996, 2005 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
29 /* functions used to create vias, pins ...
50 #include "pcb-printf.h"
58 #ifdef HAVE_LIBDMALLOC
64 /* ---------------------------------------------------------------------------
65 * some local identifiers
67 static int ID
= 1; /* current object ID; incremented after */
68 /* each creation of an object */
70 static bool be_lenient
= false;
72 /* ----------------------------------------------------------------------
73 * some local prototypes
75 static void AddTextToElement (TextTypePtr
, FontTypePtr
,
76 Coord
, Coord
, unsigned, char *, int,
79 /* ---------------------------------------------------------------------------
80 * Set the lenience mode.
84 CreateBeLenient (bool v
)
89 /* ---------------------------------------------------------------------------
90 * creates a new paste buffer
93 CreateNewBuffer (void)
96 data
= (DataTypePtr
) calloc (1, sizeof (DataType
));
97 data
->pcb
= (PCBTypePtr
) PCB
;
101 /* ---------------------------------------------------------------------------
102 * Perhaps PCB should internally just use the Settings colors? For now,
103 * use this to set PCB colors so the config can reassign PCB colors.
106 pcb_colors_from_settings (PCBTypePtr ptr
)
110 /* copy default settings */
111 ptr
->ConnectedColor
= Settings
.ConnectedColor
;
112 ptr
->ElementColor
= Settings
.ElementColor
;
113 ptr
->RatColor
= Settings
.RatColor
;
114 ptr
->InvisibleObjectsColor
= Settings
.InvisibleObjectsColor
;
115 ptr
->InvisibleMarkColor
= Settings
.InvisibleMarkColor
;
116 ptr
->ElementSelectedColor
= Settings
.ElementSelectedColor
;
117 ptr
->RatSelectedColor
= Settings
.RatSelectedColor
;
118 ptr
->PinColor
= Settings
.PinColor
;
119 ptr
->PinSelectedColor
= Settings
.PinSelectedColor
;
120 ptr
->PinNameColor
= Settings
.PinNameColor
;
121 ptr
->ViaColor
= Settings
.ViaColor
;
122 ptr
->ViaSelectedColor
= Settings
.ViaSelectedColor
;
123 ptr
->WarnColor
= Settings
.WarnColor
;
124 ptr
->MaskColor
= Settings
.MaskColor
;
125 for (i
= 0; i
< MAX_LAYER
; i
++)
127 ptr
->Data
->Layer
[i
].Color
= Settings
.LayerColor
[i
];
128 ptr
->Data
->Layer
[i
].SelectedColor
= Settings
.LayerSelectedColor
[i
];
130 ptr
->Data
->Layer
[component_silk_layer
].Color
=
131 Settings
.ShowSolderSide
?
132 Settings
.InvisibleObjectsColor
: Settings
.ElementColor
;
133 ptr
->Data
->Layer
[component_silk_layer
].SelectedColor
=
134 Settings
.ElementSelectedColor
;
135 ptr
->Data
->Layer
[solder_silk_layer
].Color
=
136 Settings
.ShowSolderSide
?
137 Settings
.ElementColor
: Settings
.InvisibleObjectsColor
;
138 ptr
->Data
->Layer
[solder_silk_layer
].SelectedColor
=
139 Settings
.ElementSelectedColor
;
142 /* ---------------------------------------------------------------------------
146 CreateNewPCB (bool SetDefaultNames
)
151 /* allocate memory, switch all layers on and copy resources */
152 ptr
= (PCBTypePtr
)calloc (1, sizeof (PCBType
));
153 ptr
->Data
= CreateNewBuffer ();
154 ptr
->Data
->pcb
= (PCBTypePtr
) ptr
;
157 ptr
->IsleArea
= 2.e8
;
158 ptr
->SilkActive
= false;
159 ptr
->RatDraw
= false;
160 SET_FLAG (NAMEONPCBFLAG
, ptr
);
161 if (Settings
.ShowNumber
)
162 SET_FLAG (SHOWNUMBERFLAG
, ptr
);
163 if (Settings
.AllDirectionLines
)
164 SET_FLAG (ALLDIRECTIONFLAG
, ptr
);
165 ptr
->Clipping
= 1; /* this is the most useful starting point for now */
166 if (Settings
.RubberBandMode
)
167 SET_FLAG (RUBBERBANDFLAG
, ptr
);
168 if (Settings
.SwapStartDirection
)
169 SET_FLAG (SWAPSTARTDIRFLAG
, ptr
);
170 if (Settings
.UniqueNames
)
171 SET_FLAG (UNIQUENAMEFLAG
, ptr
);
172 if (Settings
.SnapPin
)
173 SET_FLAG (SNAPPINFLAG
, ptr
);
174 if (Settings
.ClearLine
)
175 SET_FLAG (CLEARNEWFLAG
, ptr
);
176 if (Settings
.FullPoly
)
177 SET_FLAG (NEWFULLPOLYFLAG
, ptr
);
178 if (Settings
.OrthogonalMoves
)
179 SET_FLAG (ORTHOMOVEFLAG
, ptr
);
180 if (Settings
.liveRouting
)
181 SET_FLAG (LIVEROUTEFLAG
, ptr
);
182 if (Settings
.ShowDRC
)
183 SET_FLAG (SHOWDRCFLAG
, ptr
);
184 if (Settings
.AutoDRC
)
185 SET_FLAG (AUTODRCFLAG
, ptr
);
186 ptr
->Grid
= Settings
.Grid
;
187 ptr
->LayerGroups
= Settings
.LayerGroups
;
190 *style
= Settings
.RouteStyle
[n
];
194 ptr
->Zoom
= Settings
.Zoom
;
195 ptr
->MaxWidth
= Settings
.MaxWidth
;
196 ptr
->MaxHeight
= Settings
.MaxHeight
;
198 ptr
->ThermScale
= 0.5;
200 ptr
->Bloat
= Settings
.Bloat
;
201 ptr
->Shrink
= Settings
.Shrink
;
202 ptr
->minWid
= Settings
.minWid
;
203 ptr
->minSlk
= Settings
.minSlk
;
204 ptr
->minDrill
= Settings
.minDrill
;
205 ptr
->minRing
= Settings
.minRing
;
207 for (i
= 0; i
< MAX_LAYER
; i
++)
208 ptr
->Data
->Layer
[i
].Name
= strdup (Settings
.DefaultLayerName
[i
]);
210 CreateDefaultFont (ptr
);
215 /* This post-processing step adds the top and bottom silk layers to a
219 CreateNewPCBPost (PCBTypePtr pcb
, int use_defaults
)
221 /* copy default settings */
222 pcb_colors_from_settings (pcb
);
226 if (ParseGroupString (Settings
.Groups
, &pcb
->LayerGroups
, DEF_LAYER
))
229 pcb
->Data
->Layer
[component_silk_layer
].Name
= strdup ("silk");
230 pcb
->Data
->Layer
[solder_silk_layer
].Name
= strdup ("silk");
235 /* ---------------------------------------------------------------------------
239 CreateNewVia (DataTypePtr Data
,
241 Coord Thickness
, Coord Clearance
, Coord Mask
,
242 Coord DrillingHole
, char *Name
, FlagType Flags
)
250 if (Distance (X
, Y
, via
->X
, via
->Y
) <=
251 via
->DrillingHole
/ 2 + DrillingHole
/ 2)
253 Message (_("%m+Dropping via at %$mD because it's hole would overlap with the via "
254 "at %$mD\n"), Settings
.grid_unit
->allow
, X
, Y
, via
->X
, via
->Y
);
255 return (NULL
); /* don't allow via stacking */
261 Via
= GetViaMemory (Data
);
268 Via
->Thickness
= Thickness
;
269 Via
->Clearance
= Clearance
;
271 Via
->DrillingHole
= vendorDrillMap (DrillingHole
);
272 if (Via
->DrillingHole
!= DrillingHole
)
274 Message (_("%m+Mapped via drill hole to %$mS from %$mS per vendor table\n"),
275 Settings
.grid_unit
->allow
, Via
->DrillingHole
, DrillingHole
);
278 Via
->Name
= STRDUP (Name
);
280 CLEAR_FLAG (WARNFLAG
, Via
);
281 SET_FLAG (VIAFLAG
, Via
);
285 * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure
288 if (!TEST_FLAG (HOLEFLAG
, Via
) &&
289 (Via
->Thickness
< Via
->DrillingHole
+ MIN_PINORVIACOPPER
))
291 Via
->Thickness
= Via
->DrillingHole
+ MIN_PINORVIACOPPER
;
292 Message (_("%m+Increased via thickness to %$mS to allow enough copper"
294 Settings
.grid_unit
->allow
, Via
->Thickness
, Via
->X
, Via
->Y
);
297 SetPinBoundingBox (Via
);
299 Data
->via_tree
= r_create_tree (NULL
, 0, 0);
300 r_insert_entry (Data
->via_tree
, (BoxTypePtr
) Via
, 0);
306 Coord X1
, X2
, Y1
, Y2
;
314 line_callback (const BoxType
* b
, void *cl
)
316 LineTypePtr line
= (LineTypePtr
) b
;
317 struct line_info
*i
= (struct line_info
*) cl
;
319 if (line
->Point1
.X
== i
->X1
&&
320 line
->Point2
.X
== i
->X2
&&
321 line
->Point1
.Y
== i
->Y1
&& line
->Point2
.Y
== i
->Y2
)
323 i
->ans
= (LineTypePtr
) (-1);
326 /* check the other point order */
327 if (line
->Point1
.X
== i
->X1
&&
328 line
->Point2
.X
== i
->X2
&&
329 line
->Point1
.Y
== i
->Y1
&& line
->Point2
.Y
== i
->Y2
)
331 i
->ans
= (LineTypePtr
) (-1);
334 if (line
->Point2
.X
== i
->X1
&&
335 line
->Point1
.X
== i
->X2
&&
336 line
->Point2
.Y
== i
->Y1
&& line
->Point1
.Y
== i
->Y2
)
338 i
->ans
= (LineTypePtr
) - 1;
341 /* remove unnecessary line points */
342 if (line
->Thickness
== i
->Thickness
343 /* don't merge lines if the clear flags differ */
344 && TEST_FLAG (CLEARLINEFLAG
, line
) == TEST_FLAG (CLEARLINEFLAG
, i
))
346 if (line
->Point1
.X
== i
->X1
&& line
->Point1
.Y
== i
->Y1
)
348 i
->test
.Point1
.X
= line
->Point2
.X
;
349 i
->test
.Point1
.Y
= line
->Point2
.Y
;
350 i
->test
.Point2
.X
= i
->X2
;
351 i
->test
.Point2
.Y
= i
->Y2
;
352 if (IsPointOnLine (i
->X1
, i
->Y1
, 0.0, &i
->test
))
358 else if (line
->Point2
.X
== i
->X1
&& line
->Point2
.Y
== i
->Y1
)
360 i
->test
.Point1
.X
= line
->Point1
.X
;
361 i
->test
.Point1
.Y
= line
->Point1
.Y
;
362 i
->test
.Point2
.X
= i
->X2
;
363 i
->test
.Point2
.Y
= i
->Y2
;
364 if (IsPointOnLine (i
->X1
, i
->Y1
, 0.0, &i
->test
))
370 else if (line
->Point1
.X
== i
->X2
&& line
->Point1
.Y
== i
->Y2
)
372 i
->test
.Point1
.X
= line
->Point2
.X
;
373 i
->test
.Point1
.Y
= line
->Point2
.Y
;
374 i
->test
.Point2
.X
= i
->X1
;
375 i
->test
.Point2
.Y
= i
->Y1
;
376 if (IsPointOnLine (i
->X2
, i
->Y2
, 0.0, &i
->test
))
382 else if (line
->Point2
.X
== i
->X2
&& line
->Point2
.Y
== i
->Y2
)
384 i
->test
.Point1
.X
= line
->Point1
.X
;
385 i
->test
.Point1
.Y
= line
->Point1
.Y
;
386 i
->test
.Point2
.X
= i
->X1
;
387 i
->test
.Point2
.Y
= i
->Y1
;
388 if (IsPointOnLine (i
->X2
, i
->Y2
, 0.0, &i
->test
))
399 /* ---------------------------------------------------------------------------
400 * creates a new line on a layer and checks for overlap and extension
403 CreateDrawnLineOnLayer (LayerTypePtr Layer
,
406 Coord Thickness
, Coord Clearance
,
409 struct line_info info
;
412 search
.X1
= MIN (X1
, X2
);
413 search
.X2
= MAX (X1
, X2
);
414 search
.Y1
= MIN (Y1
, Y2
);
415 search
.Y2
= MAX (Y1
, Y2
);
416 if (search
.Y2
== search
.Y1
)
418 if (search
.X2
== search
.X1
)
424 info
.Thickness
= Thickness
;
426 info
.test
.Thickness
= 0;
427 info
.test
.Flags
= NoFlags ();
429 /* prevent stacking of duplicate lines
430 * and remove needless intermediate points
431 * verify that the layer is on the board first!
433 if (setjmp (info
.env
) == 0)
435 r_search (Layer
->line_tree
, &search
, NULL
, line_callback
, &info
);
436 return CreateNewLineOnLayer (Layer
, X1
, Y1
, X2
, Y2
,
437 Thickness
, Clearance
, Flags
);
440 if ((void *) info
.ans
== (void *) (-1))
441 return NULL
; /* stacked line */
442 /* remove unnecessary points */
445 /* must do this BEFORE getting new line memory */
446 MoveObjectToRemoveUndoList (LINE_TYPE
, Layer
, info
.ans
, info
.ans
);
447 X1
= info
.test
.Point1
.X
;
448 X2
= info
.test
.Point2
.X
;
449 Y1
= info
.test
.Point1
.Y
;
450 Y2
= info
.test
.Point2
.Y
;
452 return CreateNewLineOnLayer (Layer
, X1
, Y1
, X2
, Y2
,
453 Thickness
, Clearance
, Flags
);
457 CreateNewLineOnLayer (LayerTypePtr Layer
,
460 Coord Thickness
, Coord Clearance
,
465 Line
= GetLineMemory (Layer
);
470 CLEAR_FLAG (RATFLAG
, Line
);
471 Line
->Thickness
= Thickness
;
472 Line
->Clearance
= Clearance
;
475 Line
->Point1
.ID
= ID
++;
478 Line
->Point2
.ID
= ID
++;
479 SetLineBoundingBox (Line
);
480 if (!Layer
->line_tree
)
481 Layer
->line_tree
= r_create_tree (NULL
, 0, 0);
482 r_insert_entry (Layer
->line_tree
, (BoxTypePtr
) Line
, 0);
486 /* ---------------------------------------------------------------------------
487 * creates a new rat-line
490 CreateNewRat (DataTypePtr Data
, Coord X1
, Coord Y1
,
491 Coord X2
, Coord Y2
, Cardinal group1
,
492 Cardinal group2
, Coord Thickness
, FlagType Flags
)
494 RatTypePtr Line
= GetRatMemory (Data
);
501 SET_FLAG (RATFLAG
, Line
);
502 Line
->Thickness
= Thickness
;
505 Line
->Point1
.ID
= ID
++;
508 Line
->Point2
.ID
= ID
++;
509 Line
->group1
= group1
;
510 Line
->group2
= group2
;
511 SetLineBoundingBox ((LineTypePtr
) Line
);
513 Data
->rat_tree
= r_create_tree (NULL
, 0, 0);
514 r_insert_entry (Data
->rat_tree
, &Line
->BoundingBox
, 0);
518 /* ---------------------------------------------------------------------------
519 * creates a new arc on a layer
522 CreateNewArcOnLayer (LayerTypePtr Layer
,
527 Angle dir
, Coord Thickness
,
528 Coord Clearance
, FlagType Flags
)
534 if (arc
->X
== X1
&& arc
->Y
== Y1
&& arc
->Width
== width
&&
535 NormalizeAngle (arc
->StartAngle
) == NormalizeAngle (sa
) &&
537 return (NULL
); /* prevent stacked arcs */
540 Arc
= GetArcMemory (Layer
);
546 Arc
->Thickness
= Thickness
;
547 Arc
->Clearance
= Clearance
;
551 Arc
->Height
= height
;
552 Arc
->StartAngle
= sa
;
554 SetArcBoundingBox (Arc
);
555 if (!Layer
->arc_tree
)
556 Layer
->arc_tree
= r_create_tree (NULL
, 0, 0);
557 r_insert_entry (Layer
->arc_tree
, (BoxTypePtr
) Arc
, 0);
562 /* ---------------------------------------------------------------------------
563 * creates a new polygon from the old formats rectangle data
566 CreateNewPolygonFromRectangle (LayerTypePtr Layer
,
571 PolygonTypePtr polygon
= CreateNewPolygon (Layer
, Flags
);
575 CreateNewPointInPolygon (polygon
, X1
, Y1
);
576 CreateNewPointInPolygon (polygon
, X2
, Y1
);
577 CreateNewPointInPolygon (polygon
, X2
, Y2
);
578 CreateNewPointInPolygon (polygon
, X1
, Y2
);
579 SetPolygonBoundingBox (polygon
);
580 if (!Layer
->polygon_tree
)
581 Layer
->polygon_tree
= r_create_tree (NULL
, 0, 0);
582 r_insert_entry (Layer
->polygon_tree
, (BoxTypePtr
) polygon
, 0);
586 /* ---------------------------------------------------------------------------
587 * creates a new text on a layer
590 CreateNewText (LayerTypePtr Layer
, FontTypePtr PCBFont
,
592 unsigned Direction
, int Scale
, char *TextString
, FlagType Flags
)
596 if (TextString
== NULL
)
599 text
= GetTextMemory (Layer
);
603 /* copy values, width and height are set by drawing routine
604 * because at this point we don't know which symbols are available
608 text
->Direction
= Direction
;
611 text
->TextString
= strdup (TextString
);
613 /* calculate size of the bounding box */
614 SetTextBoundingBox (PCBFont
, text
);
616 if (!Layer
->text_tree
)
617 Layer
->text_tree
= r_create_tree (NULL
, 0, 0);
618 r_insert_entry (Layer
->text_tree
, (BoxTypePtr
) text
, 0);
622 /* ---------------------------------------------------------------------------
623 * creates a new polygon on a layer
626 CreateNewPolygon (LayerTypePtr Layer
, FlagType Flags
)
628 PolygonTypePtr polygon
= GetPolygonMemory (Layer
);
631 polygon
->Flags
= Flags
;
633 polygon
->Clipped
= NULL
;
634 polygon
->NoHoles
= NULL
;
635 polygon
->NoHolesValid
= 0;
639 /* ---------------------------------------------------------------------------
640 * creates a new point in a polygon
643 CreateNewPointInPolygon (PolygonTypePtr Polygon
, Coord X
, Coord Y
)
645 PointTypePtr point
= GetPointMemoryInPolygon (Polygon
);
654 /* ---------------------------------------------------------------------------
655 * creates a new hole in a polygon
658 CreateNewHoleInPolygon (PolygonType
*Polygon
)
660 Cardinal
*holeindex
= GetHoleIndexMemoryInPolygon (Polygon
);
661 *holeindex
= Polygon
->PointN
;
665 /* ---------------------------------------------------------------------------
666 * creates an new element
667 * memory is allocated if needed
670 CreateNewElement (DataTypePtr Data
, ElementTypePtr Element
,
673 char *Description
, char *NameOnPCB
, char *Value
,
674 Coord TextX
, Coord TextY
, BYTE Direction
,
675 int TextScale
, FlagType TextFlags
, bool uniqueName
)
678 printf("Entered CreateNewElement.....\n");
682 Element
= GetElementMemory (Data
);
684 /* copy values and set additional information */
685 TextScale
= MAX (MIN_TEXTSCALE
, TextScale
);
686 AddTextToElement (&DESCRIPTION_TEXT (Element
), PCBFont
, TextX
, TextY
,
687 Direction
, Description
, TextScale
, TextFlags
);
689 NameOnPCB
= UniqueElementName (Data
, NameOnPCB
);
690 AddTextToElement (&NAMEONPCB_TEXT (Element
), PCBFont
, TextX
, TextY
,
691 Direction
, NameOnPCB
, TextScale
, TextFlags
);
692 AddTextToElement (&VALUE_TEXT (Element
), PCBFont
, TextX
, TextY
,
693 Direction
, Value
, TextScale
, TextFlags
);
694 DESCRIPTION_TEXT (Element
).Element
= Element
;
695 NAMEONPCB_TEXT (Element
).Element
= Element
;
696 VALUE_TEXT (Element
).Element
= Element
;
697 Element
->Flags
= Flags
;
701 printf(" .... Leaving CreateNewElement.\n");
707 /* ---------------------------------------------------------------------------
708 * creates a new arc in an element
711 CreateNewArcInElement (ElementTypePtr Element
,
713 Coord Width
, Coord Height
,
714 Angle angle
, Angle delta
, Coord Thickness
)
718 arc
= g_slice_new0 (ArcType
);
719 Element
->Arc
= g_list_append (Element
->Arc
, arc
);
722 /* set Delta (0,360], StartAngle in [0,360) */
728 angle
= NormalizeAngle (angle
);
729 delta
= NormalizeAngle (delta
);
737 arc
->Height
= Height
;
738 arc
->StartAngle
= angle
;
740 arc
->Thickness
= Thickness
;
745 /* ---------------------------------------------------------------------------
746 * creates a new line for an element
749 CreateNewLineInElement (ElementTypePtr Element
,
759 line
= g_slice_new0 (LineType
);
760 Element
->Line
= g_list_append (Element
->Line
, line
);
768 line
->Thickness
= Thickness
;
769 line
->Flags
= NoFlags ();
774 /* ---------------------------------------------------------------------------
775 * creates a new pin in an element
778 CreateNewPin (ElementTypePtr Element
,
780 Coord Thickness
, Coord Clearance
, Coord Mask
,
781 Coord DrillingHole
, char *Name
, char *Number
,
784 PinTypePtr pin
= GetPinMemory (Element
);
789 pin
->Thickness
= Thickness
;
790 pin
->Clearance
= Clearance
;
792 pin
->Name
= STRDUP (Name
);
793 pin
->Number
= STRDUP (Number
);
795 CLEAR_FLAG (WARNFLAG
, pin
);
796 SET_FLAG (PINFLAG
, pin
);
798 pin
->Element
= Element
;
801 * If there is no vendor drill map installed, this will simply
802 * return DrillingHole.
804 pin
->DrillingHole
= vendorDrillMap (DrillingHole
);
806 /* Unless we should not map drills on this element, map them! */
807 if (vendorIsElementMappable (Element
))
809 if (pin
->DrillingHole
< MIN_PINORVIASIZE
)
811 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is below the minimum allowed size\n"),
812 Settings
.grid_unit
->allow
, UNKNOWN (Number
), UNKNOWN (Name
), pin
->DrillingHole
);
813 pin
->DrillingHole
= DrillingHole
;
815 else if (pin
->DrillingHole
> MAX_PINORVIASIZE
)
817 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is above the maximum allowed size\n"),
818 Settings
.grid_unit
->allow
, UNKNOWN (Number
), UNKNOWN (Name
), pin
->DrillingHole
);
819 pin
->DrillingHole
= DrillingHole
;
821 else if (!TEST_FLAG (HOLEFLAG
, pin
)
822 && (pin
->DrillingHole
> pin
->Thickness
- MIN_PINORVIACOPPER
))
824 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS does not leave enough copper\n"),
825 Settings
.grid_unit
->allow
, UNKNOWN (Number
), UNKNOWN (Name
), pin
->DrillingHole
);
826 pin
->DrillingHole
= DrillingHole
;
831 pin
->DrillingHole
= DrillingHole
;
834 if (pin
->DrillingHole
!= DrillingHole
)
836 Message (_("%m+Mapped pin drill hole to %$mS from %$mS per vendor table\n"),
837 Settings
.grid_unit
->allow
, pin
->DrillingHole
, DrillingHole
);
843 /* ---------------------------------------------------------------------------
844 * creates a new pad in an element
847 CreateNewPad (ElementTypePtr Element
,
848 Coord X1
, Coord Y1
, Coord X2
,
849 Coord Y2
, Coord Thickness
, Coord Clearance
,
850 Coord Mask
, char *Name
, char *Number
, FlagType Flags
)
852 PadTypePtr pad
= GetPadMemory (Element
);
855 if (X1
> X2
|| (X1
== X2
&& Y1
> Y2
))
869 pad
->Thickness
= Thickness
;
870 pad
->Clearance
= Clearance
;
872 pad
->Name
= STRDUP (Name
);
873 pad
->Number
= STRDUP (Number
);
875 CLEAR_FLAG (WARNFLAG
, pad
);
877 pad
->Element
= Element
;
881 /* ---------------------------------------------------------------------------
882 * creates a new textobject as part of an element
883 * copies the values to the appropriate text object
886 AddTextToElement (TextTypePtr Text
, FontTypePtr PCBFont
,
888 unsigned Direction
, char *TextString
, int Scale
, FlagType Flags
)
890 free (Text
->TextString
);
891 Text
->TextString
= (TextString
&& *TextString
) ? strdup (TextString
) : NULL
;
894 Text
->Direction
= Direction
;
898 /* calculate size of the bounding box */
899 SetTextBoundingBox (PCBFont
, Text
);
903 /* ---------------------------------------------------------------------------
904 * creates a new line in a symbol
907 CreateNewLineInSymbol (SymbolTypePtr Symbol
,
909 Coord X2
, Coord Y2
, Coord Thickness
)
911 LineTypePtr line
= Symbol
->Line
;
913 /* realloc new memory if necessary and clear it */
914 if (Symbol
->LineN
>= Symbol
->LineMax
)
916 Symbol
->LineMax
+= STEP_SYMBOLLINE
;
917 line
= (LineTypePtr
)realloc (line
, Symbol
->LineMax
* sizeof (LineType
));
919 memset (line
+ Symbol
->LineN
, 0, STEP_SYMBOLLINE
* sizeof (LineType
));
923 line
= line
+ Symbol
->LineN
++;
928 line
->Thickness
= Thickness
;
932 /* ---------------------------------------------------------------------------
933 * parses a file with font information and installs it into the provided PCB
934 * checks directories given as colon separated list by resource fontPath
935 * if the fonts filename doesn't contain a directory component
938 CreateDefaultFont (PCBTypePtr pcb
)
940 if (ParseFont (&pcb
->Font
, Settings
.FontFile
))
941 Message (_("Can't find font-symbol-file '%s'\n"), Settings
.FontFile
);
944 /* ---------------------------------------------------------------------------
945 * adds a new line to the rubberband list of 'Crosshair.AttachedObject'
946 * if Layer == 0 it is a rat line
949 CreateNewRubberbandEntry (LayerTypePtr Layer
,
950 LineTypePtr Line
, PointTypePtr MovedPoint
)
952 RubberbandTypePtr ptr
= GetRubberbandMemory ();
954 /* we toggle the RUBBERENDFLAG of the line to determine if */
955 /* both points are being moved. */
956 TOGGLE_FLAG (RUBBERENDFLAG
, Line
);
959 ptr
->MovedPoint
= MovedPoint
;
963 /* ---------------------------------------------------------------------------
964 * Add a new net to the netlist menu
967 CreateNewNet (LibraryTypePtr lib
, char *name
, char *style
)
969 LibraryMenuTypePtr menu
;
972 sprintf (temp
, " %s", name
);
973 menu
= GetLibraryMenuMemory (lib
);
974 menu
->Name
= strdup (temp
);
975 menu
->flag
= 1; /* net is enabled by default */
976 if (style
== NULL
|| NSTRCMP ("(unknown)", style
) == 0)
979 menu
->Style
= strdup (style
);
983 /* ---------------------------------------------------------------------------
984 * Add a connection to the net
987 CreateNewConnection (LibraryMenuTypePtr net
, char *conn
)
989 LibraryEntryTypePtr entry
= GetLibraryEntryMemory (net
);
991 entry
->ListEntry
= STRDUP (conn
);
995 /* ---------------------------------------------------------------------------
996 * Add an attribute to a list.
999 CreateNewAttribute (AttributeListTypePtr list
, char *name
, char *value
)
1001 if (list
->Number
>= list
->Max
)
1004 list
->List
= (AttributeType
*)realloc (list
->List
, list
->Max
* sizeof (AttributeType
));
1006 list
->List
[list
->Number
].name
= STRDUP (name
);
1007 list
->List
[list
->Number
].value
= STRDUP (value
);
1009 return &list
->List
[list
->Number
- 1];