2007-09-02 15:49:11 +00:00
|
|
|
/******************************************************/
|
2009-10-30 19:26:25 +00:00
|
|
|
/* Routines for locating an element of a schematic. */
|
2007-09-02 15:49:11 +00:00
|
|
|
/******************************************************/
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
#include "fctsys.h"
|
|
|
|
#include "common.h"
|
|
|
|
#include "program.h"
|
|
|
|
#include "trigo.h"
|
|
|
|
#include "macros.h"
|
|
|
|
|
2009-09-25 18:49:04 +00:00
|
|
|
#include "general.h"
|
|
|
|
#include "class_marker_sch.h"
|
2007-06-05 12:10:51 +00:00
|
|
|
#include "protos.h"
|
2009-09-25 18:49:04 +00:00
|
|
|
#include "class_library.h"
|
|
|
|
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-09-25 18:49:04 +00:00
|
|
|
static bool DrawStructInBox( int x1, int y1, int x2, int y2,
|
2009-11-04 20:46:53 +00:00
|
|
|
SCH_ITEM* DrawStruct );
|
|
|
|
|
2008-04-14 19:22:48 +00:00
|
|
|
static SCH_ITEM* LastSnappedStruct = NULL;
|
2007-06-05 12:10:51 +00:00
|
|
|
static bool IsBox1InBox2( int StartX1, int StartY1, int EndX1, int EndY1,
|
2007-09-02 15:49:11 +00:00
|
|
|
int StartX2, int StartY2, int EndX2, int EndY2 );
|
2009-01-02 13:19:34 +00:00
|
|
|
static bool SnapPoint2( const wxPoint& aPosRef, int SearchMask,
|
2009-07-25 04:53:39 +00:00
|
|
|
SCH_ITEM* DrawList, double aScaleFactor );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
2009-09-29 18:38:21 +00:00
|
|
|
/**
|
|
|
|
* Search the smaller (considering its area) component under the mouse
|
|
|
|
* cursor or the pcb cursor
|
|
|
|
*
|
|
|
|
* If more than 1 component is found, a pointer to the smaller component is
|
|
|
|
* returned
|
2007-09-02 15:49:11 +00:00
|
|
|
*/
|
2009-09-29 18:38:21 +00:00
|
|
|
SCH_COMPONENT* LocateSmallestComponent( SCH_SCREEN* Screen )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2009-01-31 18:08:47 +00:00
|
|
|
SCH_COMPONENT* component = NULL, * lastcomponent = NULL;
|
2008-04-14 19:22:48 +00:00
|
|
|
SCH_ITEM* DrawList;
|
|
|
|
EDA_Rect BoundaryBox;
|
|
|
|
float sizeref = 0, sizecurr;
|
2007-09-02 15:49:11 +00:00
|
|
|
|
|
|
|
DrawList = Screen->EEDrawList;
|
|
|
|
|
|
|
|
while( DrawList )
|
|
|
|
{
|
|
|
|
if( ( SnapPoint2( Screen->m_MousePosition, LIBITEM,
|
2009-11-04 20:46:53 +00:00
|
|
|
DrawList, Screen->GetZoom() ) ) == FALSE )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
if( ( SnapPoint2( Screen->m_Curseur, LIBITEM,
|
2009-11-04 20:46:53 +00:00
|
|
|
DrawList, Screen->GetScalingFactor() ) ) == FALSE )
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-01-31 18:08:47 +00:00
|
|
|
component = (SCH_COMPONENT*) LastSnappedStruct;
|
2009-06-11 14:26:17 +00:00
|
|
|
DrawList = component->Next();
|
2009-01-31 18:08:47 +00:00
|
|
|
if( lastcomponent == NULL ) // First time a component is located
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
2009-01-31 18:08:47 +00:00
|
|
|
lastcomponent = component;
|
2009-06-11 14:26:17 +00:00
|
|
|
BoundaryBox = lastcomponent->GetBoundaryBox();
|
2009-11-04 20:46:53 +00:00
|
|
|
sizeref = ABS( (float) BoundaryBox.GetWidth() *
|
|
|
|
BoundaryBox.GetHeight() );
|
2007-09-02 15:49:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-01-31 18:08:47 +00:00
|
|
|
BoundaryBox = component->GetBoundaryBox();
|
2009-11-04 20:46:53 +00:00
|
|
|
sizecurr = ABS( (float) BoundaryBox.GetWidth() *
|
|
|
|
BoundaryBox.GetHeight() );
|
2007-09-02 15:49:11 +00:00
|
|
|
if( sizeref > sizecurr ) // a smallest component is found
|
|
|
|
{
|
|
|
|
sizeref = sizecurr;
|
2009-01-31 18:08:47 +00:00
|
|
|
lastcomponent = component;
|
2007-09-02 15:49:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-31 18:08:47 +00:00
|
|
|
return lastcomponent;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-31 18:08:47 +00:00
|
|
|
/******************************************************************************/
|
2009-11-04 20:46:53 +00:00
|
|
|
SCH_ITEM* PickStruct( const wxPoint& refpos,
|
|
|
|
BASE_SCREEN* screen,
|
|
|
|
int SearchMask )
|
|
|
|
{
|
|
|
|
/******************************************************************************/
|
2009-01-31 18:08:47 +00:00
|
|
|
/* Search an item at pos refpos
|
2009-06-11 14:26:17 +00:00
|
|
|
* SearchMask = (bitwise OR):
|
2007-09-02 15:49:11 +00:00
|
|
|
* LIBITEM
|
|
|
|
* WIREITEM
|
|
|
|
* BUSITEM
|
|
|
|
* RACCORDITEM
|
|
|
|
* JUNCTIONITEM
|
|
|
|
* DRAWITEM
|
|
|
|
* TEXTITEM
|
|
|
|
* LABELITEM
|
|
|
|
* SHEETITEM
|
|
|
|
* MARKERITEM
|
|
|
|
* NOCONNECTITEM
|
|
|
|
* SEARCH_PINITEM
|
|
|
|
* SHEETLABELITEM
|
|
|
|
* FIELDCMPITEM
|
2008-03-20 01:50:21 +00:00
|
|
|
*
|
2009-11-04 20:46:53 +00:00
|
|
|
* if EXCLUDE_WIRE_BUS_ENDPOINTS is set, in wire or bus search and locate,
|
2007-09-02 15:49:11 +00:00
|
|
|
* start and end points are not included in search
|
2009-11-04 20:46:53 +00:00
|
|
|
* if WIRE_BUS_ENDPOINTS_ONLY is set, in wire or bus search and locate,
|
2007-09-02 15:49:11 +00:00
|
|
|
* only start and end points are included in search
|
2008-03-20 01:50:21 +00:00
|
|
|
*
|
|
|
|
*
|
2007-09-02 15:49:11 +00:00
|
|
|
* Return:
|
2009-01-31 18:08:47 +00:00
|
|
|
* pointer on item found or NULL
|
2008-03-20 01:50:21 +00:00
|
|
|
*
|
2007-09-02 15:49:11 +00:00
|
|
|
*/
|
2009-06-11 14:26:17 +00:00
|
|
|
bool Snapped;
|
|
|
|
|
2009-01-02 13:19:34 +00:00
|
|
|
if( screen == NULL || screen->EEDrawList == NULL )
|
2008-03-20 01:50:21 +00:00
|
|
|
return NULL;
|
2007-09-02 15:49:11 +00:00
|
|
|
|
|
|
|
if( ( Snapped = SnapPoint2( refpos, SearchMask,
|
2009-09-29 18:38:21 +00:00
|
|
|
screen->EEDrawList,
|
|
|
|
screen->GetScalingFactor() ) ) != FALSE )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
return LastSnappedStruct;
|
|
|
|
}
|
|
|
|
return NULL;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
2007-09-02 15:49:11 +00:00
|
|
|
|
2009-07-25 04:53:39 +00:00
|
|
|
/** Function PickStruct
|
|
|
|
* Search items in a block
|
|
|
|
* @return items count
|
|
|
|
* @param aBlock a BLOCK_SELECTOR that gives the search area boundary
|
|
|
|
* list of items is stored in aBlock
|
2007-09-02 15:49:11 +00:00
|
|
|
*/
|
2009-07-25 07:31:07 +00:00
|
|
|
int PickItemsInBlock( BLOCK_SELECTOR& aBlock, BASE_SCREEN* aScreen )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2009-06-11 14:26:17 +00:00
|
|
|
int x, y, OrigX, OrigY;
|
2009-07-25 04:53:39 +00:00
|
|
|
int itemcount = 0;
|
|
|
|
|
|
|
|
if( aScreen == NULL )
|
|
|
|
return itemcount;
|
2007-09-02 15:49:11 +00:00
|
|
|
|
2009-07-25 04:53:39 +00:00
|
|
|
OrigX = aBlock.GetX();
|
|
|
|
OrigY = aBlock.GetY();
|
|
|
|
x = aBlock.GetRight();
|
|
|
|
y = aBlock.GetBottom();
|
2007-09-02 15:49:11 +00:00
|
|
|
|
|
|
|
if( x < OrigX )
|
|
|
|
EXCHG( x, OrigX );
|
|
|
|
if( y < OrigY )
|
|
|
|
EXCHG( y, OrigY );
|
2008-03-20 01:50:21 +00:00
|
|
|
|
2009-07-25 04:53:39 +00:00
|
|
|
ITEM_PICKER picker;
|
2009-11-04 20:46:53 +00:00
|
|
|
SCH_ITEM* DrawStruct = aScreen->EEDrawList;
|
2009-07-25 04:53:39 +00:00
|
|
|
for( ; DrawStruct != NULL; DrawStruct = DrawStruct->Next() )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
if( DrawStructInBox( OrigX, OrigY, x, y, DrawStruct ) )
|
|
|
|
{
|
|
|
|
/* Put this structure in the picked list: */
|
2009-11-04 20:46:53 +00:00
|
|
|
picker.m_PickedItem = DrawStruct;
|
2009-07-31 05:33:11 +00:00
|
|
|
picker.m_PickedItemType = DrawStruct->Type();
|
2009-11-04 20:46:53 +00:00
|
|
|
aBlock.PushItem( picker );
|
2009-07-25 04:53:39 +00:00
|
|
|
itemcount++;
|
2007-09-02 15:49:11 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-04 20:46:53 +00:00
|
|
|
|
2009-07-25 04:53:39 +00:00
|
|
|
return itemcount;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
2007-09-02 15:49:11 +00:00
|
|
|
|
2007-06-05 12:10:51 +00:00
|
|
|
/*****************************************************************************
|
2009-09-29 18:38:21 +00:00
|
|
|
* Routine to search all objects for the closest point to a given point, in *
|
|
|
|
* drawing space, and snap it to that points if closer than SnapDistance. *
|
|
|
|
* Note we use L1 norm as distance measure, as it is the fastest. *
|
2007-06-05 12:10:51 +00:00
|
|
|
* This routine updates LastSnappedStruct to the last object used in to snap *
|
2009-09-29 18:38:21 +00:00
|
|
|
* a point. This variable is global to this module only (see above). *
|
|
|
|
* The routine returns TRUE if point was snapped. *
|
2007-06-05 12:10:51 +00:00
|
|
|
*****************************************************************************/
|
2009-01-02 13:19:34 +00:00
|
|
|
bool SnapPoint2( const wxPoint& aPosRef, int SearchMask,
|
2009-07-25 04:53:39 +00:00
|
|
|
SCH_ITEM* DrawList, double aScaleFactor )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2008-04-14 19:22:48 +00:00
|
|
|
for( ; DrawList != NULL; DrawList = DrawList->Next() )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
2009-11-04 20:46:53 +00:00
|
|
|
int hitminDist = MAX( g_DrawDefaultLineThickness, 3 );
|
2007-09-02 15:49:11 +00:00
|
|
|
switch( DrawList->Type() )
|
|
|
|
{
|
|
|
|
case DRAW_POLYLINE_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (DrawPolylineStruct*) DrawList )
|
|
|
|
if( !( SearchMask & (DRAWITEM | WIREITEM | BUSITEM) ) )
|
|
|
|
break;
|
2008-03-20 01:50:21 +00:00
|
|
|
|
2009-06-11 14:26:17 +00:00
|
|
|
for( unsigned i = 0; i < STRUCT->GetCornerCount() - 1; i++ )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
2009-06-13 17:06:07 +00:00
|
|
|
if( TestSegmentHit( aPosRef, STRUCT->m_PolyPoints[i],
|
2009-11-04 20:46:53 +00:00
|
|
|
STRUCT->m_PolyPoints[i + 1], hitminDist ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2008-04-14 19:22:48 +00:00
|
|
|
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DRAW_SEGMENT_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (EDA_DrawLineStruct*) DrawList )
|
|
|
|
if( !( SearchMask & (DRAWITEM | WIREITEM | BUSITEM) ) )
|
|
|
|
break;
|
|
|
|
|
2009-06-13 17:06:07 +00:00
|
|
|
if( TestSegmentHit( aPosRef, STRUCT->m_Start, STRUCT->m_End, 0 ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
2009-11-04 20:46:53 +00:00
|
|
|
if( ( (SearchMask & DRAWITEM)
|
|
|
|
&& (STRUCT->GetLayer() == LAYER_NOTES) )
|
|
|
|
|| ( (SearchMask & WIREITEM)
|
|
|
|
&& (STRUCT->GetLayer() == LAYER_WIRE) )
|
|
|
|
|| ( (SearchMask & BUSITEM)
|
|
|
|
&& (STRUCT->GetLayer() == LAYER_BUS) )
|
2007-09-02 15:49:11 +00:00
|
|
|
)
|
|
|
|
{
|
|
|
|
if( SearchMask & EXCLUDE_WIRE_BUS_ENDPOINTS )
|
|
|
|
{
|
2009-11-04 20:46:53 +00:00
|
|
|
if( aPosRef == STRUCT->m_Start || aPosRef ==
|
|
|
|
STRUCT->m_End )
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( SearchMask & WIRE_BUS_ENDPOINTS_ONLY )
|
|
|
|
{
|
2009-01-02 13:19:34 +00:00
|
|
|
if( !STRUCT->IsOneEndPointAt( aPosRef ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case DRAW_BUSENTRY_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (DrawBusEntryStruct*) DrawList )
|
|
|
|
if( !( SearchMask & (RACCORDITEM) ) )
|
|
|
|
break;
|
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
if( TestSegmentHit( aPosRef, STRUCT->m_Pos, STRUCT->m_End(),
|
|
|
|
hitminDist ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRAW_JUNCTION_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (DrawJunctionStruct*) DrawList )
|
|
|
|
if( !(SearchMask & JUNCTIONITEM) )
|
|
|
|
break;
|
2009-06-11 14:26:17 +00:00
|
|
|
if( STRUCT->HitTest( aPosRef ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRAW_NOCONNECT_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (DrawNoConnectStruct*) DrawList )
|
|
|
|
if( !(SearchMask & NOCONNECTITEM) )
|
|
|
|
break;
|
2009-06-11 14:26:17 +00:00
|
|
|
if( STRUCT->HitTest( aPosRef ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2009-08-01 19:26:05 +00:00
|
|
|
case TYPE_MARKER_SCH:
|
2009-01-31 18:08:47 +00:00
|
|
|
{
|
2007-09-02 15:49:11 +00:00
|
|
|
#undef STRUCT
|
2009-07-06 18:02:26 +00:00
|
|
|
#define STRUCT ( (MARKER_SCH*) DrawList )
|
2007-09-02 15:49:11 +00:00
|
|
|
if( !(SearchMask & MARKERITEM) )
|
|
|
|
break;
|
2009-11-04 20:46:53 +00:00
|
|
|
if( STRUCT->HitTest( aPosRef ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
2009-01-31 18:08:47 +00:00
|
|
|
}
|
2007-09-02 15:49:11 +00:00
|
|
|
|
2008-03-20 01:50:21 +00:00
|
|
|
case TYPE_SCH_TEXT:
|
2007-09-02 15:49:11 +00:00
|
|
|
#undef STRUCT
|
2008-03-20 01:50:21 +00:00
|
|
|
#define STRUCT ( (SCH_TEXT*) DrawList )
|
2009-05-12 12:12:34 +00:00
|
|
|
if( !( SearchMask & TEXTITEM) )
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
2009-01-31 18:08:47 +00:00
|
|
|
if( STRUCT->HitTest( aPosRef ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
2009-05-12 12:12:34 +00:00
|
|
|
case TYPE_SCH_LABEL:
|
2008-03-20 01:50:21 +00:00
|
|
|
case TYPE_SCH_GLOBALLABEL:
|
2009-01-31 18:08:47 +00:00
|
|
|
case TYPE_SCH_HIERLABEL:
|
|
|
|
#undef STRUCT
|
2009-11-04 20:46:53 +00:00
|
|
|
#define STRUCT ( (SCH_TEXT*) DrawList ) // SCH_TEXT is the base
|
|
|
|
// class of these labels
|
2009-01-31 18:08:47 +00:00
|
|
|
if( !(SearchMask & LABELITEM) )
|
|
|
|
break;
|
|
|
|
if( STRUCT->HitTest( aPosRef ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-03-20 01:50:21 +00:00
|
|
|
case TYPE_SCH_COMPONENT:
|
2007-09-02 15:49:11 +00:00
|
|
|
if( !( SearchMask & (LIBITEM | FIELDCMPITEM) ) )
|
|
|
|
break;
|
|
|
|
|
|
|
|
if( SearchMask & FIELDCMPITEM )
|
|
|
|
{
|
2009-06-11 14:26:17 +00:00
|
|
|
SCH_COMPONENT* DrawLibItem = (SCH_COMPONENT*) DrawList;
|
2009-01-02 17:07:50 +00:00
|
|
|
for( int i = REFERENCE; i < DrawLibItem->GetFieldCount(); i++ )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
2009-06-11 14:26:17 +00:00
|
|
|
SCH_CMP_FIELD* field = DrawLibItem->GetField( i );
|
2008-10-06 05:44:29 +00:00
|
|
|
|
|
|
|
if( field->m_Attributs & TEXT_NO_VISIBLE )
|
2007-09-02 15:49:11 +00:00
|
|
|
continue;
|
2008-10-06 05:44:29 +00:00
|
|
|
|
|
|
|
if( field->IsVoid() )
|
2007-09-02 15:49:11 +00:00
|
|
|
continue;
|
2008-10-06 05:44:29 +00:00
|
|
|
|
|
|
|
EDA_Rect BoundaryBox = field->GetBoundaryBox();
|
2009-01-02 13:19:34 +00:00
|
|
|
if( BoundaryBox.Inside( aPosRef ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
2008-10-06 05:44:29 +00:00
|
|
|
LastSnappedStruct = field;
|
2007-09-02 15:49:11 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#undef STRUCT
|
2008-03-20 01:50:21 +00:00
|
|
|
#define STRUCT ( (SCH_COMPONENT*) DrawList )
|
2007-09-02 15:49:11 +00:00
|
|
|
EDA_Rect BoundaryBox = STRUCT->GetBoundaryBox();
|
2009-01-02 13:19:34 +00:00
|
|
|
if( BoundaryBox.Inside( aPosRef ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRAW_SHEET_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
2009-11-04 20:46:53 +00:00
|
|
|
#define STRUCT ( (SCH_SHEET*) DrawList )
|
2007-09-02 15:49:11 +00:00
|
|
|
if( !(SearchMask & SHEETITEM) )
|
|
|
|
break;
|
2009-01-31 18:08:47 +00:00
|
|
|
if( STRUCT->HitTest( aPosRef ) )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
LastSnappedStruct = DrawList;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
wxString msg;
|
2009-11-04 20:46:53 +00:00
|
|
|
msg.Printf( wxT( "SnapPoint2() error: unexpected struct type %d (" ),
|
|
|
|
DrawList->Type() );
|
2007-09-13 11:28:58 +00:00
|
|
|
msg << DrawList->GetClass() << wxT( ")" );
|
2009-08-01 19:26:05 +00:00
|
|
|
wxMessageBox( msg );
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
2009-09-29 18:38:21 +00:00
|
|
|
* Routine to test if an object has non empty intersection with the box *
|
2007-06-05 12:10:51 +00:00
|
|
|
* defined by x1/y1 and x2/y2 (x1 < x2, y1 < y2), and return TRUE if so. This *
|
2009-09-29 18:38:21 +00:00
|
|
|
* routine is used to pick all points in a given box. *
|
2007-06-05 12:10:51 +00:00
|
|
|
*****************************************************************************/
|
2009-01-02 17:07:50 +00:00
|
|
|
bool DrawStructInBox( int x1, int y1, int x2, int y2, SCH_ITEM* DrawStruct )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2009-01-02 17:07:50 +00:00
|
|
|
int xt1, yt1, xt2, yt2;
|
2007-09-02 15:49:11 +00:00
|
|
|
int dx, dy;
|
|
|
|
wxString msg;
|
|
|
|
|
|
|
|
switch( DrawStruct->Type() )
|
|
|
|
{
|
|
|
|
case DRAW_POLYLINE_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (DrawPolylineStruct*) DrawStruct )
|
2009-06-11 14:26:17 +00:00
|
|
|
for( unsigned i = 0; i < STRUCT->GetCornerCount(); i++ )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
2009-11-04 20:46:53 +00:00
|
|
|
if( STRUCT->m_PolyPoints[i].x >= x1
|
|
|
|
&& STRUCT->m_PolyPoints[i].x <= x2
|
|
|
|
&& STRUCT->m_PolyPoints[i].y >= y1
|
|
|
|
&& STRUCT->m_PolyPoints[i].y <=y2 )
|
2007-09-02 15:49:11 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRAW_SEGMENT_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (EDA_DrawLineStruct*) DrawStruct )
|
|
|
|
if( STRUCT->m_Start.x >= x1 && STRUCT->m_Start.x <= x2
|
|
|
|
&& STRUCT->m_Start.y >= y1 && STRUCT->m_Start.y <=y2 )
|
|
|
|
return TRUE;
|
|
|
|
if( (STRUCT->m_End.x >= x1) && (STRUCT->m_End.x <= x2)
|
|
|
|
&& (STRUCT->m_End.y >= y1) && (STRUCT->m_End.y <=y2) )
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRAW_BUSENTRY_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (DrawBusEntryStruct*) DrawStruct )
|
|
|
|
if( STRUCT->m_Pos.x >= x1 && STRUCT->m_Pos.x <= x2
|
|
|
|
&& STRUCT->m_Pos.y >= y1 && STRUCT->m_Pos.y <=y2 )
|
|
|
|
return TRUE;
|
|
|
|
if( (STRUCT->m_End().x >= x1) && ( STRUCT->m_End().x <= x2)
|
|
|
|
&& ( STRUCT->m_End().y >= y1) && ( STRUCT->m_End().y <=y2) )
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DRAW_JUNCTION_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (DrawJunctionStruct*) DrawStruct )
|
|
|
|
if( (STRUCT->m_Pos.x >= x1) && (STRUCT->m_Pos.x <= x2)
|
|
|
|
&& (STRUCT->m_Pos.y >= y1) && (STRUCT->m_Pos.y <= y2) )
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case DRAW_NOCONNECT_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
|
|
|
#define STRUCT ( (DrawNoConnectStruct*) DrawStruct )
|
|
|
|
if( (STRUCT->m_Pos.x >= x1) && (STRUCT->m_Pos.x <= x2)
|
|
|
|
&& (STRUCT->m_Pos.y >= y1) && (STRUCT->m_Pos.y <= y2) )
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
2009-08-01 19:26:05 +00:00
|
|
|
case TYPE_MARKER_SCH:
|
2007-09-02 15:49:11 +00:00
|
|
|
#undef STRUCT
|
2009-07-06 18:02:26 +00:00
|
|
|
#define STRUCT ( (MARKER_SCH*) DrawStruct )
|
2007-09-02 15:49:11 +00:00
|
|
|
if( (STRUCT->m_Pos.x >= x1) && (STRUCT->m_Pos.x <= x2)
|
|
|
|
&& (STRUCT->m_Pos.y >= y1) && (STRUCT->m_Pos.y <= y2) )
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
2008-03-20 01:50:21 +00:00
|
|
|
case TYPE_SCH_LABEL:
|
|
|
|
case TYPE_SCH_TEXT:
|
2007-09-02 15:49:11 +00:00
|
|
|
#undef STRUCT
|
2008-03-20 01:50:21 +00:00
|
|
|
#define STRUCT ( (SCH_TEXT*) DrawStruct )
|
2007-09-02 15:49:11 +00:00
|
|
|
dx = STRUCT->m_Size.x * STRUCT->GetLength();
|
|
|
|
dy = STRUCT->m_Size.y;
|
|
|
|
xt1 = xt2 = STRUCT->m_Pos.x;
|
|
|
|
yt1 = yt2 = STRUCT->m_Pos.y;
|
|
|
|
|
|
|
|
switch( STRUCT->m_Orient )
|
|
|
|
{
|
2008-02-01 21:30:45 +00:00
|
|
|
case 0: /* HORIZONTAL Left justified */
|
2007-09-02 15:49:11 +00:00
|
|
|
xt2 += dx; yt2 -= dy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* VERTICAL UP */
|
|
|
|
xt2 -= dy; yt2 -= dx;
|
|
|
|
break;
|
|
|
|
|
2008-02-01 21:30:45 +00:00
|
|
|
case 2: /* horizontal Right justified */
|
|
|
|
xt2 -= dx; yt2 -= dy;
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 3: /* vertical DOWN */
|
2008-02-01 21:30:45 +00:00
|
|
|
xt2 -= dy; yt2 += dx;
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( IsBox1InBox2( xt1, yt1, xt2, yt2, x1, y1, x2, y2 ) )
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
2008-03-20 01:50:21 +00:00
|
|
|
case TYPE_SCH_HIERLABEL:
|
|
|
|
case TYPE_SCH_GLOBALLABEL:
|
2007-09-02 15:49:11 +00:00
|
|
|
#undef STRUCT
|
2008-03-20 01:50:21 +00:00
|
|
|
#define STRUCT ( (SCH_LABEL*) DrawStruct )
|
2009-11-04 20:46:53 +00:00
|
|
|
dx = STRUCT->m_Size.x * ( STRUCT->GetLength() + 1); /* total length
|
|
|
|
**/
|
|
|
|
dy = STRUCT->m_Size.y / 2; /* half height
|
|
|
|
**/
|
2007-09-02 15:49:11 +00:00
|
|
|
xt1 = xt2 = STRUCT->m_Pos.x;
|
|
|
|
yt1 = yt2 = STRUCT->m_Pos.y;
|
|
|
|
|
|
|
|
switch( STRUCT->m_Orient )
|
|
|
|
{
|
|
|
|
case 0: /* HORIZONTAL */
|
|
|
|
xt2 -= dx; yt2 += dy; yt1 -= dy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* VERTICAL UP */
|
|
|
|
xt1 -= dy; xt2 += dy; yt2 += dx;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2: /* horizontal inverse */
|
|
|
|
xt2 += dx; yt2 += dy; yt1 -= dy;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3: /* vertical DOWN */
|
|
|
|
xt1 -= dy; xt2 += dy; yt2 -= dx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( IsBox1InBox2( xt1, yt1, xt2, yt2, x1, y1, x2, y2 ) )
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
2008-03-20 01:50:21 +00:00
|
|
|
case TYPE_SCH_COMPONENT:
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
#undef STRUCT
|
2008-03-20 01:50:21 +00:00
|
|
|
#define STRUCT ( (SCH_COMPONENT*) DrawStruct )
|
2007-09-02 15:49:11 +00:00
|
|
|
EDA_Rect BoundaryBox = STRUCT->GetBoundaryBox();
|
|
|
|
xt1 = BoundaryBox.GetX();
|
|
|
|
yt1 = BoundaryBox.GetY();
|
|
|
|
xt2 = BoundaryBox.GetRight();
|
|
|
|
yt2 = BoundaryBox.GetBottom();
|
|
|
|
if( IsBox1InBox2( xt1, yt1, xt2, yt2, x1, y1, x2, y2 ) )
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case DRAW_SHEET_STRUCT_TYPE:
|
|
|
|
#undef STRUCT
|
2009-11-04 20:46:53 +00:00
|
|
|
#define STRUCT ( (SCH_SHEET*) DrawStruct )
|
2009-10-30 19:26:25 +00:00
|
|
|
/* Recalculate the coordinates of the worksheet component */
|
2007-09-02 15:49:11 +00:00
|
|
|
xt1 = STRUCT->m_Pos.x;
|
|
|
|
yt1 = STRUCT->m_Pos.y;
|
|
|
|
xt2 = STRUCT->m_Pos.x + STRUCT->m_Size.x;
|
|
|
|
yt2 = STRUCT->m_Pos.y + STRUCT->m_Size.y;
|
|
|
|
|
|
|
|
if( IsBox1InBox2( xt1, yt1, xt2, yt2, x1, y1, x2, y2 ) )
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
2008-04-15 19:38:19 +00:00
|
|
|
case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-11-04 20:46:53 +00:00
|
|
|
msg.Printf( wxT( "DrawStructInBox() Err: unexpected StructType %d (" ),
|
|
|
|
DrawStruct->Type() );
|
2007-09-13 11:28:58 +00:00
|
|
|
msg << DrawStruct->GetClass() << wxT( ")" );
|
2009-08-01 19:26:05 +00:00
|
|
|
wxMessageBox( msg );
|
2007-09-02 15:49:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
2007-09-02 15:49:11 +00:00
|
|
|
|
2007-06-05 12:10:51 +00:00
|
|
|
/****************************************************************************/
|
|
|
|
static bool IsBox1InBox2( int StartX1, int StartY1, int EndX1, int EndY1,
|
2007-09-02 15:49:11 +00:00
|
|
|
int StartX2, int StartY2, int EndX2, int EndY2 )
|
2009-11-04 20:46:53 +00:00
|
|
|
{
|
2007-06-05 12:10:51 +00:00
|
|
|
/****************************************************************************/
|
2009-10-30 19:26:25 +00:00
|
|
|
/* Routine detects that the rectangle 1 (Box1) and the rectangle 2 (Box2) is
|
|
|
|
* Overlap.
|
|
|
|
* Returns TRUE or FALSE.
|
2008-03-20 01:50:21 +00:00
|
|
|
*
|
2009-10-30 19:26:25 +00:00
|
|
|
* These assume that there is recovery if at least one corner
|
|
|
|
* A 'Box' is included in the other
|
2007-09-02 15:49:11 +00:00
|
|
|
*/
|
|
|
|
int cX, cY;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2007-09-02 15:49:11 +00:00
|
|
|
if( StartX1 > EndX1 )
|
|
|
|
EXCHG( StartX1, EndX1 );
|
|
|
|
if( StartX2 > EndX2 )
|
|
|
|
EXCHG( StartX2, EndX2 );
|
|
|
|
if( StartY1 > EndY1 )
|
|
|
|
EXCHG( StartY1, EndY1 );
|
|
|
|
if( StartY2 > EndY2 )
|
|
|
|
EXCHG( StartY2, EndY2 );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-10-30 19:26:25 +00:00
|
|
|
/* Test the 4 corners of the rectangle 1 */
|
|
|
|
cX = StartX1;
|
|
|
|
cY = StartY1;
|
2007-09-02 15:49:11 +00:00
|
|
|
if( (cX >= StartX2) && (cX <= EndX2) && (cY >= StartY2) && (cY <= EndY2) )
|
|
|
|
return TRUE;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-10-30 19:26:25 +00:00
|
|
|
cX = EndX1;
|
|
|
|
cY = StartY1;
|
2007-09-02 15:49:11 +00:00
|
|
|
if( (cX >= StartX2) && (cX <= EndX2) && (cY >= StartY2) && (cY <= EndY2) )
|
|
|
|
return TRUE;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-10-30 19:26:25 +00:00
|
|
|
cX = EndX1;
|
|
|
|
cY = EndY1;
|
2007-09-02 15:49:11 +00:00
|
|
|
if( (cX >= StartX2) && (cX <= EndX2) && (cY >= StartY2) && (cY <= EndY2) )
|
|
|
|
return TRUE;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-10-30 19:26:25 +00:00
|
|
|
cX = StartX1;
|
|
|
|
cY = EndY1;
|
2007-09-02 15:49:11 +00:00
|
|
|
if( (cX >= StartX2) && (cX <= EndX2) && (cY >= StartY2) && (cY <= EndY2) )
|
|
|
|
return TRUE;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-10-30 19:26:25 +00:00
|
|
|
/* Test the 4 corners of the rectangle 2 */
|
|
|
|
cX = StartX2;
|
|
|
|
cY = StartY2;
|
2007-09-02 15:49:11 +00:00
|
|
|
if( (cX >= StartX1) && (cX <= EndX1) && (cY >= StartY1) && (cY <= EndY1) )
|
|
|
|
return TRUE;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-10-30 19:26:25 +00:00
|
|
|
cX = EndX2;
|
|
|
|
cY = StartY2;
|
2007-09-02 15:49:11 +00:00
|
|
|
if( (cX >= StartX1) && (cX <= EndX1) && (cY >= StartY1) && (cY <= EndY1) )
|
|
|
|
return TRUE;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-10-30 19:26:25 +00:00
|
|
|
cX = EndX2;
|
|
|
|
cY = EndY2;
|
2007-09-02 15:49:11 +00:00
|
|
|
if( (cX >= StartX1) && (cX <= EndX1) && (cY >= StartY1) && (cY <= EndY1) )
|
|
|
|
return TRUE;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2009-10-30 19:26:25 +00:00
|
|
|
cX = StartX2;
|
|
|
|
cY = EndY2;
|
2007-09-02 15:49:11 +00:00
|
|
|
if( (cX >= StartX1) && (cX <= EndX1) && (cY >= StartY1) && (cY <= EndY1) )
|
|
|
|
return TRUE;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
2007-09-02 15:49:11 +00:00
|
|
|
return FALSE;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
SCH_SHEET_PIN* LocateSheetLabel( SCH_SHEET* Sheet, const wxPoint& pos )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2007-09-02 15:49:11 +00:00
|
|
|
int size, dy, minx, maxx;
|
2009-11-04 20:46:53 +00:00
|
|
|
SCH_SHEET_PIN* SheetLabel;
|
2007-09-02 15:49:11 +00:00
|
|
|
|
|
|
|
SheetLabel = Sheet->m_Label;
|
2009-09-29 18:38:21 +00:00
|
|
|
while( SheetLabel
|
|
|
|
&& SheetLabel->Type() == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
size = ( SheetLabel->GetLength() + 1 ) * SheetLabel->m_Size.x;
|
|
|
|
if( SheetLabel->m_Edge )
|
|
|
|
size = -size;
|
|
|
|
minx = SheetLabel->m_Pos.x; maxx = SheetLabel->m_Pos.x + size;
|
|
|
|
if( maxx < minx )
|
|
|
|
EXCHG( maxx, minx );
|
|
|
|
dy = SheetLabel->m_Size.x / 2;
|
|
|
|
if( (ABS( pos.y - SheetLabel->m_Pos.y ) <= dy )
|
|
|
|
&& (pos.x <= maxx)
|
|
|
|
&& (pos.x >= minx) )
|
|
|
|
return SheetLabel;
|
2008-11-24 06:53:43 +00:00
|
|
|
SheetLabel = SheetLabel->Next();
|
2007-09-02 15:49:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
2007-09-02 15:49:11 +00:00
|
|
|
|
2009-10-08 13:19:28 +00:00
|
|
|
LIB_PIN* LocateAnyPin( SCH_ITEM* DrawList, const wxPoint& RefPos,
|
|
|
|
SCH_COMPONENT** libpart )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2008-04-14 19:22:48 +00:00
|
|
|
SCH_ITEM* DrawStruct;
|
2009-09-18 14:56:05 +00:00
|
|
|
LIB_COMPONENT* Entry;
|
2009-10-06 13:19:40 +00:00
|
|
|
SCH_COMPONENT* schItem = NULL;
|
2009-10-08 13:19:28 +00:00
|
|
|
LIB_PIN* Pin = NULL;
|
2007-09-02 15:49:11 +00:00
|
|
|
|
2009-09-29 18:38:21 +00:00
|
|
|
for( DrawStruct = DrawList; DrawStruct != NULL;
|
2009-11-04 20:46:53 +00:00
|
|
|
DrawStruct = DrawStruct->Next() )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
2008-03-20 01:50:21 +00:00
|
|
|
if( DrawStruct->Type() != TYPE_SCH_COMPONENT )
|
2007-09-02 15:49:11 +00:00
|
|
|
continue;
|
2009-10-06 13:19:40 +00:00
|
|
|
schItem = (SCH_COMPONENT*) DrawStruct;
|
|
|
|
Entry = CMP_LIBRARY::FindLibraryComponent( schItem->m_ChipName );
|
2009-08-27 11:41:56 +00:00
|
|
|
|
2007-09-02 15:49:11 +00:00
|
|
|
if( Entry == NULL )
|
|
|
|
continue;
|
2009-11-04 20:46:53 +00:00
|
|
|
|
|
|
|
/* we use LocateDrawItem to locate pins. but this function suppose a
|
2009-10-08 13:19:28 +00:00
|
|
|
* component.
|
2009-10-06 13:52:43 +00:00
|
|
|
* at 0,0 location
|
|
|
|
* So we must calculate the ref position relative to the component
|
2009-10-08 13:19:28 +00:00
|
|
|
*/
|
2009-10-06 13:19:40 +00:00
|
|
|
wxPoint libPos = RefPos - schItem->m_Pos;
|
2009-10-08 13:19:28 +00:00
|
|
|
Pin = (LIB_PIN*) Entry->LocateDrawItem( schItem->m_Multi,
|
|
|
|
schItem->m_Convert,
|
|
|
|
COMPONENT_PIN_DRAW_TYPE,
|
|
|
|
libPos, schItem->m_Transform );
|
2007-09-02 15:49:11 +00:00
|
|
|
if( Pin )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( libpart )
|
2009-10-06 13:19:40 +00:00
|
|
|
*libpart = schItem;
|
2007-09-02 15:49:11 +00:00
|
|
|
return Pin;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|
|
|
|
|
2007-09-02 15:49:11 +00:00
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
SCH_SHEET_PIN* LocateAnyPinSheet( const wxPoint& RefPos, SCH_ITEM* DrawList )
|
2007-06-05 12:10:51 +00:00
|
|
|
{
|
2008-04-14 19:22:48 +00:00
|
|
|
SCH_ITEM* DrawStruct;
|
2009-11-04 20:46:53 +00:00
|
|
|
SCH_SHEET_PIN* PinSheet = NULL;
|
2007-09-02 15:49:11 +00:00
|
|
|
|
2009-09-29 18:38:21 +00:00
|
|
|
for( DrawStruct = DrawList; DrawStruct != NULL;
|
2009-11-04 20:46:53 +00:00
|
|
|
DrawStruct = DrawStruct->Next() )
|
2007-09-02 15:49:11 +00:00
|
|
|
{
|
|
|
|
if( DrawStruct->Type() != DRAW_SHEET_STRUCT_TYPE )
|
|
|
|
continue;
|
2009-09-29 18:38:21 +00:00
|
|
|
|
2009-11-04 20:46:53 +00:00
|
|
|
PinSheet = LocateSheetLabel( (SCH_SHEET*) DrawStruct, RefPos );
|
2007-09-02 15:49:11 +00:00
|
|
|
if( PinSheet )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PinSheet;
|
2007-06-05 12:10:51 +00:00
|
|
|
}
|