	/*************************************************/
	/* Functions to Load  from file and save to file */
	/* the graphic shapes  used to draw a component  */
	/* When using the import/export symbol options	 */
	/* files are the *.sym files 					 */
	/*************************************************/

	/* fichier symbedit.cpp */

#include "fctsys.h"
#include "gr_basic.h"

#include "common.h"
#include "program.h"
#include "libcmp.h"
#include "general.h"

#include "protos.h"


/* Routines locales */
static bool CompareSymbols(LibEDA_BaseStruct *DEntryRef,
							LibEDA_BaseStruct *DEntryCompare);

/* Variables locales */




/***************************************************/
void WinEDA_LibeditFrame::LoadOneSymbol(wxDC * DC)
/***************************************************/
/* Read a component shape file and add data (graphic items) to the current
	component.
*/
{
int NumOfParts;
PriorQue *Entries;
EDA_LibComponentStruct *LibEntry = NULL;
LibEDA_BaseStruct *DrawEntry;
wxString FullFileName, mask;
FILE * ImportFile;
wxString msg;

	if(CurrentDrawItem) return;
	if( CurrentLibEntry == NULL) return;

	DrawPanel->m_IgnoreMouseEvents = TRUE;

	mask = wxT("*") + g_SymbolExtBuffer;
	FullFileName = EDA_FileSelector( _("Import symbol drawings:"),
					g_RealLibDirBuffer,		 /* Chemin par defaut */
					wxEmptyString,		 /* nom fichier par defaut */
					g_SymbolExtBuffer,		 /* extension par defaut */
					mask,				/* Masque d'affichage */
					this,
					0,
					TRUE
					);

	GetScreen()->m_Curseur = wxPoint(0,0);
	DrawPanel->MouseToCursorSchema();
	DrawPanel->m_IgnoreMouseEvents = FALSE;

	if ( FullFileName.IsEmpty() ) return;


	/* Load data */
	ImportFile = wxFopen(FullFileName, wxT("rt"));
	if (ImportFile == NULL)
	{
		msg.Printf( _("Failed to open Symbol File <%s>"), FullFileName.GetData());
		DisplayError(this, msg, 20);
		return;
	}


	Entries = LoadLibraryAux(this, NULL, ImportFile, &NumOfParts);
	fclose(ImportFile);

	if( Entries == NULL) return;

	if(NumOfParts > 1 )
			DisplayError(this, _("Warning: more than 1 part in Symbol File"), 20);

	LibEntry = (EDA_LibComponentStruct *)PQFirst(&Entries,FALSE);

	if(LibEntry == NULL )
		DisplayError(this, _("Symbol File is void"), 20);

	else /* add data to the current symbol */
	{
		DrawEntry = LibEntry->m_Drawings;
		while(DrawEntry)
		{
			if(DrawEntry->m_Unit) DrawEntry->m_Unit = CurrentUnit;
			if(DrawEntry->m_Convert) DrawEntry->m_Convert = CurrentConvert;
			DrawEntry->m_Flags = IS_NEW;
			DrawEntry->m_Selected = IS_SELECTED;

			if(DrawEntry->Pnext == NULL)
			{	/* Fin de liste trouvee */
				DrawEntry->Pnext = CurrentLibEntry->m_Drawings;
				CurrentLibEntry->m_Drawings = LibEntry->m_Drawings;
				LibEntry->m_Drawings = NULL;
				break;
			}
			DrawEntry = DrawEntry->Next();
		}
		SuppressDuplicateDrawItem(CurrentLibEntry);
		m_CurrentScreen->SetModify();
		// Move (and place ) the new draw items:
		HandleBlockBegin(DC, -1, GetScreen()->m_Curseur);
		HandleBlockEnd(DC);
		RedrawActiveWindow( DC,TRUE);
	}

	PQFreeFunc(Entries, (void(*)(void*))FreeLibraryEntry);
}


