/**********************************************************/ /* libclass.cpp */ /**********************************************************/ #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "program.h" #include "libcmp.h" #include "general.h" #include "protos.h" /*******************************************************/ /* Methodes relatives a la manipulation des librairies */ /*******************************************************/ /***************************************************************************************/ LibraryStruct::LibraryStruct( int type, const wxString& name, const wxString& fullname ) /***************************************************************************************/ { m_Type = type; /* type indicator */ m_Name = name; /* Name of library loaded. */ m_FullFileName = fullname; /* Full File Name (with path) of library loaded. */ m_NumOfParts = 0; /* Number of parts this library has. */ m_Entries = NULL; /* Parts themselves are saved here. */ m_Pnext = NULL; /* Point on next lib in chain. */ m_Modified = FALSE; /* flag indicateur d'edition */ m_TimeStamp = 0; m_Flags = 0; m_IsLibCache = FALSE; } /*****************************************/ void FreeLibraryEntry( LibCmpEntry* Entry ) /*****************************************/ /* Used by PQFreeFunc() to delete all entries */ { SAFE_DELETE( Entry ); } /******************************/ LibraryStruct::~LibraryStruct() /******************************/ { if( m_Entries ) PQFreeFunc( m_Entries, ( void( * ) ( void* ) )FreeLibraryEntry ); } /*******************************************/ bool LibraryStruct::WriteHeader( FILE* file ) /*******************************************/ /* Ecrit l'entete du fichier librairie */ { char BufLine[1024]; bool succes = TRUE; DateAndTime( BufLine ); if( fprintf( file, "%s %d.%d Date: %s\n", LIBFILE_IDENT, LIB_VERSION_MAJOR, LIB_VERSION_MINOR, BufLine ) != 5 ) succes = FALSE; #if 0 if( fprintf( file, "$HEADER\n" ) != 1 ) succes = FALSE; if( fprintf( file, "TimeStamp %8.8lX\n", m_TimeStamp ) != 2 ) succes = FALSE; if( fprintf( file, "Parts %d\n", m_NumOfParts ) != 2 ) succes = FALSE; if( fprintf( file, "$ENDHEADER\n" ) != 1 ) succes = FALSE; #endif return succes; } /***********************************************************/ bool LibraryStruct::ReadHeader( FILE* libfile, int* LineNum ) /***********************************************************/ /* Ecrit l'entete du fichier librairie */ { char Line[1024], * text, * data; while( GetLine( libfile, Line, LineNum, sizeof(Line) ) ) { text = strtok( Line, " \t\r\n" ); data = strtok( NULL, " \t\r\n" ); if( stricmp( text, "TimeStamp" ) == 0 ) m_TimeStamp = atol( data ); if( stricmp( text, "$ENDHEADER" ) == 0 ) return TRUE; } return FALSE; } /*********************/ /* class LibCmpEntry */ /*********************/ /* Basic class for librarty oomponent description * Not directly used * Used to create the 2 derived classes : * - EDA_LibCmpAliasStruct * - EDA_LibComponentStruct */ /********************************************************************/ LibCmpEntry::LibCmpEntry( LibrEntryType CmpType, const wxChar* CmpName ) : EDA_BaseStruct( LIBCOMPONENT_STRUCT_TYPE ) /********************************************************************/ { Type = CmpType; m_Name.m_FieldId = VALUE; if( CmpName ) m_Name.m_Text = CmpName; } /******************************/ LibCmpEntry::~LibCmpEntry() /******************************/ { } /*******************************/ /* class EDA_LibCmpAliasStruct */ /*******************************/ /* Class to define an alias of a component * An alias uses the component defintion (graphic, pins...) * but has its own name and documentation. * Therefore, when the component is modified, alias of this component are modified. * This is a simple method to create components with differs very few * (like 74LS00, 74HC00 ... and many op amps ) */ EDA_LibCmpAliasStruct:: EDA_LibCmpAliasStruct( const wxChar* CmpName, const wxChar* CmpRootName ) : LibCmpEntry( ALIAS, CmpName ) { if( CmpRootName == NULL ) m_RootName.Empty(); else m_RootName = CmpRootName; } EDA_LibCmpAliasStruct::~EDA_LibCmpAliasStruct() { } /********************************/ /* class EDA_LibComponentStruct */ /********************************/ /* This is a standard component (in library) */ EDA_LibComponentStruct:: EDA_LibComponentStruct( const wxChar* CmpName ) : LibCmpEntry( ROOT, CmpName ) { m_Drawings = NULL; m_LastDate = 0; m_UnitCount = 1; m_TextInside = 40; m_Options = ENTRY_NORMAL; m_UnitSelectionLocked = FALSE; m_DrawPinNum = m_DrawPinName = 1; Fields = NULL; m_Prefix.m_FieldId = REFERENCE; } /******************************************************/ EDA_LibComponentStruct::~EDA_LibComponentStruct() /******************************************************/ { LibEDA_BaseStruct* DrawItem, * NextDrawItem; LibDrawField* TempField, * field; field = Fields; Fields = NULL; while( field ) { TempField = field; field = (LibDrawField*) field->Pnext; SAFE_DELETE( TempField ); } /* suppression des elements dependants */ DrawItem = m_Drawings; m_Drawings = NULL; while( DrawItem ) { NextDrawItem = DrawItem->Next(); SAFE_DELETE( DrawItem ); DrawItem = NextDrawItem; } } /**********************************************************************/ EDA_Rect EDA_LibComponentStruct::GetBoundaryBox( int Unit, int Convert ) /**********************************************************************/ /* Return the componenty boundary box ( in user coordinates ) * The unit Unit, and the shape Convert are considered. * If Unit == 0, Unit is not used * if Convert == 0 Convert is non used **/ { int xmin, xmax, ymin, ymax, x1, y1; int* pt, ii; LibEDA_BaseStruct* DrawEntry; EDA_Rect BoundaryBox; DrawEntry = m_Drawings; if( DrawEntry ) { xmin = ymin = 0x7FFFFFFF; xmax = ymax = 0x80000000; } else { xmin = ymin = -50; xmax = ymax = 50; // Min size in 1/1000 inch } for( ; DrawEntry != NULL; DrawEntry = DrawEntry->Next() ) { if( DrawEntry->m_Unit > 0 ) // The item is non common to units if( (m_UnitCount > 1 ) && (Unit > 0) && (Unit != DrawEntry->m_Unit) ) continue; if( DrawEntry->m_Convert > 0 ) //The item is not common to alls convert if( (Convert > 0) && (Convert != DrawEntry->m_Convert) ) continue; switch( DrawEntry->Type() ) { case COMPONENT_ARC_DRAW_TYPE: { // Arc is reduced to a line from m_Start to m_End. // TO DO better. LibDrawArc* Arc = (LibDrawArc*) DrawEntry; x1 = Arc->m_ArcStart.x; y1 = Arc->m_ArcStart.y; xmin = MIN( xmin, x1 ); ymin = MIN( ymin, y1 ); xmax = MAX( xmax, x1 ); ymax = MAX( ymax, y1 ); x1 = Arc->m_ArcEnd.x; y1 = Arc->m_ArcEnd.y; xmin = MIN( xmin, x1 ); ymin = MIN( ymin, y1 ); xmax = MAX( xmax, x1 ); ymax = MAX( ymax, y1 ); } break; case COMPONENT_CIRCLE_DRAW_TYPE: { LibDrawCircle* Circle = (LibDrawCircle*) DrawEntry; x1 = Circle->m_Pos.x - Circle->m_Rayon; y1 = Circle->m_Pos.y - Circle->m_Rayon; xmin = MIN( xmin, x1 ); ymin = MIN( ymin, y1 ); x1 = Circle->m_Pos.x + Circle->m_Rayon; y1 = Circle->m_Pos.y + Circle->m_Rayon; xmax = MAX( xmax, x1 ); ymax = MAX( ymax, y1 ); } break; case COMPONENT_RECT_DRAW_TYPE: { LibDrawSquare* Square = (LibDrawSquare*) DrawEntry; xmin = MIN( xmin, Square->m_Pos.x ); xmin = MIN( xmin, Square->m_End.x ); xmax = MAX( xmax, Square->m_Pos.x ); xmax = MAX( xmax, Square->m_End.x ); ymin = MIN( ymin, Square->m_Pos.y ); ymin = MIN( ymin, Square->m_End.y ); ymax = MAX( ymax, Square->m_Pos.y ); ymax = MAX( ymax, Square->m_End.y ); } break; case COMPONENT_PIN_DRAW_TYPE: { LibDrawPin* Pin = (LibDrawPin*) DrawEntry; x1 = Pin->m_Pos.x; y1 = Pin->m_Pos.y; xmin = MIN( xmin, x1 ); xmax = MAX( xmax, x1 ); ymin = MIN( ymin, y1 ); ymax = MAX( ymax, y1 ); #if 0 \ // 0 pour englober le point origine de la pin, 1 pour englober toute la pin switch( Pin->Orient ) { case PIN_UP: y1 += Pin->Len; break; case PIN_DOWN: y1 -= Pin->Len; break; case PIN_LEFT: x1 -= Pin->Len; break; case PIN_RIGHT: x1 += Pin->Len; break; } xmin = MIN( xmin, x1 ); xmax = MAX( xmax, x1 ); ymin = MIN( ymin, y1 ); ymax = MAX( ymax, y1 ); #endif } break; case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE: break; case COMPONENT_POLYLINE_DRAW_TYPE: { LibDrawPolyline* polyline = (LibDrawPolyline*) DrawEntry; pt = polyline->PolyList; for( ii = 0; ii < polyline->n; ii++ ) { if( xmin > *pt ) xmin = *pt; if( xmax < *pt ) xmax = *pt; pt++; if( ymin > *pt ) ymin = *pt; if( ymax < *pt ) ymax = *pt; pt++; } } break; default: ; } } // Update the BoundaryBox. Remenber the fact the screen Y axis is the reverse */ ymax = -ymax; ymin = -ymin; // Y is is screen axis sense // Ensure w and H > 0 (wxRect assume it) if( xmax < xmin ) EXCHG( xmax, xmin ); if( ymax < ymin ) EXCHG( ymax, ymin ); BoundaryBox.SetX( xmin ); BoundaryBox.SetWidth( xmax - xmin ); BoundaryBox.SetY( ymin ); BoundaryBox.SetHeight( ymax - ymin ); return BoundaryBox; } /***************************/ /* class LibraryFieldEntry */ /***************************/ /* a Field is a string linked to a component. * Unlike a pure graphic text, fields can be used in netlist generation * and other things. * * 4 fields have a special meaning: * REFERENCE * VALUE * FOOTPRINT NAME * SCHEMATIC LINK (reserved but not used in kicad) */ LibDrawField::LibDrawField( int idfield ) : LibEDA_BaseStruct( COMPONENT_FIELD_DRAW_TYPE ) { m_FieldId = idfield; /* 0 a 11, 0 = REFERENCE, 1 = VALUE*/ if( m_FieldId < 0 ) m_FieldId = 0; if( m_FieldId >= NUMBER_OF_FIELDS ) m_FieldId = NUMBER_OF_FIELDS - 1; m_Size.x = m_Size.y = DEFAULT_SIZE_TEXT; m_Orient = 0; /* Orientation */ m_Attributs = 0; /* Attributs = unvisible ... */ m_Width = 0; m_HJustify = GR_TEXT_HJUSTIFY_CENTER; m_VJustify = GR_TEXT_VJUSTIFY_CENTER; /* Horizontal and vertical text justification */ } LibDrawField::~LibDrawField() { } // Creation et Duplication d'un field LibDrawField* LibDrawField::GenCopy() { LibDrawField* newfield = new LibDrawField( m_FieldId ); Copy( newfield ); return newfield; } // copie du field dans le field Target void LibDrawField::Copy( LibDrawField* Target ) { Target->m_Pos = m_Pos; Target->m_Size = m_Size; Target->m_Width = m_Width; Target->m_Orient = m_Orient; Target->m_Attributs = m_Attributs; Target->m_Text = m_Text; Target->m_Name = m_Name; Target->m_HJustify = m_HJustify; Target->m_VJustify = m_VJustify; } /* Elements Graphiques */ LibEDA_BaseStruct::LibEDA_BaseStruct( KICAD_T struct_type ) : EDA_BaseStruct( struct_type ) { m_Unit = 0; /* Unit identification (for multi part per package) * 0 if the item is common to all units */ m_Convert = 0; /* Shape identification (for parts which have a convert shape) * 0 if the item is common to all shapes */ m_Width = 0; /* Default value to draw lines or arc ... */ } /***************************************************************/ LibDrawPin::LibDrawPin() : LibEDA_BaseStruct( COMPONENT_PIN_DRAW_TYPE ) /***************************************************************/ { m_PinLen = 300; /* default Pin len */ m_Orient = PIN_RIGHT; /* Pin oprient: Up, Down, Left, Right */ m_PinShape = NONE; /* Bit a bit: Pin shape (voir enum prec) */ m_PinType = PIN_UNSPECIFIED; /* electrical type of pin */ m_Attributs = 0; /* bit 0 != 0: pin invisible */ m_PinNum = 0; /*pin number ( i.e. 4 codes Ascii ) */ m_PinNumSize = 50; m_PinNameSize = 50; /* Default size for pin name and num */ m_Width = 0; // m_PinNumWidth = m_PinNameWidth = 0; // Unused } /******************************************/ wxPoint LibDrawPin::ReturnPinEndPoint() /******************************************/ /* return the pin end position, for a component in normal orient */ { wxPoint pos = m_Pos; switch( m_Orient ) { case PIN_UP: pos.y += m_PinLen; break; case PIN_DOWN: pos.y -= m_PinLen; break; case PIN_LEFT: pos.x -= m_PinLen; break; case PIN_RIGHT: pos.x += m_PinLen; break; } return pos; } /********************************************************/ int LibDrawPin::ReturnPinDrawOrient( int TransMat[2][2] ) /********************************************************/ /* Return the pin real orientation (PIN_UP, PIN_DOWN, PIN_RIGHT, PIN_LEFT), * according to its orientation, * AND the matrix transform (rot, mirror) TransMat */ { int orient; int x1 = 0, y1 = 0; int t1, t2; switch( m_Orient ) { case PIN_UP: y1 = 1; break; case PIN_DOWN: y1 = -1; break; case PIN_LEFT: x1 = -1; break; case PIN_RIGHT: x1 = 1; break; } t1 = TransMat[0][0] * x1 + TransMat[0][1] * y1; t2 = TransMat[1][0] * x1 + TransMat[1][1] * y1; orient = PIN_UP; if( t1 == 0 ) { if( t2 > 0 ) orient = PIN_DOWN; } else { orient = PIN_RIGHT; if( t1 < 0 ) orient = PIN_LEFT; } return orient; } /****************************************************/ void LibDrawPin::ReturnPinStringNum( wxString& buffer ) /****************************************************/ /* fill the buffer with pin num as a wxString * Pin num is coded as a long * Used to print/draw the pin num */ { char ascii_buf[5]; strncpy( ascii_buf, (char*) &m_PinNum, 4 ); ascii_buf[4] = 0; buffer = CONV_FROM_UTF8( ascii_buf ); } /****************************************************/ void LibDrawPin::SetPinNumFromString( wxString& buffer ) /****************************************************/ /* fill the buffer with pin num as a wxString * Pin num is coded as a long * Used to print/draw the pin num */ { char ascii_buf[4]; unsigned ii, len = buffer.Len(); ascii_buf[0] = ascii_buf[1] = ascii_buf[2] = ascii_buf[3] = 0; if( len > 4 ) len = 4; for( ii = 0; ii < len; ii++ ) { ascii_buf[ii] = buffer.GetChar( ii ) & 0xFF; } strncpy( (char*) &m_PinNum, ascii_buf, 4 ); } /*************************************/ LibDrawPin* LibDrawPin::GenCopy() /*************************************/ { LibDrawPin* newpin = new LibDrawPin(); newpin->m_Pos = m_Pos; newpin->m_PinLen = m_PinLen; newpin->m_Orient = m_Orient; newpin->m_PinShape = m_PinShape; newpin->m_PinType = m_PinType; newpin->m_Attributs = m_Attributs; newpin->m_PinNum = m_PinNum; newpin->m_PinNumSize = m_PinNumSize; newpin->m_PinNameSize = m_PinNameSize; newpin->m_Unit = m_Unit; newpin->m_Convert = m_Convert; newpin->m_Flags = m_Flags; newpin->m_Width = m_Width; newpin->m_PinName = m_PinName; return newpin; } /**************************************************************/ LibDrawArc::LibDrawArc() : LibEDA_BaseStruct( COMPONENT_ARC_DRAW_TYPE ) /**************************************************************/ { m_Rayon = 0; t1 = t2 = 0; m_Width = 0; m_Fill = NO_FILL; } /************************************/ LibDrawArc* LibDrawArc::GenCopy() /************************************/ { LibDrawArc* newitem = new LibDrawArc(); newitem->m_Pos = m_Pos; newitem->m_ArcStart = m_ArcStart; newitem->m_ArcEnd = m_ArcEnd; newitem->m_Rayon = m_Rayon; newitem->t1 = t1; newitem->t2 = t2; newitem->m_Width = m_Width; newitem->m_Unit = m_Unit; newitem->m_Convert = m_Convert; newitem->m_Flags = m_Flags; newitem->m_Fill = m_Fill; return newitem; } /**********************************************************************/ LibDrawCircle::LibDrawCircle() : LibEDA_BaseStruct( COMPONENT_CIRCLE_DRAW_TYPE ) /**********************************************************************/ { m_Rayon = 0; m_Fill = NO_FILL; } /*******************************************/ LibDrawCircle* LibDrawCircle::GenCopy() /*******************************************/ { LibDrawCircle* newitem = new LibDrawCircle(); newitem->m_Pos = m_Pos; newitem->m_Rayon = m_Rayon; newitem->m_Width = m_Width; newitem->m_Unit = m_Unit; newitem->m_Convert = m_Convert; newitem->m_Flags = m_Flags; newitem->m_Fill = m_Fill; return newitem; } /*****************************************************************/ LibDrawText::LibDrawText() : LibEDA_BaseStruct( COMPONENT_GRAPHIC_TEXT_DRAW_TYPE ) /*****************************************************************/ { m_Horiz = TEXT_ORIENT_HORIZ; m_Size = wxSize( 50, 50 ); m_Type = 0; m_Width = 0; } /***************************************/ LibDrawText* LibDrawText::GenCopy() /***************************************/ { LibDrawText* newitem = new LibDrawText(); newitem->m_Pos = m_Pos; newitem->m_Horiz = m_Horiz; newitem->m_Size = m_Size; newitem->m_Type = m_Type; newitem->m_Unit = m_Unit; newitem->m_Convert = m_Convert; newitem->m_Flags = m_Flags; newitem->m_Text = m_Text; newitem->m_Width = m_Width; return newitem; } LibDrawSquare::LibDrawSquare() : LibEDA_BaseStruct( COMPONENT_RECT_DRAW_TYPE ) { m_Width = 0; m_Fill = NO_FILL; } LibDrawSquare* LibDrawSquare::GenCopy() { LibDrawSquare* newitem = new LibDrawSquare(); newitem->m_Pos = m_Pos; newitem->m_End = m_End; newitem->m_Width = m_Width; newitem->m_Unit = m_Unit; newitem->m_Convert = m_Convert; newitem->m_Flags = m_Flags; newitem->m_Fill = m_Fill; return newitem; } LibDrawSegment::LibDrawSegment() : LibEDA_BaseStruct( COMPONENT_LINE_DRAW_TYPE ) { m_Width = 0; } LibDrawSegment* LibDrawSegment::GenCopy() { LibDrawSegment* newitem = new LibDrawSegment(); newitem->m_Pos = m_Pos; newitem->m_End = m_End; newitem->m_Width = m_Width; newitem->m_Unit = m_Unit; newitem->m_Convert = m_Convert; newitem->m_Flags = m_Flags; return newitem; } LibDrawPolyline::LibDrawPolyline() : LibEDA_BaseStruct( COMPONENT_POLYLINE_DRAW_TYPE ) { n = 0; PolyList = NULL; m_Fill = NO_FILL; m_Width = 0; } /************************************************/ LibDrawPolyline* LibDrawPolyline::GenCopy() /************************************************/ { LibDrawPolyline* newitem = new LibDrawPolyline(); int size; newitem->n = n; size = sizeof(int) * 2 * n; if( size ) { newitem->PolyList = (int*) MyMalloc( size ); memcpy( newitem->PolyList, PolyList, size ); } newitem->m_Pos = m_Pos; newitem->m_Width = m_Width; newitem->m_Unit = m_Unit; newitem->m_Convert = m_Convert; newitem->m_Flags = m_Flags; newitem->m_Fill = m_Fill; return newitem; } /***************************************************/ void LibDrawPolyline::AddPoint( const wxPoint& point ) /***************************************************/ /* add a point to the polyline coordinate list, and realloc the memory */ { int allocsize; n++; allocsize = 2 * sizeof(int) * n; if( PolyList == NULL ) PolyList = (int*) MyMalloc( allocsize ); else PolyList = (int*) realloc( PolyList, allocsize ); PolyList[(n * 2) - 2] = point.x; PolyList[(n * 2) - 1] = -point.y; }