kicad/eeschema/eelibs_read_libraryfiles.cpp

1150 lines
31 KiB
C++
Raw Blame History

/***********************************************************/
/* 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];
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 ) // Coord reelles des extremites de l'arc lues
{
Arc->m_ArcStart.x = startx; Arc->m_ArcStart.y = starty;
Arc->m_ArcEnd.x = endx; Arc->m_ArcEnd.y = endy;
}
else
{
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<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_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(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;
}