/********************************************/
void WinEDA_LibeditFrame::SaveOneSymbol(void)
/********************************************/
/* Save in file the current symbol
	file format is like the standard libraries, but there is only one symbol
	Invisible pins are not saved
*/
{
EDA_LibComponentStruct *LibEntry = CurrentLibEntry;
int Unit = CurrentUnit, convert = CurrentConvert;
int SymbUnit, SymbConvert;
LibEDA_BaseStruct *DrawEntry;
wxString FullFileName, mask;
wxString msg;
FILE * ExportFile;

	if( LibEntry->m_Drawings == NULL ) return;

	/* Creation du fichier symbole */
	mask = wxT("*") + g_SymbolExtBuffer;
	FullFileName = EDA_FileSelector( _("Export symbol drawings:"),
					g_RealLibDirBuffer,		/* Chemin par defaut */
					wxEmptyString,		 		/* nom fichier par defaut */
					g_SymbolExtBuffer,		/* extension par defaut */
					mask,					/* Masque d'affichage */
					this,
					wxFD_SAVE,
					TRUE
					);
	if ( FullFileName.IsEmpty() ) return;

	ExportFile = wxFopen(FullFileName, wxT("wt") );
	if ( ExportFile == NULL )
	{
		msg.Printf(_("Unable to create <%s>"), FullFileName.GetData());
		DisplayError(this, msg);
		return;
	}

	msg.Printf(_("Save Symbol in [%s]"), FullFileName.GetData());
	Affiche_Message(msg);

	/* Creation de l'entete de la librairie */
	char Line[256];
	fprintf(ExportFile,"%s %d.%d  %s  Date: %s\n",LIBFILE_IDENT,
			LIB_VERSION_MAJOR, LIB_VERSION_MINOR,
        "SYMBOL",DateAndTime(Line));

	/* Creation du commentaire donnant le nom du composant */
	fprintf(ExportFile,"# SYMBOL %s\n#\n",
           (const char*) LibEntry->m_Name.m_Text.GetData());

	/* Generation des lignes utiles */
	fprintf(ExportFile,"DEF %s", (const char*)LibEntry->m_Name.m_Text.GetData());
	if( ! LibEntry->m_Prefix.m_Text.IsEmpty())
		fprintf(ExportFile," %s", (const char*)LibEntry->m_Prefix.m_Text.GetData());
	else fprintf(ExportFile," ~");

	fprintf(ExportFile," %d %d %c %c %d %d %c\n",
		0,	/* unused */
		LibEntry->m_TextInside,
		LibEntry->m_DrawPinNum ? 'Y' : 'N',
		LibEntry->m_DrawPinName ? 'Y' : 'N',
		1, 0 /* unused */, 'N');

	/* Position / orientation / visibilite des champs */
    LibEntry->m_Prefix.WriteDescr( ExportFile );
    LibEntry->m_Name.WriteDescr( ExportFile );

	DrawEntry = LibEntry->m_Drawings;
	if(DrawEntry)
		{
		fprintf(ExportFile,"DRAW\n");
		for( ; DrawEntry != NULL ; DrawEntry = DrawEntry->Next())
			{
			/* Elimination des elements non relatifs a l'unite */
			if( Unit && DrawEntry->m_Unit && (DrawEntry->m_Unit != Unit) )
					continue;
			if( convert && DrawEntry->m_Convert && (DrawEntry->m_Convert != convert) )
					continue;

			/* .Unit , . Convert est laisse a 0 ou mis a 1 */
			SymbUnit = DrawEntry->m_Unit; if ( SymbUnit > 1) SymbUnit = 1;
			SymbConvert = DrawEntry->m_Convert;
			if ( SymbConvert > 1) SymbConvert = 1;
			switch( DrawEntry->m_StructType)
				{
				case COMPONENT_ARC_DRAW_TYPE:
					#define DRAWSTRUCT ((LibDrawArc *) DrawEntry)
                    DRAWSTRUCT->WriteDescr( ExportFile );
					break;

				case COMPONENT_CIRCLE_DRAW_TYPE:
					#undef DRAWSTRUCT
					#define DRAWSTRUCT ((LibDrawCircle *) DrawEntry)
                    DRAWSTRUCT->WriteDescr( ExportFile );
					break;

				case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE:
					#undef DRAWSTRUCT
					#define DRAWSTRUCT ((LibDrawText *) DrawEntry)
                    DRAWSTRUCT->WriteDescr( ExportFile );
					break;

				case COMPONENT_RECT_DRAW_TYPE:
					#undef DRAWSTRUCT
					#define DRAWSTRUCT ((LibDrawSquare *) DrawEntry)
                    DRAWSTRUCT->WriteDescr( ExportFile );
					break;

				case COMPONENT_PIN_DRAW_TYPE:
					#undef DRAWSTRUCT
					#define DRAWSTRUCT ((LibDrawPin *) DrawEntry)
					if(DRAWSTRUCT->m_Attributs & PINNOTDRAW) break;
                    DRAWSTRUCT->WriteDescr( ExportFile );
 					break;

				case COMPONENT_POLYLINE_DRAW_TYPE:
					#undef DRAWSTRUCT
					#define DRAWSTRUCT ((LibDrawPolyline *) DrawEntry)
                    DRAWSTRUCT->WriteDescr( ExportFile );
					break;
				}
			}
		fprintf(ExportFile,"ENDDRAW\n");
		}
	fprintf(ExportFile,"ENDDEF\n");
	fclose(ExportFile);
}



