Move _draw_line() routine from draw.c into HID_DRAW API
[geda-pcb/pcjc2.git] / src / create.c
blobb39ff653bfe8ab97905bd29c86fc87aeb85cca4c
1 /*
2 * COPYRIGHT
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 ...
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
34 #include <assert.h>
35 #include <memory.h>
36 #include <setjmp.h>
37 #include <stdlib.h>
39 #include "global.h"
41 #include "create.h"
42 #include "data.h"
43 #include "draw.h"
44 #include "error.h"
45 #include "mymem.h"
46 #include "misc.h"
47 #include "parse_l.h"
48 #include "pcb-printf.h"
49 #include "polygon.h"
50 #include "rtree.h"
51 #include "search.h"
52 #include "set.h"
53 #include "undo.h"
54 #include "vendor.h"
56 #ifdef HAVE_LIBDMALLOC
57 #include <dmalloc.h>
58 #endif
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,
73 FlagType);
75 /* ---------------------------------------------------------------------------
76 * Set the lenience mode.
79 void
80 CreateBeLenient (bool v)
82 be_lenient = v;
85 /* ---------------------------------------------------------------------------
86 * creates a new paste buffer
88 DataType *
89 CreateNewBuffer (void)
91 DataType *data;
92 data = (DataType *) calloc (1, sizeof (DataType));
93 data->pcb = (PCBType *) PCB;
94 return data;
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.
101 void
102 pcb_colors_from_settings (PCBType *ptr)
104 int i;
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 /* ---------------------------------------------------------------------------
139 * creates a new PCB
141 PCBType *
142 CreateNewPCB (bool SetDefaultNames)
144 PCBType *ptr;
145 int i;
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;
153 ptr->ThermStyle = 4;
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;
185 STYLE_LOOP (ptr);
187 *style = Settings.RouteStyle[n];
188 style->index = n;
190 END_LOOP;
191 ptr->MaxWidth = Settings.MaxWidth;
192 ptr->MaxHeight = Settings.MaxHeight;
193 ptr->ID = ID++;
194 ptr->ThermScale = 0.5;
196 ptr->Bloat = Settings.Bloat;
197 ptr->Shrink = Settings.Shrink;
198 ptr->minWid = Settings.minWid;
199 ptr->minSlk = Settings.minSlk;
200 ptr->minDrill = Settings.minDrill;
201 ptr->minRing = Settings.minRing;
203 for (i = 0; i < MAX_LAYER; i++)
204 ptr->Data->Layer[i].Name = strdup (Settings.DefaultLayerName[i]);
206 CreateDefaultFont (ptr);
208 return (ptr);
211 /* This post-processing step adds the top and bottom silk layers to a
212 * pre-existing PCB.
215 CreateNewPCBPost (PCBType *pcb, int use_defaults)
217 /* copy default settings */
218 pcb_colors_from_settings (pcb);
220 if (use_defaults)
222 if (ParseGroupString (Settings.Groups, &pcb->LayerGroups, DEF_LAYER))
223 return 1;
225 pcb->Data->Layer[component_silk_layer].Name = strdup ("silk");
226 pcb->Data->Layer[solder_silk_layer].Name = strdup ("silk");
228 return 0;
231 /* ---------------------------------------------------------------------------
232 * creates a new via
234 PinType *
235 CreateNewVia (DataType *Data,
236 Coord X, Coord Y,
237 Coord Thickness, Coord Clearance, Coord Mask,
238 Coord DrillingHole, char *Name, FlagType Flags)
240 PinType *Via;
242 if (!be_lenient)
244 VIA_LOOP (Data);
246 if (Distance (X, Y, via->X, via->Y) <=
247 via->DrillingHole / 2 + DrillingHole / 2)
249 Message (_("%m+Dropping via at %$mD because it's hole would overlap with the via "
250 "at %$mD\n"), Settings.grid_unit->allow, X, Y, via->X, via->Y);
251 return (NULL); /* don't allow via stacking */
254 END_LOOP;
257 Via = GetViaMemory (Data);
259 if (!Via)
260 return (Via);
261 /* copy values */
262 Via->X = X;
263 Via->Y = Y;
264 Via->Thickness = Thickness;
265 Via->Clearance = Clearance;
266 Via->Mask = Mask;
267 Via->DrillingHole = vendorDrillMap (DrillingHole);
268 if (Via->DrillingHole != DrillingHole)
270 Message (_("%m+Mapped via drill hole to %$mS from %$mS per vendor table\n"),
271 Settings.grid_unit->allow, Via->DrillingHole, DrillingHole);
274 Via->Name = STRDUP (Name);
275 Via->Flags = Flags;
276 CLEAR_FLAG (WARNFLAG, Via);
277 SET_FLAG (VIAFLAG, Via);
278 Via->ID = ID++;
281 * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure
282 * hole)
284 if (!TEST_FLAG (HOLEFLAG, Via) &&
285 (Via->Thickness < Via->DrillingHole + MIN_PINORVIACOPPER))
287 Via->Thickness = Via->DrillingHole + MIN_PINORVIACOPPER;
288 Message (_("%m+Increased via thickness to %$mS to allow enough copper"
289 " at %$mD.\n"),
290 Settings.grid_unit->allow, Via->Thickness, Via->X, Via->Y);
293 SetPinBoundingBox (Via);
294 if (!Data->via_tree)
295 Data->via_tree = r_create_tree (NULL, 0, 0);
296 r_insert_entry (Data->via_tree, (BoxType *) Via, 0);
297 return (Via);
300 struct line_info
302 Coord X1, X2, Y1, Y2;
303 Coord Thickness;
304 FlagType Flags;
305 LineType test, *ans;
306 jmp_buf env;
309 static int
310 line_callback (const BoxType * b, void *cl)
312 LineType *line = (LineType *) b;
313 struct line_info *i = (struct line_info *) cl;
315 if (line->Point1.X == i->X1 &&
316 line->Point2.X == i->X2 &&
317 line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2)
319 i->ans = (LineType *) (-1);
320 longjmp (i->env, 1);
322 /* check the other point order */
323 if (line->Point1.X == i->X1 &&
324 line->Point2.X == i->X2 &&
325 line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2)
327 i->ans = (LineType *) (-1);
328 longjmp (i->env, 1);
330 if (line->Point2.X == i->X1 &&
331 line->Point1.X == i->X2 &&
332 line->Point2.Y == i->Y1 && line->Point1.Y == i->Y2)
334 i->ans = (LineType *) - 1;
335 longjmp (i->env, 1);
337 /* remove unnecessary line points */
338 if (line->Thickness == i->Thickness
339 /* don't merge lines if the clear flags differ */
340 && TEST_FLAG (CLEARLINEFLAG, line) == TEST_FLAG (CLEARLINEFLAG, i))
342 if (line->Point1.X == i->X1 && line->Point1.Y == i->Y1)
344 i->test.Point1.X = line->Point2.X;
345 i->test.Point1.Y = line->Point2.Y;
346 i->test.Point2.X = i->X2;
347 i->test.Point2.Y = i->Y2;
348 if (IsPointOnLine (i->X1, i->Y1, 0.0, &i->test))
350 i->ans = line;
351 longjmp (i->env, 1);
354 else if (line->Point2.X == i->X1 && line->Point2.Y == i->Y1)
356 i->test.Point1.X = line->Point1.X;
357 i->test.Point1.Y = line->Point1.Y;
358 i->test.Point2.X = i->X2;
359 i->test.Point2.Y = i->Y2;
360 if (IsPointOnLine (i->X1, i->Y1, 0.0, &i->test))
362 i->ans = line;
363 longjmp (i->env, 1);
366 else if (line->Point1.X == i->X2 && line->Point1.Y == i->Y2)
368 i->test.Point1.X = line->Point2.X;
369 i->test.Point1.Y = line->Point2.Y;
370 i->test.Point2.X = i->X1;
371 i->test.Point2.Y = i->Y1;
372 if (IsPointOnLine (i->X2, i->Y2, 0.0, &i->test))
374 i->ans = line;
375 longjmp (i->env, 1);
378 else if (line->Point2.X == i->X2 && line->Point2.Y == i->Y2)
380 i->test.Point1.X = line->Point1.X;
381 i->test.Point1.Y = line->Point1.Y;
382 i->test.Point2.X = i->X1;
383 i->test.Point2.Y = i->Y1;
384 if (IsPointOnLine (i->X2, i->Y2, 0.0, &i->test))
386 i->ans = line;
387 longjmp (i->env, 1);
391 return 0;
395 /* ---------------------------------------------------------------------------
396 * creates a new line on a layer and checks for overlap and extension
398 LineType *
399 CreateDrawnLineOnLayer (LayerType *Layer,
400 Coord X1, Coord Y1,
401 Coord X2, Coord Y2,
402 Coord Thickness, Coord Clearance,
403 FlagType Flags)
405 struct line_info info;
406 BoxType search;
408 search.X1 = MIN (X1, X2);
409 search.X2 = MAX (X1, X2);
410 search.Y1 = MIN (Y1, Y2);
411 search.Y2 = MAX (Y1, Y2);
412 if (search.Y2 == search.Y1)
413 search.Y2++;
414 if (search.X2 == search.X1)
415 search.X2++;
416 info.X1 = X1;
417 info.X2 = X2;
418 info.Y1 = Y1;
419 info.Y2 = Y2;
420 info.Thickness = Thickness;
421 info.Flags = Flags;
422 info.test.Thickness = 0;
423 info.test.Flags = NoFlags ();
424 info.ans = NULL;
425 /* prevent stacking of duplicate lines
426 * and remove needless intermediate points
427 * verify that the layer is on the board first!
429 if (setjmp (info.env) == 0)
431 r_search (Layer->line_tree, &search, NULL, line_callback, &info);
432 return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
433 Thickness, Clearance, Flags);
436 if ((void *) info.ans == (void *) (-1))
437 return NULL; /* stacked line */
438 /* remove unnecessary points */
439 if (info.ans)
441 /* must do this BEFORE getting new line memory */
442 MoveObjectToRemoveUndoList (LINE_TYPE, Layer, info.ans, info.ans);
443 X1 = info.test.Point1.X;
444 X2 = info.test.Point2.X;
445 Y1 = info.test.Point1.Y;
446 Y2 = info.test.Point2.Y;
448 return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
449 Thickness, Clearance, Flags);
452 LineType *
453 CreateNewLineOnLayer (LayerType *Layer,
454 Coord X1, Coord Y1,
455 Coord X2, Coord Y2,
456 Coord Thickness, Coord Clearance,
457 FlagType Flags)
459 LineType *Line;
461 Line = GetLineMemory (Layer);
462 if (!Line)
463 return (Line);
464 Line->ID = ID++;
465 Line->Flags = Flags;
466 CLEAR_FLAG (RATFLAG, Line);
467 Line->Thickness = Thickness;
468 Line->Clearance = Clearance;
469 Line->Point1.X = X1;
470 Line->Point1.Y = Y1;
471 Line->Point1.ID = ID++;
472 Line->Point2.X = X2;
473 Line->Point2.Y = Y2;
474 Line->Point2.ID = ID++;
475 SetLineBoundingBox (Line);
476 if (!Layer->line_tree)
477 Layer->line_tree = r_create_tree (NULL, 0, 0);
478 r_insert_entry (Layer->line_tree, (BoxType *) Line, 0);
479 return (Line);
482 /* ---------------------------------------------------------------------------
483 * creates a new rat-line
485 RatType *
486 CreateNewRat (DataType *Data, Coord X1, Coord Y1,
487 Coord X2, Coord Y2, Cardinal group1,
488 Cardinal group2, Coord Thickness, FlagType Flags)
490 RatType *Line = GetRatMemory (Data);
492 if (!Line)
493 return (Line);
495 Line->ID = ID++;
496 Line->Flags = Flags;
497 SET_FLAG (RATFLAG, Line);
498 Line->Thickness = Thickness;
499 Line->Point1.X = X1;
500 Line->Point1.Y = Y1;
501 Line->Point1.ID = ID++;
502 Line->Point2.X = X2;
503 Line->Point2.Y = Y2;
504 Line->Point2.ID = ID++;
505 Line->group1 = group1;
506 Line->group2 = group2;
507 SetLineBoundingBox ((LineType *) Line);
508 if (!Data->rat_tree)
509 Data->rat_tree = r_create_tree (NULL, 0, 0);
510 r_insert_entry (Data->rat_tree, &Line->BoundingBox, 0);
511 return (Line);
514 /* ---------------------------------------------------------------------------
515 * creates a new arc on a layer
517 ArcType *
518 CreateNewArcOnLayer (LayerType *Layer,
519 Coord X1, Coord Y1,
520 Coord width,
521 Coord height,
522 Angle sa,
523 Angle dir, Coord Thickness,
524 Coord Clearance, FlagType Flags)
526 ArcType *Arc;
528 ARC_LOOP (Layer);
530 if (arc->X == X1 && arc->Y == Y1 && arc->Width == width &&
531 NormalizeAngle (arc->StartAngle) == NormalizeAngle (sa) &&
532 arc->Delta == dir)
533 return (NULL); /* prevent stacked arcs */
535 END_LOOP;
536 Arc = GetArcMemory (Layer);
537 if (!Arc)
538 return (Arc);
540 Arc->ID = ID++;
541 Arc->Flags = Flags;
542 Arc->Thickness = Thickness;
543 Arc->Clearance = Clearance;
544 Arc->X = X1;
545 Arc->Y = Y1;
546 Arc->Width = width;
547 Arc->Height = height;
548 Arc->StartAngle = sa;
549 Arc->Delta = dir;
550 SetArcBoundingBox (Arc);
551 if (!Layer->arc_tree)
552 Layer->arc_tree = r_create_tree (NULL, 0, 0);
553 r_insert_entry (Layer->arc_tree, (BoxType *) Arc, 0);
554 return (Arc);
558 /* ---------------------------------------------------------------------------
559 * creates a new polygon from the old formats rectangle data
561 PolygonType *
562 CreateNewPolygonFromRectangle (LayerType *Layer,
563 Coord X1, Coord Y1,
564 Coord X2, Coord Y2,
565 FlagType Flags)
567 PolygonType *polygon = CreateNewPolygon (Layer, Flags);
568 if (!polygon)
569 return (polygon);
571 CreateNewPointInPolygon (polygon, X1, Y1);
572 CreateNewPointInPolygon (polygon, X2, Y1);
573 CreateNewPointInPolygon (polygon, X2, Y2);
574 CreateNewPointInPolygon (polygon, X1, Y2);
575 SetPolygonBoundingBox (polygon);
576 if (!Layer->polygon_tree)
577 Layer->polygon_tree = r_create_tree (NULL, 0, 0);
578 r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0);
579 return (polygon);
582 /* ---------------------------------------------------------------------------
583 * creates a new text on a layer
585 TextType *
586 CreateNewText (LayerType *Layer, FontType *PCBFont,
587 Coord X, Coord Y,
588 unsigned Direction, int Scale, char *TextString, FlagType Flags)
590 TextType *text;
592 if (TextString == NULL)
593 return NULL;
595 text = GetTextMemory (Layer);
596 if (text == NULL)
597 return NULL;
599 /* copy values, width and height are set by drawing routine
600 * because at this point we don't know which symbols are available
602 text->X = X;
603 text->Y = Y;
604 text->Direction = Direction;
605 text->Flags = Flags;
606 text->Scale = Scale;
607 text->TextString = strdup (TextString);
609 /* calculate size of the bounding box */
610 SetTextBoundingBox (PCBFont, text);
611 text->ID = ID++;
612 if (!Layer->text_tree)
613 Layer->text_tree = r_create_tree (NULL, 0, 0);
614 r_insert_entry (Layer->text_tree, (BoxType *) text, 0);
615 return (text);
618 /* ---------------------------------------------------------------------------
619 * creates a new polygon on a layer
621 PolygonType *
622 CreateNewPolygon (LayerType *Layer, FlagType Flags)
624 PolygonType *polygon = GetPolygonMemory (Layer);
626 /* copy values */
627 polygon->Flags = Flags;
628 polygon->ID = ID++;
629 polygon->Clipped = NULL;
630 polygon->NoHoles = NULL;
631 polygon->NoHolesValid = 0;
632 return (polygon);
635 /* ---------------------------------------------------------------------------
636 * creates a new point in a polygon
638 PointType *
639 CreateNewPointInPolygon (PolygonType *Polygon, Coord X, Coord Y)
641 PointType *point = GetPointMemoryInPolygon (Polygon);
643 /* copy values */
644 point->X = X;
645 point->Y = Y;
646 point->ID = ID++;
647 return (point);
650 /* ---------------------------------------------------------------------------
651 * creates a new hole in a polygon
653 PolygonType *
654 CreateNewHoleInPolygon (PolygonType *Polygon)
656 Cardinal *holeindex = GetHoleIndexMemoryInPolygon (Polygon);
657 *holeindex = Polygon->PointN;
658 return Polygon;
661 /* ---------------------------------------------------------------------------
662 * creates an new element
663 * memory is allocated if needed
665 ElementType *
666 CreateNewElement (DataType *Data, ElementType *Element,
667 FontType *PCBFont,
668 FlagType Flags,
669 char *Description, char *NameOnPCB, char *Value,
670 Coord TextX, Coord TextY, BYTE Direction,
671 int TextScale, FlagType TextFlags, bool uniqueName)
673 #ifdef DEBUG
674 printf("Entered CreateNewElement.....\n");
675 #endif
677 if (!Element)
678 Element = GetElementMemory (Data);
680 /* copy values and set additional information */
681 TextScale = MAX (MIN_TEXTSCALE, TextScale);
682 AddTextToElement (&DESCRIPTION_TEXT (Element), PCBFont, TextX, TextY,
683 Direction, Description, TextScale, TextFlags);
684 if (uniqueName)
685 NameOnPCB = UniqueElementName (Data, NameOnPCB);
686 AddTextToElement (&NAMEONPCB_TEXT (Element), PCBFont, TextX, TextY,
687 Direction, NameOnPCB, TextScale, TextFlags);
688 AddTextToElement (&VALUE_TEXT (Element), PCBFont, TextX, TextY,
689 Direction, Value, TextScale, TextFlags);
690 DESCRIPTION_TEXT (Element).Element = Element;
691 NAMEONPCB_TEXT (Element).Element = Element;
692 VALUE_TEXT (Element).Element = Element;
693 Element->Flags = Flags;
694 Element->ID = ID++;
696 #ifdef DEBUG
697 printf(" .... Leaving CreateNewElement.\n");
698 #endif
700 return (Element);
703 /* ---------------------------------------------------------------------------
704 * creates a new arc in an element
706 ArcType *
707 CreateNewArcInElement (ElementType *Element,
708 Coord X, Coord Y,
709 Coord Width, Coord Height,
710 Angle angle, Angle delta, Coord Thickness)
712 ArcType *arc;
714 arc = g_slice_new0 (ArcType);
715 Element->Arc = g_list_append (Element->Arc, arc);
716 Element->ArcN ++;
718 /* set Delta (0,360], StartAngle in [0,360) */
719 if (delta < 0)
721 delta = -delta;
722 angle -= delta;
724 angle = NormalizeAngle (angle);
725 delta = NormalizeAngle (delta);
726 if (delta == 0)
727 delta = 360;
729 /* copy values */
730 arc->X = X;
731 arc->Y = Y;
732 arc->Width = Width;
733 arc->Height = Height;
734 arc->StartAngle = angle;
735 arc->Delta = delta;
736 arc->Thickness = Thickness;
737 arc->ID = ID++;
738 return arc;
741 /* ---------------------------------------------------------------------------
742 * creates a new line for an element
744 LineType *
745 CreateNewLineInElement (ElementType *Element,
746 Coord X1, Coord Y1,
747 Coord X2, Coord Y2,
748 Coord Thickness)
750 LineType *line;
752 if (Thickness == 0)
753 return NULL;
755 line = g_slice_new0 (LineType);
756 Element->Line = g_list_append (Element->Line, line);
757 Element->LineN ++;
759 /* copy values */
760 line->Point1.X = X1;
761 line->Point1.Y = Y1;
762 line->Point2.X = X2;
763 line->Point2.Y = Y2;
764 line->Thickness = Thickness;
765 line->Flags = NoFlags ();
766 line->ID = ID++;
767 return line;
770 /* ---------------------------------------------------------------------------
771 * creates a new pin in an element
773 PinType *
774 CreateNewPin (ElementType *Element,
775 Coord X, Coord Y,
776 Coord Thickness, Coord Clearance, Coord Mask,
777 Coord DrillingHole, char *Name, char *Number,
778 FlagType Flags)
780 PinType *pin = GetPinMemory (Element);
782 /* copy values */
783 pin->X = X;
784 pin->Y = Y;
785 pin->Thickness = Thickness;
786 pin->Clearance = Clearance;
787 pin->Mask = Mask;
788 pin->Name = STRDUP (Name);
789 pin->Number = STRDUP (Number);
790 pin->Flags = Flags;
791 CLEAR_FLAG (WARNFLAG, pin);
792 SET_FLAG (PINFLAG, pin);
793 pin->ID = ID++;
794 pin->Element = Element;
797 * If there is no vendor drill map installed, this will simply
798 * return DrillingHole.
800 pin->DrillingHole = vendorDrillMap (DrillingHole);
802 /* Unless we should not map drills on this element, map them! */
803 if (vendorIsElementMappable (Element))
805 if (pin->DrillingHole < MIN_PINORVIASIZE)
807 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is below the minimum allowed size\n"),
808 Settings.grid_unit->allow, UNKNOWN (Number), UNKNOWN (Name), pin->DrillingHole);
809 pin->DrillingHole = DrillingHole;
811 else if (pin->DrillingHole > MAX_PINORVIASIZE)
813 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is above the maximum allowed size\n"),
814 Settings.grid_unit->allow, UNKNOWN (Number), UNKNOWN (Name), pin->DrillingHole);
815 pin->DrillingHole = DrillingHole;
817 else if (!TEST_FLAG (HOLEFLAG, pin)
818 && (pin->DrillingHole > pin->Thickness - MIN_PINORVIACOPPER))
820 Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS does not leave enough copper\n"),
821 Settings.grid_unit->allow, UNKNOWN (Number), UNKNOWN (Name), pin->DrillingHole);
822 pin->DrillingHole = DrillingHole;
825 else
827 pin->DrillingHole = DrillingHole;
830 if (pin->DrillingHole != DrillingHole)
832 Message (_("%m+Mapped pin drill hole to %$mS from %$mS per vendor table\n"),
833 Settings.grid_unit->allow, pin->DrillingHole, DrillingHole);
836 return (pin);
839 /* ---------------------------------------------------------------------------
840 * creates a new pad in an element
842 PadType *
843 CreateNewPad (ElementType *Element,
844 Coord X1, Coord Y1, Coord X2,
845 Coord Y2, Coord Thickness, Coord Clearance,
846 Coord Mask, char *Name, char *Number, FlagType Flags)
848 PadType *pad = GetPadMemory (Element);
850 /* copy values */
851 if (X1 > X2 || (X1 == X2 && Y1 > Y2))
853 pad->Point1.X = X2;
854 pad->Point1.Y = Y2;
855 pad->Point2.X = X1;
856 pad->Point2.Y = Y1;
858 else
860 pad->Point1.X = X1;
861 pad->Point1.Y = Y1;
862 pad->Point2.X = X2;
863 pad->Point2.Y = Y2;
865 pad->Thickness = Thickness;
866 pad->Clearance = Clearance;
867 pad->Mask = Mask;
868 pad->Name = STRDUP (Name);
869 pad->Number = STRDUP (Number);
870 pad->Flags = Flags;
871 CLEAR_FLAG (WARNFLAG, pad);
872 pad->ID = ID++;
873 pad->Element = Element;
874 return (pad);
877 /* ---------------------------------------------------------------------------
878 * creates a new textobject as part of an element
879 * copies the values to the appropriate text object
881 static void
882 AddTextToElement (TextType *Text, FontType *PCBFont,
883 Coord X, Coord Y,
884 unsigned Direction, char *TextString, int Scale, FlagType Flags)
886 free (Text->TextString);
887 Text->TextString = (TextString && *TextString) ? strdup (TextString) : NULL;
888 Text->X = X;
889 Text->Y = Y;
890 Text->Direction = Direction;
891 Text->Flags = Flags;
892 Text->Scale = Scale;
894 /* calculate size of the bounding box */
895 SetTextBoundingBox (PCBFont, Text);
896 Text->ID = ID++;
899 /* ---------------------------------------------------------------------------
900 * creates a new line in a symbol
902 LineType *
903 CreateNewLineInSymbol (SymbolType *Symbol,
904 Coord X1, Coord Y1,
905 Coord X2, Coord Y2, Coord Thickness)
907 LineType *line = Symbol->Line;
909 /* realloc new memory if necessary and clear it */
910 if (Symbol->LineN >= Symbol->LineMax)
912 Symbol->LineMax += STEP_SYMBOLLINE;
913 line = (LineType *)realloc (line, Symbol->LineMax * sizeof (LineType));
914 Symbol->Line = line;
915 memset (line + Symbol->LineN, 0, STEP_SYMBOLLINE * sizeof (LineType));
918 /* copy values */
919 line = line + Symbol->LineN++;
920 line->Point1.X = X1;
921 line->Point1.Y = Y1;
922 line->Point2.X = X2;
923 line->Point2.Y = Y2;
924 line->Thickness = Thickness;
925 return (line);
928 /* ---------------------------------------------------------------------------
929 * parses a file with font information and installs it into the provided PCB
930 * checks directories given as colon separated list by resource fontPath
931 * if the fonts filename doesn't contain a directory component
933 void
934 CreateDefaultFont (PCBType *pcb)
936 if (ParseFont (&pcb->Font, Settings.FontFile))
937 Message (_("Can't find font-symbol-file '%s'\n"), Settings.FontFile);
940 /* ---------------------------------------------------------------------------
941 * adds a new line to the rubberband list of 'Crosshair.AttachedObject'
942 * if Layer == 0 it is a rat line
944 RubberbandType *
945 CreateNewRubberbandEntry (LayerType *Layer,
946 LineType *Line, PointType *MovedPoint)
948 RubberbandType *ptr = GetRubberbandMemory ();
950 /* we toggle the RUBBERENDFLAG of the line to determine if */
951 /* both points are being moved. */
952 TOGGLE_FLAG (RUBBERENDFLAG, Line);
953 ptr->Layer = Layer;
954 ptr->Line = Line;
955 ptr->MovedPoint = MovedPoint;
956 return (ptr);
959 /* ---------------------------------------------------------------------------
960 * Add a new net to the netlist menu
962 LibraryMenuType *
963 CreateNewNet (LibraryType *lib, char *name, char *style)
965 LibraryMenuType *menu;
966 char temp[64];
968 sprintf (temp, " %s", name);
969 menu = GetLibraryMenuMemory (lib);
970 menu->Name = strdup (temp);
971 menu->flag = 1; /* net is enabled by default */
972 if (style == NULL || NSTRCMP ("(unknown)", style) == 0)
973 menu->Style = NULL;
974 else
975 menu->Style = strdup (style);
976 return (menu);
979 /* ---------------------------------------------------------------------------
980 * Add a connection to the net
982 LibraryEntryType *
983 CreateNewConnection (LibraryMenuType *net, char *conn)
985 LibraryEntryType *entry = GetLibraryEntryMemory (net);
987 entry->ListEntry = STRDUP (conn);
988 return (entry);
991 /* ---------------------------------------------------------------------------
992 * Add an attribute to a list.
994 AttributeType *
995 CreateNewAttribute (AttributeListType *list, char *name, char *value)
997 if (list->Number >= list->Max)
999 list->Max += 10;
1000 list->List = (AttributeType *)realloc (list->List, list->Max * sizeof (AttributeType));
1002 list->List[list->Number].name = STRDUP (name);
1003 list->List[list->Number].value = STRDUP (value);
1004 list->Number++;
1005 return &list->List[list->Number - 1];