load_one_schematic_file.cpp 13.4 KB
Newer Older
1
/****************************************/
2
/*  Module to load/save EESchema files. */
3
/****************************************/
4 5

#include "fctsys.h"
6 7
#include "confirm.h"
#include "kicad_string.h"
8

9 10 11
#include "program.h"
#include "general.h"
#include "protos.h"
12
#include "class_marker_sch.h"
13

14

15 16
/* in read_from_file_schematic_items_description.cpp */
SCH_ITEM* ReadTextDescr( FILE* aFile, wxString& aMsgDiag, char* aLine,
17 18 19 20 21 22 23
                         int aBufsize, int* aLineNum,
                         int aSchematicFileVersion );

extern int ReadSheetDescr( wxWindow* frame, char* Line, FILE* f,
                           wxString& aMsgDiag, int* aLineNum,
                           BASE_SCREEN* Window );

24 25 26
extern bool ReadSchemaDescr( wxWindow* frame, char* Line, FILE* f,
                             wxString& aMsgDiag, int* aLineNum,
                             BASE_SCREEN* Window );
27 28 29

extern int ReadPartDescr( wxWindow* frame, char* Line, FILE* f,
                          wxString& aMsgDiag, int* aLineNum,
30
                          BASE_SCREEN* Window );
31

32
static void LoadLayers( FILE* f, int* linecnt );
33

34

35 36
/**
 * Routine to load an EESchema file.
37
 *  Returns true if file has been loaded (at least partially.)
38
 */
39 40
bool WinEDA_SchematicFrame::LoadOneEEFile( SCH_SCREEN* screen,
                                           const wxString& FullFileName )