/*****************************************************************/
void SuppressDuplicateDrawItem(EDA_LibComponentStruct * LibEntry)
/*****************************************************************/
/* Delete redundant graphic items.
	Useful after loading asymbole from a file symbol, because some graphic items
	can be duplicated.
*/
{
LibEDA_BaseStruct *DEntryRef, *DEntryCompare;
bool deleted;
wxDC * DC = NULL;

	DEntryRef = LibEntry->m_Drawings;
	while( DEntryRef)
	{
		if( DEntryRef->Pnext == NULL ) return;
		DEntryCompare = DEntryRef->Next();
		if( DEntryCompare == NULL ) return;
		deleted = 0;
		while( DEntryCompare )
		{
			if( CompareSymbols(DEntryRef,DEntryCompare) == TRUE)
			{
				DeleteOneLibraryDrawStruct(NULL, DC, LibEntry,DEntryRef, 1);
				deleted = TRUE;
				break;
			}
			DEntryCompare = DEntryCompare->Next();
		}
		if ( ! deleted ) DEntryRef = DEntryRef->Next();
		else DEntryRef = LibEntry->m_Drawings;
	}
}



/********************************************************************/
static bool CompareSymbols(LibEDA_BaseStruct *DEntryRef,
							LibEDA_BaseStruct *DEntryCompare)
	/********************************************************************/
/* Compare 2 graphic items (arc, lines ...).
	return FALSE si different
			TRUE si they are identical, and therefore redundant
*/
{
int ii;
int * ptref, *ptcomp;

	/* Comparaison des proprietes generales */
	if( DEntryRef->m_StructType != DEntryCompare->m_StructType) return(FALSE);
	if( DEntryRef->m_Unit != DEntryCompare->m_Unit) return(FALSE);
	if( DEntryRef->m_Convert != DEntryCompare->m_Convert) return(FALSE);

	switch( DEntryRef->m_StructType)
		{
		case COMPONENT_ARC_DRAW_TYPE:
			#undef REFSTRUCT
			#undef CMPSTRUCT
			#define REFSTRUCT ((LibDrawArc *) DEntryRef)
			#define CMPSTRUCT ((LibDrawArc *) DEntryCompare)
			if( REFSTRUCT->m_Pos.x != CMPSTRUCT->m_Pos.x) return(FALSE);
			if( REFSTRUCT->m_Pos.y != CMPSTRUCT->m_Pos.y) return(FALSE);
			if( REFSTRUCT->t1 != CMPSTRUCT->t1) return(FALSE);
			if( REFSTRUCT->t2 != CMPSTRUCT->t2) return(FALSE);
			break;

		case COMPONENT_CIRCLE_DRAW_TYPE:
			#undef REFSTRUCT
			#undef CMPSTRUCT
			#define REFSTRUCT ((LibDrawCircle *) DEntryRef)
			#define CMPSTRUCT ((LibDrawCircle *) DEntryCompare)
			if( REFSTRUCT->m_Pos.x != CMPSTRUCT->m_Pos.x) return(FALSE);
			if( REFSTRUCT->m_Pos.y != CMPSTRUCT->m_Pos.y) return(FALSE);
			if( REFSTRUCT->m_Rayon != CMPSTRUCT->m_Rayon) return(FALSE);
			break;

		case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE:
			#undef REFSTRUCT
			#undef CMPSTRUCT
			#define REFSTRUCT ((LibDrawText *) DEntryRef)
			#define CMPSTRUCT ((LibDrawText *) DEntryCompare)
			if( REFSTRUCT->m_Pos != CMPSTRUCT->m_Pos) return(FALSE);
			if( REFSTRUCT->m_Size != CMPSTRUCT->m_Size) return(FALSE);
			if( REFSTRUCT->m_Text != CMPSTRUCT->m_Text )
				return(FALSE);
			break;

		case COMPONENT_RECT_DRAW_TYPE:
			#undef REFSTRUCT
			#undef CMPSTRUCT
			#define REFSTRUCT ((LibDrawSquare *) DEntryRef)
			#define CMPSTRUCT ((LibDrawSquare *) DEntryCompare)
			if( REFSTRUCT->m_Pos != CMPSTRUCT->m_Pos) return(FALSE);
			if( REFSTRUCT->m_End != CMPSTRUCT->m_End) return(FALSE);
			break;

		case COMPONENT_PIN_DRAW_TYPE:
			#undef REFSTRUCT
			#undef CMPSTRUCT
			#define REFSTRUCT ((LibDrawPin *) DEntryRef)
			#define CMPSTRUCT ((LibDrawPin *) DEntryCompare)
			if( REFSTRUCT->m_Pos != CMPSTRUCT->m_Pos) return(FALSE);
			break;

		case COMPONENT_POLYLINE_DRAW_TYPE:
			#undef REFSTRUCT
			#undef CMPSTRUCT
			#define REFSTRUCT ((LibDrawPolyline *) DEntryRef)
			#define CMPSTRUCT ((LibDrawPolyline *) DEntryCompare)
			if( REFSTRUCT->n != CMPSTRUCT->n) return(FALSE);
			ptref = REFSTRUCT->PolyList;
			ptcomp = CMPSTRUCT->PolyList;
			for( ii = 2 * REFSTRUCT->n ; ii > 0; ii-- )
				{
				if( *ptref != *ptcomp) return(FALSE);
				ptref++; ptcomp++;
				}
			break;
		}
	return(TRUE);
}



