/*****************************************************************/ /* Functions to handle component library files : read functions */ /*****************************************************************/ #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "trigo.h" #include "program.h" #include "libcmp.h" #include "general.h" #include "protos.h" /* Local Functions */ static LibEDA_BaseStruct* GetDrawEntry( WinEDA_DrawFrame* frame, FILE* f, char* Line, int* LineNum ); static bool GetLibEntryField( EDA_LibComponentStruct* LibEntry, char* line ); static bool AddAliasNames( EDA_LibComponentStruct* LibEntry, char* line ); static void InsertAlias( PriorQue** PQ, EDA_LibComponentStruct* LibEntry, int* NumOfParts ); static bool ReadLibEntryDateAndTime( EDA_LibComponentStruct* LibEntry, char* Line ); static int AddFootprintFilterList( EDA_LibComponentStruct* LibEntryLibEntry, FILE* f, char* Line, int* LineNum ); static wxString currentLibraryName; // If this code was written in C++ then this would not be needed. /*************************************************************************************/ LibraryStruct* LoadLibraryName( WinEDA_DrawFrame* frame, const wxString& FullLibName, const wxString& LibName ) /*************************************************************************************/ /** Function LoadLibraryName * Routine to load the given library name. FullLibName should hold full path * of file name to open, while LibName should hold only its name. * IF library already exists, it is NOT reloaded. * @return : new lib or NULL */ { int NumOfParts; FILE* f; LibraryStruct* NewLib; PriorQue* Entries; wxString FullFileName; if( ( NewLib = FindLibrary( LibName ) ) != NULL ) { if( NewLib->m_FullFileName == FullLibName ) return NewLib; FreeCmpLibrary( frame, LibName ); } NewLib = NULL; f = wxFopen( FullLibName, wxT( "rt" ) ); if( f == NULL ) { wxString msg; msg.Printf( _( "Library <%s> not found" ), FullLibName.GetData() ); DisplayError( frame, msg ); return NULL; } currentLibraryName = FullLibName; NewLib = new LibraryStruct( LIBRARY_TYPE_EESCHEMA, LibName, FullLibName ); Entries = LoadLibraryAux( frame, NewLib, f, &NumOfParts ); if( Entries != NULL ) { NewLib->m_Entries = Entries; NewLib->m_NumOfParts = NumOfParts; if( g_LibraryList == NULL ) g_LibraryList = NewLib; else { LibraryStruct* tmplib = g_LibraryList; while( tmplib->m_Pnext ) tmplib = tmplib->m_Pnext; tmplib->m_Pnext = NewLib; } FullFileName = FullLibName; ChangeFileNameExt( FullFileName, DOC_EXT ); LoadDocLib( frame, FullFileName, NewLib->m_Name ); } else delete NewLib; fclose( f ); return NewLib; } /******************************************/ void LoadLibraries( WinEDA_DrawFrame* frame ) /******************************************/ /* Function LoadLibraries * Clear all alredy loaded librries and load all librairies * given in g_LibName_List */ { wxString FullLibName, msg; wxString LibName; unsigned ii, iimax = g_LibName_List.GetCount(); frame->PrintMsg( _( "Start loading schematic libs" ) ); // Free the unwanted libraries (i.e. not in list) but keep the .cache lib LibraryStruct* nextlib, * lib = g_LibraryList; for( ; lib != NULL; lib = nextlib ) { nextlib = lib->m_Pnext; if( lib->m_IsLibCache ) continue; wxString libname = lib->m_Name; // is this library in "wanted list" g_LibName_List ? int test = g_LibName_List.Index( libname ); if( test == wxNOT_FOUND ) FreeCmpLibrary( frame, libname ); } // Load missing libraries (if any) for( ii = 0; ii < iimax; ii++ ) { LibName = g_LibName_List[ii]; if( LibName.IsEmpty() ) continue; FullLibName = MakeFileName( g_RealLibDirBuffer, LibName, g_LibExtBuffer ); msg = wxT( "Loading " ) + FullLibName; frame->PrintMsg( msg ); if( LoadLibraryName( frame, FullLibName, LibName ) ) msg += wxT( " OK" ); else msg += wxT( " ->Error" ); frame->PrintMsg( msg ); } // reorder the linked list to match the order filename list: int NumOfLibs; for( NumOfLibs = 0, lib = g_LibraryList; lib != NULL; lib = lib->m_Pnext ) { lib->m_Flags = 0; NumOfLibs++; } if( NumOfLibs == 0 ) return; LibraryStruct** libs = (LibraryStruct**) MyZMalloc( sizeof(LibraryStruct*) * (NumOfLibs + 2) ); int jj = 0; for( ii = 0; ii < g_LibName_List.GetCount(); ii++ ) { if( jj >= NumOfLibs ) break; lib = FindLibrary( g_LibName_List[ii] ); if( lib ) { lib->m_Flags = 1; libs[jj++] = lib; } } /* Put lib cache at end of list */ for( lib = g_LibraryList; lib != NULL; lib = lib->m_Pnext ) { if( lib->m_Flags == 0 ) libs[jj++] = lib; } libs[jj] = NULL; /* Change the linked list pointers */ for( ii = 0; libs[ii] != NULL; ii++ ) libs[ii]->m_Pnext = libs[ii + 1]; g_LibraryList = libs[0]; MyFree( libs ); for( lib = g_LibraryList; lib != NULL; lib = lib->m_Pnext ) lib->m_Flags = 0; } /**************************************************************/ void FreeCmpLibrary( wxWindow* frame, const wxString& LibName ) /**************************************************************/ /** Function FreeCmpLibrary * Routine to remove and free a library from the current loaded libraries. */ { int NumOfLibs = NumOfLibraries(); LibraryStruct* Lib, * TempLib; if( NumOfLibs == 0 ) { DisplayError( frame, wxT( "No libraries are loaded" ), 20 ); return; } /* Search for this library name: */ for( Lib = g_LibraryList; Lib != NULL; Lib = Lib->m_Pnext ) { if( LibName == Lib->m_Name ) break; } if( Lib == NULL ) return; if( Lib == g_LibraryList ) g_LibraryList = Lib->m_Pnext; else { for( TempLib = g_LibraryList; TempLib->m_Pnext != Lib; TempLib = TempLib->m_Pnext ) ; TempLib->m_Pnext = TempLib->m_Pnext->m_Pnext; } delete Lib; /* The removed librairy can be the current library in libedit. * If so, clear the current library in libedit */ if( Lib == CurrentLib ) CurrentLib = NULL; } /******************************/ const wxChar** GetLibNames() /******************************/ /** GetLibNames() * Routine to return pointers to all library names. * User is responsible to deallocate memory */ { int ii, NumOfLibs = NumOfLibraries(); const wxChar** Names; LibraryStruct* Lib; Names = (const wxChar**) MyZMalloc( sizeof(wxChar*) * (NumOfLibs + 1) ); for( ii = 0, Lib = g_LibraryList; Lib != NULL; Lib = Lib->m_Pnext, ii++ ) { Names[ii] = Lib->m_Name.GetData(); } Names[ii] = NULL; return Names; } /** Function LibraryEntryCompare * Routine to compare two EDA_LibComponentStruct for the PriorQue module. * Comparison (insensitive case) is based on Part name. */ int LibraryEntryCompare( EDA_LibComponentStruct* LE1, EDA_LibComponentStruct* LE2 ) { return LE1->m_Name.m_Text.CmpNoCase( LE2->m_Name.m_Text ); } /***************************************************************************** * Routine to load a library from given open file. * *****************************************************************************/ PriorQue* LoadLibraryAux( WinEDA_DrawFrame* frame, LibraryStruct* Library, FILE* libfile, int* NumOfParts ) { int LineNum = 0; char Line[1024]; PriorQue* PQ = NULL; EDA_LibComponentStruct* LibEntry; wxString msg; wxBusyCursor ShowWait; // Display a Busy Cursor.. *NumOfParts = 0; if( GetLine( libfile, Line, &LineNum, sizeof(Line) ) == NULL ) { msg = _( "File <" ) + Library->m_Name + _( "> is empty!" ); DisplayError( frame, msg ); return NULL; } if( strnicmp( Line, LIBFILE_IDENT, 10 ) != 0 ) { msg = _( "File <" ) + Library->m_Name + _( "> is NOT EESCHEMA library!" ); DisplayError( frame, msg ); return NULL; } if( Library ) Library->m_Header = CONV_FROM_UTF8( Line ); PQInit( &PQ ); PQCompFunc( (PQCompFuncType) LibraryEntryCompare ); while( GetLine( libfile, Line, &LineNum, sizeof(Line) ) ) { if( strnicmp( Line, "$HEADER", 7 ) == 0 ) { if( Library ) { if( !Library->ReadHeader( libfile, &LineNum ) ) { msg = _( "Library <" ) + Library->m_Name + _( "> header read error" ); DisplayError( frame, msg, 30 ); } } continue; } if( strnicmp( Line, "DEF", 3 ) == 0 ) { /* Read one DEF/ENDDEF part entry from library: */ LibEntry = Read_Component_Definition( frame, Line, libfile, &LineNum ); if( LibEntry ) { /* If we are here, this part is O.k. - put it in: */ ++ * NumOfParts; PQInsert( &PQ, LibEntry ); InsertAlias( &PQ, LibEntry, NumOfParts ); } } } return PQ; } /*********************************************************************************************/ EDA_LibComponentStruct* Read_Component_Definition( WinEDA_DrawFrame* frame, char* Line, FILE* f, int* LineNum ) /*********************************************************************************************/ /* Routine to Read a DEF/ENDDEF part entry from given open file. */ { int unused; char* p; char* name; char* prefix = NULL; EDA_LibComponentStruct* LibEntry = NULL; bool Res; wxString Msg; p = strtok( Line, " \t\r\n" ); if( strcmp( p, "DEF" ) != 0 ) { Msg.Printf( wxT( "DEF command expected in line %d, aborted." ), *LineNum ); DisplayError( frame, Msg ); return NULL; } /* Read DEF line: */ char drawnum = 0, drawname = 0; LibEntry = new EDA_LibComponentStruct( NULL ); if( ( name = strtok( NULL, " \t\n" ) ) == NULL /* Part name: */ || ( prefix = strtok( NULL, " \t\n" ) ) == NULL /* Prefix name: */ || ( p = strtok( NULL, " \t\n" ) ) == NULL /* NumOfPins: */ || sscanf( p, "%d", &unused ) != 1 || ( p = strtok( NULL, " \t\n" ) ) == NULL /* TextInside: */ || sscanf( p, "%d", &LibEntry->m_TextInside ) != 1 || ( p = strtok( NULL, " \t\n" ) ) == NULL /* DrawNums: */ || sscanf( p, "%c", &drawnum ) != 1 || ( p = strtok( NULL, " \t\n" ) ) == NULL /* DrawNums: */ || sscanf( p, "%c", &drawname ) != 1 || ( p = strtok( NULL, " \t\n" ) ) == NULL /* m_UnitCount: */ || sscanf( p, "%d", &LibEntry->m_UnitCount ) != 1 ) { Msg.Printf( wxT( "Wrong DEF format in line %d, skipped." ), *LineNum ); DisplayError( frame, Msg ); while( GetLine( f, Line, LineNum, 1024 ) ) { p = strtok( Line, " \t\n" ); if( stricmp( p, "ENDDEF" ) == 0 ) break; } return NULL; } else /* Update infos read from the line "DEF" */ { LibEntry->m_DrawPinNum = (drawnum == 'N') ? FALSE : TRUE; LibEntry->m_DrawPinName = (drawname == 'N') ? FALSE : TRUE; /* Copy part name and prefix. */ strupper( name ); if( name[0] != '~' ) LibEntry->m_Name.m_Text = CONV_FROM_UTF8( name ); else { LibEntry->m_Name.m_Text = CONV_FROM_UTF8( &name[1] ); LibEntry->m_Name.m_Attributs |= TEXT_NO_VISIBLE; } if( strcmp( prefix, "~" ) == 0 ) { LibEntry->m_Prefix.m_Text.Empty(); LibEntry->m_Prefix.m_Attributs |= TEXT_NO_VISIBLE; } else LibEntry->m_Prefix.m_Text = CONV_FROM_UTF8( prefix ); // Copy optional infos if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) // m_UnitSelectionLocked param { if( *p == 'L' ) LibEntry->m_UnitSelectionLocked = TRUE; } if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) /* Type Of Component */ { if( *p == 'P' ) LibEntry->m_Options = ENTRY_POWER; } } /* Read next lines */ while( GetLine( f, Line, LineNum, 1024 ) ) { p = strtok( Line, " \t\n" ); Res = TRUE; /* This is the error flag ( if an error occurs, Res = FALSE) */ if( (Line[0] == 'T') && (Line[1] == 'i') ) { Res = ReadLibEntryDateAndTime( LibEntry, Line ); } else if( Line[0] == 'F' ) { Res = GetLibEntryField( LibEntry, Line ); } else if( strcmp( p, "ENDDEF" ) == 0 ) { break; } else if( strcmp( p, "DRAW" ) == 0 ) { LibEntry->m_Drawings = GetDrawEntry( frame, f, Line, LineNum ); } else if( strncmp( p, "ALIAS", 5 ) == 0 ) { p = strtok( NULL, "\r\n" ); Res = AddAliasNames( LibEntry, p ); } else if( strncmp( p, "$FPLIST", 5 ) == 0 ) { Res = AddFootprintFilterList( LibEntry, f, Line, LineNum ); } else { Msg.Printf( wxT( "Undefined command \"%s\" in line %d, skipped." ), p, *LineNum ); frame->PrintMsg( Msg ); } /* End line or block analysis: test for an error */ if( !Res ) { /* Something went wrong there. */ Msg.Printf( wxT( " Error at line %d of library \n\"%s\",\nlibrary not loaded" ), *LineNum, currentLibraryName.GetData() ); DisplayError( frame, Msg ); delete LibEntry; return NULL; } } /* If we are here, this part is O.k. - put it in: */ LibEntry->SortDrawItems(); return LibEntry; } /***************************************************************************** * Routine to load a DRAW definition from given file. Note "DRAW" line has * * been read already. Reads upto and include ENDDRAW, or an error (NULL ret). * *****************************************************************************/ static LibEDA_BaseStruct* GetDrawEntry( WinEDA_DrawFrame* frame, FILE* f, char* Line, int* LineNum ) { int i = 0, jj, ll, Unit, Convert, size1, size2; char* p, Buffer[1024], BufName[256], PinNum[256], chartmp[256], chartmp1[256]; wxString MsgLine; bool Error = FALSE; LibEDA_BaseStruct* Tail = NULL, * New = NULL, * Head = NULL; while( TRUE ) { if( GetLine( f, Line, LineNum, 1024 ) == NULL ) { DisplayError( frame, wxT( "File ended prematurely" ) ); return Head; } if( strncmp( Line, "ENDDRAW", 7 ) == 0 ) { break; } New = NULL; switch( Line[0] ) { case 'A': /* Arc */ { int startx, starty, endx, endy; LibDrawArc* Arc = new LibDrawArc(); New = Arc; ll = 0; int nbarg = sscanf( &Line[2], "%d %d %d %d %d %d %d %d %s %d %d %d %d", &Arc->m_Pos.x, &Arc->m_Pos.y, &Arc->m_Rayon, &Arc->t1, &Arc->t2, &Unit, &Convert, &Arc->m_Width, chartmp, &startx, &starty, &endx, &endy ); if( nbarg < 8 ) Error = TRUE; Arc->m_Unit = Unit; Arc->m_Convert = Convert; if( chartmp[0] == 'F' ) Arc->m_Fill = FILLED_SHAPE; if( chartmp[0] == 'f' ) Arc->m_Fill = FILLED_WITH_BG_BODYCOLOR; NORMALIZE_ANGLE( Arc->t1 ); NORMALIZE_ANGLE( Arc->t2 ); if( nbarg >= 13 ) // Actual Coordinates of arc ends are read from file { Arc->m_ArcStart.x = startx; Arc->m_ArcStart.y = starty; Arc->m_ArcEnd.x = endx; Arc->m_ArcEnd.y = endy; } else // Actual Coordinates of arc ends are not read from file (old library), calculate them { Arc->m_ArcStart.x = Arc->m_Rayon; Arc->m_ArcStart.y = 0; Arc->m_ArcEnd.x = Arc->m_Rayon; Arc->m_ArcEnd.y = 0; RotatePoint( &Arc->m_ArcStart.x, &Arc->m_ArcStart.y, -Arc->t1 ); Arc->m_ArcStart.x += Arc->m_Pos.x; Arc->m_ArcStart.y += Arc->m_Pos.y; RotatePoint( &Arc->m_ArcEnd.x, &Arc->m_ArcEnd.y, -Arc->t2 ); Arc->m_ArcEnd.x += Arc->m_Pos.x; Arc->m_ArcEnd.y += Arc->m_Pos.y; } } break; case 'C': /* Circle */ { LibDrawCircle* Circle = new LibDrawCircle(); New = Circle; ll = 0; Error = sscanf( &Line[2], "%d %d %d %d %d %d %s", &Circle->m_Pos.x, &Circle->m_Pos.y, &Circle->m_Rayon, &Unit, &Convert, &Circle->m_Width, chartmp ) < 6; Circle->m_Unit = Unit; Circle->m_Convert = Convert; if( chartmp[0] == 'F' ) Circle->m_Fill = FILLED_SHAPE; if( chartmp[0] == 'f' ) Circle->m_Fill = FILLED_WITH_BG_BODYCOLOR; } break; case 'T': /* Text */ { LibDrawText* Text = new LibDrawText(); New = Text; Buffer[0] = 0; Error = sscanf( &Line[2], "%d %d %d %d %d %d %d %s", &Text->m_Horiz, &Text->m_Pos.x, &Text->m_Pos.y, &Text->m_Size.x, &Text->m_Type, &Unit, &Convert, Buffer ) != 8; Text->m_Unit = Unit; Text->m_Convert = Convert; Text->m_Size.y = Text->m_Size.x; if( !Error ) { /* Convert '~' to spaces. */ Text->m_Text = CONV_FROM_UTF8( Buffer ); Text->m_Text.Replace( wxT( "~" ), wxT( " " ) ); // Les espaces sont restitués } } break; case 'S': /* Square */ { LibDrawSquare* Square = new LibDrawSquare(); New = Square; ll = 0; Error = sscanf( &Line[2], "%d %d %d %d %d %d %d %s", &Square->m_Pos.x, &Square->m_Pos.y, &Square->m_End.x, &Square->m_End.y, &Unit, &Convert, &Square->m_Width, chartmp ) < 7; Square->m_Unit = Unit; Square->m_Convert = Convert; if( chartmp[0] == 'F' ) Square->m_Fill = FILLED_SHAPE; if( chartmp[0] == 'f' ) Square->m_Fill = FILLED_WITH_BG_BODYCOLOR; } break; case 'X': /* Pin Description */ { *Buffer = 0; LibDrawPin* Pin = new LibDrawPin(); New = Pin; i = sscanf( Line + 2, "%s %s %d %d %d %s %d %d %d %d %s %s", BufName, PinNum, &Pin->m_Pos.x, &Pin->m_Pos.y, &ll, chartmp1, &size1, &size2, &Unit, &Convert, chartmp, Buffer ); Pin->m_PinNumSize = size1; /* Parametres type short */ Pin->m_PinNameSize = size2; Pin->m_PinLen = ll; Pin->m_Orient = chartmp1[0] & 255; Pin->m_Unit = Unit; Pin->m_Convert = Convert; strncpy( (char*) &Pin->m_PinNum, PinNum, 4 ); Error = (i != 11 && i != 12); Pin->m_PinName = CONV_FROM_UTF8( BufName ); jj = *chartmp & 255; switch( jj ) { case 'I': Pin->m_PinType = PIN_INPUT; break; case 'O': Pin->m_PinType = PIN_OUTPUT; break; case 'B': Pin->m_PinType = PIN_BIDI; break; case 'T': Pin->m_PinType = PIN_TRISTATE; break; case 'P': Pin->m_PinType = PIN_PASSIVE; break; case 'U': Pin->m_PinType = PIN_UNSPECIFIED; break; case 'W': Pin->m_PinType = PIN_POWER_IN; break; case 'w': Pin->m_PinType = PIN_POWER_OUT; break; case 'C': Pin->m_PinType = PIN_OPENCOLLECTOR; break; case 'E': Pin->m_PinType = PIN_OPENEMITTER; break; default: MsgLine.Printf( wxT( "Unknown Pin Type [%c] line %d" ), jj, *LineNum ); DisplayError( frame, MsgLine ); } if( i == 12 ) /* Special Symbole defined */ { for( jj = strlen( Buffer ); jj > 0; ) { switch( Buffer[--jj] ) { case '~': break; case 'N': Pin->m_Attributs |= PINNOTDRAW; break; case 'I': Pin->m_PinShape |= INVERT; break; case 'C': Pin->m_PinShape |= CLOCK; break; case 'L': Pin->m_PinShape |= LOWLEVEL_IN; break; case 'V': Pin->m_PinShape |= LOWLEVEL_OUT; break; default: MsgLine.Printf( wxT( "Unknown Pin Shape [%c] line %d" ), Buffer[jj], *LineNum ); DisplayError( frame, MsgLine ); break; } } } } break; case 'P': /* Polyline */ { LibDrawPolyline* Polyl = new LibDrawPolyline(); New = Polyl; if( sscanf( &Line[2], "%d %d %d %d", &Polyl->n, &Unit, &Convert, &Polyl->m_Width ) == 4 && Polyl->n > 0 ) { Polyl->m_Unit = Unit; Polyl->m_Convert = Convert; Polyl->PolyList = (int*) MyZMalloc( sizeof(int) * Polyl->n * 2 ); p = strtok( &Line[2], " \t\n" ); p = strtok( NULL, " \t\n" ); p = strtok( NULL, " \t\n" ); p = strtok( NULL, " \t\n" ); for( i = 0; i < Polyl->n * 2 && !Error; i++ ) { p = strtok( NULL, " \t\n" ); Error = sscanf( p, "%d", &Polyl->PolyList[i] ) != 1; } Polyl->m_Fill = NO_FILL; if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) { if( p[0] == 'F' ) Polyl->m_Fill = FILLED_SHAPE; if( p[0] == 'f' ) Polyl->m_Fill = FILLED_WITH_BG_BODYCOLOR; } } else Error = TRUE; } break; default: MsgLine.Printf( wxT( "Undefined DRAW command in line %d, aborted." ), *LineNum ); DisplayError( frame, MsgLine ); return Head; } if( Error ) { MsgLine.Printf( wxT( "Error in %c DRAW command in line %d, aborted." ), Line[0], *LineNum ); DisplayError( frame, MsgLine ); delete New; /* FLush till end of draw: */ do { if( GetLine( f, Line, LineNum, 1024 ) == NULL ) { DisplayError( frame, wxT( "File ended prematurely" ) ); return Head; } } while( strncmp( Line, "ENDDRAW", 7 ) != 0 ); return Head; } else { if( Head == NULL ) Head = Tail = New; else { Tail->Pnext = New; Tail = New; } } } return Head; } /***************************************************************************** * Routine to find the library given its name. * *****************************************************************************/ LibraryStruct* FindLibrary( const wxString& Name ) { LibraryStruct* Lib = g_LibraryList; while( Lib ) { if( Lib->m_Name == Name ) return Lib; Lib = Lib->m_Pnext; } return NULL; } /***************************************************************************** * Routine to find the number of libraries currently loaded. * *****************************************************************************/ int NumOfLibraries() { int ii; LibraryStruct* Lib = g_LibraryList; for( ii = 0; Lib != NULL; Lib = Lib->m_Pnext ) ii++; return ii; } /*****************************************************************************/ static bool GetLibEntryField( EDA_LibComponentStruct* LibEntry, char* line ) /*****************************************************************************/ /* Analyse la ligne de description du champ de la forme: * Fn "CA3130" 150 -200 50 H V * ou n = 0 (REFERENCE), 1 (VALUE) , 2 .. 11 = autres champs, facultatifs */ { int posx, posy, size, orient, hjustify, vjustify; bool draw; char* Text, Char1[256], Char2[256], Char3[256], Char4[256], FieldUserName[1024]; int NumOfField, nbparam; LibDrawField* Field = NULL; if( sscanf( line + 1, "%d", &NumOfField ) != 1 ) return 0; /* Recherche du debut des donnees (debut du texte suivant) */ while( *line != 0 ) line++; while( *line == 0 ) line++; /* recherche du texte */ while( *line && (*line != '"') ) line++; if( *line == 0 ) return 0; line++; Text = line; /* recherche fin de texte */ while( *line && (*line != '"') ) line++; if( *line == 0 ) return 0; *line = 0; line++; FieldUserName[0] = 0; nbparam = sscanf( line, " %d %d %d %c %c %c %c", &posx, &posy, &size, Char1, Char2, Char3, Char4 ); orient = TEXT_ORIENT_HORIZ; if( Char1[0] == 'V' ) orient = TEXT_ORIENT_VERT; draw = TRUE; if( Char2[0] == 'I' ) draw = FALSE; hjustify = GR_TEXT_HJUSTIFY_CENTER; vjustify = GR_TEXT_VJUSTIFY_CENTER; if( nbparam >= 6 ) { if( *Char3 == 'L' ) hjustify = GR_TEXT_HJUSTIFY_LEFT; else if( *Char3 == 'R' ) hjustify = GR_TEXT_HJUSTIFY_RIGHT; if( *Char4 == 'B' ) vjustify = GR_TEXT_VJUSTIFY_BOTTOM; else if( *Char4 == 'T' ) vjustify = GR_TEXT_VJUSTIFY_TOP; } switch( NumOfField ) { case REFERENCE: Field = &LibEntry->m_Prefix; Field->m_FieldId = REFERENCE; break; case VALUE: Field = &LibEntry->m_Name; Field->m_FieldId = VALUE; break; default: if( NumOfField >= NUMBER_OF_FIELDS ) break; Field = new LibDrawField( NumOfField ); Field->Pnext = LibEntry->Fields; LibEntry->Fields = Field; break; } if( Field == NULL ) return FALSE; Field->m_Pos.x = posx; Field->m_Pos.y = posy; Field->m_Orient = orient; if( draw == FALSE ) Field->m_Attributs |= TEXT_NO_VISIBLE; Field->m_Size.x = Field->m_Size.y = size; Field->m_Text = CONV_FROM_UTF8( Text ); if( NumOfField >= FIELD1 ) { ReadDelimitedText( FieldUserName, line, sizeof(FieldUserName) ); Field->m_Name = CONV_FROM_UTF8( FieldUserName ); } Field->m_HJustify = hjustify; Field->m_VJustify = vjustify; return TRUE; } /********************************************************************/ static bool AddAliasNames( EDA_LibComponentStruct* LibEntry, char* line ) /********************************************************************/ /* Read the alias names (in buffer line) and add them in alias list * names are separated by spaces */ { char* text; wxString name; text = strtok( line, " \t\r\n" ); while( text ) { name = CONV_FROM_UTF8( text ); LibEntry->m_AliasList.Add( name ); text = strtok( NULL, " \t\r\n" ); } return TRUE; } /********************************************************************/ static void InsertAlias( PriorQue** PQ, EDA_LibComponentStruct* LibEntry, int* NumOfParts ) /********************************************************************/ /* create in library (in list PQ) aliases of the "root" component LibEntry*/ { EDA_LibCmpAliasStruct* AliasEntry; unsigned ii; if( LibEntry->m_AliasList.GetCount() == 0 ) return; /* No alias for this component */ for( ii = 0; ii < LibEntry->m_AliasList.GetCount(); ii++ ) { AliasEntry = new EDA_LibCmpAliasStruct( LibEntry->m_AliasList[ii], LibEntry->m_Name.m_Text.GetData() ); ++ * NumOfParts; PQInsert( PQ, AliasEntry ); } } /*******************************************************/ /* Routines de lecture des Documentation de composants */ /*******************************************************/ /**********************************************************************************************/ int LoadDocLib( WinEDA_DrawFrame* frame, const wxString& FullDocLibName, const wxString& Libname ) /**********************************************************************************************/ /* Routine to load a library from given open file.*/ { int LineNum = 0; char Line[1024], * Name, * Text; EDA_LibComponentStruct* Entry; FILE* f; wxString msg; f = wxFopen( FullDocLibName, wxT( "rt" ) ); if( f == NULL ) return 0; if( GetLine( f, Line, &LineNum, sizeof(Line) ) == NULL ) { /* pas de lignes utiles */ fclose( f ); return 0; } if( strnicmp( Line, DOCFILE_IDENT, 10 ) != 0 ) { DisplayError( frame, wxT( "File is NOT EESCHEMA doclib!" ) ); fclose( f ); return 0; } while( GetLine( f, Line, &LineNum, sizeof(Line) ) ) { if( strncmp( Line, "$CMP", 4 ) != 0 ) { msg.Printf( wxT( "$CMP command expected in line %d, aborted." ), LineNum ); DisplayError( frame, msg ); fclose( f ); return 0; } /* Read one $CMP/$ENDCMP part entry from library: */ Name = strtok( Line + 5, "\n\r" ); wxString cmpname; cmpname = CONV_FROM_UTF8( Name ); Entry = FindLibPart( cmpname.GetData(), Libname, FIND_ALIAS ); while( GetLine( f, Line, &LineNum, sizeof(Line) ) ) { if( strncmp( Line, "$ENDCMP", 7 ) == 0 ) break; Text = strtok( Line + 2, "\n\r" ); switch( Line[0] ) { case 'D': if( Entry ) Entry->m_Doc = CONV_FROM_UTF8( Text ); break; case 'K': if( Entry ) Entry->m_KeyWord = CONV_FROM_UTF8( Text ); break; case 'F': if( Entry ) Entry->m_DocFile = CONV_FROM_UTF8( Text ); break; } } } fclose( f ); return 1; } /*********************************************************************************/ static bool ReadLibEntryDateAndTime( EDA_LibComponentStruct* LibEntry, char* Line ) /*********************************************************************************/ /* lit date et time de modif composant sous le format: * "Ti yy/mm/jj hh:mm:ss" */ { int year, mon, day, hour, min, sec; char* text; year = mon = day = hour = min = sec = 0; text = strtok( Line, " \r\t\n" ); text = strtok( NULL, " \r\t\n" ); // text pointe donnees utiles sscanf( Line, "%d/%d/%d %d:%d:%d", &year, &mon, &day, &hour, &min, &sec ); LibEntry->m_LastDate = (sec & 63) + ( (min & 63) << 6 ) + ( (hour & 31) << 12 ) + ( (day & 31) << 17 ) + ( (mon & 15) << 22 ) + ( (year - 1990) << 26 ); return TRUE; } /*******************************************/ static int SortItemsFct( const void* ref, const void* item ); void EDA_LibComponentStruct::SortDrawItems() /*******************************************/ /* Trie les éléments graphiques d'un composant lib pour améliorer * le tracé: * items remplis en premier, pins en dernier * En cas de superposition d'items, c'est plus lisible */ { LibEDA_BaseStruct** Bufentry, ** BufentryBase, * Entry = m_Drawings; int ii, nbitems; if( Entry == NULL ) return; /* Pas d'alias pour ce composant */ /* calcul du nombre d'items */ for( nbitems = 0; Entry != NULL; Entry = Entry->Next() ) nbitems++; BufentryBase = (LibEDA_BaseStruct**) MyZMalloc( (nbitems + 1) * sizeof(LibEDA_BaseStruct*) ); /* memorisation du chainage : */ for( Entry = m_Drawings, ii = 0; Entry != NULL; Entry = Entry->Next() ) BufentryBase[ii++] = Entry; /* Tri du chainage */ qsort( BufentryBase, nbitems, sizeof(LibEDA_BaseStruct*), SortItemsFct ); /* Mise a jour du chainage. Remarque: * le dernier element de BufEntryBase (BufEntryBase[nbitems]) est NULL*/ m_Drawings = *BufentryBase; Bufentry = BufentryBase; for( ii = 0; ii < nbitems; ii++ ) { (*Bufentry)->Pnext = *(Bufentry + 1); Bufentry++; } MyFree( BufentryBase ); } int SortItemsFct( const void* ref, const void* item ) { #define Ref ( *(LibEDA_BaseStruct**) (ref) ) #define Item ( *(LibEDA_BaseStruct**) (item) ) #define BEFORE -1 #define AFTER 1 int fill_ref = 0, fill_item = 0; switch( Ref->Type() ) { case COMPONENT_ARC_DRAW_TYPE: { const LibDrawArc* draw = (const LibDrawArc*) Ref; fill_ref = draw->m_Fill; break; } case COMPONENT_CIRCLE_DRAW_TYPE: { const LibDrawCircle* draw = (const LibDrawCircle*) Ref; fill_ref = draw->m_Fill; break; } case COMPONENT_RECT_DRAW_TYPE: { const LibDrawSquare* draw = (const LibDrawSquare*) Ref; fill_ref = draw->m_Fill; break; } case COMPONENT_POLYLINE_DRAW_TYPE: { const LibDrawPolyline* draw = (const LibDrawPolyline*) Ref; fill_ref = draw->m_Fill; break; } case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE: if( Item->Type() == COMPONENT_PIN_DRAW_TYPE ) return BEFORE; if( Item->Type() == COMPONENT_GRAPHIC_TEXT_DRAW_TYPE ) return 0; return 1; break; case COMPONENT_PIN_DRAW_TYPE: if( Item->Type() == COMPONENT_PIN_DRAW_TYPE ) { int ii; // We sort the pins by orientation ii = ( (LibDrawPin*) Ref )->m_Orient - ( (LibDrawPin*) Item )->m_Orient; if( ii ) return ii; /* We sort the pins by position (x or y). * note: at this point, most of pins have same x pos or y pos, * because they are sorted by orientation and generally are vertically or * horizontally aligned */ wxPoint pos_ref, pos_tst; pos_ref = ( (LibDrawPin*) Ref )->m_Pos; pos_tst = ( (LibDrawPin*) Item )->m_Pos; if( (ii = pos_ref.x - pos_tst.x) ) return ii; ii = pos_ref.y - pos_tst.y; return ii; } else return AFTER; break; default: ; } /* Test de l'item */ switch( Item->Type() ) { case COMPONENT_ARC_DRAW_TYPE: { const LibDrawArc* draw = (const LibDrawArc*) Item; fill_item = draw->m_Fill; break; } case COMPONENT_CIRCLE_DRAW_TYPE: { const LibDrawCircle* draw = (const LibDrawCircle*) Item; fill_item = draw->m_Fill; break; } case COMPONENT_RECT_DRAW_TYPE: { const LibDrawSquare* draw = (const LibDrawSquare*) Item; fill_item = draw->m_Fill; break; } case COMPONENT_POLYLINE_DRAW_TYPE: { const LibDrawPolyline* draw = (const LibDrawPolyline*) Item; fill_item = draw->m_Fill; break; } case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE: return BEFORE; break; case COMPONENT_PIN_DRAW_TYPE: return BEFORE; break; default: ; } if( fill_ref & fill_item ) return 0; if( fill_ref ) return BEFORE; return AFTER; } /*****************************************************************************/ int AddFootprintFilterList( EDA_LibComponentStruct* LibEntryLibEntry, FILE* f, char* Line, int* LineNum ) /******************************************************************************/ /* read the FootprintFilter List stating with: * FPLIST * and ending with: * ENDFPLIST */ { for( ; ; ) { if( GetLine( f, Line, LineNum, 1024 ) == NULL ) { DisplayError( NULL, wxT( "File ended prematurely" ) ); return 0; } if( stricmp( Line, "$ENDFPLIST" ) == 0 ) { break; /*normal exit on end of list */ } LibEntryLibEntry->m_FootprintList.Add( CONV_FROM_UTF8( Line + 1 ) ); } return 1; }