41
{
42 43 44 45 46 47 48 49 50 51 52 53 54 55
    char            Line[1024], * SLine;
    char            Name1[256],
                    Name2[256];
    int             ii, layer;
    wxPoint         pos;
    bool            Failed = FALSE;
    SCH_ITEM*       Phead, * Pnext;
    SCH_JUNCTION*   ConnectionStruct;
    SCH_POLYLINE*   PolylineStruct;
    SCH_LINE*       SegmentStruct;
    SCH_BUS_ENTRY*  RaccordStruct;
    SCH_NO_CONNECT* NoConnectStruct;
    int             LineCount;
    wxString        MsgDiag;   /* Error and log messages */
56 57 58 59 60 61 62 63 64

    FILE*                f;

    if( screen == NULL )
        return FALSE;
    if( FullFileName.IsEmpty() )
        return FALSE;

    screen->SetCurItem( NULL );
65
    screen->m_FileName = FullFileName;
66 67 68 69 70 71 72 73 74

    LineCount = 1;
    if( ( f = wxFopen( FullFileName, wxT( "rt" ) ) ) == NULL )
    {
        MsgDiag = _( "Failed to open " ) + FullFileName;
        DisplayError( this, MsgDiag );
        return FALSE;
    }

75
    MsgDiag = _( "Loading " ) + screen->m_FileName;
76 77
    PrintMsg( MsgDiag );

dickelbeck's avatar
dickelbeck committed
78
    if( fgets( Line, sizeof(Line), f ) == NULL
79 80
        || strncmp( Line + 9, SCHEMATIC_HEAD_STRING,
                    sizeof(SCHEMATIC_HEAD_STRING) - 1 ) != 0 )
81
    {
82
        MsgDiag = FullFileName + _( " is NOT an EESchema file!" );
83 84 85 86
        DisplayError( this, MsgDiag );
        fclose( f );
        return FALSE;
    }
87

88
    //get the file version here. TODO: Support version numbers > 9
89
    char version = Line[9 + sizeof(SCHEMATIC_HEAD_STRING)];
90
    int  ver     = version - '0';
91
    if( ver > EESCHEMA_VERSION )
92
    {
93 94
        MsgDiag = FullFileName + _( " was created by a more recent \
version of EESchema and may not load correctly. Please consider updating!" );
95
        DisplayInfoMessage( this, MsgDiag );
96
    }
97

charras's avatar
charras committed
98
#if 0
99
    // Compile it if the new version is unreadable by previous eeschema versions
100
    else if( ver < EESCHEMA_VERSION )
101
    {
102 103 104 105
        MsgDiag = FullFileName + _( " was created by an older version of \
EESchema. It will be stored in the new file format when you save this file \
again." );

106
        DisplayInfoMessage( this, MsgDiag );
107
    }
charras's avatar
charras committed
108
#endif
109

110
    LineCount++;
dickelbeck's avatar
dickelbeck committed
111
    if( fgets( Line, sizeof(Line), f ) == NULL || strncmp( Line, "LIBS:", 5 ) != 0 )
112
    {
113
        MsgDiag = FullFileName + _( " is NOT an EESchema file!" );
114 115 116 117 118
        DisplayError( this, MsgDiag );
        fclose( f );
        return FALSE;
    }

dickelbeck's avatar
dickelbeck committed
119
    // Read the rest of a potentially very long line.  fgets() puts a '\n' into
120 121
    // the buffer if the end of line was reached.  Read until end of line if
    // necessary.
dickelbeck's avatar
dickelbeck committed
122 123 124 125 126 127 128
    if( Line[ strlen( Line )-1 ] != '\n' )
    {
        int c;
        while( !feof( f ) && (c = fgetc( f )) != '\n' )
            ;
    }

129 130 131 132 133 134 135 136 137 138
    LoadLayers( f, &LineCount );

    while( !feof( f ) && GetLine( f, Line, &LineCount, sizeof(Line) ) != NULL )
    {
        SLine = Line;
        while( (*SLine != ' ' ) && *SLine )
            SLine++;

        switch( Line[0] )
        {
139
        case '$':           /* identification block */
140
            if( Line[1] == 'C' )
141 142
                Failed = ReadPartDescr( this, Line, f, MsgDiag, &LineCount,
                                        screen );
143

144
            else if( Line[1] == 'S' )
145 146
                Failed = ReadSheetDescr( this, Line, f, MsgDiag, &LineCount,
                                         screen );
147

148
            else if( Line[1] == 'D' )
149 150
                Failed = ReadSchemaDescr( this, Line, f, MsgDiag, &LineCount,
                                          screen );
151 152 153 154 155 156 157 158 159 160 161 162 163 164
        else if( Line[1] == 'T' ) //text part
        {
          printf("**** TEXT PART\n");
          SCH_ITEM* Struct;
          Struct = ReadTextDescr( f, MsgDiag, Line, sizeof(Line),
                      &LineCount, version);
          if( Struct )
          {
          Struct->SetNext( screen->EEDrawList );
          screen->EEDrawList = Struct;
          }
          else
          Failed = true;
        }
165

166 167
            break;

168
        case 'L':        /* Its a library item. */
169
            Failed = ReadPartDescr( this, Line, f, MsgDiag, &LineCount, screen );
170
            break;
171 172 173 174 175


        case 'W':        /* Its a Segment (WIRE or BUS) item. */
            if( sscanf( SLine, "%s %s", Name1, Name2 ) != 2  )
            {
176
                MsgDiag.Printf( wxT( "EESchema file segment error at line %d, aborted" ),
177
                                LineCount );
178 179
                MsgDiag << wxT( "\n" ) << CONV_FROM_UTF8( Line );
                Failed = true;
180 181 182 183 184 185 186 187
                break;
            }
            layer = LAYER_NOTES;
            if( Name1[0] == 'W' )
                layer = LAYER_WIRE;
            if( Name1[0] == 'B' )
                layer = LAYER_BUS;

188
            SegmentStruct = new SCH_LINE( wxPoint( 0, 0 ), layer );
189 190 191

            LineCount++;
            if( fgets( Line, 256 - 1, f ) == NULL
192 193 194
                || sscanf( Line, "%d %d %d %d ", &SegmentStruct->m_Start.x,
                           &SegmentStruct->m_Start.y, &SegmentStruct->m_End.x,
                           &SegmentStruct->m_End.y ) != 4 )
195
            {
196 197
                MsgDiag.Printf( wxT( "EESchema file Segment struct error at line %d, aborted" ),
                                LineCount );
198 199
                MsgDiag << wxT( "\n" ) << CONV_FROM_UTF8( Line );
                Failed = true;
200
                SAFE_DELETE( SegmentStruct );
201 202 203 204 205
                break;
            }

            if( !Failed )
            {
206
                SegmentStruct->SetNext( screen->EEDrawList );
207
                screen->EEDrawList = SegmentStruct;
208 209 210 211
            }
            break;


212
        case 'E':        /* Its a WIRE or BUS item. */
213 214
            if( sscanf( SLine, "%s %s", Name1, Name2 ) != 2  )
            {
215 216
                MsgDiag.Printf( wxT( "EESchema file record struct error at line %d, aborted" ),
                                LineCount );
217 218
                MsgDiag << wxT( "\n" ) << CONV_FROM_UTF8( Line );
                Failed = true;
219 220 221 222 223 224
                break;
            }

            ii = WIRE_TO_BUS;
            if( Name1[0] == 'B' )
                ii = BUS_TO_BUS;
225
            RaccordStruct = new SCH_BUS_ENTRY( wxPoint( 0, 0 ), '\\', ii );
226

227 228
            LineCount++;
            if( fgets( Line, 256 - 1, f ) == NULL
229 230 231
                || sscanf( Line, "%d %d %d %d ", &RaccordStruct->m_Pos.x,
                           &RaccordStruct->m_Pos.y, &RaccordStruct->m_Size.x,
                           &RaccordStruct->m_Size.y ) != 4 )
232
            {
233 234
                MsgDiag.Printf( wxT( "EESchema file Bus Entry struct error at line %d, aborted" ),
                                LineCount );
235 236
                MsgDiag << wxT( "\n" ) << CONV_FROM_UTF8( Line );
                Failed = true;
237
                SAFE_DELETE( RaccordStruct );
238 239 240 241 242 243 244
                break;
            }

            if( !Failed )
            {
                RaccordStruct->m_Size.x -= RaccordStruct->m_Pos.x;
                RaccordStruct->m_Size.y -= RaccordStruct->m_Pos.y;
245
                RaccordStruct->SetNext( screen->EEDrawList );
246
                screen->EEDrawList = RaccordStruct;
247 248 249 250 251 252
            }
            break;

        case 'P':        /* Its a polyline item. */
            if( sscanf( SLine, "%s %s %d", Name1, Name2, &ii ) != 3 )
            {
253 254
                MsgDiag.Printf( wxT( "EESchema file polyline struct error at line %d, aborted" ),
                                LineCount );
255 256
                MsgDiag << wxT( "\n" ) << CONV_FROM_UTF8( Line );
                Failed = true;
257 258 259 260 261 262 263 264
                break;
            }
            layer = LAYER_NOTES;
            if( Name2[0] == 'W' )
                layer = LAYER_WIRE;
            if( Name2[0] == 'B' )
                layer = LAYER_BUS;

265
            PolylineStruct = new SCH_POLYLINE( layer );
charras's avatar
charras committed
266
            for( unsigned jj = 0; jj < (unsigned)ii; jj++ )
267 268
            {
                LineCount++;
charras's avatar
charras committed
269
                wxPoint point;
270
                if( fgets( Line, 256 - 1, f ) == NULL
charras's avatar
charras committed
271
                    || sscanf( Line, "%d %d", &point.x, &point.y ) != 2 )
272
                {
273 274
                    MsgDiag.Printf( wxT( "EESchema file polyline struct error \
at line %d, aborted" ),
275
                                    LineCount );
276 277
                    MsgDiag << wxT( "\n" ) << CONV_FROM_UTF8( Line );
                    Failed = true;
278
                    SAFE_DELETE( PolylineStruct );
279 280
                    break;
                }
charras's avatar
charras committed
281 282

                PolylineStruct->AddPoint( point );
283 284 285 286
            }

            if( !Failed )
            {
287
                PolylineStruct->SetNext( screen->EEDrawList );
288
                screen->EEDrawList = PolylineStruct;
289 290 291
            }
            break;

292
        case 'C':                       /* It is a connection item. */
293
            ConnectionStruct = new SCH_JUNCTION( wxPoint( 0, 0 ) );
294

295 296
            if( sscanf( SLine, "%s %d %d", Name1, &ConnectionStruct->m_Pos.x,
                        &ConnectionStruct->m_Pos.y ) != 3 )
297
            {
298
                MsgDiag.Printf( wxT( "EESchema file connection struct error \
299 300
at line %d, aborted" ),
                                LineCount );
301 302
                MsgDiag << wxT( "\n" ) << CONV_FROM_UTF8( Line );
                Failed = true;
303
                SAFE_DELETE( ConnectionStruct );
304 305 306
            }
            else
            {
307
                ConnectionStruct->SetNext( screen->EEDrawList );
308 309 310 311
                screen->EEDrawList = ConnectionStruct;
            }
            break;

312
        case 'N':                       /* It is a NoConnect item. */
313 314
            if( sscanf( SLine, "%s %d %d", Name1, &pos.x, &pos.y ) != 3 )
            {
315 316
                MsgDiag.Printf( wxT( "EESchema file NoConnect struct error at line %d, aborted" ),
                                LineCount );
317 318
                MsgDiag << wxT( "\n" ) << CONV_FROM_UTF8( Line );
                Failed = true;
319 320 321
            }
            else
            {
322
                NoConnectStruct = new SCH_NO_CONNECT( pos );
323
                NoConnectStruct->SetNext( screen->EEDrawList );
324 325 326 327
                screen->EEDrawList = NoConnectStruct;
            }
            break;

328
        case 'K':                       /* It is a Marker item. */
329 330
            // Markers are no more read from file. they are only created on
            // demand in schematic
331 332
            break;

333
        case 'T':                       /* It is a text item. */
334
        {
335
            SCH_ITEM* Struct;
336 337
            Struct = ReadTextDescr( f, MsgDiag, Line, sizeof(Line),
                                    &LineCount, version);
338
            if( Struct )
339
            {
340 341
                Struct->SetNext( screen->EEDrawList );
                screen->EEDrawList = Struct;
342 343
            }
            else
344
                Failed = true;
345 346 347 348
            break;
        }

        default:
349
            Failed = true;
350 351
            MsgDiag.Printf( wxT( "EESchema file undefined object at line %d, aborted" ),
                            LineCount );
352
            MsgDiag << wxT( "\n" ) << CONV_FROM_UTF8( Line );
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
            break;
        }

        if( Failed )
        {
            DisplayError( this, MsgDiag );
            break;
        }
    }

    /* EEDrawList was constructed in reverse order - reverse it back: */
    Phead = NULL;
    while( screen->EEDrawList )
    {
        Pnext = screen->EEDrawList;
368
        screen->EEDrawList = screen->EEDrawList->Next();
369
        Pnext->SetNext( Phead );
370 371 372 373 374
        Phead = Pnext;
    }

    screen->EEDrawList = Phead;

375
#if 0 && defined (DEBUG)
376 377
    screen->Show( 0, std::cout );
#endif
378

379 380 381 382
    fclose( f );

    TestDanglingEnds( screen->EEDrawList, NULL );

383
    MsgDiag = _( "Done Loading " ) + screen->m_FileName;
384 385
    PrintMsg( MsgDiag );

386
    return true;    /* Although it may be that file is only partially loaded. */
387 388
}

389 390

static void LoadLayers( FILE* f, int* linecnt )
391
{
dickelbeck's avatar
dickelbeck committed
392
    int  Number;
393 394
    char Line[1024];

dickelbeck's avatar
dickelbeck committed
395
    //int Mode,Color,Layer;
396 397
    char Name[256];

dickelbeck's avatar
dickelbeck committed
398 399
    GetLine( f, Line, linecnt, sizeof(Line) );       /* read line */

400 401 402
    sscanf( Line, "%s %d %d", Name, &Number, &g_LayerDescr.CurrentLayer );
    if( strcmp( Name, "EELAYER" ) !=0 )
    {
403
        /* error : init par default */
404 405
        Number = MAX_LAYER;
    }
dickelbeck's avatar
dickelbeck committed
406

407 408 409 410 411 412 413
    if( Number <= 0 )
        Number = MAX_LAYER;
    if( Number > MAX_LAYER )
        Number = MAX_LAYER;

    g_LayerDescr.NumberOfLayers = Number;

dickelbeck's avatar
dickelbeck committed
414
    while( GetLine( f, Line, linecnt, sizeof(Line) ) )
415 416 417 418
    {
        if( strnicmp( Line, "EELAYER END", 11 ) == 0 )
            break;
    }
419
}