/***************************************************************************/
/* Routine de placement du point d'ancrage ( reference des coordonnes pour */
/* le trace) du composant courant											  */
/*	Toutes les coord apparaissant dans les structures sont modifiees		  */
/*	pour repositionner le point repere par le curseur souris au point	  */
/*	d'ancrage ( coord 0,0 ).                                               */
/***************************************************************************/

void WinEDA_LibeditFrame::PlaceAncre(void)
{
int ii, *ptsegm;
int dx, dy;				/* Offsets de deplacement */
EDA_LibComponentStruct * LibEntry;
LibEDA_BaseStruct * DrawEntry;

	dx = - m_CurrentScreen->m_Curseur.x;
	dy = m_CurrentScreen->m_Curseur.y;

	LibEntry = CurrentLibEntry;
	if( LibEntry == NULL ) return;

	m_CurrentScreen->SetModify();

	LibEntry->m_Name.m_Pos.x += dx; LibEntry->m_Name.m_Pos.y += dy;
	LibEntry->m_Prefix.m_Pos.x += dx; LibEntry->m_Prefix.m_Pos.y += dy;

	DrawEntry = LibEntry->m_Drawings;
	while(DrawEntry)
		{
		switch(DrawEntry->m_StructType)
			{
			case COMPONENT_ARC_DRAW_TYPE:
				#undef STRUCT
				#define STRUCT ((LibDrawArc *) DrawEntry)
				STRUCT->m_Pos.x += dx;
				STRUCT->m_Pos.y += dy;
				STRUCT->m_ArcStart.x += dx;
				STRUCT->m_ArcStart.y += dy;
				STRUCT->m_ArcEnd.x += dx;
				STRUCT->m_ArcEnd.y += dy;
				break;

			case COMPONENT_CIRCLE_DRAW_TYPE:
				#undef STRUCT
				#define STRUCT ((LibDrawCircle *) DrawEntry)
				STRUCT->m_Pos.x += dx;
				STRUCT->m_Pos.y += dy;
				break;

			case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE:
				#undef STRUCT
				#define STRUCT ((LibDrawText *) DrawEntry)
				STRUCT->m_Pos.x += dx;
				STRUCT->m_Pos.y += dy;
				break;

			case COMPONENT_RECT_DRAW_TYPE:
				#undef STRUCT
				#define STRUCT ((LibDrawSquare *) DrawEntry)
				STRUCT->m_Pos.x += dx;
				STRUCT->m_Pos.y += dy;
				STRUCT->m_End.x += dx;
				STRUCT->m_End.y += dy;
				break;

			case COMPONENT_PIN_DRAW_TYPE:
				#undef STRUCT
				#define STRUCT ((LibDrawPin *) DrawEntry)
				STRUCT->m_Pos.x += dx;
				STRUCT->m_Pos.y += dy;
				break;

			case COMPONENT_POLYLINE_DRAW_TYPE:
				#undef STRUCT
				#define STRUCT ((LibDrawPolyline *) DrawEntry)
				ptsegm = STRUCT->PolyList;
				for( ii = STRUCT->n ; ii > 0; ii-- )
					{
					*ptsegm += dx; ptsegm++;
					*ptsegm += dy;ptsegm++;
					}
				break;
			}
		DrawEntry = DrawEntry->Next();
		}
	/* Redraw the symbol */
	m_CurrentScreen->m_Curseur.x = m_CurrentScreen->m_Curseur.y = 0;
	Recadre_Trace(TRUE);
	m_CurrentScreen->SetRefreshReq();
}

