Move internationalization macros to one header
[geda-pcb/gde.git] / src / create.c
blobeced68d904886800afd86ff5306356dde6db7a3e
1 /* $Id$ */
3 /*
4 * COPYRIGHT
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 ...
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include <assert.h>
37 #include <memory.h>
38 #include <setjmp.h>
39 #include <stdlib.h>
41 #include "global.h"
43 #include "create.h"
44 #include "data.h"
45 #include "draw.h"
46 #include "error.h"
47 #include "mymem.h"
48 #include "misc.h"
49 #include "parse_l.h"
50 #include "polygon.h"
51 #include "rtree.h"
52 #include "search.h"
53 #include "set.h"
54 #include "undo.h"
55 #include "vendor.h"
57 #ifdef HAVE_LIBDMALLOC
58 #include <dmalloc.h>
59 #endif
61 RCSID ("$Id$");
63 /* ---------------------------------------------------------------------------
64 * some local identifiers
66 static int ID = 1; /* current object ID; incremented after */
67 /* each creation of an object */
69 /* ----------------------------------------------------------------------
70 * some local prototypes
72 static void AddTextToElement (TextTypePtr, FontTypePtr,
73 LocationType, LocationType, BYTE, char *, int,
74 FlagType);
76 /* ---------------------------------------------------------------------------
77 * creates a new paste buffer
79 DataTypePtr
80 CreateNewBuffer (void)
82 DataTypePtr data;
83 data = (DataTypePtr) MyCalloc (1, sizeof (DataType), "CreateNewBuffer()");
84 data->pcb = (void *) PCB;
85 return data;
88 /* ---------------------------------------------------------------------------
89 * Perhaps PCB should internally just use the Settings colors? For now,
90 * use this to set PCB colors so the config can reassign PCB colors.
92 void
93 pcb_colors_from_settings (PCBTypePtr ptr)
95 int i;
97 /* copy default settings */
98 ptr->ConnectedColor = Settings.ConnectedColor;
99 ptr->ElementColor = Settings.ElementColor;
100 ptr->RatColor = Settings.RatColor;
101 ptr->InvisibleObjectsColor = Settings.InvisibleObjectsColor;
102 ptr->InvisibleMarkColor = Settings.InvisibleMarkColor;
103 ptr->ElementSelectedColor = Settings.ElementSelectedColor;
104 ptr->RatSelectedColor = Settings.RatSelectedColor;
105 ptr->PinColor = Settings.PinColor;
106 ptr->PinSelectedColor = Settings.PinSelectedColor;
107 ptr->PinNameColor = Settings.PinNameColor;
108 ptr->ViaColor = Settings.ViaColor;
109 ptr->ViaSelectedColor = Settings.ViaSelectedColor;
110 ptr->WarnColor = Settings.WarnColor;
111 ptr->MaskColor = Settings.MaskColor;
112 for (i = 0; i < MAX_LAYER; i++)
114 ptr->Data->Layer[i].Color = Settings.LayerColor[i];
115 ptr->Data->Layer[i].SelectedColor = Settings.LayerSelectedColor[i];
117 ptr->Data->Layer[max_layer + COMPONENT_LAYER].Color =
118 Settings.ShowSolderSide ?
119 Settings.InvisibleObjectsColor : Settings.ElementColor;
120 ptr->Data->Layer[max_layer + COMPONENT_LAYER].SelectedColor =
121 Settings.ElementSelectedColor;
122 ptr->Data->Layer[max_layer + SOLDER_LAYER].Color =
123 Settings.ShowSolderSide ?
124 Settings.ElementColor : Settings.InvisibleObjectsColor;
125 ptr->Data->Layer[max_layer + SOLDER_LAYER].SelectedColor =
126 Settings.ElementSelectedColor;
129 /* ---------------------------------------------------------------------------
130 * creates a new PCB
132 PCBTypePtr
133 CreateNewPCB (Boolean SetDefaultNames)
135 PCBTypePtr ptr;
136 int i;
138 /* allocate memory, switch all layers on and copy resources */
139 ptr = MyCalloc (1, sizeof (PCBType), "CreateNewPCB()");
140 ptr->Data = CreateNewBuffer ();
141 ptr->Data->pcb = (void *) ptr;
143 ptr->ThermStyle = 4;
144 ptr->IsleArea = 2.e8;
145 ptr->SilkActive = False;
146 ptr->RatDraw = False;
147 SET_FLAG (NAMEONPCBFLAG, ptr);
148 if (Settings.ShowNumber)
149 SET_FLAG (SHOWNUMBERFLAG, ptr);
150 if (Settings.AllDirectionLines)
151 SET_FLAG (ALLDIRECTIONFLAG, ptr);
152 ptr->Clipping = 1; /* this is the most useful starting point for now */
153 if (Settings.RubberBandMode)
154 SET_FLAG (RUBBERBANDFLAG, ptr);
155 if (Settings.SwapStartDirection)
156 SET_FLAG (SWAPSTARTDIRFLAG, ptr);
157 if (Settings.UniqueNames)
158 SET_FLAG (UNIQUENAMEFLAG, ptr);
159 if (Settings.SnapPin)
160 SET_FLAG (SNAPPINFLAG, ptr);
161 if (Settings.ClearLine)
162 SET_FLAG (CLEARNEWFLAG, ptr);
163 if (Settings.FullPoly)
164 SET_FLAG (NEWFULLPOLYFLAG, ptr);
165 if (Settings.OrthogonalMoves)
166 SET_FLAG (ORTHOMOVEFLAG, ptr);
167 if (Settings.liveRouting)
168 SET_FLAG (LIVEROUTEFLAG, ptr);
169 if (Settings.ShowDRC)
170 SET_FLAG (SHOWDRCFLAG, ptr);
171 if (Settings.AutoDRC)
172 SET_FLAG (AUTODRCFLAG, ptr);
173 ptr->Grid = Settings.Grid;
174 ptr->LayerGroups = Settings.LayerGroups;
175 STYLE_LOOP (ptr);
177 *style = Settings.RouteStyle[n];
178 style->index = n;
180 END_LOOP;
181 hid_action ("RouteStylesChanged");
182 ptr->Zoom = Settings.Zoom;
183 ptr->MaxWidth = Settings.MaxWidth;
184 ptr->MaxHeight = Settings.MaxHeight;
185 ptr->ID = ID++;
186 ptr->ThermScale = 0.5;
188 ptr->Bloat = Settings.Bloat;
189 ptr->Shrink = Settings.Shrink;
190 ptr->minWid = Settings.minWid;
191 ptr->minSlk = Settings.minSlk;
192 ptr->minDrill = Settings.minDrill;
193 ptr->minRing = Settings.minRing;
195 for (i = 0; i < MAX_LAYER; i++)
196 ptr->Data->Layer[i].Name = MyStrdup (Settings.DefaultLayerName[i],
197 "CreateNewPCB()");
199 return (ptr);
202 /* This post-processing step adds the top and bottom silk layers to a
203 * pre-existing PCB.
206 CreateNewPCBPost (PCBTypePtr pcb, int use_defaults)
208 /* copy default settings */
209 pcb_colors_from_settings (pcb);
211 if (use_defaults)
213 if (ParseGroupString (Settings.Groups, &pcb->LayerGroups, DEF_LAYER))
214 return 1;
216 pcb->Data->Layer[max_layer + COMPONENT_LAYER].Name =
217 MyStrdup ("silk", "CreateNewPCB()");
218 pcb->Data->Layer[max_layer + SOLDER_LAYER].Name =
219 MyStrdup ("silk", "CreateNewPCB()");
221 return 0;
224 /* ---------------------------------------------------------------------------
225 * creates a new via
227 PinTypePtr
228 CreateNewVia (DataTypePtr Data,
229 LocationType X, LocationType Y,
230 BDimension Thickness, BDimension Clearance, BDimension Mask,
231 BDimension DrillingHole, char *Name, FlagType Flags)
233 PinTypePtr Via;
235 VIA_LOOP (Data);
237 if (SQUARE (via->X - X) + SQUARE (via->Y - Y) <=
238 SQUARE (via->Thickness / 2 + Thickness / 2))
240 Message ("Dropping via at (%d, %d) because it would overlap with the via"
241 "at (%d, %d)\n", X/100, Y/100, via->X/100, via->Y/100);
242 return (NULL); /* don't allow via stacking */
245 END_LOOP;
247 Via = GetViaMemory (Data);
249 if (!Via)
250 return (Via);
251 /* copy values */
252 Via->X = X;
253 Via->Y = Y;
254 Via->Thickness = Thickness;
255 Via->Clearance = Clearance;
256 Via->Mask = Mask;
257 Via->DrillingHole = vendorDrillMap (DrillingHole);
258 if (Via->DrillingHole != DrillingHole)
260 Message (_
261 ("Mapped via drill hole to %.2f mils from %.2f mils per vendor table\n"),
262 0.01 * Via->DrillingHole, 0.01 * DrillingHole);
265 Via->Name = MyStrdup (Name, "CreateNewVia()");
266 Via->Flags = Flags;
267 CLEAR_FLAG (WARNFLAG, Via);
268 SET_FLAG (VIAFLAG, Via);
269 Via->ID = ID++;
272 * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure
273 * hole)
275 if (!TEST_FLAG (HOLEFLAG, Via) &&
276 (Via->Thickness < Via->DrillingHole + MIN_PINORVIACOPPER))
278 Via->Thickness = Via->DrillingHole + MIN_PINORVIACOPPER;
279 Message (_("Increased via thickness to %.2f mils to allow enough copper"
280 " at (%.2f,%.2f).\n"),
281 0.01 * Via->Thickness, 0.01 * Via->X, 0.01 * Via->Y);
284 SetPinBoundingBox (Via);
285 if (!Data->via_tree)
286 Data->via_tree = r_create_tree (NULL, 0, 0);
287 r_insert_entry (Data->via_tree, (BoxTypePtr) Via, 0);
288 return (Via);
291 struct line_info
293 LocationType X1, X2, Y1, Y2;
294 BDimension Thickness;
295 FlagType Flags;
296 LineType test, *ans;
297 jmp_buf env;
300 static int
301 line_callback (const BoxType * b, void *cl)
303 LineTypePtr line = (LineTypePtr) b;
304 struct line_info *i = (struct line_info *) cl;
306 if (line->Point1.X == i->X1 &&
307 line->Point2.X == i->X2 &&
308 line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2)
310 i->ans = (LineTypePtr) (-1);
311 longjmp (i->env, 1);
313 /* check the other point order */
314 if (line->Point1.X == i->X1 &&
315 line->Point2.X == i->X2 &&
316 line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2)
318 i->ans = (LineTypePtr) (-1);
319 longjmp (i->env, 1);
321 if (line->Point2.X == i->X1 &&
322 line->Point1.X == i->X2 &&
323 line->Point2.Y == i->Y1 && line->Point1.Y == i->Y2)
325 i->ans = (LineTypePtr) - 1;
326 longjmp (i->env, 1);
328 /* remove unnecessary line points */
329 if (line->Thickness == i->Thickness
330 /* don't merge lines if the clear flags differ */
331 && TEST_FLAG (CLEARLINEFLAG, line) == TEST_FLAG (CLEARLINEFLAG, i))
333 if (line->Point1.X == i->X1 && line->Point1.Y == i->Y1)
335 i->test.Point1.X = line->Point2.X;
336 i->test.Point1.Y = line->Point2.Y;
337 i->test.Point2.X = i->X2;
338 i->test.Point2.Y = i->Y2;
339 if (IsPointOnLine ((float) i->X1, (float) i->Y1, 0.0, &i->test))
341 i->ans = line;
342 longjmp (i->env, 1);
345 else if (line->Point2.X == i->X1 && line->Point2.Y == i->Y1)
347 i->test.Point1.X = line->Point1.X;
348 i->test.Point1.Y = line->Point1.Y;
349 i->test.Point2.X = i->X2;
350 i->test.Point2.Y = i->Y2;
351 if (IsPointOnLine ((float) i->X1, (float) i->Y1, 0.0, &i->test))
353 i->ans = line;
354 longjmp (i->env, 1);
357 else if (line->Point1.X == i->X2 && line->Point1.Y == i->Y2)
359 i->test.Point1.X = line->Point2.X;
360 i->test.Point1.Y = line->Point2.Y;
361 i->test.Point2.X = i->X1;
362 i->test.Point2.Y = i->Y1;
363 if (IsPointOnLine ((float) i->X2, (float) i->Y2, 0.0, &i->test))
365 i->ans = line;
366 longjmp (i->env, 1);
369 else if (line->Point2.X == i->X2 && line->Point2.Y == i->Y2)
371 i->test.Point1.X = line->Point1.X;
372 i->test.Point1.Y = line->Point1.Y;
373 i->test.Point2.X = i->X1;
374 i->test.Point2.Y = i->Y1;
375 if (IsPointOnLine ((float) i->X2, (float) i->Y2, 0.0, &i->test))
377 i->ans = line;
378 longjmp (i->env, 1);
382 return 0;
386 /* ---------------------------------------------------------------------------
387 * creates a new line on a layer and checks for overlap and extension
389 LineTypePtr
390 CreateDrawnLineOnLayer (LayerTypePtr Layer,
391 LocationType X1, LocationType Y1,
392 LocationType X2, LocationType Y2,
393 BDimension Thickness, BDimension Clearance,
394 FlagType Flags)
396 struct line_info info;
397 BoxType search;
399 search.X1 = MIN (X1, X2);
400 search.X2 = MAX (X1, X2);
401 search.Y1 = MIN (Y1, Y2);
402 search.Y2 = MAX (Y1, Y2);
403 if (search.Y2 == search.Y1)
404 search.Y2++;
405 if (search.X2 == search.X1)
406 search.X2++;
407 info.X1 = X1;
408 info.X2 = X2;
409 info.Y1 = Y1;
410 info.Y2 = Y2;
411 info.Thickness = Thickness;
412 info.Flags = Flags;
413 info.test.Thickness = 0;
414 info.test.Flags = NoFlags ();
415 info.ans = NULL;
416 /* prevent stacking of duplicate lines
417 * and remove needless intermediate points
418 * verify that the layer is on the board first!
420 if (setjmp (info.env) == 0)
422 r_search (Layer->line_tree, &search, NULL, line_callback, &info);
423 return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
424 Thickness, Clearance, Flags);
427 if ((void *) info.ans == (void *) (-1))
428 return NULL; /* stacked line */
429 /* remove unnecessary points */
430 if (info.ans)
432 /* must do this BEFORE getting new line memory */
433 MoveObjectToRemoveUndoList (LINE_TYPE, Layer, info.ans, info.ans);
434 X1 = info.test.Point1.X;
435 X2 = info.test.Point2.X;
436 Y1 = info.test.Point1.Y;
437 Y2 = info.test.Point2.Y;
439 return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
440 Thickness, Clearance, Flags);
443 LineTypePtr
444 CreateNewLineOnLayer (LayerTypePtr Layer,
445 LocationType X1, LocationType Y1,
446 LocationType X2, LocationType Y2,
447 BDimension Thickness, BDimension Clearance,
448 FlagType Flags)
450 LineTypePtr Line;
452 Line = GetLineMemory (Layer);
453 if (!Line)
454 return (Line);
455 Line->ID = ID++;
456 Line->Flags = Flags;
457 CLEAR_FLAG (RATFLAG, Line);
458 Line->Thickness = Thickness;
459 Line->Clearance = Clearance;
460 Line->Point1.X = X1;
461 Line->Point1.Y = Y1;
462 Line->Point1.ID = ID++;
463 Line->Point2.X = X2;
464 Line->Point2.Y = Y2;
465 Line->Point2.ID = ID++;
466 SetLineBoundingBox (Line);
467 if (!Layer->line_tree)
468 Layer->line_tree = r_create_tree (NULL, 0, 0);
469 r_insert_entry (Layer->line_tree, (BoxTypePtr) Line, 0);
470 return (Line);
473 /* ---------------------------------------------------------------------------
474 * creates a new rat-line
476 RatTypePtr
477 CreateNewRat (DataTypePtr Data, LocationType X1, LocationType Y1,
478 LocationType X2, LocationType Y2, Cardinal group1,
479 Cardinal group2, BDimension Thickness, FlagType Flags)
481 RatTypePtr Line = GetRatMemory (Data);
483 if (!Line)
484 return (Line);
486 Line->ID = ID++;
487 Line->Flags = Flags;
488 SET_FLAG (RATFLAG, Line);
489 Line->Thickness = Thickness;
490 Line->Point1.X = X1;
491 Line->Point1.Y = Y1;
492 Line->Point1.ID = ID++;
493 Line->Point2.X = X2;
494 Line->Point2.Y = Y2;
495 Line->Point2.ID = ID++;
496 Line->group1 = group1;
497 Line->group2 = group2;
498 SetLineBoundingBox ((LineTypePtr) Line);
499 if (!Data->rat_tree)
500 Data->rat_tree = r_create_tree (NULL, 0, 0);
501 r_insert_entry (Data->rat_tree, &Line->BoundingBox, 0);
502 return (Line);
505 /* ---------------------------------------------------------------------------
506 * creates a new arc on a layer
508 ArcTypePtr
509 CreateNewArcOnLayer (LayerTypePtr Layer,
510 LocationType X1, LocationType Y1,
511 BDimension width,
512 BDimension height,
513 int sa,
514 int dir, BDimension Thickness,
515 BDimension Clearance, FlagType Flags)
517 ArcTypePtr Arc;
519 ARC_LOOP (Layer);
521 if (arc->X == X1 && arc->Y == Y1 && arc->Width == width &&
522 (arc->StartAngle + 360) % 360 == (sa + 360) % 360 &&
523 arc->Delta == dir)
524 return (NULL); /* prevent stacked arcs */
526 END_LOOP;
527 Arc = GetArcMemory (Layer);
528 if (!Arc)
529 return (Arc);
531 Arc->ID = ID++;
532 Arc->Flags = Flags;
533 Arc->Thickness = Thickness;
534 Arc->Clearance = Clearance;
535 Arc->X = X1;
536 Arc->Y = Y1;
537 Arc->Width = width;
538 Arc->Height = height;
539 Arc->StartAngle = sa;
540 Arc->Delta = dir;
541 SetArcBoundingBox (Arc);
542 if (!Layer->arc_tree)
543 Layer->arc_tree = r_create_tree (NULL, 0, 0);
544 r_insert_entry (Layer->arc_tree, (BoxTypePtr) Arc, 0);
545 return (Arc);
549 /* ---------------------------------------------------------------------------
550 * creates a new polygon from the old formats rectangle data
552 PolygonTypePtr
553 CreateNewPolygonFromRectangle (LayerTypePtr Layer,
554 LocationType X1, LocationType Y1,
555 LocationType X2, LocationType Y2,
556 FlagType Flags)
558 PolygonTypePtr polygon = CreateNewPolygon (Layer, Flags);
559 if (!polygon)
560 return (polygon);
562 CreateNewPointInPolygon (polygon, X1, Y1);
563 CreateNewPointInPolygon (polygon, X2, Y1);
564 CreateNewPointInPolygon (polygon, X2, Y2);
565 CreateNewPointInPolygon (polygon, X1, Y2);
566 SetPolygonBoundingBox (polygon);
567 if (!Layer->polygon_tree)
568 Layer->polygon_tree = r_create_tree (NULL, 0, 0);
569 r_insert_entry (Layer->polygon_tree, (BoxTypePtr) polygon, 0);
570 return (polygon);
573 /* ---------------------------------------------------------------------------
574 * creates a new text on a layer
576 TextTypePtr
577 CreateNewText (LayerTypePtr Layer, FontTypePtr PCBFont,
578 LocationType X, LocationType Y,
579 BYTE Direction, int Scale, char *TextString, FlagType Flags)
581 TextTypePtr text = GetTextMemory (Layer);
582 if (!text)
583 return (text);
585 /* copy values, width and height are set by drawing routine
586 * because at this point we don't know which symbols are available
588 text->X = X;
589 text->Y = Y;
590 text->Direction = Direction;
591 text->Flags = Flags;
592 text->Scale = Scale;
593 text->TextString = MyStrdup (TextString, "CreateNewText()");
595 /* calculate size of the bounding box */
596 SetTextBoundingBox (PCBFont, text);
597 text->ID = ID++;
598 if (!Layer->text_tree)
599 Layer->text_tree = r_create_tree (NULL, 0, 0);
600 r_insert_entry (Layer->text_tree, (BoxTypePtr) text, 0);
601 return (text);
604 /* ---------------------------------------------------------------------------
605 * creates a new polygon on a layer
607 PolygonTypePtr
608 CreateNewPolygon (LayerTypePtr Layer, FlagType Flags)
610 PolygonTypePtr polygon = GetPolygonMemory (Layer);
612 /* copy values */
613 polygon->Flags = Flags;
614 polygon->ID = ID++;
615 polygon->Clipped = NULL;
616 polygon->NoHoles = NULL;
617 polygon->NoHolesValid = 0;
618 return (polygon);
621 /* ---------------------------------------------------------------------------
622 * creates a new point in a polygon
624 PointTypePtr
625 CreateNewPointInPolygon (PolygonTypePtr Polygon, LocationType X,
626 LocationType Y)
628 PointTypePtr point = GetPointMemoryInPolygon (Polygon);
630 /* copy values */
631 point->X = X;
632 point->Y = Y;
633 point->ID = ID++;
634 return (point);
637 /* ---------------------------------------------------------------------------
638 * creates an new element
639 * memory is allocated if needed
641 ElementTypePtr
642 CreateNewElement (DataTypePtr Data, ElementTypePtr Element,
643 FontTypePtr PCBFont,
644 FlagType Flags,
645 char *Description, char *NameOnPCB, char *Value,
646 LocationType TextX, LocationType TextY, BYTE Direction,
647 int TextScale, FlagType TextFlags, Boolean uniqueName)
649 #ifdef DEBUG
650 printf("Entered CreateNewElement.....\n");
651 #endif
653 if (!Element)
654 Element = GetElementMemory (Data);
656 /* copy values and set additional information */
657 TextScale = MAX (MIN_TEXTSCALE, TextScale);
658 AddTextToElement (&DESCRIPTION_TEXT (Element), PCBFont, TextX, TextY,
659 Direction, Description, TextScale, TextFlags);
660 if (uniqueName)
661 NameOnPCB = UniqueElementName (Data, NameOnPCB);
662 AddTextToElement (&NAMEONPCB_TEXT (Element), PCBFont, TextX, TextY,
663 Direction, NameOnPCB, TextScale, TextFlags);
664 AddTextToElement (&VALUE_TEXT (Element), PCBFont, TextX, TextY,
665 Direction, Value, TextScale, TextFlags);
666 DESCRIPTION_TEXT (Element).Element = Element;
667 NAMEONPCB_TEXT (Element).Element = Element;
668 VALUE_TEXT (Element).Element = Element;
669 Element->Flags = Flags;
670 Element->ID = ID++;
672 #ifdef DEBUG
673 printf(" .... Leaving CreateNewElement.\n");
674 #endif
676 return (Element);
679 /* ---------------------------------------------------------------------------
680 * creates a new arc in an element
682 ArcTypePtr
683 CreateNewArcInElement (ElementTypePtr Element,
684 LocationType X, LocationType Y,
685 BDimension Width, BDimension Height,
686 int Angle, int Delta, BDimension Thickness)
688 ArcTypePtr arc = Element->Arc;
690 /* realloc new memory if necessary and clear it */
691 if (Element->ArcN >= Element->ArcMax)
693 Element->ArcMax += STEP_ELEMENTARC;
694 arc = MyRealloc (arc, Element->ArcMax * sizeof (ArcType),
695 "CreateNewArcInElement()");
696 Element->Arc = arc;
697 memset (arc + Element->ArcN, 0, STEP_ELEMENTARC * sizeof (ArcType));
700 /* set Delta (0,360], StartAngle in [0,360) */
701 if ((Delta = Delta % 360) == 0)
702 Delta = 360;
703 if (Delta < 0)
705 Angle += Delta;
706 Delta = -Delta;
708 if ((Angle = Angle % 360) < 0)
709 Angle += 360;
711 /* copy values */
712 arc = arc + Element->ArcN++;
713 arc->X = X;
714 arc->Y = Y;
715 arc->Width = Width;
716 arc->Height = Height;
717 arc->StartAngle = Angle;
718 arc->Delta = Delta;
719 arc->Thickness = Thickness;
720 arc->ID = ID++;
721 return (arc);
724 /* ---------------------------------------------------------------------------
725 * creates a new line for an element
727 LineTypePtr
728 CreateNewLineInElement (ElementTypePtr Element,
729 LocationType X1, LocationType Y1,
730 LocationType X2, LocationType Y2,
731 BDimension Thickness)
733 LineTypePtr line = Element->Line;
735 if (Thickness == 0)
736 return (NULL);
737 /* realloc new memory if necessary and clear it */
738 if (Element->LineN >= Element->LineMax)
740 Element->LineMax += STEP_ELEMENTLINE;
741 line = MyRealloc (line, Element->LineMax * sizeof (LineType),
742 "CreateNewLineInElement()");
743 Element->Line = line;
744 memset (line + Element->LineN, 0, STEP_ELEMENTLINE * sizeof (LineType));
747 /* copy values */
748 line = line + Element->LineN++;
749 line->Point1.X = X1;
750 line->Point1.Y = Y1;
751 line->Point2.X = X2;
752 line->Point2.Y = Y2;
753 line->Thickness = Thickness;
754 line->Flags = NoFlags ();
755 line->ID = ID++;
756 return (line);
759 /* ---------------------------------------------------------------------------
760 * creates a new pin in an element
762 PinTypePtr
763 CreateNewPin (ElementTypePtr Element,
764 LocationType X, LocationType Y,
765 BDimension Thickness, BDimension Clearance, BDimension Mask,
766 BDimension DrillingHole, char *Name, char *Number,
767 FlagType Flags)
769 PinTypePtr pin = GetPinMemory (Element);
771 /* copy values */
772 pin->X = X;
773 pin->Y = Y;
774 pin->Thickness = Thickness;
775 pin->Clearance = Clearance;
776 pin->Mask = Mask;
777 pin->Name = MyStrdup (Name, "CreateNewPin()");
778 pin->Number = MyStrdup (Number, "CreateNewPin()");
779 pin->Flags = Flags;
780 CLEAR_FLAG (WARNFLAG, pin);
781 SET_FLAG (PINFLAG, pin);
782 pin->ID = ID++;
783 pin->Element = Element;
786 * If there is no vendor drill map installed, this will simply
787 * return DrillingHole.
789 pin->DrillingHole = vendorDrillMap (DrillingHole);
791 /* Unless we should not map drills on this element, map them! */
792 if (vendorIsElementMappable (Element))
794 if (pin->DrillingHole < MIN_PINORVIASIZE)
796 Message (_
797 ("Did not map pin #%s (%s) drill hole because %6.2f mil is below the minimum allowed size\n"),
798 UNKNOWN (Number), UNKNOWN (Name),
799 0.01 * pin->DrillingHole);
800 pin->DrillingHole = DrillingHole;
802 else if (pin->DrillingHole > MAX_PINORVIASIZE)
804 Message (_
805 ("Did not map pin #%s (%s) drill hole because %6.2f mil is above the maximum allowed size\n"),
806 UNKNOWN (Number), UNKNOWN (Name),
807 0.01 * pin->DrillingHole);
808 pin->DrillingHole = DrillingHole;
810 else if (!TEST_FLAG (HOLEFLAG, pin)
811 && (pin->DrillingHole > pin->Thickness - MIN_PINORVIACOPPER))
813 Message (_
814 ("Did not map pin #%s (%s) drill hole because %6.2f mil does not leave enough copper\n"),
815 UNKNOWN (Number), UNKNOWN (Name),
816 0.01 * pin->DrillingHole);
817 pin->DrillingHole = DrillingHole;
820 else
822 pin->DrillingHole = DrillingHole;
825 if (pin->DrillingHole != DrillingHole)
827 Message (_
828 ("Mapped pin drill hole to %.2f mils from %.2f mils per vendor table\n"),
829 0.01 * pin->DrillingHole, 0.01 * DrillingHole);
832 return (pin);
835 /* ---------------------------------------------------------------------------
836 * creates a new pad in an element
838 PadTypePtr
839 CreateNewPad (ElementTypePtr Element,
840 LocationType X1, LocationType Y1, LocationType X2,
841 LocationType Y2, BDimension Thickness, BDimension Clearance,
842 BDimension Mask, char *Name, char *Number, FlagType Flags)
844 PadTypePtr pad = GetPadMemory (Element);
846 /* copy values */
847 if (X1 > X2 || (X1 == X2 && Y1 > Y2))
849 pad->Point1.X = X2;
850 pad->Point1.Y = Y2;
851 pad->Point2.X = X1;
852 pad->Point2.Y = Y1;
854 else
856 pad->Point1.X = X1;
857 pad->Point1.Y = Y1;
858 pad->Point2.X = X2;
859 pad->Point2.Y = Y2;
861 pad->Thickness = Thickness;
862 pad->Clearance = Clearance;
863 pad->Mask = Mask;
864 pad->Name = MyStrdup (Name, "CreateNewPad()");
865 pad->Number = MyStrdup (Number, "CreateNewPad()");
866 pad->Flags = Flags;
867 CLEAR_FLAG (WARNFLAG, pad);
868 pad->ID = ID++;
869 pad->Element = Element;
870 return (pad);
873 /* ---------------------------------------------------------------------------
874 * creates a new textobject as part of an element
875 * copies the values to the appropriate text object
877 static void
878 AddTextToElement (TextTypePtr Text, FontTypePtr PCBFont,
879 LocationType X, LocationType Y,
880 BYTE Direction, char *TextString, int Scale, FlagType Flags)
882 MYFREE (Text->TextString);
883 Text->X = X;
884 Text->Y = Y;
885 Text->Direction = Direction;
886 Text->Flags = Flags;
887 Text->Scale = Scale;
888 Text->TextString = (TextString && *TextString) ?
889 MyStrdup (TextString, "AddTextToElement()") : NULL;
891 /* calculate size of the bounding box */
892 SetTextBoundingBox (PCBFont, Text);
893 Text->ID = ID++;
896 /* ---------------------------------------------------------------------------
897 * creates a new line in a symbol
899 LineTypePtr
900 CreateNewLineInSymbol (SymbolTypePtr Symbol,
901 LocationType X1, LocationType Y1,
902 LocationType X2, LocationType Y2, BDimension Thickness)
904 LineTypePtr line = Symbol->Line;
906 /* realloc new memory if necessary and clear it */
907 if (Symbol->LineN >= Symbol->LineMax)
909 Symbol->LineMax += STEP_SYMBOLLINE;
910 line = MyRealloc (line, Symbol->LineMax * sizeof (LineType),
911 "CreateNewLineInSymbol()");
912 Symbol->Line = line;
913 memset (line + Symbol->LineN, 0, STEP_SYMBOLLINE * sizeof (LineType));
916 /* copy values */
917 line = line + Symbol->LineN++;
918 line->Point1.X = X1;
919 line->Point1.Y = Y1;
920 line->Point2.X = X2;
921 line->Point2.Y = Y2;
922 line->Thickness = Thickness;
923 return (line);
926 /* ---------------------------------------------------------------------------
927 * parses a file with font information and installs it
928 * checks directories given as colon separated list by resource fontPath
929 * if the fonts filename doesn't contain a directory component
931 void
932 CreateDefaultFont (void)
934 if (ParseFont (&PCB->Font, Settings.FontFile))
935 Message (_("Can't find font-symbol-file '%s'\n"), Settings.FontFile);
938 /* ---------------------------------------------------------------------------
939 * adds a new line to the rubberband list of 'Crosshair.AttachedObject'
940 * if Layer == 0 it is a rat line
942 RubberbandTypePtr
943 CreateNewRubberbandEntry (LayerTypePtr Layer,
944 LineTypePtr Line, PointTypePtr MovedPoint)
946 RubberbandTypePtr ptr = GetRubberbandMemory ();
948 /* we toggle the RUBBERENDFLAG of the line to determine if */
949 /* both points are being moved. */
950 TOGGLE_FLAG (RUBBERENDFLAG, Line);
951 ptr->Layer = Layer;
952 ptr->Line = Line;
953 ptr->MovedPoint = MovedPoint;
954 return (ptr);
957 /* ---------------------------------------------------------------------------
958 * Add a new net to the netlist menu
960 LibraryMenuTypePtr
961 CreateNewNet (LibraryTypePtr lib, char *name, char *style)
963 LibraryMenuTypePtr menu;
964 char temp[64];
966 sprintf (temp, " %s", name);
967 menu = GetLibraryMenuMemory (lib);
968 menu->Name = MyStrdup (temp, "CreateNewNet()");
969 menu->flag = 1; /* net is enabled by default */
970 if (style == NULL || NSTRCMP ("(unknown)", style) == 0)
971 menu->Style = NULL;
972 else
973 menu->Style = MyStrdup (style, "CreateNewNet()");
974 return (menu);
977 /* ---------------------------------------------------------------------------
978 * Add a connection to the net
980 LibraryEntryTypePtr
981 CreateNewConnection (LibraryMenuTypePtr net, char *conn)
983 LibraryEntryTypePtr entry = GetLibraryEntryMemory (net);
985 entry->ListEntry = MyStrdup (conn, "CreateNewConnection()");
986 return (entry);
989 /* ---------------------------------------------------------------------------
990 * Add an attribute to a list.
992 AttributeTypePtr
993 CreateNewAttribute (AttributeListTypePtr list, char *name, char *value)
995 if (list->Number >= list->Max)
997 list->Max += 10;
998 list->List = MyRealloc (list->List,
999 list->Max * sizeof (AttributeType),
1000 "CreateNewAttribute");
1002 list->List[list->Number].name = MyStrdup (name, "CreateNewAttribute");
1003 list->List[list->Number].value = MyStrdup (value, "CreateNewAttribute");
1004 list->Number++;
1005 return &list->List[list->Number - 1];