/***********************************************************/ /* Module to handle libraries (first part - file and io). */ /***********************************************************/ #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" /* Variables Locales */ /* Fonctions locales */ /* pour librairies de composants */ 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); /* pour doc librairies */ /****************************************************/ /* Routines de lecture des librairies de composants */ /****************************************************/ /***************************************************************************** * 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 * *****************************************************************************/ LibraryStruct * LoadLibraryName(WinEDA_DrawFrame * frame, const wxString & FullLibName, const wxString & LibName) { 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; } 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) /******************************************/ /* Delete toutes les librairies chargees et recree toutes les librairies donnes dans la liste 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; 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; } /***************************************************************************** * Routine to free a library from the current loaded libraries. * *****************************************************************************/ void FreeCmpLibrary(wxWindow * frame, const wxString & LibName) { 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; /* La librairie supprimee est peut etre celle selectee dans libedit */ if ( Lib == CurrentLib ) CurrentLib = NULL; } /******************************/ const wxChar **GetLibNames(void) /******************************/ /* 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; } /***************************************************************************** * 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, *Name, *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 /* Mise a jour des infos de la ligne "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; } } /* Analyse lignes suivantes */ while (GetLine(f, Line, LineNum, 1024) ) { p = strtok(Line, " \t\n"); Res = TRUE; /* Pour test d'erreur (Res = FALSE = erreur) */ 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); } /* Fin analyse de la ligne ou block: test de l'info lue */ if (!Res) { /* Something went wrong there. */ Msg.Printf( wxT(" Error Line %d, Library not loaded"), *LineNum); 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]; int ctmp; 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 %c %d %d %d %d", &Arc->m_Pos.x, &Arc->m_Pos.y, &Arc->m_Rayon, &Arc->t1, &Arc->t2, &Unit, &Convert, &Arc->m_Width, &ctmp, &startx, &starty, &endx, &endy); if ( nbarg < 8 ) Error = TRUE; Arc->m_Unit = Unit; Arc->m_Convert = Convert; if ( ctmp == 'F') Arc->m_Fill = FILLED_SHAPE; if ( ctmp == 'f') Arc->m_Fill = FILLED_WITH_BG_BODYCOLOR; NORMALIZE_ANGLE(Arc->t1); NORMALIZE_ANGLE(Arc->t2); if ( nbarg >= 13 ) // Coord reelles des extremites de l'arc lues { Arc->m_Start.x = startx; Arc->m_Start.y = starty; Arc->m_End.x = endx; Arc->m_End.y = endy; } else { Arc->m_Start.x = Arc->m_Rayon; Arc->m_Start.y = 0; Arc->m_End.x = Arc->m_Rayon; Arc->m_End.y = 0; RotatePoint( &Arc->m_Start.x, &Arc->m_Start.y, -Arc->t1); Arc->m_Start.x += Arc->m_Pos.x; Arc->m_Start.y +=Arc->m_Pos.y; RotatePoint( &Arc->m_End.x, &Arc->m_End.y, -Arc->t2); Arc->m_End.x += Arc->m_Pos.x; Arc->m_End.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 %c", &Circle->m_Pos.x, &Circle->m_Pos.y, &Circle->m_Rayon, &Unit, &Convert,&Circle->m_Width, &ctmp) < 6; Circle->m_Unit = Unit; Circle->m_Convert = Convert; if ( ctmp == 'F') Circle->m_Fill = FILLED_SHAPE; if ( ctmp == '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_Start.x, &Square->m_Start.y, &Square->m_End.x, &Square->m_End.y, &Unit, &Convert,&Square->m_Width, &ctmp) < 7; Square->m_Unit = Unit; Square->m_Convert = Convert; if ( ctmp == 'F') Square->m_Fill = FILLED_SHAPE; if ( ctmp == '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_SizeNum = size1; /* Parametres type short */ Pin->m_SizeName = 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(void) { 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(void) /*******************************************/ /* 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->m_StructType) { 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->m_StructType == COMPONENT_PIN_DRAW_TYPE ) return BEFORE; if ( Item->m_StructType == COMPONENT_GRAPHIC_TEXT_DRAW_TYPE ) return 0; return 1; break; case COMPONENT_PIN_DRAW_TYPE: if ( Item->m_StructType == 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; } /* Test de l'item */ switch (Item->m_StructType) { 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; } 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; }