files.cpp 10.6 KB
Newer Older
1 2 3
/***************************************/
/* files.cpp: read / write board files */
/***************************************/
4 5 6

#include "fctsys.h"
#include "common.h"
7 8 9 10
#include "class_drawpanel.h"
#include "confirm.h"
#include "kicad_string.h"
#include "gestfich.h"
11
#include "pcbnew.h"
charras's avatar
charras committed
12
#include "wxPcbStruct.h"
13
#include "protos.h"
14
#include "pcbnew_id.h"
15 16


17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
void WinEDA_PcbFrame::OnFileHistory( wxCommandEvent& event )
{
    wxString fn;
    wxClientDC dc( DrawPanel );

    fn = GetFileFromHistory( event.GetId(), _( "Printed circuit board" ) );

    if( fn != wxEmptyString )
    {
        if( DrawPanel->ManageCurseur && DrawPanel->ForceCloseManageCurseur )
        {
            DrawPanel->PrepareGraphicContext( &dc );
            DrawPanel->ForceCloseManageCurseur( DrawPanel, &dc );
        }

        SetToolID( 0, wxCURSOR_ARROW, wxEmptyString );
        ::wxSetWorkingDirectory( ::wxPathOnly( fn ) );
        LoadOnePcbFile( fn, false );
        ReCreateAuxiliaryToolbar();
        DrawPanel->MouseToCursorSchema();
        DrawPanel->CursorOn( &dc );
    }
}

41
/****************************************************/
42
void WinEDA_PcbFrame::Files_io( wxCommandEvent& event )
43
/****************************************************/
44

45
/* Handle the read/write file commands
46
 */
47
{
48 49 50 51
    int        id = event.GetId();
    wxString   msg;


52
    // If an edition is in progress, stop it
53 54
    if( DrawPanel->ManageCurseur && DrawPanel->ForceCloseManageCurseur )
    {
55 56
        wxClientDC dc( DrawPanel );
        DrawPanel->PrepareGraphicContext( &dc );
57 58 59 60 61 62 63
        DrawPanel->ForceCloseManageCurseur( DrawPanel, &dc );
    }
    SetToolID( 0, wxCURSOR_ARROW, wxEmptyString );

    switch( id )
    {
    case ID_LOAD_FILE:
dickelbeck's avatar
dickelbeck committed
64
        LoadOnePcbFile( wxEmptyString, false );
65 66 67 68 69
        ReCreateAuxiliaryToolbar();
        break;

    case ID_MENU_READ_LAST_SAVED_VERSION_BOARD:
    case ID_MENU_RECOVER_BOARD:
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
    {
        wxFileName fn;

        if( id == ID_MENU_RECOVER_BOARD )
        {
            fn = wxFileName( wxEmptyString, g_SaveFileName, PcbExtBuffer );
        }
        else
        {
            fn = GetScreen()->m_FileName;
            fn.SetExt( wxT( "000" ) );
        }

        if( !fn.FileExists() )
        {
            msg = _( "Recovery file " ) + fn.GetFullPath() + _( " not found" );
86
            DisplayInfoMessage( this, msg );
87 88 89
            break;
        }
        else
90
        {
91 92
            msg = _( "Ok to load Recovery file " ) + fn.GetFullPath();
            if( !IsOK( this, msg ) )
93 94
                break;
        }
95 96 97 98 99 100

        LoadOnePcbFile( fn.GetFullPath(), false );
        fn.SetExt( PcbExtBuffer );
        GetScreen()->m_FileName = fn.GetFullPath();
        SetTitle( GetScreen()->m_FileName );
        ReCreateAuxiliaryToolbar();
101
        break;
102
    }
103 104

    case ID_APPEND_FILE:
105
        LoadOnePcbFile( wxEmptyString, true );
106 107 108
        break;

    case ID_NEW_BOARD:
109
        Clear_Pcb( true );
110
        GetScreen()->m_FileName.Printf( wxT( "%s%cnoname%s" ),
111 112
                                        GetChars( wxGetCwd() ), DIR_SEP,
                                        GetChars( PcbExtBuffer ) );
113
        SetTitle( GetScreen()->m_FileName );
dickelbeck's avatar
dickelbeck committed
114
        ReCreateLayerBox( NULL );
115 116 117 118 119 120
        break;

    case ID_SAVE_BOARD:
        SavePcbFile( GetScreen()->m_FileName );
        break;

121
    case ID_SAVE_BOARD_AS:
122 123 124 125 126 127
        SavePcbFile( wxEmptyString );
        break;

    default:
        DisplayError( this, wxT( "File_io Internal Error" ) ); break;
    }
128 129 130
}


131 132 133 134
/**
 *  Read a board file
 *  @param FullFileName = file name. If empty, a file name will be asked
 *  @return 0 if fails or abort, 1 if OK
135
 */
