pcb 4.1.1
An interactive printed circuit board layout editor.

create.c

Go to the documentation of this file.
00001 
00033 #ifdef HAVE_CONFIG_H
00034 #include "config.h"
00035 #endif
00036 
00037 #include <assert.h>
00038 #include <memory.h>
00039 #include <setjmp.h>
00040 #include <stdlib.h>
00041 
00042 #include "global.h"
00043 
00044 #include "create.h"
00045 #include "data.h"
00046 #include "draw.h"
00047 #include "error.h"
00048 #include "mymem.h"
00049 #include "misc.h"
00050 #include "parse_l.h"
00051 #include "pcb-printf.h"
00052 #include "polygon.h"
00053 #include "rtree.h"
00054 #include "search.h"
00055 #include "set.h"
00056 #include "undo.h"
00057 #include "vendor.h"
00058 
00059 #ifdef HAVE_LIBDMALLOC
00060 #include <dmalloc.h>
00061 #endif
00062 
00063 /* ---------------------------------------------------------------------------
00064  * some local identifiers
00065  */
00066 static long int ID = 1;
00069 static bool be_lenient = false;
00070 
00071 /* ----------------------------------------------------------------------
00072  * some local prototypes
00073  */
00074 static void AddTextToElement (TextType *, FontType *,
00075                               Coord, Coord, unsigned, char *, int,
00076                               FlagType);
00077 
00085 void
00086 CreateBeLenient (bool v)
00087 {
00088   be_lenient = v;
00089 }
00090 
00094 DataType *
00095 CreateNewBuffer (void)
00096 {
00097   DataType *data;
00098   data = (DataType *) calloc (1, sizeof (DataType));
00099   data->pcb = (PCBType *) PCB;
00100   return data;
00101 }
00102 
00109 void
00110 pcb_colors_from_settings (PCBType *ptr)
00111 {
00112   int i;
00113 
00114   /* copy default settings */
00115   ptr->ConnectedColor = Settings.ConnectedColor;
00116   ptr->FoundColor = Settings.FoundColor;
00117   ptr->ElementColor = Settings.ElementColor;
00118   ptr->RatColor = Settings.RatColor;
00119   ptr->InvisibleObjectsColor = Settings.InvisibleObjectsColor;
00120   ptr->InvisibleMarkColor = Settings.InvisibleMarkColor;
00121   ptr->ElementSelectedColor = Settings.ElementSelectedColor;
00122   ptr->RatSelectedColor = Settings.RatSelectedColor;
00123   ptr->PinColor = Settings.PinColor;
00124   ptr->PinSelectedColor = Settings.PinSelectedColor;
00125   ptr->PinNameColor = Settings.PinNameColor;
00126   ptr->ViaColor = Settings.ViaColor;
00127   ptr->ViaSelectedColor = Settings.ViaSelectedColor;
00128   ptr->WarnColor = Settings.WarnColor;
00129   ptr->MaskColor = Settings.MaskColor;
00130   for (i = 0; i < MAX_LAYER; i++)
00131     {
00132       ptr->Data->Layer[i].Color = Settings.LayerColor[i];
00133       ptr->Data->Layer[i].SelectedColor = Settings.LayerSelectedColor[i];
00134     }
00135   ptr->Data->Layer[top_silk_layer].Color =
00136     Settings.ShowBottomSide ?
00137     Settings.InvisibleObjectsColor : Settings.ElementColor;
00138   ptr->Data->Layer[top_silk_layer].SelectedColor =
00139     Settings.ElementSelectedColor;
00140   ptr->Data->Layer[bottom_silk_layer].Color =
00141     Settings.ShowBottomSide ?
00142     Settings.ElementColor : Settings.InvisibleObjectsColor;
00143   ptr->Data->Layer[bottom_silk_layer].SelectedColor =
00144     Settings.ElementSelectedColor;
00145 }
00146 
00150 PCBType *
00151 CreateNewPCB (void)
00152 {
00153   PCBType *ptr;
00154   int i;
00155 
00156   /* allocate memory, switch all layers on and copy resources */
00157   ptr = (PCBType *)calloc (1, sizeof (PCBType));
00158   ptr->Data = CreateNewBuffer ();
00159   ptr->Data->pcb = (PCBType *) ptr;
00160   ptr->Data->polyClip = 1;
00161 
00162   ptr->ThermStyle = 4;
00163   ptr->IsleArea = 2.e8;
00164   ptr->SilkActive = false;
00165   ptr->RatDraw = false;
00166   SET_FLAG (NAMEONPCBFLAG, ptr);
00167   if (Settings.ShowNumber)
00168     SET_FLAG (SHOWNUMBERFLAG, ptr);
00169   if (Settings.AllDirectionLines)
00170     SET_FLAG (ALLDIRECTIONFLAG, ptr);
00171   ptr->Clipping = 1;            /* this is the most useful starting point for now */
00172   if (Settings.RubberBandMode)
00173     SET_FLAG (RUBBERBANDFLAG, ptr);
00174   if (Settings.SwapStartDirection)
00175     SET_FLAG (SWAPSTARTDIRFLAG, ptr);
00176   if (Settings.UniqueNames)
00177     SET_FLAG (UNIQUENAMEFLAG, ptr);
00178   if (Settings.SnapPin)
00179     SET_FLAG (SNAPPINFLAG, ptr);
00180   if (Settings.ClearLine)
00181     SET_FLAG (CLEARNEWFLAG, ptr);
00182   if (Settings.FullPoly)
00183     SET_FLAG (NEWFULLPOLYFLAG, ptr);
00184   if (Settings.OrthogonalMoves)
00185     SET_FLAG (ORTHOMOVEFLAG, ptr);
00186   if (Settings.liveRouting)
00187     SET_FLAG (LIVEROUTEFLAG, ptr);
00188   if (Settings.ShowDRC)
00189     SET_FLAG (SHOWDRCFLAG, ptr);
00190   if (Settings.AutoDRC)
00191     SET_FLAG (AUTODRCFLAG, ptr);
00192   if (Settings.AutoBuriedVias)
00193     SET_FLAG (AUTOBURIEDVIASFLAG, ptr);
00194   ptr->Grid = Settings.Grid;
00195   ptr->LayerGroups = Settings.LayerGroups;
00196   STYLE_LOOP (ptr);
00197   {
00198     *style = Settings.RouteStyle[n];
00199     style->index = n;
00200   }
00201   END_LOOP;
00202   ptr->MaxWidth = Settings.MaxWidth;
00203   ptr->MaxHeight = Settings.MaxHeight;
00204   ptr->ID = ID++;
00205   ptr->ThermScale = 0.5;
00206 
00207   ptr->Bloat = Settings.Bloat;
00208   ptr->Shrink = Settings.Shrink;
00209   ptr->minWid = Settings.minWid;
00210   ptr->minSlk = Settings.minSlk;
00211   ptr->minDrill = Settings.minDrill;
00212   ptr->minRing = Settings.minRing;
00213 
00214   for (i = 0; i < MAX_LAYER; i++)
00215     ptr->Data->Layer[i].Name = strdup (Settings.DefaultLayerName[i]);
00216 
00217         CreateDefaultFont (ptr);
00218 
00219   return (ptr);
00220 }
00221 
00230 int
00231 CreateNewPCBPost (PCBType *pcb, int use_defaults)
00232 {
00233   /* copy default settings */
00234   pcb_colors_from_settings (pcb);
00235 
00236   if (use_defaults)
00237     {
00238       if (ParseGroupString (Settings.Groups, &pcb->LayerGroups, &pcb->Data->LayerN))
00239         return 1;
00240     }
00241 
00242   pcb->Data->Layer[top_silk_layer].Name = strdup ("top silk");
00243   pcb->Data->Layer[top_silk_layer].Type = LT_SILK;
00244   pcb->Data->Layer[bottom_silk_layer].Name = strdup ("bottom silk");
00245   pcb->Data->Layer[bottom_silk_layer].Type = LT_SILK;
00246 
00247   return 0;
00248 }
00249 
00253 PinType *
00254 CreateNewVia (DataType *Data,
00255               Coord X, Coord Y,
00256               Coord Thickness, Coord Clearance, Coord Mask,
00257               Coord DrillingHole, char *Name, FlagType Flags)
00258 {
00259   PinType *Via;
00260 
00261   if (!be_lenient)
00262     {
00263       VIA_LOOP (Data);
00264       {
00265         if (Distance (X, Y, via->X, via->Y) <=
00266             via->DrillingHole / 2 + DrillingHole / 2)
00267           {
00268             Message (_("%m+Dropping via at %$mD because it's hole would overlap with the via "
00269                        "at %$mD\n"), Settings.grid_unit->allow, X, Y, via->X, via->Y);
00270             return (NULL);              /* don't allow via stacking */
00271           }
00272       }
00273       END_LOOP;
00274     }
00275 
00276   Via = GetViaMemory (Data);
00277 
00278   if (!Via)
00279     return (Via);
00280   /* copy values */
00281   Via->X = X;
00282   Via->Y = Y;
00283   Via->Thickness = Thickness;
00284   Via->Clearance = Clearance;
00285   Via->Mask = Mask;
00286   Via->DrillingHole = vendorDrillMap (DrillingHole);
00287   if (Via->DrillingHole != DrillingHole)
00288     {
00289       Message (_("%m+Mapped via drill hole to %$mS from %$mS per vendor table\n"),
00290                Settings.grid_unit->allow, Via->DrillingHole, DrillingHole);
00291     }
00292 
00293   Via->Name = STRDUP (Name);
00294   Via->Flags = Flags;
00295   Via->BuriedFrom = 0;
00296   Via->BuriedTo = 0;
00297   CLEAR_FLAG (WARNFLAG, Via);
00298   SET_FLAG (VIAFLAG, Via);
00299   Via->ID = ID++;
00300 
00301   /* 
00302    * don't complain about MIN_PINORVIACOPPER on a mounting hole (pure
00303    * hole)
00304    */
00305   if (!TEST_FLAG (HOLEFLAG, Via) &&
00306       (Via->Thickness < Via->DrillingHole + MIN_PINORVIACOPPER))
00307     {
00308       Via->Thickness = Via->DrillingHole + MIN_PINORVIACOPPER;
00309       Message (_("%m+Increased via thickness to %$mS to allow enough copper"
00310                  " at %$mD.\n"),
00311                Settings.grid_unit->allow, Via->Thickness, Via->X, Via->Y);
00312     }
00313 
00314   SetPinBoundingBox (Via);
00315   if (!Data->via_tree)
00316     Data->via_tree = r_create_tree (NULL, 0, 0);
00317   r_insert_entry (Data->via_tree, (BoxType *) Via, 0);
00318   return (Via);
00319 }
00320 
00324 PinType *
00325 CreateNewViaEx (DataType *Data,
00326               Coord X, Coord Y,
00327               Coord Thickness, Coord Clearance, Coord Mask,
00328               Coord DrillingHole, char *Name, FlagType Flags,
00329               Cardinal buried_from, Cardinal buried_to)
00330 {
00331   PinType *Via;
00332 
00333   Via = CreateNewVia (Data, X, Y, Thickness, Clearance, Mask,
00334               DrillingHole, Name, Flags);
00335   if (Via)
00336     {
00337       if (buried_from == buried_to)
00338         {
00339           Via->BuriedFrom = 0;
00340           Via->BuriedTo = 0;
00341         }
00342       else if (buried_from <= buried_to)
00343         {
00344           Via->BuriedFrom = buried_from;
00345           Via->BuriedTo = buried_to;
00346         }
00347       else
00348         {
00349           Via->BuriedFrom = buried_to;
00350           Via->BuriedTo = buried_from;
00351         }
00352     }
00353   return Via;
00354 }
00355 
00356 
00357 struct line_info
00358 {
00359   Coord X1, X2, Y1, Y2;
00360   Coord Thickness;
00361   Coord Clearance;
00362   FlagType Flags;
00363   LineType test, *ans;
00364   jmp_buf env;
00365 };
00366 
00367 static int
00368 line_callback (const BoxType * b, void *cl)
00369 {
00370   LineType *line = (LineType *) b;
00371   struct line_info *i = (struct line_info *) cl;
00372 
00373   if (line->Point1.X == i->X1 &&
00374       line->Point2.X == i->X2 &&
00375       line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2)
00376     {
00377       i->ans = (LineType *) (-1);
00378       longjmp (i->env, 1);
00379     }
00380   /* check the other point order */
00381   if (line->Point1.X == i->X1 &&
00382       line->Point2.X == i->X2 &&
00383       line->Point1.Y == i->Y1 && line->Point2.Y == i->Y2)
00384     {
00385       i->ans = (LineType *) (-1);
00386       longjmp (i->env, 1);
00387     }
00388   if (line->Point2.X == i->X1 &&
00389       line->Point1.X == i->X2 &&
00390       line->Point2.Y == i->Y1 && line->Point1.Y == i->Y2)
00391     {
00392       i->ans = (LineType *) - 1;
00393       longjmp (i->env, 1);
00394     }
00395   /* remove unnecessary line points */
00396   if (line->Thickness == i->Thickness &&
00397       /* don't merge lines if the clearances differ  */
00398       line->Clearance == i->Clearance &&
00399       /* don't merge lines if the clear flags differ  */
00400       TEST_FLAG (CLEARLINEFLAG, line) == TEST_FLAG (CLEARLINEFLAG, i))
00401     {
00402       if (line->Point1.X == i->X1 && line->Point1.Y == i->Y1)
00403         {
00404           i->test.Point1.X = line->Point2.X;
00405           i->test.Point1.Y = line->Point2.Y;
00406           i->test.Point2.X = i->X2;
00407           i->test.Point2.Y = i->Y2;
00408           if (IsPointOnLine (i->X1, i->Y1, 0.0, &i->test))
00409             {
00410               i->ans = line;
00411               longjmp (i->env, 1);
00412             }
00413         }
00414       else if (line->Point2.X == i->X1 && line->Point2.Y == i->Y1)
00415         {
00416           i->test.Point1.X = line->Point1.X;
00417           i->test.Point1.Y = line->Point1.Y;
00418           i->test.Point2.X = i->X2;
00419           i->test.Point2.Y = i->Y2;
00420           if (IsPointOnLine (i->X1, i->Y1, 0.0, &i->test))
00421             {
00422               i->ans = line;
00423               longjmp (i->env, 1);
00424             }
00425         }
00426       else if (line->Point1.X == i->X2 && line->Point1.Y == i->Y2)
00427         {
00428           i->test.Point1.X = line->Point2.X;
00429           i->test.Point1.Y = line->Point2.Y;
00430           i->test.Point2.X = i->X1;
00431           i->test.Point2.Y = i->Y1;
00432           if (IsPointOnLine (i->X2, i->Y2, 0.0, &i->test))
00433             {
00434               i->ans = line;
00435               longjmp (i->env, 1);
00436             }
00437         }
00438       else if (line->Point2.X == i->X2 && line->Point2.Y == i->Y2)
00439         {
00440           i->test.Point1.X = line->Point1.X;
00441           i->test.Point1.Y = line->Point1.Y;
00442           i->test.Point2.X = i->X1;
00443           i->test.Point2.Y = i->Y1;
00444           if (IsPointOnLine (i->X2, i->Y2, 0.0, &i->test))
00445             {
00446               i->ans = line;
00447               longjmp (i->env, 1);
00448             }
00449         }
00450     }
00451   return 0;
00452 }
00453 
00454 
00459 LineType *
00460 CreateDrawnLineOnLayer (LayerType *Layer,
00461                         Coord X1, Coord Y1,
00462                         Coord X2, Coord Y2,
00463                         Coord Thickness, Coord Clearance,
00464                         FlagType Flags)
00465 {
00466   struct line_info info;
00467   BoxType search;
00468 
00469   search.X1 = MIN (X1, X2);
00470   search.X2 = MAX (X1, X2);
00471   search.Y1 = MIN (Y1, Y2);
00472   search.Y2 = MAX (Y1, Y2);
00473   if (search.Y2 == search.Y1)
00474     search.Y2++;
00475   if (search.X2 == search.X1)
00476     search.X2++;
00477   info.X1 = X1;
00478   info.X2 = X2;
00479   info.Y1 = Y1;
00480   info.Y2 = Y2;
00481   info.Thickness = Thickness;
00482   info.Clearance = Clearance;
00483   info.Flags = Flags;
00484   info.test.Thickness = 0;
00485   info.test.Flags = NoFlags ();
00486   info.ans = NULL;
00487   /* prevent stacking of duplicate lines
00488    * and remove needless intermediate points
00489    * verify that the layer is on the board first!
00490    */
00491   if (setjmp (info.env) == 0)
00492     {
00493       r_search (Layer->line_tree, &search, NULL, line_callback, &info);
00494       return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
00495                                    Thickness, Clearance, Flags);
00496     }
00497 
00498   if ((void *) info.ans == (void *) (-1))
00499     return NULL;                /* stacked line */
00500   /* remove unnecessary points */
00501   if (info.ans)
00502     {
00503       /* must do this BEFORE getting new line memory */
00504       MoveObjectToRemoveUndoList (LINE_TYPE, Layer, info.ans, info.ans);
00505       X1 = info.test.Point1.X;
00506       X2 = info.test.Point2.X;
00507       Y1 = info.test.Point1.Y;
00508       Y2 = info.test.Point2.Y;
00509     }
00510   return CreateNewLineOnLayer (Layer, X1, Y1, X2, Y2,
00511                                Thickness, Clearance, Flags);
00512 }
00513 
00514 LineType *
00515 CreateNewLineOnLayer (LayerType *Layer,
00516                       Coord X1, Coord Y1,
00517                       Coord X2, Coord Y2,
00518                       Coord Thickness, Coord Clearance,
00519                       FlagType Flags)
00520 {
00521   LineType *Line;
00522 
00523   Line = GetLineMemory (Layer);
00524   if (!Line)
00525     return (Line);
00526   Line->ID = ID++;
00527   Line->Flags = Flags;
00528   CLEAR_FLAG (RATFLAG, Line);
00529   Line->Thickness = Thickness;
00530   Line->Clearance = Clearance;
00531   Line->Point1.X = X1;
00532   Line->Point1.Y = Y1;
00533   Line->Point1.ID = ID++;
00534   Line->Point2.X = X2;
00535   Line->Point2.Y = Y2;
00536   Line->Point2.ID = ID++;
00537   SetLineBoundingBox (Line);
00538   if (!Layer->line_tree)
00539     Layer->line_tree = r_create_tree (NULL, 0, 0);
00540   r_insert_entry (Layer->line_tree, (BoxType *) Line, 0);
00541   return (Line);
00542 }
00543 
00547 RatType *
00548 CreateNewRat (DataType *Data, Coord X1, Coord Y1,
00549               Coord X2, Coord Y2, Cardinal group1,
00550               Cardinal group2, Coord Thickness, FlagType Flags)
00551 {
00552   RatType *Line = GetRatMemory (Data);
00553 
00554   if (!Line)
00555     return (Line);
00556 
00557   Line->ID = ID++;
00558   Line->Flags = Flags;
00559   SET_FLAG (RATFLAG, Line);
00560   Line->Thickness = Thickness;
00561   Line->Point1.X = X1;
00562   Line->Point1.Y = Y1;
00563   Line->Point1.ID = ID++;
00564   Line->Point2.X = X2;
00565   Line->Point2.Y = Y2;
00566   Line->Point2.ID = ID++;
00567   Line->group1 = group1;
00568   Line->group2 = group2;
00569   SetLineBoundingBox ((LineType *) Line);
00570   if (!Data->rat_tree)
00571     Data->rat_tree = r_create_tree (NULL, 0, 0);
00572   r_insert_entry (Data->rat_tree, &Line->BoundingBox, 0);
00573   return (Line);
00574 }
00575 
00579 ArcType *
00580 CreateNewArcOnLayer (LayerType *Layer,
00581                      Coord X1, Coord Y1,
00582                      Coord width,
00583                      Coord height,
00584                      Angle sa,
00585                      Angle dir, Coord Thickness,
00586                      Coord Clearance, FlagType Flags)
00587 {
00588   ArcType *Arc;
00589 
00590   ARC_LOOP (Layer);
00591   {
00592     if (arc->X == X1 && arc->Y == Y1 && arc->Width == width &&
00593         NormalizeAngle (arc->StartAngle) == NormalizeAngle (sa) &&
00594         arc->Delta == dir)
00595       return (NULL);            /* prevent stacked arcs */
00596   }
00597   END_LOOP;
00598   Arc = GetArcMemory (Layer);
00599   if (!Arc)
00600     return (Arc);
00601 
00602   Arc->ID = ID++;
00603   Arc->Flags = Flags;
00604   Arc->Thickness = Thickness;
00605   Arc->Clearance = Clearance;
00606   Arc->X = X1;
00607   Arc->Y = Y1;
00608   Arc->Width = width;
00609   Arc->Height = height;
00610   Arc->StartAngle = sa;
00611   Arc->Delta = dir;
00612   SetArcBoundingBox (Arc);
00613   if (!Layer->arc_tree)
00614     Layer->arc_tree = r_create_tree (NULL, 0, 0);
00615   r_insert_entry (Layer->arc_tree, (BoxType *) Arc, 0);
00616   return (Arc);
00617 }
00618 
00619 
00623 PolygonType *
00624 CreateNewPolygonFromRectangle (LayerType *Layer,
00625                                Coord X1, Coord Y1,
00626                                Coord X2, Coord Y2,
00627                                FlagType Flags)
00628 {
00629   PolygonType *polygon = CreateNewPolygon (Layer, Flags);
00630   if (!polygon)
00631     return (polygon);
00632 
00633   CreateNewPointInPolygon (polygon, X1, Y1);
00634   CreateNewPointInPolygon (polygon, X2, Y1);
00635   CreateNewPointInPolygon (polygon, X2, Y2);
00636   CreateNewPointInPolygon (polygon, X1, Y2);
00637   SetPolygonBoundingBox (polygon);
00638   if (!Layer->polygon_tree)
00639     Layer->polygon_tree = r_create_tree (NULL, 0, 0);
00640   r_insert_entry (Layer->polygon_tree, (BoxType *) polygon, 0);
00641   return (polygon);
00642 }
00643 
00647 TextType *
00648 CreateNewText (LayerType *Layer, FontType *PCBFont,
00649                Coord X, Coord Y,
00650                unsigned Direction, int Scale, char *TextString, FlagType Flags)
00651 {
00652   TextType *text;
00653 
00654   if (TextString == NULL)
00655     return NULL;
00656 
00657   text = GetTextMemory (Layer);
00658   if (text == NULL)
00659     return NULL;
00660 
00661   /* copy values, width and height are set by drawing routine
00662    * because at this point we don't know which symbols are available
00663    */
00664   text->X = X;
00665   text->Y = Y;
00666   text->Direction = Direction;
00667   text->Flags = Flags;
00668   text->Scale = Scale;
00669   text->TextString = strdup (TextString);
00670 
00671   /* calculate size of the bounding box */
00672   SetTextBoundingBox (PCBFont, text);
00673   text->ID = ID++;
00674   if (!Layer->text_tree)
00675     Layer->text_tree = r_create_tree (NULL, 0, 0);
00676   r_insert_entry (Layer->text_tree, (BoxType *) text, 0);
00677   return (text);
00678 }
00679 
00683 PolygonType *
00684 CreateNewPolygon (LayerType *Layer, FlagType Flags)
00685 {
00686   PolygonType *polygon = GetPolygonMemory (Layer);
00687 
00688   /* copy values */
00689   polygon->Flags = Flags;
00690   polygon->ID = ID++;
00691   polygon->Clipped = NULL;
00692   polygon->NoHoles = NULL;
00693   polygon->NoHolesValid = 0;
00694   return (polygon);
00695 }
00696 
00700 PointType *
00701 CreateNewPointInPolygon (PolygonType *Polygon, Coord X, Coord Y)
00702 {
00703   PointType *point = GetPointMemoryInPolygon (Polygon);
00704 
00705   /* copy values */
00706   point->X = X;
00707   point->Y = Y;
00708   point->ID = ID++;
00709   return (point);
00710 }
00711 
00715 PolygonType *
00716 CreateNewHoleInPolygon (PolygonType *Polygon)
00717 {
00718   Cardinal *holeindex = GetHoleIndexMemoryInPolygon (Polygon);
00719   *holeindex = Polygon->PointN;
00720   return Polygon;
00721 }
00722 
00728 ElementType *
00729 CreateNewElement (DataType *Data, FontType *PCBFont, FlagType Flags,
00730                   char *Description, char *NameOnPCB, char *Value,
00731                   Coord TextX, Coord TextY, BYTE Direction,
00732                   int TextScale, FlagType TextFlags, bool uniqueName)
00733 {
00734   ElementType *Element;
00735 
00736 #ifdef DEBUG
00737   printf("Entered CreateNewElement.....\n");
00738 #endif
00739 
00740   Element = GetElementMemory (Data);
00741 
00742   /* copy values and set additional information */
00743   TextScale = MAX (MIN_TEXTSCALE, TextScale);
00744   AddTextToElement (&DESCRIPTION_TEXT (Element), PCBFont, TextX, TextY,
00745                     Direction, Description, TextScale, TextFlags);
00746   if (uniqueName)
00747     NameOnPCB = UniqueElementName (Data, NameOnPCB);
00748   AddTextToElement (&NAMEONPCB_TEXT (Element), PCBFont, TextX, TextY,
00749                     Direction, NameOnPCB, TextScale, TextFlags);
00750   AddTextToElement (&VALUE_TEXT (Element), PCBFont, TextX, TextY,
00751                     Direction, Value, TextScale, TextFlags);
00752   DESCRIPTION_TEXT (Element).Element = Element;
00753   NAMEONPCB_TEXT (Element).Element = Element;
00754   VALUE_TEXT (Element).Element = Element;
00755   Element->Flags = Flags;
00756   Element->ID = ID++;
00757 
00758 #ifdef DEBUG
00759   printf("  .... Leaving CreateNewElement.\n");
00760 #endif
00761 
00762   return (Element);
00763 }
00764 
00768 ArcType *
00769 CreateNewArcInElement (ElementType *Element,
00770                        Coord X, Coord Y,
00771                        Coord Width, Coord Height,
00772                        Angle angle, Angle delta, Coord Thickness)
00773 {
00774   ArcType *arc;
00775 
00776   arc = g_slice_new0 (ArcType);
00777   Element->Arc = g_list_append (Element->Arc, arc);
00778   Element->ArcN ++;
00779 
00780   /* set Delta (0,360], StartAngle in [0,360) */
00781   if (delta < 0)
00782     {
00783       delta = -delta;
00784       angle -= delta;
00785     }
00786   angle = NormalizeAngle (angle);
00787   delta = NormalizeAngle (delta);
00788   if (delta == 0)
00789     delta = 360;
00790 
00791   /* copy values */
00792   arc->X = X;
00793   arc->Y = Y;
00794   arc->Width = Width;
00795   arc->Height = Height;
00796   arc->StartAngle = angle;
00797   arc->Delta = delta;
00798   arc->Thickness = Thickness;
00799   arc->ID = ID++;
00800   return arc;
00801 }
00802 
00806 LineType *
00807 CreateNewLineInElement (ElementType *Element,
00808                         Coord X1, Coord Y1,
00809                         Coord X2, Coord Y2,
00810                         Coord Thickness)
00811 {
00812   LineType *line;
00813 
00814   if (Thickness == 0)
00815     return NULL;
00816 
00817   line = g_slice_new0 (LineType);
00818   Element->Line = g_list_append (Element->Line, line);
00819   Element->LineN ++;
00820 
00821   /* copy values */
00822   line->Point1.X = X1;
00823   line->Point1.Y = Y1;
00824   line->Point2.X = X2;
00825   line->Point2.Y = Y2;
00826   line->Thickness = Thickness;
00827   line->Flags = NoFlags ();
00828   line->ID = ID++;
00829   return line;
00830 }
00831 
00835 PinType *
00836 CreateNewPin (ElementType *Element,
00837               Coord X, Coord Y,
00838               Coord Thickness, Coord Clearance, Coord Mask,
00839               Coord DrillingHole, char *Name, char *Number,
00840               FlagType Flags)
00841 {
00842   PinType *pin = GetPinMemory (Element);
00843 
00844   /* copy values */
00845   pin->X = X;
00846   pin->Y = Y;
00847   pin->Thickness = Thickness;
00848   pin->Clearance = Clearance;
00849   pin->Mask = Mask;
00850   pin->Name = STRDUP (Name);
00851   pin->Number = STRDUP (Number);
00852   pin->Flags = Flags;
00853   CLEAR_FLAG (WARNFLAG, pin);
00854   SET_FLAG (PINFLAG, pin);
00855   pin->ID = ID++;
00856   pin->Element = Element;
00857 
00858   /* 
00859    * If there is no vendor drill map installed, this will simply
00860    * return DrillingHole.
00861    */
00862   pin->DrillingHole = vendorDrillMap (DrillingHole);
00863 
00864   /* Unless we should not map drills on this element, map them! */
00865   if (vendorIsElementMappable (Element))
00866     {
00867       if (pin->DrillingHole < MIN_PINORVIASIZE)
00868         {
00869           Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is below the minimum allowed size\n"),
00870                    Settings.grid_unit->allow, UNKNOWN (Number), UNKNOWN (Name), pin->DrillingHole);
00871           pin->DrillingHole = DrillingHole;
00872         }
00873       else if (pin->DrillingHole > MAX_PINORVIASIZE)
00874         {
00875           Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS is above the maximum allowed size\n"),
00876                    Settings.grid_unit->allow, UNKNOWN (Number), UNKNOWN (Name), pin->DrillingHole);
00877           pin->DrillingHole = DrillingHole;
00878         }
00879       else if (!TEST_FLAG (HOLEFLAG, pin)
00880                && (pin->DrillingHole > pin->Thickness - MIN_PINORVIACOPPER))
00881         {
00882           Message (_("%m+Did not map pin #%s (%s) drill hole because %$mS does not leave enough copper\n"),
00883                    Settings.grid_unit->allow, UNKNOWN (Number), UNKNOWN (Name), pin->DrillingHole);
00884           pin->DrillingHole = DrillingHole;
00885         }
00886     }
00887   else
00888     {
00889       pin->DrillingHole = DrillingHole;
00890     }
00891 
00892   if (pin->DrillingHole != DrillingHole)
00893     {
00894       Message (_("%m+Mapped pin drill hole to %$mS from %$mS per vendor table\n"),
00895                Settings.grid_unit->allow, pin->DrillingHole, DrillingHole);
00896     }
00897 
00898   return (pin);
00899 }
00900 
00904 PadType *
00905 CreateNewPad (ElementType *Element,
00906               Coord X1, Coord Y1, Coord X2,
00907               Coord Y2, Coord Thickness, Coord Clearance,
00908               Coord Mask, char *Name, char *Number, FlagType Flags)
00909 {
00910   PadType *pad = GetPadMemory (Element);
00911 
00912   /* copy values */
00913   if (X1 > X2 || (X1 == X2 && Y1 > Y2))
00914     {
00915       pad->Point1.X = X2;
00916       pad->Point1.Y = Y2;
00917       pad->Point2.X = X1;
00918       pad->Point2.Y = Y1;
00919     }
00920   else
00921     {
00922       pad->Point1.X = X1;
00923       pad->Point1.Y = Y1;
00924       pad->Point2.X = X2;
00925       pad->Point2.Y = Y2;
00926     }
00927   pad->Thickness = Thickness;
00928   pad->Clearance = Clearance;
00929   pad->Mask = Mask;
00930   pad->Name = STRDUP (Name);
00931   pad->Number = STRDUP (Number);
00932   pad->Flags = Flags;
00933   CLEAR_FLAG (WARNFLAG, pad);
00934   pad->ID = ID++;
00935   pad->Element = Element;
00936   return (pad);
00937 }
00938 
00944 static void
00945 AddTextToElement (TextType *Text, FontType *PCBFont,
00946                   Coord X, Coord Y,
00947                   unsigned Direction, char *TextString, int Scale, FlagType Flags)
00948 {
00949   free (Text->TextString);
00950   Text->TextString = (TextString && *TextString) ? strdup (TextString) : NULL;
00951   Text->X = X;
00952   Text->Y = Y;
00953   Text->Direction = Direction;
00954   Text->Flags = Flags;
00955   Text->Scale = Scale;
00956 
00957   /* calculate size of the bounding box */
00958   SetTextBoundingBox (PCBFont, Text);
00959   Text->ID = ID++;
00960 }
00961 
00965 LineType *
00966 CreateNewLineInSymbol (SymbolType *Symbol,
00967                        Coord X1, Coord Y1,
00968                        Coord X2, Coord Y2, Coord Thickness)
00969 {
00970   LineType *line = Symbol->Line;
00971 
00972   /* realloc new memory if necessary and clear it */
00973   if (Symbol->LineN >= Symbol->LineMax)
00974     {
00975       Symbol->LineMax += STEP_SYMBOLLINE;
00976       line = (LineType *)realloc (line, Symbol->LineMax * sizeof (LineType));
00977       Symbol->Line = line;
00978       memset (line + Symbol->LineN, 0, STEP_SYMBOLLINE * sizeof (LineType));
00979     }
00980 
00981   /* copy values */
00982   line = line + Symbol->LineN++;
00983   line->Point1.X = X1;
00984   line->Point1.Y = Y1;
00985   line->Point2.X = X2;
00986   line->Point2.Y = Y2;
00987   line->Thickness = Thickness;
00988   return (line);
00989 }
00990 
00998 void
00999 CreateDefaultFont (PCBType *pcb)
01000 {
01001   if (ParseFont (&pcb->Font, Settings.FontFile))
01002     Message (_("Can't find font-symbol-file '%s'\n"), Settings.FontFile);
01003 }
01004 
01011 RubberbandType *
01012 CreateNewRubberbandEntry (LayerType *Layer,
01013                           LineType *Line, PointType *MovedPoint)
01014 {
01015   RubberbandType *ptr = GetRubberbandMemory ();
01016 
01017   /* we toggle the RUBBERENDFLAG of the line to determine if */
01018   /* both points are being moved. */
01019   TOGGLE_FLAG (RUBBERENDFLAG, Line);
01020   ptr->Layer = Layer;
01021   ptr->Line = Line;
01022   ptr->MovedPoint = MovedPoint;
01023   return (ptr);
01024 }
01025 
01029 LibraryMenuType *
01030 CreateNewNet (LibraryType *lib, char *name, char *style)
01031 {
01032   LibraryMenuType *menu;
01033   char temp[64];
01034 
01035   sprintf (temp, "  %s", name);
01036   menu = GetLibraryMenuMemory (lib);
01037   menu->Name = strdup (temp);
01038   menu->flag = 1;               /* net is enabled by default */
01039   if (style == NULL || NSTRCMP ("(unknown)", style) == 0)
01040     menu->Style = NULL;
01041   else
01042     menu->Style = strdup (style);
01043   return (menu);
01044 }
01045 
01049 LibraryEntryType *
01050 CreateNewConnection (LibraryMenuType *net, char *conn)
01051 {
01052   LibraryEntryType *entry = GetLibraryEntryMemory (net);
01053 
01054   entry->ListEntry = STRDUP (conn);
01055   return (entry);
01056 }
01057 
01061 AttributeType *
01062 CreateNewAttribute (AttributeListType *list, char *name, char *value)
01063 {
01064   if (list->Number >= list->Max)
01065     {
01066       list->Max += 10;
01067       list->List = (AttributeType *)realloc (list->List, list->Max * sizeof (AttributeType));
01068     }
01069   list->List[list->Number].name = STRDUP (name);
01070   list->List[list->Number].value = STRDUP (value);
01071   list->Number++;
01072   return &list->List[list->Number - 1];
01073 }