4 * PCB, interactive printed circuit board design
5 * Copyright (C) 1994,1995,1996, 2005 Thomas Nau
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * Contact addresses for paper mail and Email:
22 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
23 * Thomas.Nau@rz.uni-ulm.de
27 /* functions used to create vias, pins ...
48 #include "pcb-printf.h"
56 #ifdef HAVE_LIBDMALLOC
60 /* ---------------------------------------------------------------------------
61 * some local identifiers
63 static int ID
= 1; /* current object ID; incremented after */
64 /* each creation of an object */
66 static bool be_lenient
= false;
68 /* ----------------------------------------------------------------------
69 * some local prototypes
71 static void AddTextToElement (TextType
*, FontType
*,
72 Coord
, Coord
, unsigned, char *, int,
75 /* ---------------------------------------------------------------------------
76 * Set the lenience mode.
80 CreateBeLenient (bool v
)
85 /* ---------------------------------------------------------------------------
86 * creates a new paste buffer
89 CreateNewBuffer (void)
92 data
= (DataType
*) calloc (1, sizeof (DataType
));
93 data
->pcb
= (PCBType
*) PCB
;
97 /* ---------------------------------------------------------------------------
98 * Perhaps PCB should internally just use the Settings colors? For now,
99 * use this to set PCB colors so the config can reassign PCB colors.
102 pcb_colors_from_settings (PCBType
*ptr
)
106 /* copy default settings */
107 ptr
->ConnectedColor
= Settings
.ConnectedColor
;
108 ptr
->ElementColor
= Settings
.ElementColor
;
109 ptr
->RatColor
= Settings
.RatColor
;
110 ptr
->InvisibleObjectsColor
= Settings
.InvisibleObjectsColor
;
111 ptr
->InvisibleMarkColor
= Settings
.InvisibleMarkColor
;
112 ptr
->ElementSelectedColor
= Settings
.ElementSelectedColor
;
113 ptr
->RatSelectedColor
= Settings
.RatSelectedColor
;
114 ptr
->PinColor
= Settings
.PinColor
;
115 ptr
->PinSelectedColor
= Settings
.PinSelectedColor
;
116 ptr
->PinNameColor
= Settings
.PinNameColor
;
117 ptr
->ViaColor
= Settings
.ViaColor
;
118 ptr
->ViaSelectedColor
= Settings
.ViaSelectedColor
;
119 ptr
->WarnColor
= Settings
.WarnColor
;
120 ptr
->MaskColor
= Settings
.MaskColor
;
121 for (i
= 0; i
< MAX_LAYER
; i
++)
123 ptr
->Data
->Layer
[i
].Color
= Settings
.LayerColor
[i
];
124 ptr
->Data
->Layer
[i
].SelectedColor
= Settings
.LayerSelectedColor
[i
];
126 ptr
->Data
->Layer
[component_silk_layer
].Color
=
127 Settings
.ShowSolderSide
?
128 Settings
.InvisibleObjectsColor
: Settings
.ElementColor
;
129 ptr
->Data
->Layer
[component_silk_layer
].SelectedColor
=
130 Settings
.ElementSelectedColor
;
131 ptr
->Data
->Layer
[solder_silk_layer
].Color
=
132 Settings
.ShowSolderSide
?
133 Settings
.ElementColor
: Settings
.InvisibleObjectsColor
;
134 ptr
->Data
->Layer
[solder_silk_layer
].SelectedColor
=
135 Settings
.ElementSelectedColor
;
138 /* ---------------------------------------------------------------------------
142 CreateNewPCB (bool SetDefaultNames
)
147 /* allocate memory, switch all layers on and copy resources */
148 ptr
= (PCBType
*)calloc (1, sizeof (PCBType
));
149 ptr
->Data
= CreateNewBuffer ();
150 ptr
->Data
->pcb
= (PCBType
*) ptr
;
151 ptr
->Data
->polyClip
= 1;
154 ptr
->IsleArea
= 2.e8
;
155 ptr
->SilkActive
= false;
156 ptr
->RatDraw
= false;
157 SET_FLAG (NAMEONPCBFLAG
, ptr
);
158 if (Settings
.ShowNumber
)
159 SET_FLAG (SHOWNUMBERFLAG
, ptr
);
160 if (Settings
.AllDirectionLines
)
161 SET_FLAG (ALLDIRECTIONFLAG
, ptr
);
162 ptr
->Clipping
= 1; /* this is the most useful starting point for now */
163 if (Settings
.RubberBandMode
)
164 SET_FLAG (RUBBERBANDFLAG
, ptr
);
165 if (Settings
.SwapStartDirection
)
166 SET_FLAG (SWAPSTARTDIRFLAG
, ptr
);
167 if (Settings
.UniqueNames
)
168 SET_FLAG (UNIQUENAMEFLAG
, ptr
);
169 if (Settings
.SnapPin
)
170 SET_FLAG (SNAPPINFLAG
, ptr
);
171 if (Settings
.ClearLine
)
172 SET_FLAG (CLEARNEWFLAG
, ptr
);
173 if (Settings
.FullPoly
)
174 SET_FLAG (NEWFULLPOLYFLAG
, ptr
);
175 if (Settings
.OrthogonalMoves
)
176 SET_FLAG (ORTHOMOVEFLAG
, ptr
);
177 if (Settings
.liveRouting
)
178 SET_FLAG (LIVEROUTEFLAG
, ptr
);
179 if (Settings
.ShowDRC
)
180 SET_FLAG (SHOWDRCFLAG
, ptr
);
181 if (Settings
.AutoDRC
)
182 SET_FLAG (AUTODRCFLAG
, ptr
);
183 ptr
->Grid
= Settings
.Grid
;
184 ptr
->LayerGroups
= Settings
.LayerGroups
;
187 *style
= Settings
.RouteStyle
[n
];
191 ptr
->Zoom
= Settings
.Zoom
;
192 ptr
->MaxWidth
= Settings
.MaxWidth
;
193 ptr
->MaxHeight
= Settings
.MaxHeight
;
195 ptr
->ThermScale
= 0.5;
197 ptr
->Bloat
= Settings
.Bloat
;
198 ptr
->Shrink
= Settings
.Shrink
;
199 ptr
->minWid
= Settings
.minWid
;
200 ptr
->minSlk
= Settings
.minSlk
;
201 ptr
->minDrill
= Settings
.minDrill
;
202 ptr
->minRing
= Settings
.minRing
;
204 for (i
= 0; i
< MAX_LAYER
; i
++)
205 ptr
->Data
->Layer
[i
].Name
= strdup (Settings
.DefaultLayerName
[i
]);
207 CreateDefaultFont (ptr
);
212 /* This post-processing step adds the top and bottom silk layers to a
216 CreateNewPCBPost (PCBType
*pcb
, int use_defaults
)
218 /* copy default settings */
219 pcb_colors_from_settings (pcb
);
223 if (ParseGroupString (Settings
.Groups
, &pcb
->LayerGroups
, DEF_LAYER
))
226 pcb
->Data
->Layer
[component_silk_layer
].Name
= strdup ("silk");
227 pcb
->Data
->Layer
[solder_silk_layer
].Name
= strdup ("silk");
232 /* ---------------------------------------------------------------------------
236 CreateNewVia (DataType
*Data
,
238 Coord Thickness
, Coord Clearance
, Coord Mask
,
239 Coord DrillingHole
, char *Name
, FlagType Flags
)
247 if (Distance (X
, Y
, via
->X
, via
->Y
) <=
248 via
->DrillingHole
/ 2 + DrillingHole
/ 2)
250 Message (_("%m+Dropping via at %$mD because it's hole would overlap with the via "
251 "at %$mD\n"), Settings
.grid_unit
->allow
, X
, Y
, via
->X
, via
->Y
);
252 return (NULL
); /* don't allow via stacking */
258 Via
= GetViaMemory (Data
);
265 Via
->Thickness
= Thickness
;
266 Via
->Clearance
= Clearance
;
268 Via
->DrillingHole
= vendorDrillMap (DrillingHole
);
269 if (Via
->DrillingHole
!= DrillingHole
)
271 Message (_("%m+Mapped via drill hole to %$mS from %$mS per vendor table\n"),
272 Settings
.grid_unit
->allow
, Via
->DrillingHole
, DrillingHole
);
275 Via
->Name
= STRDUP (Name
);
277 CLEAR_FLAG (WARNFLAG
, Via
);
278 SET_FLAG (VIAFLAG
, Via
);
282 * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure
285 if (!TEST_FLAG (HOLEFLAG
, Via
) &&
286 (Via
->Thickness
< Via
->DrillingHole
+ MIN_PINORVIACOPPER
))
288 Via
->Thickness
= Via
->DrillingHole
+ MIN_PINORVIACOPPER
;
289 Message (_("%m+Increased via thickness to %$mS to allow enough copper"
291 Settings
.grid_unit
->allow
, Via
->Thickness
, Via
->X
, Via
->Y
);
294 SetPinBoundingBox (Via
);
296 Data
->via_tree
= r_create_tree (NULL
, 0, 0);
297 r_insert_entry (Data
->via_tree
, (BoxType
*) Via
, 0);
303 Coord X1
, X2
, Y1
, Y2
;
311 line_callback (const BoxType
* b
, void *cl
)
313 LineType
*line
= (LineType
*) b
;
314 struct line_info
*i
= (struct line_info
*) cl
;
316 if (line
->Point1
.X
== i
->X1
&&
317 line
->Point2
.X
== i
->X2
&&
318 line
->Point1
.Y
== i
->Y1
&& line
->Point2
.Y
== i
->Y2
)
320 i
->ans
= (LineType
*) (-1);
323 /* check the other point order */
324 if (line
->Point1
.X
== i
->X1
&&
325 line
->Point2
.X
== i
->X2
&&
326 line
->Point1
.Y
== i
->Y1
&& line
->Point2
.Y
== i
->Y2
)
328 i
->ans
= (LineType
*) (-1);
331 if (line
->Point2
.X
== i
->X1
&&
332 line
->Point1
.X
== i
->X2
&&
333 line
->Point2
.Y
== i
->Y1
&& line
->Point1
.Y
== i
->Y2
)
335 i
->ans
= (LineType
*) - 1;
338 /* remove unnecessary line points */
339 if (line
->Thickness
== i
->Thickness
340 /* don't merge lines if the clear flags differ */
341 && TEST_FLAG (CLEARLINEFLAG
, line
) == TEST_FLAG (CLEARLINEFLAG
, i
))
343 if (line
->Point1
.X
== i
->X1
&& line
->Point1
.Y
== i
->Y1
)
345 i
->test
.Point1
.X
= line
->Point2
.X
;
346 i
->test
.Point1
.Y
= line
->Point2
.Y
;
347 i
->test
.Point2
.X
= i
->X2
;
348 i
->test
.Point2
.Y
= i
->Y2
;
349 if (IsPointOnLine (i
->X1
, i
->Y1
, 0.0, &i
->test
))
355 else if (line
->Point2
.X
== i
->X1
&& line
->Point2
.Y
== i
->Y1
)
357 i
->test
.Point1
.X
= line
->Point1
.X
;
358 i
->test
.Point1
.Y
= line
->Point1
.Y
;
359 i
->test
.Point2
.X
= i
->X2
;
360 i
->test
.Point2
.Y
= i
->Y2
;
361 if (IsPointOnLine (i
->X1
, i
->Y1
, 0.0, &i
->test
))
367 else if (line
->Point1
.X
== i
->X2
&& line
->Point1
.Y
== i
->Y2
)
369 i
->test
.Point1
.X
= line
->Point2
.X
;
370 i
->test
.Point1
.Y
= line
->Point2
.Y
;
371 i
->test
.Point2
.X
= i
->X1
;
372 i
->test
.Point2
.Y
= i
->Y1
;
373 if (IsPointOnLine (i
->X2
, i
->Y2
, 0.0, &i
->test
))
379 else if (line
->Point2
.X
== i
->X2
&& line
->Point2
.Y
== i
->Y2
)
381 i
->test
.Point1
.X
= line
->Point1
.X
;
382 i
->test
.Point1
.Y
= line
->Point1
.Y
;
383 i
->test
.Point2
.X
= i
->X1
;
384 i
->test
.Point2
.Y
= i
->Y1
;
385 if (IsPointOnLine (i
->X2
, i
->Y2
, 0.0, &i
->test
))
396 /* ---------------------------------------------------------------------------
397 * creates a new line on a layer and checks for overlap and extension
400 CreateDrawnLineOnLayer (LayerType
*Layer
,
403 Coord Thickness
, Coord Clearance
,
406 struct line_info info
;
409 search
.X1
= MIN (X1
, X2
);
410 search
.X2
= MAX (X1
, X2
);
411 search
.Y1
= MIN (Y1
, Y2
);
412 search
.Y2
= MAX (Y1
, Y2
);
413 if (search
.Y2
== search
.Y1
)
415 if (search
.X2
== search
.X1
)
421 info
.Thickness
= Thickness
;
423 info
.test
.Thickness
= 0;
424 info
.test
.Flags
= NoFlags ();
426 /* prevent stacking of duplicate lines
427 * and remove needless intermediate points
428 * verify that the layer is on the board first!
430 if (setjmp (info
.env
) == 0)
432 r_search (Layer
->line_tree
, &search
, NULL
, line_callback
, &info
);
433 return CreateNewLineOnLayer (Layer
, X1
, Y1
, X2
, Y2
,
434 Thickness
, Clearance
, Flags
);
437 if ((void *) info
.ans
== (void *) (-1))
438 return NULL
; /* stacked line */
439 /* remove unnecessary points */
442 /* must do this BEFORE getting new line memory */
443 MoveObjectToRemoveUndoList (LINE_TYPE
, Layer
, info
.ans
, info
.ans
);
444 X1
= info
.test
.Point1
.X
;
445 X2
= info
.test
.Point2
.X
;
446 Y1
= info
.test
.Point1
.Y
;
447 Y2
= info
.test
.Point2
.Y
;
449 return CreateNewLineOnLayer (Layer
, X1
, Y1
, X2
, Y2
,
450 Thickness
, Clearance
, Flags
);
454 CreateNewLineOnLayer (LayerType
*Layer
,
457 Coord Thickness
, Coord Clearance
,
462 Line
= GetLineMemory (Layer
);
467 CLEAR_FLAG (RATFLAG
, Line
);
468 Line
->Thickness
= Thickness
;
469 Line
->Clearance
= Clearance
;
472 Line
->Point1
.ID
= ID
++;
475 Line
->Point2
.ID
= ID
++;
476 SetLineBoundingBox (Line
);
477 if (!Layer
->line_tree
)
478 Layer
->line_tree
= r_create_tree (NULL
, 0, 0);
479 r_insert_entry (Layer
->line_tree
, (BoxType
*) Line
, 0);
483 /* ---------------------------------------------------------------------------
484 * creates a new rat-line
487 CreateNewRat (DataType
*Data
, Coord X1
, Coord Y1
,
488 Coord X2
, Coord Y2
, Cardinal group1
,
489 Cardinal group2
, Coord Thickness
, FlagType Flags
)
491 RatType
*Line
= GetRatMemory (Data
);
498 SET_FLAG (RATFLAG
, Line
);
499 Line
->Thickness
= Thickness
;
502 Line
->Point1
.ID
= ID
++;
505 Line
->Point2
.ID
= ID
++;
506 Line
->group1
= group1
;
507 Line
->group2
= group2
;
508 SetLineBoundingBox ((LineType
*) Line
);
510 Data
->rat_tree
= r_create_tree (NULL
, 0, 0);
511 r_insert_entry (Data
->rat_tree
, &Line
->BoundingBox
, 0);
515 /* ---------------------------------------------------------------------------
516 * creates a new arc on a layer
519 CreateNewArcOnLayer (LayerType
*Layer
,
524 Angle dir
, Coord Thickness
,
525 Coord Clearance
, FlagType Flags
)
531 if (arc
->X
== X1
&& arc
->Y
== Y1
&& arc
->Width
== width
&&
532 NormalizeAngle (arc
->StartAngle
) == NormalizeAngle (sa
) &&
534 return (NULL
); /* prevent stacked arcs */
537 Arc
= GetArcMemory (Layer
);
543 Arc
->Thickness
= Thickness
;
544 Arc
->Clearance
= Clearance
;
548 Arc
->Height
= height
;
549 Arc
->StartAngle
= sa
;
551 SetArcBoundingBox (Arc
);
552 if (!Layer
->arc_tree
)
553 Layer
->arc_tree
= r_create_tree (NULL
, 0, 0);
554 r_insert_entry (Layer
->arc_tree
, (BoxType
*) Arc
, 0);
559 /* ---------------------------------------------------------------------------
560 * creates a new polygon from the old formats rectangle data
563 CreateNewPolygonFromRectangle (LayerType
*Layer
,
568 PolygonType
*polygon
= CreateNewPolygon (Layer
, Flags
);
572 CreateNewPointInPolygon (polygon
, X1
, Y1
);
573 CreateNewPointInPolygon (polygon
, X2
, Y1
);
574 CreateNewPointInPolygon (polygon
, X2
, Y2
);
575 CreateNewPointInPolygon (polygon
, X1
, Y2
);
576 SetPolygonBoundingBox (polygon
);
577 if (!Layer
->polygon_tree
)
578 Layer
->polygon_tree
= r_create_tree (NULL
, 0, 0);
579 r_insert_entry (Layer
->polygon_tree
, (BoxType
*) polygon
, 0);
583 /* ---------------------------------------------------------------------------
584 * creates a new text on a layer
587 CreateNewText (LayerType
*Layer
, FontType
*PCBFont
,
589 unsigned Direction
, int Scale
, char *TextString
, FlagType Flags
)
593 if (TextString
== NULL
)
596 text
= GetTextMemory (Layer
);
600 /* copy values, width and height are set by drawing routine
601 * because at this point we don't know which symbols are available
605 text
->Direction
= Direction
;
608 text
->TextString
= strdup (TextString
);
610 /* calculate size of the bounding box */
611 SetTextBoundingBox (PCBFont
, text
);
613 if (!Layer
->text_tree
)
614 Layer
->text_tree
= r_create_tree (NULL
, 0, 0);
615 r_insert_entry (Layer
->text_tree
, (BoxType
*) text
, 0);
619 /* ---------------------------------------------------------------------------
620 * creates a new polygon on a layer
623 CreateNewPolygon (LayerType
*Layer
, FlagType Flags
)
625 PolygonType
*polygon
= GetPolygonMemory (Layer
);
628 polygon
->Flags
= Flags
;
630 polygon
->Clipped
= NULL
;
631 polygon
->NoHoles
= NULL
;
632 polygon
->NoHolesValid
= 0;
636 /* ---------------------------------------------------------------------------
637 * creates a new point in a polygon
640 CreateNewPointInPolygon (PolygonType
*Polygon
, Coord X
, Coord Y
)
642 PointType
*point
= GetPointMemoryInPolygon (Polygon
);
651 /* ---------------------------------------------------------------------------
652 * creates a new hole in a polygon
655 CreateNewHoleInPolygon (PolygonType
*Polygon
)
657 Cardinal
*holeindex
= GetHoleIndexMemoryInPolygon (Polygon
);
658 *holeindex
= Polygon
->PointN
;
662 /* ---------------------------------------------------------------------------
663 * creates an new element
664 * memory is allocated if needed
667 CreateNewElement (DataType
*Data
, ElementType
*Element
,
670 char *Description
, char *NameOnPCB
, char *Value
,
671 Coord TextX
, Coord TextY
, BYTE Direction
,
672 int TextScale
, FlagType TextFlags
, bool uniqueName
)
675 printf("Entered CreateNewElement.....\n");
679 Element
= GetElementMemory (Data
);
681 /* copy values and set additional information */
682 TextScale
= MAX (MIN_TEXTSCALE
, TextScale
);
683 AddTextToElement (&DESCRIPTION_TEXT (Element
), PCBFont
, TextX
, TextY
,
684 Direction
, Description
, TextScale
, TextFlags
);
686 NameOnPCB
= UniqueElementName (Data
, NameOnPCB
);
687 AddTextToElement (&NAMEONPCB_TEXT (Element
), PCBFont
, TextX
, TextY
,
688 Direction
, NameOnPCB
, TextScale
, TextFlags
);
689 AddTextToElement (&VALUE_TEXT (Element
), PCBFont
, TextX
, TextY
,
690 Direction
, Value
, TextScale
, TextFlags
);
691 DESCRIPTION_TEXT (Element
).Element
= Element
;
692 NAMEONPCB_TEXT (Element
).Element
= Element
;
693 VALUE_TEXT (Element
).Element
= Element
;
694 Element
->Flags
= Flags
;
698 printf(" .... Leaving CreateNewElement.\n");
704 /* ---------------------------------------------------------------------------
705 * creates a new arc in an element
708 CreateNewArcInElement (ElementType
*Element
,
710 Coord Width
, Coord Height
,
711 Angle angle
, Angle delta
, Coord Thickness
)
715 arc
= g_slice_new0 (ArcType
);
716 Element
->Arc
= g_list_append (Element
->Arc
, arc
);
719 /* set Delta (0,360], StartAngle in [0,360) */
725 angle
= NormalizeAngle (angle
);
726 delta
= NormalizeAngle (delta
);
734 arc
->Height
= Height
;
735 arc
->StartAngle
= angle
;
737 arc
->Thickness
= Thickness
;
742 /* ---------------------------------------------------------------------------
743 * creates a new line for an element
746 CreateNewLineInElement (ElementType
*Element
,
756 line
= g_slice_new0 (LineType
);
757 Element
->Line
= g_list_append (Element
->Line
, line
);
765 line
->Thickness
= Thickness
;
766 line
->Flags
= NoFlags ();
771 /* ---------------------------------------------------------------------------
772 * creates a new pin in an element
775 CreateNewPin (ElementType
*Element
,
777 Coord Thickness
, Coord Clearance
, Coord Mask
,
778 Coord DrillingHole
, char *Name
, char *Number
,
781 PinType
*pin
= GetPinMemory (Element
);
786 pin
->Thickness
= Thickness
;
787 pin
->Clearance
= Clearance
;
789 pin
->Name
= STRDUP (Name
);
790 pin
->Number
= STRDUP (Number
);
792 CLEAR_FLAG (WARNFLAG
, pin
);
793 SET_FLAG (PINFLAG
, pin
);
795 pin
->Element
= Element
;
798 * If there is no vendor drill map installed, this will simply
799 * return DrillingHole.
801 pin
->DrillingHole
= vendorDrillMap (DrillingHole
);
803 /* Unless we should not map drills on this element, map them! */
804 if (vendorIsElementMappable (Element
))
806 if (pin
->DrillingHole
< MIN_PINORVIASIZE
)
808 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is below the minimum allowed size\n"),
809 Settings
.grid_unit
->allow
, UNKNOWN (Number
), UNKNOWN (Name
), pin
->DrillingHole
);
810 pin
->DrillingHole
= DrillingHole
;
812 else if (pin
->DrillingHole
> MAX_PINORVIASIZE
)
814 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is above the maximum allowed size\n"),
815 Settings
.grid_unit
->allow
, UNKNOWN (Number
), UNKNOWN (Name
), pin
->DrillingHole
);
816 pin
->DrillingHole
= DrillingHole
;
818 else if (!TEST_FLAG (HOLEFLAG
, pin
)
819 && (pin
->DrillingHole
> pin
->Thickness
- MIN_PINORVIACOPPER
))
821 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS does not leave enough copper\n"),
822 Settings
.grid_unit
->allow
, UNKNOWN (Number
), UNKNOWN (Name
), pin
->DrillingHole
);
823 pin
->DrillingHole
= DrillingHole
;
828 pin
->DrillingHole
= DrillingHole
;
831 if (pin
->DrillingHole
!= DrillingHole
)
833 Message (_("%m+Mapped pin drill hole to %$mS from %$mS per vendor table\n"),
834 Settings
.grid_unit
->allow
, pin
->DrillingHole
, DrillingHole
);
840 /* ---------------------------------------------------------------------------
841 * creates a new pad in an element
844 CreateNewPad (ElementType
*Element
,
845 Coord X1
, Coord Y1
, Coord X2
,
846 Coord Y2
, Coord Thickness
, Coord Clearance
,
847 Coord Mask
, char *Name
, char *Number
, FlagType Flags
)
849 PadType
*pad
= GetPadMemory (Element
);
852 if (X1
> X2
|| (X1
== X2
&& Y1
> Y2
))
866 pad
->Thickness
= Thickness
;
867 pad
->Clearance
= Clearance
;
869 pad
->Name
= STRDUP (Name
);
870 pad
->Number
= STRDUP (Number
);
872 CLEAR_FLAG (WARNFLAG
, pad
);
874 pad
->Element
= Element
;
878 /* ---------------------------------------------------------------------------
879 * creates a new textobject as part of an element
880 * copies the values to the appropriate text object
883 AddTextToElement (TextType
*Text
, FontType
*PCBFont
,
885 unsigned Direction
, char *TextString
, int Scale
, FlagType Flags
)
887 free (Text
->TextString
);
888 Text
->TextString
= (TextString
&& *TextString
) ? strdup (TextString
) : NULL
;
891 Text
->Direction
= Direction
;
895 /* calculate size of the bounding box */
896 SetTextBoundingBox (PCBFont
, Text
);
900 /* ---------------------------------------------------------------------------
901 * creates a new line in a symbol
904 CreateNewLineInSymbol (SymbolType
*Symbol
,
906 Coord X2
, Coord Y2
, Coord Thickness
)
908 LineType
*line
= Symbol
->Line
;
910 /* realloc new memory if necessary and clear it */
911 if (Symbol
->LineN
>= Symbol
->LineMax
)
913 Symbol
->LineMax
+= STEP_SYMBOLLINE
;
914 line
= (LineType
*)realloc (line
, Symbol
->LineMax
* sizeof (LineType
));
916 memset (line
+ Symbol
->LineN
, 0, STEP_SYMBOLLINE
* sizeof (LineType
));
920 line
= line
+ Symbol
->LineN
++;
925 line
->Thickness
= Thickness
;
929 /* ---------------------------------------------------------------------------
930 * parses a file with font information and installs it into the provided PCB
931 * checks directories given as colon separated list by resource fontPath
932 * if the fonts filename doesn't contain a directory component
935 CreateDefaultFont (PCBType
*pcb
)
937 if (ParseFont (&pcb
->Font
, Settings
.FontFile
))
938 Message (_("Can't find font-symbol-file '%s'\n"), Settings
.FontFile
);
941 /* ---------------------------------------------------------------------------
942 * adds a new line to the rubberband list of 'Crosshair.AttachedObject'
943 * if Layer == 0 it is a rat line
946 CreateNewRubberbandEntry (LayerType
*Layer
,
947 LineType
*Line
, PointType
*MovedPoint
)
949 RubberbandType
*ptr
= GetRubberbandMemory ();
951 /* we toggle the RUBBERENDFLAG of the line to determine if */
952 /* both points are being moved. */
953 TOGGLE_FLAG (RUBBERENDFLAG
, Line
);
956 ptr
->MovedPoint
= MovedPoint
;
960 /* ---------------------------------------------------------------------------
961 * Add a new net to the netlist menu
964 CreateNewNet (LibraryType
*lib
, char *name
, char *style
)
966 LibraryMenuType
*menu
;
969 sprintf (temp
, " %s", name
);
970 menu
= GetLibraryMenuMemory (lib
);
971 menu
->Name
= strdup (temp
);
972 menu
->flag
= 1; /* net is enabled by default */
973 if (style
== NULL
|| NSTRCMP ("(unknown)", style
) == 0)
976 menu
->Style
= strdup (style
);
980 /* ---------------------------------------------------------------------------
981 * Add a connection to the net
984 CreateNewConnection (LibraryMenuType
*net
, char *conn
)
986 LibraryEntryType
*entry
= GetLibraryEntryMemory (net
);
988 entry
->ListEntry
= STRDUP (conn
);
992 /* ---------------------------------------------------------------------------
993 * Add an attribute to a list.
996 CreateNewAttribute (AttributeListType
*list
, char *name
, char *value
)
998 if (list
->Number
>= list
->Max
)
1001 list
->List
= (AttributeType
*)realloc (list
->List
, list
->Max
* sizeof (AttributeType
));
1003 list
->List
[list
->Number
].name
= STRDUP (name
);
1004 list
->List
[list
->Number
].value
= STRDUP (value
);
1006 return &list
->List
[list
->Number
- 1];