136
bool WinEDA_PcbFrame::LoadOnePcbFile( const wxString& FullFileName, bool Append )
137
{
138 139 140
    int      ii;
    FILE*    source;
    wxString msg;
141
    char     cbuf[1024];
142 143 144

    ActiveScreen = GetScreen();

145
    if( GetScreen()->IsModify() && !Append )
146 147
    {
        if( !IsOK( this, _( "Board Modified: Continue ?" ) ) )
148
            return false;
149 150
    }

151
    m_TrackAndViasSizesList_Changed = true;
152 153 154 155 156

    if( Append )
    {
        GetScreen()->m_FileName = wxEmptyString;
        GetScreen()->SetModify();
157
        GetBoard()->m_Status_Pcb = 0;
158 159
    }

dickelbeck's avatar
dickelbeck committed
160 161
    wxString fileName;

162 163
    if( FullFileName == wxEmptyString )
    {
164 165 166 167 168 169 170 171 172 173
        wxFileName fn = GetScreen()->m_FileName;

        wxFileDialog dlg( this, _( "Open Board File" ), wxEmptyString,
                          fn.GetFullName(), PcbFileWildcard,
                          wxFD_OPEN | wxFD_FILE_MUST_EXIST );

        if( dlg.ShowModal() == wxID_CANCEL )
            return false;

        fileName = dlg.GetPath();
174 175
    }
    else
dickelbeck's avatar
dickelbeck committed
176 177 178 179 180 181
        fileName = FullFileName;

    if( !Append )
        Clear_Pcb( false );     // pass false since we prompted above for a modified board

    GetScreen()->m_FileName = fileName;
182

183
    /* Start read PCB file
dickelbeck's avatar
dickelbeck committed
184
    */
185 186 187 188

    source = wxFopen( GetScreen()->m_FileName, wxT( "rt" ) );
    if( source == NULL )
    {
189
        msg.Printf( _( "File <%s> not found" ),
190
                    GetChars( GetScreen()->m_FileName ) );
191
        DisplayError( this, msg );
192
        return false;
193 194 195
    }


196
    /* Read header and TEST if it is a PCB file format */
197 198 199 200 201
    GetLine( source, cbuf, &ii );
    if( strncmp( cbuf, "PCBNEW-BOARD", 12 ) != 0 )
    {
        fclose( source );
        DisplayError( this, wxT( "Unknown file type" ) );
202
        return false;
203 204
    }

205 206 207 208
    int ver;
    sscanf(cbuf, "PCBNEW-BOARD Version %d date", &ver );
    if ( ver > g_CurrentVersionPCB )
    {
209 210
        DisplayInfoMessage( this, _( "This file was created by a more recent \
version of PCBnew and may not load correctly. Please consider updating!"));
211 212 213
    }
    else if ( ver < g_CurrentVersionPCB )
    {
214 215 216
        DisplayInfoMessage( this, _( "This file was created by an older \
version of PCBnew. It will be stored in the new file format when you save \
this file again."));
217 218
    }

219
    // Reload the corresponding configuration file:
220 221
    wxSetWorkingDirectory( wxPathOnly( GetScreen()->m_FileName ) );
    if( Append )
charras's avatar
charras committed
222
        ReadPcbFile( source, true );
223 224 225 226
    else
    {
        Read_Config( GetScreen()->m_FileName );

227
        // Update the option toolbar
228 229 230 231
        m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill;
        m_DisplayModText = DisplayOpt.DisplayModText;
        m_DisplayModEdge = DisplayOpt.DisplayModEdge;
        m_DisplayPadFill = DisplayOpt.DisplayPadFill;
dickelbeck's avatar
dickelbeck committed
232
        m_DisplayViaFill = DisplayOpt.DisplayViaFill;
233

charras's avatar
charras committed
234
        ReadPcbFile( source, false );
235 236 237 238 239 240
    }

    fclose( source );

    GetScreen()->ClrModify();

241
    /* If append option: change the initial board name to <oldname>-append.brd */
242 243
    if( Append )
    {
244 245 246 247 248 249
        wxString new_filename = GetScreen()->m_FileName.BeforeLast('.');
        if ( ! new_filename.EndsWith(wxT("-append")) )
            new_filename += wxT("-append");

        new_filename += PcbExtBuffer;

250
        GetScreen()->SetModify();
251
        GetScreen()->m_FileName = new_filename;
252 253
    }

254 255 256 257 258
    GetScreen()->m_FileName.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );

    SetTitle( GetScreen()->m_FileName );
    SetLastProject( GetScreen()->m_FileName );

259
    /* Rebuild the new pad list (for drc and ratsnet control ...) */
260
    GetBoard()->m_Status_Pcb = 0;
261

charras's avatar
charras committed
262
    // Display the loaded board:
263
    DrawPanel->Refresh( true);
charras's avatar
charras committed
264
    wxSafeYield();      // Needed if we want to see the board now.
charras's avatar
charras committed
265

charras's avatar
charras committed
266
    // Compile rastnest and displays net info
267
    Compile_Ratsnest( NULL, true );
