/*********************************************/ /* eesave.cpp Module to Save EESchema files */ /*********************************************/ #include "fctsys.h" #include "gr_basic.h" #include "common.h" #include "program.h" #include "libcmp.h" #include "general.h" #include "macros.h" #include "protos.h" #include "schframe.h" /* Format des fichiers: Voir EELOAD.CC */ /* Fonctions externes */ /* Fonctions Locales */ static int SavePartDescr( FILE *f, EDA_SchComponentStruct * LibItemStruct); static int SaveSheetDescr( FILE *f, DrawSheetStruct * SheetStruct); static void SaveLayers(FILE *f); /* Variables locales */ /***************************************************************************** * Routine to save an EESchema file. * * FileSave controls how the file is to be saved - under what name. * * Returns TRUE if the file has been saved. * *****************************************************************************/ bool WinEDA_SchematicFrame::SaveEEFile(SCH_SCREEN *screen, int FileSave) { wxString msg; wxString Name, BakName; const wxChar **LibNames; const char * layer, *width; int ii, shape; bool Failed = FALSE; EDA_BaseStruct *Phead; Ki_PageDescr * PlotSheet; FILE *f; wxString dirbuf; if ( screen == NULL ) screen = (SCH_SCREEN*)GetScreen(); /* If no name exists in the window yet - save as new. */ if( screen->m_FileName.IsEmpty() ) FileSave = FILE_SAVE_NEW; switch (FileSave) { case FILE_SAVE_AS: dirbuf = wxGetCwd() + STRING_DIR_SEP; Name = MakeFileName(dirbuf, screen->m_FileName, g_SchExtBuffer); /* Rename the old file to a '.bak' one: */ BakName = Name; if ( wxFileExists(Name) ) { ChangeFileNameExt(BakName, wxT(".bak")); wxRemoveFile(BakName); /* delete Old .bak file */ if( ! wxRenameFile(Name, BakName) ){ DisplayError(this, wxT("Warning: unable to rename old file"), 10); } } break; case FILE_SAVE_NEW: { wxString mask = wxT("*") + g_SchExtBuffer; Name = EDA_FileSelector(_("Schematic files:"), wxEmptyString, /* Chemin par defaut */ screen->m_FileName, /* nom fichier par defaut, et resultat */ g_SchExtBuffer, /* extension par defaut */ mask, /* Masque d'affichage */ this, wxFD_SAVE, FALSE ); if ( Name.IsEmpty() ) return FALSE; screen->m_FileName = Name; dirbuf = wxGetCwd() + STRING_DIR_SEP; Name = MakeFileName(dirbuf, Name, g_SchExtBuffer); break; } default: break; } if ((f = wxFopen(Name, wxT("wt"))) == NULL) { msg = _("Failed to create file ") + Name; DisplayError(this, msg); return FALSE; } msg = _("Save file ") + Name; Affiche_Message(msg); LibNames = GetLibNames(); BakName.Empty(); // temporary buffer! for (ii = 0; LibNames[ii] != NULL; ii++) { if (ii > 0) BakName += wxT(","); BakName += LibNames[ii]; } MyFree( LibNames); if (fprintf(f, "%s %s %d\n", EESCHEMA_FILE_STAMP, SCHEMATIC_HEAD_STRING, EESCHEMA_VERSION) == EOF || fprintf(f, "LIBS:%s\n", CONV_TO_UTF8(BakName)) == EOF) { DisplayError(this, _("File write operation failed.")); fclose(f); return FALSE; } screen->ClrModify(); SaveLayers(f); /* Sauvegarde des dimensions du schema, des textes du cartouche.. */ PlotSheet = screen->m_CurrentSheetDesc; fprintf(f,"$Descr %s %d %d\n",CONV_TO_UTF8(PlotSheet->m_Name), PlotSheet->m_Size.x, PlotSheet->m_Size.y); fprintf(f,"Sheet %d %d\n",screen->m_ScreenNumber, screen->m_NumberOfScreen); fprintf(f,"Title \"%s\"\n",CONV_TO_UTF8(screen->m_Title)); fprintf(f,"Date \"%s\"\n",CONV_TO_UTF8(screen->m_Date)); fprintf(f,"Rev \"%s\"\n",CONV_TO_UTF8(screen->m_Revision)); fprintf(f,"Comp \"%s\"\n",CONV_TO_UTF8(screen->m_Company)); fprintf(f,"Comment1 \"%s\"\n", CONV_TO_UTF8(screen->m_Commentaire1)); fprintf(f,"Comment2 \"%s\"\n", CONV_TO_UTF8(screen->m_Commentaire2)); fprintf(f,"Comment3 \"%s\"\n", CONV_TO_UTF8(screen->m_Commentaire3)); fprintf(f,"Comment4 \"%s\"\n", CONV_TO_UTF8(screen->m_Commentaire4)); fprintf(f,"$EndDescr\n"); /* Sauvegarde des elements du dessin */ Phead = screen->EEDrawList; while (Phead) { switch(Phead->Type()) { case DRAW_LIB_ITEM_STRUCT_TYPE: /* Its a library item. */ SavePartDescr( f, (EDA_SchComponentStruct *) Phead); break; case DRAW_SHEET_STRUCT_TYPE: /* Its a Sheet item. */ SaveSheetDescr( f, (DrawSheetStruct *) Phead); break; case DRAW_SEGMENT_STRUCT_TYPE: /* Its a Segment item. */ #undef STRUCT #define STRUCT ((EDA_DrawLineStruct *) Phead) layer = "Notes"; width = "Line"; if (STRUCT->m_Layer == LAYER_WIRE) layer = "Wire"; if (STRUCT->m_Layer == LAYER_BUS) layer = "Bus"; if( STRUCT->m_Width != GR_NORM_WIDTH) layer = "Bus"; if (fprintf(f, "Wire %s %s\n", layer, width ) == EOF) { Failed = TRUE; break; } if (fprintf(f, "\t%-4d %-4d %-4d %-4d\n", STRUCT->m_Start.x,STRUCT->m_Start.y, STRUCT->m_End.x,STRUCT->m_End.y) == EOF) { Failed = TRUE; break; } break; case DRAW_BUSENTRY_STRUCT_TYPE: /* Its a Raccord item. */ #undef STRUCT #define STRUCT ((DrawBusEntryStruct *) Phead) layer = "Wire"; width = "Line"; if (STRUCT->m_Layer == LAYER_BUS) { layer = "Bus"; width = "Bus"; } if (fprintf(f, "Entry %s %s\n", layer, width) == EOF) { Failed = TRUE; break; } if( fprintf(f, "\t%-4d %-4d %-4d %-4d\n", STRUCT->m_Pos.x,STRUCT->m_Pos.y, STRUCT->m_End().x,STRUCT->m_End().y) == EOF) { Failed = TRUE; break; } break; case DRAW_POLYLINE_STRUCT_TYPE: /* Its a polyline item. */ #undef STRUCT #define STRUCT ((DrawPolylineStruct *) Phead) layer = "Notes"; width = "Line"; if (STRUCT->m_Layer == LAYER_WIRE) layer = "Wire"; if (STRUCT->m_Layer == LAYER_BUS) layer = "Bus"; if( STRUCT->m_Width != GR_NORM_WIDTH) width = "Bus"; if (fprintf(f, "Poly %s %s %d\n", width, layer, STRUCT->m_NumOfPoints) == EOF) { Failed = TRUE; break; } for (ii = 0; ii < STRUCT->m_NumOfPoints; ii++) { if (fprintf(f, "\t%-4d %-4d\n", STRUCT->m_Points[ii*2], STRUCT->m_Points[ii*2+1]) == EOF) { Failed = TRUE; break; } } break; case DRAW_JUNCTION_STRUCT_TYPE: /* Its a connection item. */ #undef STRUCT #define STRUCT ((DrawJunctionStruct *) Phead) if (fprintf(f, "Connection ~ %-4d %-4d\n", STRUCT->m_Pos.x, STRUCT->m_Pos.y) == EOF) { Failed = TRUE; } break; case DRAW_NOCONNECT_STRUCT_TYPE: /* Its a NoConnection item. */ #undef STRUCT #define STRUCT ((DrawNoConnectStruct *) Phead) if (fprintf(f, "NoConn ~ %-4d %-4d\n", STRUCT->m_Pos.x, STRUCT->m_Pos.y) == EOF) { Failed = TRUE; } break; case DRAW_TEXT_STRUCT_TYPE: /* Its a text item. */ #undef STRUCT #define STRUCT ((DrawTextStruct *) Phead) if (fprintf(f, "Text Notes %-4d %-4d %-4d %-4d ~\n%s\n", STRUCT->m_Pos.x, STRUCT->m_Pos.y, STRUCT->m_Orient, STRUCT->m_Size.x, CONV_TO_UTF8(STRUCT->m_Text)) == EOF) Failed = TRUE; break; case DRAW_LABEL_STRUCT_TYPE: /* Its a label item. */ #undef STRUCT #define STRUCT ((DrawLabelStruct *) Phead) shape = '~'; if (fprintf(f, "Text Label %-4d %-4d %-4d %-4d %c\n%s\n", STRUCT->m_Pos.x, STRUCT->m_Pos.y, STRUCT->m_Orient, STRUCT->m_Size.x, shape, CONV_TO_UTF8(STRUCT->m_Text)) == EOF) Failed = TRUE; break; case DRAW_GLOBAL_LABEL_STRUCT_TYPE: /* Its a Global label item. */ #undef STRUCT #define STRUCT ((DrawGlobalLabelStruct *) Phead) shape = STRUCT->m_Shape; if (fprintf(f, "Text GLabel %-4d %-4d %-4d %-4d %s\n%s\n", STRUCT->m_Pos.x, STRUCT->m_Pos.y, STRUCT->m_Orient, STRUCT->m_Size.x, SheetLabelType[shape], CONV_TO_UTF8(STRUCT->m_Text)) == EOF) Failed = TRUE; break; case DRAW_HIER_LABEL_STRUCT_TYPE: /* Its a Hierarchical label item. */ #undef STRUCT #define STRUCT ((DrawHierLabelStruct *) Phead) shape = STRUCT->m_Shape; if (fprintf(f, "Text HLabel %-4d %-4d %-4d %-4d %s\n%s\n", STRUCT->m_Pos.x, STRUCT->m_Pos.y, STRUCT->m_Orient, STRUCT->m_Size.x, SheetLabelType[shape], CONV_TO_UTF8(STRUCT->m_Text)) == EOF) Failed = TRUE; break; case DRAW_MARKER_STRUCT_TYPE: /* Its a marker item. */ #undef STRUCT #define STRUCT ((DrawMarkerStruct *) Phead) if( STRUCT->GetComment() ) msg = STRUCT->GetComment(); else msg.Empty(); if (fprintf(f, "Kmarq %c %-4d %-4d \"%s\" F=%X\n", (int) STRUCT->m_Type + 'A', STRUCT->m_Pos.x, STRUCT->m_Pos.y, CONV_TO_UTF8(msg), STRUCT->m_MarkFlags) == EOF) { Failed = TRUE; } break; case DRAW_SHEETLABEL_STRUCT_TYPE : case DRAW_PICK_ITEM_STRUCT_TYPE : break; default: break; } if (Failed) { DisplayError(this, _("File write operation failed.")); break; } Phead = Phead->Pnext; } if (fprintf(f, "$EndSCHEMATC\n") == EOF) Failed = TRUE; fclose(f); if (FileSave == FILE_SAVE_NEW) screen->m_FileName = Name; return !Failed; } /*******************************************************************/ static int SavePartDescr( FILE *f, EDA_SchComponentStruct * LibItemStruct) /*******************************************************************/ /* Routine utilisee dans la routine precedente. Assure la sauvegarde de la structure LibItemStruct */ { int ii, Failed = FALSE; char Name1[256], Name2[256]; int hjustify, vjustify; //this is redundant with the AR entries below, but it makes the //files backwards-compatible. if(LibItemStruct->m_References.GetCount() > 0) strncpy(Name1, CONV_TO_UTF8(LibItemStruct->m_References[0]), sizeof(Name1)); else{ if(LibItemStruct->m_Field[REFERENCE].m_Text.IsEmpty()) strncpy(Name1, CONV_TO_UTF8(LibItemStruct->m_PrefixString),sizeof(Name1)); else strncpy(Name1, CONV_TO_UTF8(LibItemStruct->m_Field[REFERENCE].m_Text),sizeof(Name1)); } for (ii = 0; ii < (int)strlen(Name1); ii++){ if (Name1[ii] <= ' ') Name1[ii] = '~'; } if ( ! LibItemStruct->m_ChipName.IsEmpty() ) { strncpy(Name2, CONV_TO_UTF8(LibItemStruct->m_ChipName),sizeof(Name2)); for (ii = 0; ii < (int)strlen(Name2); ii++) if (Name2[ii] <= ' ') Name2[ii] = '~'; } else strncpy(Name2, NULL_STRING,sizeof(Name2)); fprintf(f, "$Comp\n"); if(fprintf (f, "L %s %s\n", Name2, Name1) == EOF) { Failed = TRUE; return(Failed); } /* Generation de numero d'unit, convert et Time Stamp*/ if(fprintf(f, "U %d %d %8.8lX\n", LibItemStruct->m_Multi, LibItemStruct->m_Convert, LibItemStruct->m_TimeStamp) == EOF) { Failed = TRUE; return(Failed); } /* Sortie de la position */ if(fprintf(f, "P %d %d\n", LibItemStruct->m_Pos.x, LibItemStruct->m_Pos.y) == EOF) { Failed = TRUE; return(Failed); } unsigned int i; for(i=0; i< LibItemStruct->m_References.GetCount(); i++){ /*format: AR Path="/140/2" Ref="C99" where 140 is the uid of the contianing sheet and 2 is the timestamp of this component. (timestamps are actually 8 hex chars) Ref is the conventional component reference for this 'path' */ /*printf("AR Path=\"%s\" Ref=\"%s\" \n", CONV_TO_UTF8( LibItemStruct->m_Paths[i]), CONV_TO_UTF8( LibItemStruct->m_References[i] ) ); */ if( fprintf(f, "AR Path=\"%s\" Ref=\"%s\" \n", CONV_TO_UTF8( LibItemStruct->m_Paths[i]), CONV_TO_UTF8( LibItemStruct->m_References[i] ) ) == EOF ) { Failed = TRUE; break; } } for( ii = 0; ii < NUMBER_OF_FIELDS; ii++ ) { PartTextStruct * field = & LibItemStruct->m_Field[ii]; if( field->m_Text.IsEmpty() ) continue; hjustify = 'C'; if ( field->m_HJustify == GR_TEXT_HJUSTIFY_LEFT) hjustify = 'L'; else if ( field->m_HJustify == GR_TEXT_HJUSTIFY_RIGHT) hjustify = 'R'; vjustify = 'C'; if ( field->m_VJustify == GR_TEXT_VJUSTIFY_BOTTOM) vjustify = 'B'; else if ( field->m_VJustify == GR_TEXT_VJUSTIFY_TOP) vjustify = 'T'; if( fprintf(f,"F %d \"%s\" %c %-3d %-3d %-3d %4.4X %c %c", ii, CONV_TO_UTF8(field->m_Text), field->m_Orient == TEXT_ORIENT_HORIZ ? 'H' : 'V', field->m_Pos.x, field->m_Pos.y, field->m_Size.x, field->m_Attributs, hjustify, vjustify) == EOF) { Failed = TRUE; break; } // Save field name, if necessary if ( ii >= FIELD1 && ! field->m_Name.IsEmpty() ) { wxString fieldname = ReturnDefaultFieldName(ii); if ( fieldname != field->m_Name ) if( fprintf(f," \"%s\"", CONV_TO_UTF8(field->m_Name) ) == EOF) { Failed = TRUE; break; } } if( fprintf(f,"\n") == EOF) { Failed = TRUE; break; } } if (Failed) return(Failed); /* Generation du num unit, position, box ( ancienne norme )*/ if(fprintf(f, "\t%-4d %-4d %-4d\n", LibItemStruct->m_Multi, LibItemStruct->m_Pos.x, LibItemStruct->m_Pos.y) == EOF) { Failed = TRUE; return(Failed); } if( fprintf(f, "\t%-4d %-4d %-4d %-4d\n", LibItemStruct->m_Transform[0][0], LibItemStruct->m_Transform[0][1], LibItemStruct->m_Transform[1][0], LibItemStruct->m_Transform[1][1]) == EOF) { Failed = TRUE; return(Failed); } fprintf(f, "$EndComp\n"); return(Failed); } /*******************************************************************/ static int SaveSheetDescr( FILE *f, DrawSheetStruct * SheetStruct) /*******************************************************************/ /* Routine utilisee dans la routine precedente. Assure la sauvegarde de la structure LibItemStruct */ { int ii; int Failed = FALSE; DrawSheetLabelStruct * SheetLabel; fprintf(f, "$Sheet\n"); if (fprintf(f, "S %-4d %-4d %-4d %-4d\n", SheetStruct->m_Pos.x,SheetStruct->m_Pos.y, SheetStruct->m_Size.x,SheetStruct->m_Size.y) == EOF){ Failed = TRUE; return(Failed); } //save the unique timestamp, like other shematic parts. if( fprintf(f, "U %8.8lX\n", SheetStruct->m_TimeStamp) == EOF ){ Failed = TRUE; return(Failed); } /* Generation de la liste des 2 textes (sheetname et filename) */ if ( ! SheetStruct->m_SheetName.IsEmpty()) { if(fprintf(f,"F0 \"%s\" %d\n", CONV_TO_UTF8(SheetStruct->m_SheetName), SheetStruct->m_SheetNameSize) == EOF) { Failed = TRUE; return(Failed); } } if( ! SheetStruct->GetFileName().IsEmpty()) { if(fprintf(f,"F1 \"%s\" %d\n", CONV_TO_UTF8(SheetStruct->GetFileName()), SheetStruct->m_FileNameSize) == EOF) { Failed = TRUE; return(Failed); } } /* Generation de la liste des labels (entrees) de la sous feuille */ ii = 2; SheetLabel = SheetStruct->m_Label; while( SheetLabel != NULL ) { int type = 'U', side = 'L'; if( SheetLabel->m_Text.IsEmpty() ) continue; if( SheetLabel->m_Edge ) side = 'R'; switch(SheetLabel->m_Shape) { case NET_INPUT: type = 'I'; break; case NET_OUTPUT: type = 'O'; break; case NET_BIDI: type = 'B'; break; case NET_TRISTATE: type = 'T'; break; case NET_UNSPECIFIED: type = 'U'; break; } if(fprintf(f,"F%d \"%s\" %c %c %-3d %-3d %-3d\n", ii, CONV_TO_UTF8(SheetLabel->m_Text), type, side, SheetLabel->m_Pos.x, SheetLabel->m_Pos.y, SheetLabel->m_Size.x) == EOF) { Failed = TRUE; break; } ii++; SheetLabel = (DrawSheetLabelStruct*)SheetLabel->Pnext; } fprintf(f, "$EndSheet\n"); return(Failed); } /****************************/ static void SaveLayers(FILE *f) /****************************/ /* Save a Layer Structure to a file theses infos are not used in eeschema */ { fprintf(f,"EELAYER %2d %2d\n", g_LayerDescr.NumberOfLayers,g_LayerDescr.CurrentLayer); fprintf(f,"EELAYER END\n"); }