/***************************************************************/ /* Code for handling creation of buses, wires, and junctions. */ /***************************************************************/ #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "class_drawpanel.h" #include "confirm.h" #include "program.h" #include "classes_body_items.h" #include "general.h" #include "protos.h" /* Routines Locales */ static void Show_Polyline_in_Ghost( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); static void Segment_in_Ghost( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ); static void AbortCreateNewLine( WinEDA_DrawPanel* Panel, wxDC* DC ); static bool IsTerminalPoint( SCH_SCREEN* screen, const wxPoint& pos, int layer ); static bool IsJunctionNeeded( WinEDA_SchematicFrame* frame, wxPoint& pos ); static void ComputeBreakPoint( EDA_DrawLineStruct* segment, const wxPoint& new_pos ); SCH_ITEM* s_OldWiresList; wxPoint s_ConnexionStartPoint; /*********************************************************/ SCH_ITEM* SCH_SCREEN::ExtractWires( bool CreateCopy ) { /*********************************************************/ /* Extract the old wires, junctions and buses, an if CreateCopy replace them * by a copy. Old ones must be put in undo list, and the new ones can be * modified by clean up safely. * If an abort command is made, old wires must be put in EEDrawList, and * copies must be deleted. This is because previously stored undo commands * can handle pointers on wires or bus, and we do not delete wires or bus, * we must put they in undo list. * * Because cleanup delete and/or modify bus and wires, the more easy is to put * all wires in undo list and use a new copy of wires for cleanup. */ SCH_ITEM* item, * next_item, * new_item, * List = NULL; for( item = EEDrawList; item != NULL; item = next_item ) { next_item = item->Next(); switch( item->Type() ) { case DRAW_JUNCTION_STRUCT_TYPE: case DRAW_SEGMENT_STRUCT_TYPE: RemoveFromDrawList( item ); item->SetNext( List ); List = item; if( CreateCopy ) { if( item->Type() == DRAW_JUNCTION_STRUCT_TYPE ) new_item = ( (DrawJunctionStruct*) item )->GenCopy(); else new_item = ( (EDA_DrawLineStruct*) item )->GenCopy(); new_item->SetNext( EEDrawList ); EEDrawList = new_item; } break; default: break; } } return List; } /*************************************************/ static void RestoreOldWires( SCH_SCREEN* screen ) { /*************************************************/ /* Replace the wires in screen->EEDrawList by s_OldWiresList wires. */ SCH_ITEM* item; SCH_ITEM* next_item; for( item = screen->EEDrawList; item != NULL; item = next_item ) { next_item = item->Next(); switch( item->Type() ) { case DRAW_JUNCTION_STRUCT_TYPE: case DRAW_SEGMENT_STRUCT_TYPE: screen->RemoveFromDrawList( item ); delete item; break; default: break; } } while( s_OldWiresList ) { next_item = s_OldWiresList->Next(); s_OldWiresList->SetNext( screen->EEDrawList ); screen->EEDrawList = s_OldWiresList; s_OldWiresList = next_item; } } /*************************************************************/ void WinEDA_SchematicFrame::BeginSegment( wxDC* DC, int type ) { /*************************************************************/ /* Creates a new segment ( WIRE, BUS ), * or terminates the current segment * If the end of the current segment is on an other segment, place a junction * if needed and terminates the command * If the end of the current segment is on a pin, terminates the command * In others cases starts a new segment */ EDA_DrawLineStruct* oldsegment, * newsegment, * nextsegment; wxPoint cursorpos = GetScreen()->m_Curseur; if( GetScreen()->GetCurItem() && (GetScreen()->GetCurItem()->m_Flags == 0) ) GetScreen()->SetCurItem( NULL ); if( GetScreen()->GetCurItem() ) { switch( GetScreen()->GetCurItem()->Type() ) { case DRAW_SEGMENT_STRUCT_TYPE: case DRAW_POLYLINE_STRUCT_TYPE: break; default: return; } } oldsegment = newsegment = (EDA_DrawLineStruct*) GetScreen()->GetCurItem(); if( !newsegment ) /* first point : Create first wire or bus */ { s_ConnexionStartPoint = cursorpos; s_OldWiresList = ( (SCH_SCREEN*) GetScreen() )->ExtractWires( TRUE ); ( (SCH_SCREEN*) GetScreen() )->SchematicCleanUp( NULL ); switch( type ) { default: newsegment = new EDA_DrawLineStruct( cursorpos, LAYER_NOTES ); break; case LAYER_WIRE: newsegment = new EDA_DrawLineStruct( cursorpos, LAYER_WIRE ); /* A junction will be created later, when we'll know the * segment end position, and if the junction is really needed */ break; case LAYER_BUS: newsegment = new EDA_DrawLineStruct( cursorpos, LAYER_BUS ); break; } newsegment->m_Flags = IS_NEW; if( g_HVLines ) // We need 2 segments to go from a given start pint to // an end point { nextsegment = newsegment->GenCopy(); nextsegment->m_Flags = IS_NEW; newsegment->SetNext( nextsegment ); nextsegment->SetBack( newsegment ); } GetScreen()->SetCurItem( newsegment ); DrawPanel->ManageCurseur = Segment_in_Ghost; DrawPanel->ForceCloseManageCurseur = AbortCreateNewLine; g_ItemToRepeat = NULL; } else /* A segment is in progress: terminates the current segment and add * a new segment */ { nextsegment = oldsegment->Next(); if( !g_HVLines ) /* if only one segment is needed and the current is * has len = 0, do not create a new one */ { if( oldsegment->IsNull() ) return; } else { /* if we want 2 segment and the last two have len = 0, do not * create a new one */ if( oldsegment->IsNull() && nextsegment && nextsegment->IsNull() ) return; } DrawPanel->ManageCurseur( DrawPanel, DC, FALSE ); /* Creates the new segment, or terminates the command * if the end point is on a pin, junction or an other wire or bus */ if( IsTerminalPoint( GetScreen(), cursorpos, oldsegment->GetLayer() ) ) { EndSegment( DC ); return; } oldsegment->SetNext( GetScreen()->EEDrawList ); GetScreen()->EEDrawList = oldsegment; DrawPanel->CursorOff( DC ); // Erase schematic cursor RedrawOneStruct( DrawPanel, DC, oldsegment, GR_DEFAULT_DRAWMODE ); DrawPanel->CursorOn( DC ); // Display schematic cursor /* Create a new segment, and chain it after the current new segment */ if( nextsegment ) { newsegment = nextsegment->GenCopy(); nextsegment->m_Start = newsegment->m_End; nextsegment->SetNext( NULL ); nextsegment->SetBack( newsegment ); newsegment->SetNext( nextsegment ); newsegment->SetBack( NULL ); } else { newsegment = oldsegment->GenCopy(); newsegment->m_Start = oldsegment->m_End; } newsegment->m_End = cursorpos; oldsegment->m_Flags = SELECTED; newsegment->m_Flags = IS_NEW; GetScreen()->SetCurItem( newsegment ); DrawPanel->ManageCurseur( DrawPanel, DC, FALSE ); /* This is the first segment: Now we know the start segment position. * Create a junction if needed. Note: a junction can be needed later, * if the new segment is merged (after a cleanup) with an older one * (tested when the connection will be finished)*/ if( oldsegment->m_Start == s_ConnexionStartPoint ) { if( IsJunctionNeeded( this, s_ConnexionStartPoint ) ) CreateNewJunctionStruct( DC, s_ConnexionStartPoint ); } } } /***********************************************/ void WinEDA_SchematicFrame::EndSegment( wxDC* DC ) { /***********************************************/ /* Called to terminate a bus, wire, or line creation */ EDA_DrawLineStruct* firstsegment = (EDA_DrawLineStruct*) GetScreen()->GetCurItem(); EDA_DrawLineStruct* lastsegment = firstsegment; EDA_DrawLineStruct* segment; if( firstsegment == NULL ) return; if( (firstsegment->m_Flags & IS_NEW) == 0 ) return; /* Delete Null segments and Put line it in Drawlist */ lastsegment = firstsegment; while( lastsegment ) { EDA_DrawLineStruct* nextsegment = lastsegment->Next(); if( lastsegment->IsNull() ) { EDA_DrawLineStruct* previous_segment = lastsegment->Back(); if( firstsegment == lastsegment ) firstsegment = nextsegment; if( nextsegment ) nextsegment->SetBack( NULL ); if( previous_segment ) previous_segment->SetNext( nextsegment ); delete lastsegment; } lastsegment = nextsegment; } /* put the segment list to the main linked list */ segment = lastsegment = firstsegment; while( segment ) { lastsegment = segment; segment = segment->Next(); lastsegment->SetNext( GetScreen()->EEDrawList ); GetScreen()->EEDrawList = lastsegment; } DrawPanel->ManageCurseur = NULL; DrawPanel->ForceCloseManageCurseur = NULL; GetScreen()->SetCurItem( NULL ); wxPoint end_point, alt_end_point; /* A junction can be needed to connect the last segment * usually to m_End coordinate. * But if the last segment is removed by a cleanup, because of redundancy, * a junction can be needed to connect the previous segment m_End * coordinate with is also the lastsegment->m_Start coordinate */ if( lastsegment ) { end_point = lastsegment->m_End; alt_end_point = lastsegment->m_Start; } ( (SCH_SCREEN*) GetScreen() )->SchematicCleanUp( NULL ); /* clear flags and find last segment entered, for repeat function */ segment = (EDA_DrawLineStruct*) GetScreen()->EEDrawList; while( segment ) { if( segment->m_Flags ) { if( !g_ItemToRepeat ) g_ItemToRepeat = segment; } segment->m_Flags = 0; segment = segment->Next(); } // Automatic place of a junction on the end point, if needed if( lastsegment ) { if( IsJunctionNeeded( this, end_point ) ) CreateNewJunctionStruct( DC, end_point ); else if( IsJunctionNeeded( this, alt_end_point ) ) CreateNewJunctionStruct( DC, alt_end_point ); } /* Automatic place of a junction on the start point if necessary because * the cleanup can suppress intermediate points by merging wire segments */ if( IsJunctionNeeded( this, s_ConnexionStartPoint ) ) CreateNewJunctionStruct( DC, s_ConnexionStartPoint ); TestDanglingEnds( GetScreen()->EEDrawList, DC ); /* Redraw wires and junctions which can be changed by TestDanglingEnds() */ DrawPanel->CursorOff( DC ); // Erase schematic cursor EDA_BaseStruct* item = GetScreen()->EEDrawList; while( item ) { switch( item->Type() ) { case DRAW_JUNCTION_STRUCT_TYPE: case DRAW_SEGMENT_STRUCT_TYPE: DrawPanel->PostDirtyRect( item->GetBoundingBox() ); break; default: break; } item = item->Next(); } DrawPanel->CursorOn( DC ); // Display schematic cursor SaveCopyInUndoList( s_OldWiresList, UR_WIRE_IMAGE ); s_OldWiresList = NULL; GetScreen()->SetModify(); } /****************************************************************************/ static void Segment_in_Ghost( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) { /****************************************************************************/ /* Redraw the segment (g_HVLines == FALSE ) or the two segments (g_HVLines == * TRUE ) * from the start point to the cursor, when moving the mouse */ EDA_DrawLineStruct* CurrentLine = (EDA_DrawLineStruct*) panel->GetScreen()->GetCurItem(); EDA_DrawLineStruct* segment; int color; if( CurrentLine == NULL ) return; color = ReturnLayerColor( CurrentLine->GetLayer() ) ^ HIGHT_LIGHT_FLAG; if( erase ) { segment = CurrentLine; while( segment ) { if( !segment->IsNull() ) // Redraw if segment length != 0 RedrawOneStruct( panel, DC, segment, g_XorMode, color ); segment = segment->Next(); } } wxPoint endpos = panel->GetScreen()->m_Curseur; if( g_HVLines ) /* Coerce the line to vertical or horizontal one: */ { ComputeBreakPoint( CurrentLine, endpos ); } else CurrentLine->m_End = endpos; segment = CurrentLine; while( segment ) { if( !segment->IsNull() ) // Redraw if segment length != 0 RedrawOneStruct( panel, DC, segment, g_XorMode, color ); segment = segment->Next(); } } /***************************************************************************/ static void ComputeBreakPoint( EDA_DrawLineStruct* segment, const wxPoint& new_pos ) { /***************************************************************************/ /* compute the middle coordinate for 2 segments, from the start point to * new_pos * with the 2 segments kept H or V only */ EDA_DrawLineStruct* nextsegment = segment->Next(); wxPoint middle_position = new_pos; if( nextsegment == NULL ) return; #if 0 if( ABS( middle_position.x - segment->m_Start.x ) < ABS( middle_position.y - segment->m_Start.y ) ) middle_position.x = segment->m_Start.x; else middle_position.y = segment->m_Start.y; #else int iDx = segment->m_End.x - segment->m_Start.x; int iDy = segment->m_End.y - segment->m_Start.y; if( iDy != 0 ) // keep the first segment orientation (currently // horizontal) { middle_position.x = segment->m_Start.x; } else if( iDx != 0 ) // keep the first segment orientation (currently // vertical) { middle_position.y = segment->m_Start.y; } else { if( ABS( middle_position.x - segment->m_Start.x ) < ABS( middle_position.y - segment->m_Start.y ) ) middle_position.x = segment->m_Start.x; else middle_position.y = segment->m_Start.y; } #endif segment->m_End = middle_position; nextsegment->m_Start = middle_position; nextsegment->m_End = new_pos; } /*****************************************************************************/ static void Show_Polyline_in_Ghost( WinEDA_DrawPanel* panel, wxDC* DC, bool erase ) { /*****************************************************************************/ /* Drawing Polyline phantom at the displacement of the cursor */ DrawPolylineStruct* NewPoly = (DrawPolylineStruct*) panel->GetScreen()->GetCurItem(); int color; wxPoint endpos; endpos = panel->GetScreen()->m_Curseur; color = ReturnLayerColor( NewPoly->GetLayer() ); GRSetDrawMode( DC, g_XorMode ); int idx = NewPoly->GetCornerCount() - 1; if( g_HVLines ) { /* Coerce the line to vertical or horizontal one: */ if( ABS( endpos.x - NewPoly->m_PolyPoints[idx].x ) < ABS( endpos.y - NewPoly->m_PolyPoints[idx].y ) ) endpos.x = NewPoly->m_PolyPoints[idx].x; else endpos.y = NewPoly->m_PolyPoints[idx].y; } if( erase ) RedrawOneStruct( panel, DC, NewPoly, g_XorMode, color ); NewPoly->m_PolyPoints[idx] = endpos; RedrawOneStruct( panel, DC, NewPoly, g_XorMode, color ); } /**********************************************************/ void WinEDA_SchematicFrame::DeleteCurrentSegment( wxDC* DC ) { /**********************************************************/ /* * Erase the last trace or the element at the current mouse position. */ g_ItemToRepeat = NULL; if( (GetScreen()->GetCurItem() == NULL) || ( (GetScreen()->GetCurItem()->m_Flags & IS_NEW) == 0 ) ) { return; } /* Cancel trace in progress */ if( GetScreen()->GetCurItem()->Type() == DRAW_POLYLINE_STRUCT_TYPE ) { Show_Polyline_in_Ghost( DrawPanel, DC, FALSE ); } else { Segment_in_Ghost( DrawPanel, DC, FALSE ); } EraseStruct( (SCH_ITEM*) GetScreen()->GetCurItem(), (SCH_SCREEN*) GetScreen() ); DrawPanel->ManageCurseur = NULL; GetScreen()->SetCurItem( NULL ); } /***************************************************************************/ DrawJunctionStruct* WinEDA_SchematicFrame::CreateNewJunctionStruct( wxDC* DC, const wxPoint& pos, bool PutInUndoList ) { /***************************************************************************/ /* Routine to create new connection struct. */ DrawJunctionStruct* NewJunction; NewJunction = new DrawJunctionStruct( pos ); g_ItemToRepeat = NewJunction; DrawPanel->CursorOff( DC ); // Erase schematic cursor RedrawOneStruct( DrawPanel, DC, NewJunction, GR_DEFAULT_DRAWMODE ); DrawPanel->CursorOn( DC ); // Display schematic cursor NewJunction->SetNext( GetScreen()->EEDrawList ); GetScreen()->EEDrawList = NewJunction; GetScreen()->SetModify(); if( PutInUndoList ) SaveCopyInUndoList( NewJunction, UR_NEW ); return NewJunction; } /*******************************************************************************/ DrawNoConnectStruct* WinEDA_SchematicFrame::CreateNewNoConnectStruct( wxDC* DC ) { /*******************************************************************************/ /* Routine to create new NoConnect struct. */ DrawNoConnectStruct* NewNoConnect; NewNoConnect = new DrawNoConnectStruct( GetScreen()->m_Curseur ); g_ItemToRepeat = NewNoConnect; DrawPanel->CursorOff( DC ); // Erase schematic cursor RedrawOneStruct( DrawPanel, DC, NewNoConnect, GR_DEFAULT_DRAWMODE ); DrawPanel->CursorOn( DC ); // Display schematic cursor NewNoConnect->SetNext( GetScreen()->EEDrawList ); GetScreen()->EEDrawList = NewNoConnect; GetScreen()->SetModify(); SaveCopyInUndoList( NewNoConnect, UR_NEW ); return NewNoConnect; } /*****************************************************************/ static void AbortCreateNewLine( WinEDA_DrawPanel* Panel, wxDC* DC ) { /*****************************************************************/ /* Abort function for wire, bus or line creation */ SCH_SCREEN* Screen = (SCH_SCREEN*) Panel->GetScreen(); if( Screen->GetCurItem() ) { Panel->ManageCurseur = NULL; Panel->ForceCloseManageCurseur = NULL; EraseStruct( (SCH_ITEM*) Screen->GetCurItem(), (SCH_SCREEN*) Screen ); Screen->SetCurItem( NULL ); RestoreOldWires( Screen ); Panel->Refresh(); } else g_ItemToRepeat = NULL; /* Clear m_Flags which is used in edit functions: */ SCH_ITEM* item = Screen->EEDrawList; while( item ) { item->m_Flags = 0; item = item->Next(); } } /***************************************************/ void WinEDA_SchematicFrame::RepeatDrawItem( wxDC* DC ) { /***************************************************/ /* Repeat the last item placement. * Bus lines, text, labels * Labels that end with a number will be incremented. */ wxPoint new_pos; if( g_ItemToRepeat == NULL ) return; switch( g_ItemToRepeat->Type() ) { case DRAW_JUNCTION_STRUCT_TYPE: #undef STRUCT #define STRUCT ( (DrawJunctionStruct*) g_ItemToRepeat ) g_ItemToRepeat = STRUCT->GenCopy(); STRUCT->m_Pos += g_RepeatStep; new_pos = STRUCT->m_Pos; break; case DRAW_NOCONNECT_STRUCT_TYPE: #undef STRUCT #define STRUCT ( (DrawNoConnectStruct*) g_ItemToRepeat ) g_ItemToRepeat = STRUCT->GenCopy(); STRUCT->m_Pos += g_RepeatStep; new_pos = STRUCT->m_Pos; break; case TYPE_SCH_TEXT: #undef STRUCT #define STRUCT ( (SCH_TEXT*) g_ItemToRepeat ) g_ItemToRepeat = STRUCT->GenCopy(); STRUCT->m_Pos += g_RepeatStep; new_pos = STRUCT->m_Pos; IncrementLabelMember( STRUCT->m_Text ); break; case TYPE_SCH_LABEL: #undef STRUCT #define STRUCT ( (SCH_LABEL*) g_ItemToRepeat ) g_ItemToRepeat = STRUCT->GenCopy(); STRUCT->m_Pos += g_RepeatStep; new_pos = STRUCT->m_Pos; IncrementLabelMember( STRUCT->m_Text ); break; case TYPE_SCH_HIERLABEL: #undef STRUCT #define STRUCT ( (SCH_HIERLABEL*) g_ItemToRepeat ) g_ItemToRepeat = STRUCT->GenCopy(); STRUCT->m_Pos += g_RepeatStep; new_pos = STRUCT->m_Pos; IncrementLabelMember( STRUCT->m_Text ); break; case TYPE_SCH_GLOBALLABEL: #undef STRUCT #define STRUCT ( (SCH_GLOBALLABEL*) g_ItemToRepeat ) g_ItemToRepeat = STRUCT->GenCopy(); STRUCT->m_Pos += g_RepeatStep; new_pos = STRUCT->m_Pos; IncrementLabelMember( STRUCT->m_Text ); break; case DRAW_SEGMENT_STRUCT_TYPE: #undef STRUCT #define STRUCT ( (EDA_DrawLineStruct*) g_ItemToRepeat ) g_ItemToRepeat = STRUCT->GenCopy(); STRUCT->m_Start += g_RepeatStep; new_pos = STRUCT->m_Start; STRUCT->m_End += g_RepeatStep; break; case DRAW_BUSENTRY_STRUCT_TYPE: #undef STRUCT #define STRUCT ( (DrawBusEntryStruct*) g_ItemToRepeat ) g_ItemToRepeat = STRUCT->GenCopy(); STRUCT->m_Pos += g_RepeatStep; new_pos = STRUCT->m_Pos; break; case TYPE_SCH_COMPONENT: // In repeat command the new component is put // in move mode #undef STRUCT #define STRUCT ( (SCH_COMPONENT*) g_ItemToRepeat ) // Create the duplicate component, position = mouse cursor g_ItemToRepeat = STRUCT->GenCopy(); new_pos.x = GetScreen()->m_Curseur.x - STRUCT->m_Pos.x; new_pos.y = GetScreen()->m_Curseur.y - STRUCT->m_Pos.y; STRUCT->m_Pos = GetScreen()->m_Curseur; STRUCT->m_Flags = IS_NEW; STRUCT->m_TimeStamp = GetTimeStamp(); for( int ii = 0; ii < STRUCT->GetFieldCount(); ii++ ) { STRUCT->GetField( ii )->m_Pos += new_pos; } RedrawOneStruct( DrawPanel, DC, STRUCT, g_XorMode ); StartMovePart( STRUCT, DC ); return; break; default: g_ItemToRepeat = NULL; DisplayError( this, wxT( "Repeat Type Error" ), 10 ); break; } if( g_ItemToRepeat ) { g_ItemToRepeat->SetNext( GetScreen()->EEDrawList ); GetScreen()->EEDrawList = g_ItemToRepeat; TestDanglingEnds( GetScreen()->EEDrawList, NULL ); RedrawOneStruct( DrawPanel, DC, g_ItemToRepeat, GR_DEFAULT_DRAWMODE ); SaveCopyInUndoList( g_ItemToRepeat, UR_NEW ); g_ItemToRepeat->m_Flags = 0; // GetScreen()->Curseur = new_pos; // DrawPanel->MouseTo( DrawPanel->CursorScreenPosition() ); } } /******************************************/ void IncrementLabelMember( wxString& name ) { /******************************************/ /* Routine incrementing labels, ie for the text ending with a number, adding * that a number */ int ii, nn; long number = 0; ii = name.Len() - 1; nn = 0; if( !isdigit( name.GetChar( ii ) ) ) return; while( (ii >= 0) && isdigit( name.GetChar( ii ) ) ) { ii--; nn++; } ii++; /* digits are starting at ii position */ wxString litt_number = name.Right( nn ); if( litt_number.ToLong( &number ) ) { number += g_RepeatDeltaLabel; name.Remove( ii ); name << number; } } /***************************************************************************/ static bool IsTerminalPoint( SCH_SCREEN* screen, const wxPoint& pos, int layer ) { /***************************************************************************/ /* Return TRUE if pos can be a terminal point for a wire or a bus * i.e. : * for a WIRE, if at pos is found: * - a junction * - or a pin * - or an other wire * * - for a BUS, if at pos is found: * - a BUS */ EDA_BaseStruct* item; LIB_PIN* pin; SCH_COMPONENT* LibItem = NULL; SCH_SHEET_PIN* pinsheet; wxPoint itempos; switch( layer ) { case LAYER_BUS: item = PickStruct( pos, screen, BUSITEM ); if( item ) return TRUE; pinsheet = LocateAnyPinSheet( pos, screen->EEDrawList ); if( pinsheet && IsBusLabel( pinsheet->m_Text ) ) { itempos = pinsheet->m_Pos; if( (itempos.x == pos.x) && (itempos.y == pos.y) ) return TRUE; } break; case LAYER_NOTES: item = PickStruct( pos, screen, DRAWITEM ); if( item ) return TRUE; break; case LAYER_WIRE: item = PickStruct( pos, screen, RACCORDITEM | JUNCTIONITEM ); if( item ) return TRUE; pin = LocateAnyPin( screen->EEDrawList, pos, &LibItem ); if( pin && LibItem ) { // Calculate the exact position of the connection point of the pin, // depending on orientation of the component. itempos = LibItem->GetScreenCoord( pin->m_Pos ); itempos.x += LibItem->m_Pos.x; itempos.y += LibItem->m_Pos.y; if( (itempos.x == pos.x) && (itempos.y == pos.y) ) return TRUE; } item = PickStruct( pos, screen, WIREITEM ); if( item ) return TRUE; item = PickStruct( pos, screen, LABELITEM ); if( item && (item->Type() != TYPE_SCH_TEXT) && ( ( (SCH_GLOBALLABEL*) item )->m_Pos.x == pos.x ) && ( ( (SCH_GLOBALLABEL*) item )->m_Pos.y == pos.y ) ) return TRUE; pinsheet = LocateAnyPinSheet( pos, screen->EEDrawList ); if( pinsheet && !IsBusLabel( pinsheet->m_Text ) ) { itempos = pinsheet->m_Pos; if( (itempos.x == pos.x) && (itempos.y == pos.y) ) return TRUE; } break; default: break; } return FALSE; } /****************************************************************/ bool IsJunctionNeeded( WinEDA_SchematicFrame* frame, wxPoint& pos ) { /****************************************************************/ /* Return True when a wire is located at pos "pos" if * - there is no junction. * - The wire has no ends at pos "pos", * and therefore it is considered as no connected. * - One (or more) wire has one end at pos "pos" * or * - a pin is on location pos */ if( PickStruct( pos, frame->GetScreen(), JUNCTIONITEM ) ) return FALSE; if( PickStruct( pos, frame->GetScreen(), WIREITEM | EXCLUDE_WIRE_BUS_ENDPOINTS ) ) { if( PickStruct( pos, frame->GetScreen(), WIREITEM | WIRE_BUS_ENDPOINTS_ONLY ) ) return TRUE; if( frame->LocatePinEnd( frame->GetScreen()->EEDrawList, pos ) ) return TRUE; } return FALSE; }