268
    GetBoard()->DisplayInfo( this );
269

dickelbeck's avatar
dickelbeck committed
270
    /* reset the auto save timer */
271 272
    g_SaveTime = time( NULL );

charras's avatar
charras committed
273 274 275

#if 0 && defined(DEBUG)
    // note this freezes up pcbnew when run under the kicad project
dickelbeck's avatar
dickelbeck committed
276 277
    // manager.  runs fine from command prompt.  This is because the kicad
    // project manager redirects stdout of the child pcbnew process to itself,
charras's avatar
charras committed
278
    // but never reads from that pipe, and that in turn eventually blocks
dickelbeck's avatar
dickelbeck committed
279
    // the pcbnew program when the pipe it is writing to gets full.
charras's avatar
charras committed
280

dickelbeck's avatar
dickelbeck committed
281
    // Output the board object tree to stdout, but please run from command prompt:
282
    GetBoard()->Show( 0, std::cout );
283
#endif
charras's avatar
charras committed
284

285
    return true;
286 287 288 289
}


/***********************************************************/
290
bool WinEDA_PcbFrame::SavePcbFile( const wxString& FileName )
291
/************************************************************/
292

293
/* Write the board file
294
 */
295
{
296 297
    wxFileName  backupFileName;
    wxFileName  pcbFileName;
dickelbeck's avatar
dickelbeck committed
298 299 300
    wxString    upperTxt;
    wxString    lowerTxt;
    wxString    msg;
charras's avatar
charras committed
301

302
    bool        saveok = true;
dickelbeck's avatar
dickelbeck committed
303
    FILE*       dest;
304 305 306

    if( FileName == wxEmptyString )
    {
307 308 309
        wxFileDialog dlg( this, _( "Save Board File" ), wxEmptyString,
                          GetScreen()->m_FileName, BoardFileWildcard,
                          wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
charras's avatar
charras committed
310

311 312
        if( dlg.ShowModal() == wxID_CANCEL )
            return false;
charras's avatar
charras committed
313

314
        GetScreen()->m_FileName = dlg.GetPath();
315 316 317 318
    }
    else
        GetScreen()->m_FileName = FileName;

319
    /* If changes are made, update the board date */
320 321 322 323 324
    if( GetScreen()->IsModify() )
    {
        GetScreen()->m_Date = GenDate();
    }

325
    pcbFileName = GetScreen()->m_FileName;
326

327
    /* Get the backup file name */
328 329
    backupFileName = pcbFileName;
    backupFileName.SetExt( wxT( "000" ) );
330

331
    /* If an old backup file exists, delete it.
dickelbeck's avatar
dickelbeck committed
332 333
    if an old board file existes, rename it to the backup file name
    */
334
    if( backupFileName.FileExists() )
335
    {
336
        /* rename the "old" file" from xxx.brd to xxx.000 */
337 338 339
        wxRemoveFile( backupFileName.GetFullPath() ); /* Remove the old file xxx.000 (if exists) */
        if( !wxRenameFile( pcbFileName.GetFullPath(),
                           backupFileName.GetFullPath() ) )
340
        {
341 342
            msg = _( "Warning: unable to create backup file " ) +
                backupFileName.GetFullPath();
343
            DisplayError( this, msg, 15 );
344
            saveok = false;
345 346 347 348
        }
    }
    else
    {
349
        backupFileName.Clear();
350
        saveok = false;
351 352
    }

353
    /* Create the file */
354 355
    dest = wxFopen( pcbFileName.GetFullPath(), wxT( "wt" ) );

356 357
    if( dest == 0 )
    {
358
        msg = _( "Unable to create " ) + pcbFileName.GetFullPath();
359
        DisplayError( this, msg );
360
        saveok = false;
361 362 363 364
    }

    if( dest )
    {
365
        GetScreen()->m_FileName = pcbFileName.GetFullPath();
366
        SetTitle( GetScreen()->m_FileName );
charras's avatar
charras committed
367

368 369 370 371
        SavePcbFormatAscii( dest );
        fclose( dest );
    }

372
    /* Display the file names: */
373 374 375 376
    MsgPanel->EraseMsgBox();

    if( saveok )
    {
377
        upperTxt = _( "Backup file: " ) + backupFileName.GetFullPath();
378 379 380
    }

    if( dest )
dickelbeck's avatar
dickelbeck committed
381
        lowerTxt = _( "Wrote board file: " );
382
    else
dickelbeck's avatar
dickelbeck committed
383
        lowerTxt = _( "Failed to create " );
384
    lowerTxt += pcbFileName.GetFullPath();
385

dickelbeck's avatar
dickelbeck committed
386
    Affiche_1_Parametre( this, 1, upperTxt, lowerTxt, CYAN );
charras's avatar
charras committed
387

388
    g_SaveTime = time( NULL );    /* Reset timer for the automatic saving */
charras's avatar
charras committed
389

390
    GetScreen()->ClrModify();
391
    return true;
392
}