pcb 4.1.1
An interactive printed circuit board layout editor.

search.c

Go to the documentation of this file.
00001 
00038 #ifdef HAVE_CONFIG_H
00039 #include "config.h"
00040 #endif
00041 
00042 #include <math.h>
00043 #include <setjmp.h>
00044 
00045 #include "global.h"
00046 
00047 #include "box.h"
00048 #include "data.h"
00049 #include "draw.h"
00050 #include "error.h"
00051 #include "find.h"
00052 #include "misc.h"
00053 #include "polygon.h"
00054 #include "rtree.h"
00055 #include "search.h"
00056 
00057 #ifdef HAVE_LIBDMALLOC
00058 #include <dmalloc.h>
00059 #endif
00060 
00061 /* ---------------------------------------------------------------------------
00062  * some local identifiers
00063  */
00064 static double PosX, PosY;               /* search position for subroutines */
00065 static Coord SearchRadius;
00066 static BoxType SearchBox;
00067 static LayerType *SearchLayer;
00068 
00069 /* ---------------------------------------------------------------------------
00070  * some local prototypes.  The first parameter includes LOCKED_TYPE if we
00071  * want to include locked types in the search.
00072  */
00073 static bool SearchLineByLocation (int, LayerType **, LineType **,
00074                                      LineType **);
00075 static bool SearchArcByLocation (int, LayerType **, ArcType **,
00076                                     ArcType **);
00077 static bool SearchRatLineByLocation (int, RatType **, RatType **,
00078                                         RatType **);
00079 static bool SearchTextByLocation (int, LayerType **, TextType **,
00080                                      TextType **);
00081 static bool SearchPolygonByLocation (int, LayerType **, PolygonType **,
00082                                         PolygonType **);
00083 static bool SearchPinByLocation (int, ElementType **, PinType **,
00084                                     PinType **);
00085 static bool SearchPadByLocation (int, ElementType **, PadType **,
00086                                     PadType **, bool);
00087 static bool SearchViaByLocation (int, PinType **, PinType **,
00088                                     PinType **);
00089 static bool SearchElementNameByLocation (int, ElementType **,
00090                                             TextType **, TextType **,
00091                                             bool);
00092 static bool SearchLinePointByLocation (int, LayerType **, LineType **,
00093                                           PointType **);
00094 static bool SearchPointByLocation (int, LayerType **, PolygonType **,
00095                                       PointType **);
00096 static bool SearchElementByLocation (int, ElementType **,
00097                                         ElementType **, ElementType **,
00098                                         bool);
00099 
00100 struct ans_info
00101 {
00102   void **ptr1, **ptr2, **ptr3;
00103   bool BackToo;
00104   double area;
00105   jmp_buf env;
00106   int locked; 
00107   bool found_anything;
00108   double nearest_sq_dist;
00109 };
00110 
00111 static int
00112 pinorvia_callback (const BoxType * box, void *cl)
00113 {
00114   struct ans_info *i = (struct ans_info *) cl;
00115   PinType *pin = (PinType *) box;
00116   AnyObjectType *ptr1 = pin->Element ? pin->Element : pin;
00117 
00118   if (TEST_FLAG (i->locked, ptr1))
00119     return 0;
00120 
00121   if (!IsPointOnPin (PosX, PosY, SearchRadius, pin))
00122     return 0;
00123   *i->ptr1 = ptr1;
00124   *i->ptr2 = *i->ptr3 = pin;
00125   longjmp (i->env, 1);
00126   return 1;                     /* never reached */
00127 }
00128 
00132 static bool
00133 SearchViaByLocation (int locked, PinType ** Via, PinType ** Dummy1,
00134                      PinType ** Dummy2)
00135 {
00136   struct ans_info info;
00137 
00138   /* search only if via-layer is visible */
00139   if (!PCB->ViaOn)
00140     return false;
00141 
00142   info.ptr1 = (void **) Via;
00143   info.ptr2 = (void **) Dummy1;
00144   info.ptr3 = (void **) Dummy2;
00145   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00146 
00147   if (setjmp (info.env) == 0)
00148     {
00149       r_search (PCB->Data->via_tree, &SearchBox, NULL, pinorvia_callback,
00150                 &info);
00151       return false;
00152     }
00153   return true;
00154 }
00155 
00161 static bool
00162 SearchPinByLocation (int locked, ElementType ** Element, PinType ** Pin,
00163                      PinType ** Dummy)
00164 {
00165   struct ans_info info;
00166 
00167   /* search only if pin-layer is visible */
00168   if (!PCB->PinOn)
00169     return false;
00170   info.ptr1 = (void **) Element;
00171   info.ptr2 = (void **) Pin;
00172   info.ptr3 = (void **) Dummy;
00173   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00174 
00175   if (setjmp (info.env) == 0)
00176     r_search (PCB->Data->pin_tree, &SearchBox, NULL, pinorvia_callback,
00177               &info);
00178   else
00179     return true;
00180   return false;
00181 }
00182 
00183 static int
00184 pad_callback (const BoxType * b, void *cl)
00185 {
00186   PadType *pad = (PadType *) b;
00187   struct ans_info *i = (struct ans_info *) cl;
00188   AnyObjectType *ptr1 = pad->Element;
00189   double sq_dist;
00190 
00191   /* Reject locked pads, backside pads (if !BackToo), and non-hit pads */
00192   if (TEST_FLAG (i->locked, ptr1) ||
00193       (!FRONT (pad) && !i->BackToo) ||
00194       !IsPointInPad (PosX, PosY, SearchRadius, pad))
00195     return 0;
00196 
00197   /* Determine how close our test-position was to the center of the pad  */
00198   sq_dist = (PosX - (pad->Point1.X + (pad->Point2.X - pad->Point1.X) / 2)) *
00199             (PosX - (pad->Point1.X + (pad->Point2.X - pad->Point1.X) / 2)) +
00200             (PosY - (pad->Point1.Y + (pad->Point2.Y - pad->Point1.Y) / 2)) *
00201             (PosY - (pad->Point1.Y + (pad->Point2.Y - pad->Point1.Y) / 2));
00202 
00203   /* If this was the closest hit so far, record it */
00204   if (!i->found_anything || sq_dist < i->nearest_sq_dist)
00205     {
00206       *i->ptr1 = ptr1;
00207       *i->ptr2 = *i->ptr3 = pad;
00208       i->found_anything = true;
00209       i->nearest_sq_dist = sq_dist;
00210     }
00211   return 0;
00212 }
00213 
00219 static bool
00220 SearchPadByLocation (int locked, ElementType ** Element, PadType ** Pad,
00221                      PadType ** Dummy, bool BackToo)
00222 {
00223   struct ans_info info;
00224 
00225   /* search only if pin-layer is visible */
00226   if (!PCB->PinOn)
00227     return (false);
00228   info.ptr1 = (void **) Element;
00229   info.ptr2 = (void **) Pad;
00230   info.ptr3 = (void **) Dummy;
00231   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00232   info.BackToo = (BackToo && PCB->InvisibleObjectsOn);
00233   info.found_anything = false;
00234   r_search (PCB->Data->pad_tree, &SearchBox, NULL, pad_callback, &info);
00235   return info.found_anything;
00236 }
00237 
00238 struct line_info
00239 {
00240   LineType **Line;
00241   PointType **Point;
00242   double least;
00243   jmp_buf env;
00244   int locked;
00245 };
00246 
00247 static int
00248 line_callback (const BoxType * box, void *cl)
00249 {
00250   struct line_info *i = (struct line_info *) cl;
00251   LineType *l = (LineType *) box;
00252 
00253   if (TEST_FLAG (i->locked, l))
00254     return 0;
00255 
00256   if (!IsPointInPad (PosX, PosY, SearchRadius, (PadType *)l))
00257     return 0;
00258   *i->Line = l;
00259   *i->Point = (PointType *) l;
00260   longjmp (i->env, 1);
00261   return 1;                     /* never reached */
00262 }
00263 
00264 
00268 static bool
00269 SearchLineByLocation (int locked, LayerType ** Layer, LineType ** Line,
00270                       LineType ** Dummy)
00271 {
00272   struct line_info info;
00273 
00274   info.Line = Line;
00275   info.Point = (PointType **) Dummy;
00276   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00277 
00278   *Layer = SearchLayer;
00279   if (setjmp (info.env) == 0)
00280     {
00281       r_search (SearchLayer->line_tree, &SearchBox, NULL, line_callback,
00282                 &info);
00283       return false;
00284     }
00285   return (true);
00286 }
00287 
00288 static int
00289 rat_callback (const BoxType * box, void *cl)
00290 {
00291   LineType *line = (LineType *) box;
00292   struct ans_info *i = (struct ans_info *) cl;
00293 
00294   if (TEST_FLAG (i->locked, line))
00295     return 0;
00296 
00297   if (TEST_FLAG (VIAFLAG, line) ?
00298       (Distance (line->Point1.X, line->Point1.Y, PosX, PosY) <=
00299            line->Thickness * 2 + SearchRadius) :
00300       IsPointOnLine (PosX, PosY, SearchRadius, line))
00301     {
00302       *i->ptr1 = *i->ptr2 = *i->ptr3 = line;
00303       longjmp (i->env, 1);
00304     }
00305   return 0;
00306 }
00307 
00311 static bool
00312 SearchRatLineByLocation (int locked, RatType ** Line, RatType ** Dummy1,
00313                          RatType ** Dummy2)
00314 {
00315   struct ans_info info;
00316 
00317   info.ptr1 = (void **) Line;
00318   info.ptr2 = (void **) Dummy1;
00319   info.ptr3 = (void **) Dummy2;
00320   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00321 
00322   if (setjmp (info.env) == 0)
00323     {
00324       r_search (PCB->Data->rat_tree, &SearchBox, NULL, rat_callback, &info);
00325       return false;
00326     }
00327   return (true);
00328 }
00329 
00330 struct arc_info
00331 {
00332   ArcType **Arc, **Dummy;
00333   PointType **Point;
00334   double least;
00335   jmp_buf env;
00336   int locked;
00337 };
00338 
00339 static int
00340 arc_callback (const BoxType * box, void *cl)
00341 {
00342   struct arc_info *i = (struct arc_info *) cl;
00343   ArcType *a = (ArcType *) box;
00344 
00345   if (TEST_FLAG (i->locked, a))
00346     return 0;
00347 
00348   if (!IsPointOnArc (PosX, PosY, SearchRadius, a))
00349     return 0;
00350   *i->Arc = a;
00351   *i->Dummy = a;
00352   longjmp (i->env, 1);
00353   return 1;                     /* never reached */
00354 }
00355 
00356 
00360 static bool
00361 SearchArcByLocation (int locked, LayerType ** Layer, ArcType ** Arc,
00362                      ArcType ** Dummy)
00363 {
00364   struct arc_info info;
00365 
00366   info.Arc = Arc;
00367   info.Dummy = Dummy;
00368   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00369 
00370   *Layer = SearchLayer;
00371   if (setjmp (info.env) == 0)
00372     {
00373       r_search (SearchLayer->arc_tree, &SearchBox, NULL, arc_callback, &info);
00374       return false;
00375     }
00376   return (true);
00377 }
00378 
00379 static int
00380 text_callback (const BoxType * box, void *cl)
00381 {
00382   TextType *text = (TextType *) box;
00383   struct ans_info *i = (struct ans_info *) cl;
00384 
00385   if (TEST_FLAG (i->locked, text))
00386     return 0;
00387 
00388   if (POINT_IN_BOX (PosX, PosY, &text->BoundingBox))
00389     {
00390       *i->ptr2 = *i->ptr3 = text;
00391       longjmp (i->env, 1);
00392     }
00393   return 0;
00394 }
00395 
00399 static bool
00400 SearchTextByLocation (int locked, LayerType ** Layer, TextType ** Text,
00401                       TextType ** Dummy)
00402 {
00403   struct ans_info info;
00404 
00405   *Layer = SearchLayer;
00406   info.ptr2 = (void **) Text;
00407   info.ptr3 = (void **) Dummy;
00408   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00409 
00410   if (setjmp (info.env) == 0)
00411     {
00412       r_search (SearchLayer->text_tree, &SearchBox, NULL, text_callback,
00413                 &info);
00414       return false;
00415     }
00416   return (true);
00417 }
00418 
00419 static int
00420 polygon_callback (const BoxType * box, void *cl)
00421 {
00422   PolygonType *polygon = (PolygonType *) box;
00423   struct ans_info *i = (struct ans_info *) cl;
00424 
00425   if (TEST_FLAG (i->locked, polygon))
00426     return 0;
00427 
00428   if (IsPointInPolygon (PosX, PosY, SearchRadius, polygon))
00429     {
00430       *i->ptr2 = *i->ptr3 = polygon;
00431       longjmp (i->env, 1);
00432     }
00433   return 0;
00434 }
00435 
00436 
00440 static bool
00441 SearchPolygonByLocation (int locked, LayerType ** Layer,
00442                          PolygonType ** Polygon, PolygonType ** Dummy)
00443 {
00444   struct ans_info info;
00445 
00446   *Layer = SearchLayer;
00447   info.ptr2 = (void **) Polygon;
00448   info.ptr3 = (void **) Dummy;
00449   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00450 
00451   if (setjmp (info.env) == 0)
00452     {
00453       r_search (SearchLayer->polygon_tree, &SearchBox, NULL, polygon_callback,
00454                 &info);
00455       return false;
00456     }
00457   return (true);
00458 }
00459 
00460 static int
00461 linepoint_callback (const BoxType * b, void *cl)
00462 {
00463   LineType *line = (LineType *) b;
00464   struct line_info *i = (struct line_info *) cl;
00465   int ret_val = 0;
00466   double d;
00467 
00468   if (TEST_FLAG (i->locked, line))
00469     return 0;
00470 
00471   /* some stupid code to check both points */
00472   d = Distance (PosX, PosY, line->Point1.X, line->Point1.Y);
00473   if (d < i->least)
00474     {
00475       i->least = d;
00476       *i->Line = line;
00477       *i->Point = &line->Point1;
00478       ret_val = 1;
00479     }
00480 
00481   d = Distance (PosX, PosY, line->Point2.X, line->Point2.Y);
00482   if (d < i->least)
00483     {
00484       i->least = d;
00485       *i->Line = line;
00486       *i->Point = &line->Point2;
00487       ret_val = 1;
00488     }
00489   return ret_val;
00490 }
00491 
00495 static bool
00496 SearchLinePointByLocation (int locked, LayerType ** Layer,
00497                            LineType ** Line, PointType ** Point)
00498 {
00499   struct line_info info;
00500   *Layer = SearchLayer;
00501   info.Line = Line;
00502   info.Point = Point;
00503   *Point = NULL;
00504   info.least = MAX_LINE_POINT_DISTANCE + SearchRadius;
00505   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00506   if (r_search
00507       (SearchLayer->line_tree, &SearchBox, NULL, linepoint_callback, &info))
00508     return true;
00509   return false;
00510 }
00511 
00512 static int
00513 arcpoint_callback (const BoxType * b, void *cl)
00514 {
00515   ArcType *arc = (ArcType *) b;
00516   struct arc_info *i = (struct arc_info *) cl;
00517   int ret_val = 0;
00518   double d;
00519 
00520   if (TEST_FLAG (i->locked, arc))
00521     return 0;
00522 
00523   d = Distance (PosX, PosY, arc->Point1.X, arc->Point1.Y);
00524   if (d < i->least)
00525     {
00526       i->least = d;
00527       *i->Arc = arc;
00528       *i->Point = &arc->Point1;
00529       ret_val = 1;
00530     }
00531 
00532   d = Distance (PosX, PosY, arc->Point2.X, arc->Point2.Y);
00533   if (d < i->least)
00534     {
00535       i->least = d;
00536       *i->Arc = arc;
00537       *i->Point = &arc->Point2;
00538       ret_val = 1;
00539     }
00540   return ret_val;
00541 }
00542 
00546 static bool
00547 SearchArcPointByLocation (int locked, LayerType **Layer,
00548                           ArcType **arc, PointType **Point)
00549 {
00550   struct arc_info info;
00551   *Layer = SearchLayer;
00552   info.Arc = arc;
00553   info.Point = Point;
00554   *Point = NULL;
00555   info.least = MAX_ARC_POINT_DISTANCE + SearchRadius;
00556   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00557   if (r_search
00558       (SearchLayer->arc_tree, &SearchBox, NULL, arcpoint_callback, &info))
00559     return true;
00560   return false;
00561 }
00566 static bool
00567 SearchPointByLocation (int locked, LayerType ** Layer,
00568                        PolygonType ** Polygon, PointType ** Point)
00569 {
00570   double d, least;
00571   bool found = false;
00572 
00573   least = SearchRadius + MAX_POLYGON_POINT_DISTANCE;
00574   *Layer = SearchLayer;
00575   POLYGON_LOOP (*Layer);
00576   {
00577     POLYGONPOINT_LOOP (polygon);
00578     {
00579       d = Distance (point->X, point->Y, PosX, PosY);
00580       if (d < least)
00581         {
00582           least = d;
00583           *Polygon = polygon;
00584           *Point = point;
00585           found = true;
00586         }
00587     }
00588     END_LOOP;
00589   }
00590   END_LOOP;
00591   if (found)
00592     return (true);
00593   return (false);
00594 }
00595 
00596 static int
00597 name_callback (const BoxType * box, void *cl)
00598 {
00599   TextType *text = (TextType *) box;
00600   struct ans_info *i = (struct ans_info *) cl;
00601   ElementType *element = (ElementType *) text->Element;
00602   double newarea;
00603 
00604   if (TEST_FLAG (i->locked, text))
00605     return 0;
00606 
00607   if ((FRONT (element) || i->BackToo) && !TEST_FLAG (HIDENAMEFLAG, element) &&
00608       POINT_IN_BOX (PosX, PosY, &text->BoundingBox))
00609     {
00610       /* use the text with the smallest bounding box */
00611       newarea = (text->BoundingBox.X2 - text->BoundingBox.X1) *
00612         (double) (text->BoundingBox.Y2 - text->BoundingBox.Y1);
00613       if (newarea < i->area)
00614         {
00615           i->area = newarea;
00616           *i->ptr1 = element;
00617           *i->ptr2 = *i->ptr3 = text;
00618         }
00619       return 1;
00620     }
00621   return 0;
00622 }
00623 
00630 static bool
00631 SearchElementNameByLocation (int locked, ElementType ** Element,
00632                              TextType ** Text, TextType ** Dummy,
00633                              bool BackToo)
00634 {
00635   struct ans_info info;
00636 
00637   /* package layer have to be switched on */
00638   if (PCB->ElementOn)
00639     {
00640       info.ptr1 = (void **) Element;
00641       info.ptr2 = (void **) Text;
00642       info.ptr3 = (void **) Dummy;
00643       info.area = SQUARE (MAX_COORD);
00644       info.BackToo = (BackToo && PCB->InvisibleObjectsOn);
00645       info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00646       if (r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], &SearchBox, NULL,
00647                     name_callback, &info))
00648         return true;
00649     }
00650   return (false);
00651 }
00652 
00653 static int
00654 element_callback (const BoxType * box, void *cl)
00655 {
00656   ElementType *element = (ElementType *) box;
00657   struct ans_info *i = (struct ans_info *) cl;
00658   double newarea;
00659 
00660   if (TEST_FLAG (i->locked, element))
00661     return 0;
00662 
00663   if ((FRONT (element) || i->BackToo) &&
00664       POINT_IN_BOX (PosX, PosY, &element->VBox))
00665     {
00666       /* use the element with the smallest bounding box */
00667       newarea = (element->VBox.X2 - element->VBox.X1) *
00668         (double) (element->VBox.Y2 - element->VBox.Y1);
00669       if (newarea < i->area)
00670         {
00671           i->area = newarea;
00672           *i->ptr1 = *i->ptr2 = *i->ptr3 = element;
00673           return 1;
00674         }
00675     }
00676   return 0;
00677 }
00678 
00687 static bool
00688 SearchElementByLocation (int locked,
00689                          ElementType ** Element,
00690                          ElementType ** Dummy1, ElementType ** Dummy2,
00691                          bool BackToo)
00692 {
00693   struct ans_info info;
00694 
00695   /* Both package layers have to be switched on */
00696   if (PCB->ElementOn && PCB->PinOn)
00697     {
00698       info.ptr1 = (void **) Element;
00699       info.ptr2 = (void **) Dummy1;
00700       info.ptr3 = (void **) Dummy2;
00701       info.area = SQUARE (MAX_COORD);
00702       info.BackToo = (BackToo && PCB->InvisibleObjectsOn);
00703       info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
00704       if (r_search
00705           (PCB->Data->element_tree, &SearchBox, NULL, element_callback,
00706            &info))
00707         return true;
00708     }
00709   return false;
00710 }
00711 
00715 bool
00716 IsPointOnPin (Coord X, Coord Y, Coord Radius, PinType *pin)
00717 {
00718   Coord t = PIN_SIZE (pin) / 2;
00719   if (TEST_FLAG (SQUAREFLAG, pin))
00720     {
00721       BoxType b;
00722 
00723       b.X1 = pin->X - t;
00724       b.X2 = pin->X + t;
00725       b.Y1 = pin->Y - t;
00726       b.Y2 = pin->Y + t;
00727       if (IsPointInBox (X, Y, &b, Radius))
00728         return true;
00729     }
00730   else if (Distance (pin->X, pin->Y, X, Y) <= Radius + t)
00731     return true;
00732   return false;
00733 }
00734 
00738 bool
00739 IsPointOnLineEnd (Coord X, Coord Y, RatType *Line)
00740 {
00741   if (((X == Line->Point1.X) && (Y == Line->Point1.Y)) ||
00742       ((X == Line->Point2.X) && (Y == Line->Point2.Y)))
00743     return (true);
00744   return (false);
00745 }
00746 
00781 bool
00782 IsPointOnLine (Coord X, Coord Y, Coord Radius, LineType *Line)
00783 {
00784   double D1, D2, L;
00785 
00786   /* Get length of segment */
00787   L = Distance (Line->Point1.X, Line->Point1.Y, Line->Point2.X, Line->Point2.Y);
00788   if (L < 0.1)
00789     return Distance (X, Y, Line->Point1.X, Line->Point1.Y) < Radius + Line->Thickness / 2;
00790 
00791   /* Get distance from (X1, Y1) to Q (on the line) */
00792   D1 = ((double) (Y - Line->Point1.Y) * (Line->Point2.Y - Line->Point1.Y)
00793         + (double) (X - Line->Point1.X) * (Line->Point2.X - Line->Point1.X)) / L;
00794   /* Translate this into distance to Q from segment */
00795   if (D1 < 0)       D1 = -D1;
00796   else if (D1 > L)  D1 -= L;
00797   else              D1 = 0;
00798   /* Get distance from (X, Y) to Q */
00799   D2 = ((double) (X - Line->Point1.X) * (Line->Point2.Y - Line->Point1.Y)
00800         - (double) (Y - Line->Point1.Y) * (Line->Point2.X - Line->Point1.X)) / L;
00801   /* Total distance is then the pythagorean sum of these */
00802   return hypot (D1, D2) <= Radius + Line->Thickness / 2;
00803 }
00804 
00808 bool
00809 IsLineInRectangle (Coord X1, Coord Y1, Coord X2, Coord Y2, LineType *Line)
00810 {
00811   LineType line;
00812 
00813   /* first, see if point 1 is inside the rectangle */
00814   /* in case the whole line is inside the rectangle */
00815   if (X1 < Line->Point1.X && X2 > Line->Point1.X &&
00816       Y1 < Line->Point1.Y && Y2 > Line->Point1.Y)
00817     return (true);
00818   /* construct a set of dummy lines and check each of them */
00819   line.Thickness = 0;
00820   line.Flags = NoFlags ();
00821 
00822   /* upper-left to upper-right corner */
00823   line.Point1.Y = line.Point2.Y = Y1;
00824   line.Point1.X = X1;
00825   line.Point2.X = X2;
00826   if (LineLineIntersect (&line, Line))
00827     return (true);
00828 
00829   /* upper-right to lower-right corner */
00830   line.Point1.X = X2;
00831   line.Point1.Y = Y1;
00832   line.Point2.Y = Y2;
00833   if (LineLineIntersect (&line, Line))
00834     return (true);
00835 
00836   /* lower-right to lower-left corner */
00837   line.Point1.Y = Y2;
00838   line.Point1.X = X1;
00839   line.Point2.X = X2;
00840   if (LineLineIntersect (&line, Line))
00841     return (true);
00842 
00843   /* lower-left to upper-left corner */
00844   line.Point2.X = X1;
00845   line.Point1.Y = Y1;
00846   line.Point2.Y = Y2;
00847   if (LineLineIntersect (&line, Line))
00848     return (true);
00849 
00850   return (false);
00851 }
00852 
00856 static int
00857 IsPointInQuadrangle(PointType p[4], PointType *l)
00858 {
00859   Coord dx, dy, x, y;
00860   double prod0, prod1;
00861 
00862   dx = p[1].X - p[0].X;
00863   dy = p[1].Y - p[0].Y;
00864   x = l->X - p[0].X;
00865   y = l->Y - p[0].Y;
00866   prod0 = (double) x * dx + (double) y * dy;
00867   x = l->X - p[1].X;
00868   y = l->Y - p[1].Y;
00869   prod1 = (double) x * dx + (double) y * dy;
00870   if (prod0 * prod1 <= 0)
00871     {
00872       dx = p[1].X - p[2].X;
00873       dy = p[1].Y - p[2].Y;
00874       prod0 = (double) x * dx + (double) y * dy;
00875       x = l->X - p[2].X;
00876       y = l->Y - p[2].Y;
00877       prod1 = (double) x * dx + (double) y * dy;
00878       if (prod0 * prod1 <= 0)
00879         return true;
00880     }
00881   return false;
00882 }
00883 
00890 bool
00891 IsLineInQuadrangle (PointType p[4], LineType *Line)
00892 {
00893   LineType line;
00894 
00895   /* first, see if point 1 is inside the rectangle */
00896   /* in case the whole line is inside the rectangle */
00897   if (IsPointInQuadrangle(p,&(Line->Point1)))
00898     return true;
00899   if (IsPointInQuadrangle(p,&(Line->Point2)))
00900     return true;
00901   /* construct a set of dummy lines and check each of them */
00902   line.Thickness = 0;
00903   line.Flags = NoFlags ();
00904 
00905   /* upper-left to upper-right corner */
00906   line.Point1.X = p[0].X; line.Point1.Y = p[0].Y;
00907   line.Point2.X = p[1].X; line.Point2.Y = p[1].Y;
00908   if (LineLineIntersect (&line, Line))
00909     return (true);
00910 
00911   /* upper-right to lower-right corner */
00912   line.Point1.X = p[2].X; line.Point1.Y = p[2].Y;
00913   if (LineLineIntersect (&line, Line))
00914     return (true);
00915 
00916   /* lower-right to lower-left corner */
00917   line.Point2.X = p[3].X; line.Point2.Y = p[3].Y;
00918   if (LineLineIntersect (&line, Line))
00919     return (true);
00920 
00921   /* lower-left to upper-left corner */
00922   line.Point1.X = p[0].X; line.Point1.Y = p[0].Y;
00923   if (LineLineIntersect (&line, Line))
00924     return (true);
00925 
00926   return (false);
00927 }
00931 bool
00932 IsArcInRectangle (Coord X1, Coord Y1, Coord X2, Coord Y2, ArcType *Arc)
00933 {
00934   LineType line;
00935 
00936   /* construct a set of dummy lines and check each of them */
00937   line.Thickness = 0;
00938   line.Flags = NoFlags ();
00939 
00940   /* upper-left to upper-right corner */
00941   line.Point1.Y = line.Point2.Y = Y1;
00942   line.Point1.X = X1;
00943   line.Point2.X = X2;
00944   if (LineArcIntersect (&line, Arc))
00945     return (true);
00946 
00947   /* upper-right to lower-right corner */
00948   line.Point1.X = line.Point2.X = X2;
00949   line.Point1.Y = Y1;
00950   line.Point2.Y = Y2;
00951   if (LineArcIntersect (&line, Arc))
00952     return (true);
00953 
00954   /* lower-right to lower-left corner */
00955   line.Point1.Y = line.Point2.Y = Y2;
00956   line.Point1.X = X1;
00957   line.Point2.X = X2;
00958   if (LineArcIntersect (&line, Arc))
00959     return (true);
00960 
00961   /* lower-left to upper-left corner */
00962   line.Point1.X = line.Point2.X = X1;
00963   line.Point1.Y = Y1;
00964   line.Point2.Y = Y2;
00965   if (LineArcIntersect (&line, Arc))
00966     return (true);
00967 
00968   return (false);
00969 }
00970 
00977 bool
00978 IsPointInPad (Coord X, Coord Y, Coord Radius, PadType *Pad)
00979 {
00980   double r, Sin, Cos;
00981   Coord x; 
00982   Coord t2 = (Pad->Thickness + 1) / 2, range;
00983   PadType pad = *Pad;
00984 
00985   /* series of transforms saving range */
00986   /* move Point1 to the origin */
00987   X -= pad.Point1.X;
00988   Y -= pad.Point1.Y;
00989 
00990   pad.Point2.X -= pad.Point1.X;
00991   pad.Point2.Y -= pad.Point1.Y;
00992   /* so, pad.Point1.X = pad.Point1.Y = 0; */
00993 
00994   /* rotate round (0, 0) so that Point2 coordinates be (r, 0) */
00995   r = Distance (0, 0, pad.Point2.X, pad.Point2.Y);
00996   if (r < .1)
00997     {
00998       Cos = 1;
00999       Sin = 0;
01000     }
01001   else
01002     {
01003       Sin = pad.Point2.Y / r;
01004       Cos = pad.Point2.X / r;
01005     }
01006   x = X;
01007   X = X * Cos + Y * Sin;
01008   Y = Y * Cos - x * Sin;
01009   /* now pad.Point2.X = r; pad.Point2.Y = 0; */
01010 
01011   /* take into account the ends */
01012   if (TEST_FLAG (SQUAREFLAG, Pad))
01013     {
01014       r += Pad->Thickness;
01015       X += t2;
01016     }
01017   if (Y < 0)
01018     Y = -Y;     /* range value is evident now*/
01019 
01020   if (TEST_FLAG (SQUAREFLAG, Pad))
01021     {
01022       if (X <= 0)
01023         {
01024           if (Y <= t2)
01025             range = -X;
01026           else
01027             return Radius > Distance (0, t2, X, Y);
01028         }
01029       else if (X >= r)
01030         {
01031           if (Y <= t2)
01032             range = X - r;
01033           else 
01034             return Radius > Distance (r, t2, X, Y);
01035         }
01036       else
01037         range = Y - t2;
01038     }
01039   else/*Rounded pad: even more simple*/
01040     {
01041       if (X <= 0)
01042         return (Radius + t2) > Distance (0, 0, X, Y);
01043       else if (X >= r) 
01044         return (Radius + t2) > Distance (r, 0, X, Y);
01045       else
01046         range = Y - t2;
01047     }
01048   return range < Radius;
01049 }
01050 
01057 bool
01058 IsPointInBox (Coord X, Coord Y, BoxType *box, Coord Radius)
01059 {
01060   Coord width, height, range;
01061 
01062   /* Compute coordinates relative to Point1 */
01063   X -= box->X1;
01064   Y -= box->Y1;
01065 
01066   width =  box->X2 - box->X1;
01067   height = box->Y2 - box->Y1;
01068 
01069   if (X <= 0)
01070     {
01071       if (Y < 0)
01072         return Radius > Distance (0, 0, X, Y);
01073       else if (Y > height)
01074         return Radius > Distance (0, height, X, Y);
01075       else
01076         range = -X;
01077     }
01078   else if (X >= width)
01079     {
01080       if (Y < 0)
01081         return Radius > Distance (width, 0, X, Y);
01082       else if (Y > height)
01083         return Radius > Distance (width, height, X, Y);
01084       else
01085         range = X - width;
01086     }
01087   else
01088     {
01089       if (Y < 0)
01090         range = -Y;
01091       else if (Y > height)
01092         range = Y - height;
01093       else
01094         return true;
01095     }
01096 
01097   return range < Radius;
01098 }
01099 
01106 bool
01107 IsPointOnArc (Coord X, Coord Y, Coord Radius, ArcType *Arc)
01108 {
01109   /* Calculate angle of point from arc center */
01110   double p_dist = Distance (X, Y, Arc->X, Arc->Y);
01111   double p_cos = (X - Arc->X) / p_dist;
01112   Angle p_ang = acos (p_cos) * RAD_TO_DEG;
01113   Angle ang1, ang2;
01114 
01115   /* Convert StartAngle, Delta into bounding angles in [0, 720) */
01116   if (Arc->Delta > 0)
01117     {
01118       ang1 = NormalizeAngle (Arc->StartAngle);
01119       ang2 = NormalizeAngle (Arc->StartAngle + Arc->Delta);
01120     }
01121   else
01122     {
01123       ang1 = NormalizeAngle (Arc->StartAngle + Arc->Delta);
01124       ang2 = NormalizeAngle (Arc->StartAngle);
01125     }
01126   if (ang1 > ang2)
01127     ang2 += 360;
01128   /* Make sure full circles aren't treated as zero-length arcs */
01129   if (Arc->Delta == 360 || Arc->Delta == -360)
01130     ang2 = ang1 + 360;
01131 
01132   if (Y > Arc->Y)
01133     p_ang = -p_ang;
01134   p_ang += 180;
01135 
01136   /* Check point is outside arc range, check distance from endpoints */
01137   if (ang1 >= p_ang || ang2 <= p_ang)
01138     {
01139       Coord ArcX, ArcY;
01140 
01141       ArcX = Arc->X + Arc->Width *
01142               cos ((Arc->StartAngle + 180) / RAD_TO_DEG);
01143       ArcY = Arc->Y - Arc->Width *
01144               sin ((Arc->StartAngle + 180) / RAD_TO_DEG);
01145       if (Distance (X, Y, ArcX, ArcY) < Radius + Arc->Thickness / 2)
01146         return true;
01147 
01148       ArcX = Arc->X + Arc->Width *
01149               cos ((Arc->StartAngle + Arc->Delta + 180) / RAD_TO_DEG);
01150       ArcY = Arc->Y - Arc->Width *
01151               sin ((Arc->StartAngle + Arc->Delta + 180) / RAD_TO_DEG);
01152       if (Distance (X, Y, ArcX, ArcY) < Radius + Arc->Thickness / 2)
01153         return true;
01154       return false;
01155     }
01156   /* If point is inside the arc range, just compare it to the arc */
01157   return fabs (Distance (X, Y, Arc->X, Arc->Y) - Arc->Width) < Radius + Arc->Thickness / 2;
01158 }
01159 
01178 int
01179 SearchObjectByLocation (unsigned Type,
01180                         void **Result1, void **Result2, void **Result3,
01181                         Coord X, Coord Y, Coord Radius)
01182 {
01183   void *r1, *r2, *r3;
01184   void **pr1 = &r1, **pr2 = &r2, **pr3 = &r3;
01185   int i;
01186   double HigherBound = 0;
01187   int HigherAvail = NO_TYPE;
01188   int locked = Type & LOCKED_TYPE;
01189   /* setup variables used by local functions */
01190   PosX = X;
01191   PosY = Y;
01192   SearchRadius = Radius;
01193   if (Radius)
01194     {
01195       SearchBox.X1 = X - Radius;
01196       SearchBox.Y1 = Y - Radius;
01197       SearchBox.X2 = X + Radius;
01198       SearchBox.Y2 = Y + Radius;
01199     }
01200   else
01201     {
01202       SearchBox = point_box (X, Y);
01203     }
01204 
01205   if (TEST_FLAG (LOCKNAMESFLAG, PCB))
01206     {
01207       Type &= ~ (ELEMENTNAME_TYPE | TEXT_TYPE);
01208     }
01209   if (TEST_FLAG (HIDENAMESFLAG, PCB))
01210     {
01211       Type &= ~ELEMENTNAME_TYPE;
01212     }
01213   if (TEST_FLAG (ONLYNAMESFLAG, PCB))
01214     {
01215       Type &= (ELEMENTNAME_TYPE | TEXT_TYPE);
01216     }
01217   if (TEST_FLAG (THINDRAWFLAG, PCB) || TEST_FLAG (THINDRAWPOLYFLAG, PCB))
01218     {
01219       Type &= ~POLYGON_TYPE;
01220     }
01221 
01222   if (Type & RATLINE_TYPE && PCB->RatOn &&
01223       SearchRatLineByLocation (locked,
01224                                (RatType **) Result1,
01225                                (RatType **) Result2,
01226                                (RatType **) Result3))
01227     return (RATLINE_TYPE);
01228 
01229   if (Type & VIA_TYPE &&
01230       SearchViaByLocation (locked,
01231                            (PinType **) Result1,
01232                            (PinType **) Result2, (PinType **) Result3))
01233     return (VIA_TYPE);
01234 
01235   if (Type & PIN_TYPE &&
01236       SearchPinByLocation (locked,
01237                            (ElementType **) pr1,
01238                            (PinType **) pr2, (PinType **) pr3))
01239     HigherAvail = PIN_TYPE;
01240 
01241   if (!HigherAvail && Type & PAD_TYPE &&
01242       SearchPadByLocation (locked,
01243                            (ElementType **) pr1,
01244                            (PadType **) pr2, (PadType **) pr3, false))
01245     HigherAvail = PAD_TYPE;
01246 
01247   if (!HigherAvail && Type & ELEMENTNAME_TYPE &&
01248       SearchElementNameByLocation (locked,
01249                                    (ElementType **) pr1,
01250                                    (TextType **) pr2, (TextType **) pr3,
01251                                    false))
01252     {
01253       BoxType *box = &((TextType *) r2)->BoundingBox;
01254       HigherBound = (double) (box->X2 - box->X1) * (double) (box->Y2 - box->Y1);
01255       HigherAvail = ELEMENTNAME_TYPE;
01256     }
01257 
01258   if (!HigherAvail && Type & ELEMENT_TYPE &&
01259       SearchElementByLocation (locked,
01260                                (ElementType **) pr1,
01261                                (ElementType **) pr2,
01262                                (ElementType **) pr3, false))
01263     {
01264       BoxType *box = &((ElementType *) r1)->BoundingBox;
01265       HigherBound = (double) (box->X2 - box->X1) * (double) (box->Y2 - box->Y1);
01266       HigherAvail = ELEMENT_TYPE;
01267     }
01268 
01269   for (i = -1; i < max_copper_layer + 1; i++)
01270     {
01271       if (i < 0)
01272         SearchLayer = &PCB->Data->SILKLAYER;
01273       else if (i < max_copper_layer)
01274         SearchLayer = LAYER_ON_STACK (i);
01275       else
01276         {
01277           SearchLayer = &PCB->Data->BACKSILKLAYER;
01278           if (!PCB->InvisibleObjectsOn)
01279             continue;
01280         }
01281       if (SearchLayer->On)
01282         {
01283           if ((HigherAvail & (PIN_TYPE | PAD_TYPE)) == 0 &&
01284               Type & POLYGONPOINT_TYPE &&
01285               SearchPointByLocation (locked,
01286                                      (LayerType **) Result1,
01287                                      (PolygonType **) Result2,
01288                                      (PointType **) Result3))
01289             return (POLYGONPOINT_TYPE);
01290 
01291           if ((HigherAvail & (PIN_TYPE | PAD_TYPE)) == 0 &&
01292               Type & LINEPOINT_TYPE &&
01293               SearchLinePointByLocation (locked,
01294                                          (LayerType **) Result1,
01295                                          (LineType **) Result2,
01296                                          (PointType **) Result3))
01297             return (LINEPOINT_TYPE);
01298 
01299           if ((HigherAvail & (PIN_TYPE | PAD_TYPE)) == 0 && Type & LINE_TYPE
01300               && SearchLineByLocation (locked,
01301                                        (LayerType **) Result1,
01302                                        (LineType **) Result2,
01303                                        (LineType **) Result3))
01304             return (LINE_TYPE);
01305 
01306     if ((HigherAvail & (PIN_TYPE | PAD_TYPE)) == 0 &&
01307               Type & ARCPOINT_TYPE &&
01308               SearchArcPointByLocation (locked,
01309                                         (LayerType **) Result1,
01310                                         (ArcType **) Result2,
01311                                         (PointType **) Result3))
01312             return (ARCPOINT_TYPE);
01313 
01314           if ((HigherAvail & (PIN_TYPE | PAD_TYPE)) == 0 && Type & ARC_TYPE &&
01315               SearchArcByLocation (locked,
01316                                    (LayerType **) Result1,
01317                                    (ArcType **) Result2,
01318                                    (ArcType **) Result3))
01319             return (ARC_TYPE);
01320 
01321           if ((HigherAvail & (PIN_TYPE | PAD_TYPE)) == 0 && Type & TEXT_TYPE
01322               && SearchTextByLocation (locked,
01323                                        (LayerType **) Result1,
01324                                        (TextType **) Result2,
01325                                        (TextType **) Result3))
01326             return (TEXT_TYPE);
01327 
01328           if (Type & POLYGON_TYPE &&
01329               SearchPolygonByLocation (locked,
01330                                        (LayerType **) Result1,
01331                                        (PolygonType **) Result2,
01332                                        (PolygonType **) Result3))
01333             {
01334               if (HigherAvail)
01335                 {
01336                   BoxType *box =
01337                     &(*(PolygonType **) Result2)->BoundingBox;
01338                   double area =
01339                     (double) (box->X2 - box->X1) * (double) (box->X2 - box->X1);
01340                   if (HigherBound < area)
01341                     break;
01342                   else
01343                     return (POLYGON_TYPE);
01344                 }
01345               else
01346                 return (POLYGON_TYPE);
01347             }
01348         }
01349     }
01350   /* return any previously found objects */
01351   if (HigherAvail & PIN_TYPE)
01352     {
01353       *Result1 = r1;
01354       *Result2 = r2;
01355       *Result3 = r3;
01356       return (PIN_TYPE);
01357     }
01358 
01359   if (HigherAvail & PAD_TYPE)
01360     {
01361       *Result1 = r1;
01362       *Result2 = r2;
01363       *Result3 = r3;
01364       return (PAD_TYPE);
01365     }
01366 
01367   if (HigherAvail & ELEMENTNAME_TYPE)
01368     {
01369       *Result1 = r1;
01370       *Result2 = r2;
01371       *Result3 = r3;
01372       return (ELEMENTNAME_TYPE);
01373     }
01374 
01375   if (HigherAvail & ELEMENT_TYPE)
01376     {
01377       *Result1 = r1;
01378       *Result2 = r2;
01379       *Result3 = r3;
01380       return (ELEMENT_TYPE);
01381     }
01382 
01383   /* search the 'invisible objects' last */
01384   if (!PCB->InvisibleObjectsOn)
01385     return (NO_TYPE);
01386 
01387   if (Type & PAD_TYPE &&
01388       SearchPadByLocation (locked,
01389                            (ElementType **) Result1,
01390                            (PadType **) Result2, (PadType **) Result3,
01391                            true))
01392     return (PAD_TYPE);
01393 
01394   if (Type & ELEMENTNAME_TYPE &&
01395       SearchElementNameByLocation (locked,
01396                                    (ElementType **) Result1,
01397                                    (TextType **) Result2,
01398                                    (TextType **) Result3, true))
01399     return (ELEMENTNAME_TYPE);
01400 
01401   if (Type & ELEMENT_TYPE &&
01402       SearchElementByLocation (locked,
01403                                (ElementType **) Result1,
01404                                (ElementType **) Result2,
01405                                (ElementType **) Result3, true))
01406     return (ELEMENT_TYPE);
01407 
01408   return (NO_TYPE);
01409 }
01410 
01424 int
01425 SearchObjectByID (DataType *Base,
01426                   void **Result1, void **Result2, void **Result3, int ID,
01427                   int type)
01428 {
01429   if (type == LINE_TYPE || type == LINEPOINT_TYPE)
01430     {
01431       ALLLINE_LOOP (Base);
01432       {
01433         if (line->ID == ID)
01434           {
01435             *Result1 = (void *) layer;
01436             *Result2 = *Result3 = (void *) line;
01437             return (LINE_TYPE);
01438           }
01439         if (line->Point1.ID == ID)
01440           {
01441             *Result1 = (void *) layer;
01442             *Result2 = (void *) line;
01443             *Result3 = (void *) &line->Point1;
01444             return (LINEPOINT_TYPE);
01445           }
01446         if (line->Point2.ID == ID)
01447           {
01448             *Result1 = (void *) layer;
01449             *Result2 = (void *) line;
01450             *Result3 = (void *) &line->Point2;
01451             return (LINEPOINT_TYPE);
01452           }
01453       }
01454       ENDALL_LOOP;
01455     }
01456   if (type == ARC_TYPE)
01457     {
01458       ALLARC_LOOP (Base);
01459       {
01460         if (arc->ID == ID)
01461           {
01462             *Result1 = (void *) layer;
01463             *Result2 = *Result3 = (void *) arc;
01464             return (ARC_TYPE);
01465           }
01466       }
01467       ENDALL_LOOP;
01468     }
01469 
01470   if (type == TEXT_TYPE)
01471     {
01472       ALLTEXT_LOOP (Base);
01473       {
01474         if (text->ID == ID)
01475           {
01476             *Result1 = (void *) layer;
01477             *Result2 = *Result3 = (void *) text;
01478             return (TEXT_TYPE);
01479           }
01480       }
01481       ENDALL_LOOP;
01482     }
01483 
01484   if (type == POLYGON_TYPE || type == POLYGONPOINT_TYPE)
01485     {
01486       ALLPOLYGON_LOOP (Base);
01487       {
01488         if (polygon->ID == ID)
01489           {
01490             *Result1 = (void *) layer;
01491             *Result2 = *Result3 = (void *) polygon;
01492             return (POLYGON_TYPE);
01493           }
01494         if (type == POLYGONPOINT_TYPE)
01495           POLYGONPOINT_LOOP (polygon);
01496         {
01497           if (point->ID == ID)
01498             {
01499               *Result1 = (void *) layer;
01500               *Result2 = (void *) polygon;
01501               *Result3 = (void *) point;
01502               return (POLYGONPOINT_TYPE);
01503             }
01504         }
01505         END_LOOP;
01506       }
01507       ENDALL_LOOP;
01508     }
01509   if (type == VIA_TYPE)
01510     {
01511       VIA_LOOP (Base);
01512       {
01513         if (via->ID == ID)
01514           {
01515             *Result1 = *Result2 = *Result3 = (void *) via;
01516             return (VIA_TYPE);
01517           }
01518       }
01519       END_LOOP;
01520     }
01521 
01522   if (type == RATLINE_TYPE || type == LINEPOINT_TYPE)
01523     {
01524       RAT_LOOP (Base);
01525       {
01526         if (line->ID == ID)
01527           {
01528             *Result1 = *Result2 = *Result3 = (void *) line;
01529             return (RATLINE_TYPE);
01530           }
01531         if (line->Point1.ID == ID)
01532           {
01533             *Result1 = (void *) NULL;
01534             *Result2 = (void *) line;
01535             *Result3 = (void *) &line->Point1;
01536             return (LINEPOINT_TYPE);
01537           }
01538         if (line->Point2.ID == ID)
01539           {
01540             *Result1 = (void *) NULL;
01541             *Result2 = (void *) line;
01542             *Result3 = (void *) &line->Point2;
01543             return (LINEPOINT_TYPE);
01544           }
01545       }
01546       END_LOOP;
01547     }
01548 
01549   if (type == ELEMENT_TYPE || type == PAD_TYPE || type == PIN_TYPE
01550       || type == ELEMENTLINE_TYPE || type == ELEMENTNAME_TYPE
01551       || type == ELEMENTARC_TYPE)
01552     /* check pins and elementnames too */
01553     ELEMENT_LOOP (Base);
01554   {
01555     if (element->ID == ID)
01556       {
01557         *Result1 = *Result2 = *Result3 = (void *) element;
01558         return (ELEMENT_TYPE);
01559       }
01560     if (type == ELEMENTLINE_TYPE)
01561       ELEMENTLINE_LOOP (element);
01562     {
01563       if (line->ID == ID)
01564         {
01565           *Result1 = (void *) element;
01566           *Result2 = *Result3 = (void *) line;
01567           return (ELEMENTLINE_TYPE);
01568         }
01569     }
01570     END_LOOP;
01571     if (type == ELEMENTARC_TYPE)
01572       ARC_LOOP (element);
01573     {
01574       if (arc->ID == ID)
01575         {
01576           *Result1 = (void *) element;
01577           *Result2 = *Result3 = (void *) arc;
01578           return (ELEMENTARC_TYPE);
01579         }
01580     }
01581     END_LOOP;
01582     if (type == ELEMENTNAME_TYPE)
01583       ELEMENTTEXT_LOOP (element);
01584     {
01585       if (text->ID == ID)
01586         {
01587           *Result1 = (void *) element;
01588           *Result2 = *Result3 = (void *) text;
01589           return (ELEMENTNAME_TYPE);
01590         }
01591     }
01592     END_LOOP;
01593     if (type == PIN_TYPE)
01594       PIN_LOOP (element);
01595     {
01596       if (pin->ID == ID)
01597         {
01598           *Result1 = (void *) element;
01599           *Result2 = *Result3 = (void *) pin;
01600           return (PIN_TYPE);
01601         }
01602     }
01603     END_LOOP;
01604     if (type == PAD_TYPE)
01605       PAD_LOOP (element);
01606     {
01607       if (pad->ID == ID)
01608         {
01609           *Result1 = (void *) element;
01610           *Result2 = *Result3 = (void *) pad;
01611           return (PAD_TYPE);
01612         }
01613     }
01614     END_LOOP;
01615   }
01616   END_LOOP;
01617 
01618   Message ("hace: Internal error, search for ID %d failed\n", ID);
01619   return (NO_TYPE);
01620 }
01621 
01628 ElementType *
01629 SearchElementByName (DataType *Base, char *Name)
01630 {
01631   ElementType *result = NULL;
01632 
01633   ELEMENT_LOOP (Base);
01634   {
01635     if (element->Name[1].TextString &&
01636         NSTRCMP (element->Name[1].TextString, Name) == 0)
01637       {
01638         result = element;
01639         return (result);
01640       }
01641   }
01642   END_LOOP;
01643   return result;
01644 }
01645 
01652 int
01653 SearchLayerByName (DataType *Base, char *Name)
01654 {
01655   int result = 0;
01656 
01657   LAYER_LOOP (Base, max_copper_layer);
01658   {
01659     if (layer->Name &&
01660         NSTRCMP (layer->Name, Name) == 0)
01661       {
01662         return result;
01663       }
01664     else
01665       result++;
01666   }
01667   END_LOOP;
01668   return -1;
01669 }
01670 
01674 int
01675 SearchScreen (Coord X, Coord Y, int Type, void **Result1,
01676               void **Result2, void **Result3)
01677 {
01678   int ans;
01679 
01680   ans = SearchObjectByLocation (Type, Result1, Result2, Result3,
01681                                 X, Y, SLOP * pixel_slop);
01682   return (ans);
01683 }