1151 lines
31 KiB
C++
1151 lines
31 KiB
C++
/***********************************************************/
|
||
/* 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<74>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 <20>l<EFBFBD>ments graphiques d'un composant lib pour am<61>liorer
|
||
le trac<61>:
|
||
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;
|
||
}
|