56
67
#include "netlist.h"
57
68
#include "parse_l.h"
59
71
#include "remove.h"
74
#ifdef HAVE_LIBDMALLOC
78
RCSID("$Id: file.c,v 1.20 2005/01/03 12:56:59 danmc Exp $");
62
80
#if !defined(HAS_ATEXIT) && !defined(HAS_ON_EXIT)
63
81
/* ---------------------------------------------------------------------------
64
82
* some local identifiers for OS without an atexit() or on_exit()
67
static char TMPFilename[80];
85
static char TMPFilename[80];
70
88
/* ---------------------------------------------------------------------------
71
89
* some local prototypes
73
static void PrintQuotedString(FILE *, char *);
74
static void WritePCBInfoHeader(FILE *);
75
static void WritePCBDataHeader(FILE *);
76
static void WritePCBFontData(FILE *);
77
static void WritePCBViaData(FILE *);
78
static void WritePCBRatData(FILE *);
79
static void WritePCBElementData(FILE *);
80
static void WritePCBLayerData(FILE *, Cardinal);
81
static int WritePCB(FILE *);
82
static int WritePCBFile(char *);
83
static int WritePCBPipe(char *);
91
static void PrintQuotedString (FILE *, char *);
92
static void WritePCBInfoHeader (FILE *);
93
static void WritePCBDataHeader (FILE *);
94
static void WritePCBFontData (FILE *);
95
static void WriteViaData (FILE *, DataTypePtr);
96
static void WritePCBRatData (FILE *);
97
static void WriteElementData (FILE *, DataTypePtr);
98
static void WriteLayerData (FILE *, Cardinal, LayerTypePtr);
99
static int WritePCB (FILE *);
100
static int WritePCBFile (char *);
101
static int WritePipe (char *, Boolean);
102
static void ParseLibraryTree (void);
85
104
/* ---------------------------------------------------------------------------
86
105
* opens a file and check if it exists
88
FILE *CheckAndOpenFile(char *Filename,
89
Boolean Confirm, Boolean AllButton, Boolean *WasAllButton)
108
CheckAndOpenFile (char *Filename,
109
Boolean Confirm, Boolean AllButton, Boolean * WasAllButton)
93
char message[MAXPATHLEN+80];
113
char message[MAXPATHLEN + 80];
95
if (Filename && *Filename)
115
if (Filename && *Filename)
117
if (!stat (Filename, &buffer) && Confirm)
97
if (!stat(Filename, &buffer) && Confirm)
99
sprintf(message, "file '%s' exists, use anyway?", Filename);
100
*WasAllButton = False;
101
switch(ConfirmReplaceFileDialog(message, AllButton))
103
case ALL_BUTTON: *WasAllButton = True; break;
104
case CANCEL_BUTTON: return(NULL);
107
if ((fp = fopen(Filename, "w")) == NULL)
108
OpenErrorMessage(Filename);
119
sprintf (message, "file '%s' exists, use anyway?", Filename);
120
*WasAllButton = False;
121
switch (ConfirmReplaceFileDialog (message, AllButton))
124
*WasAllButton = True;
130
if ((fp = fopen (Filename, "w")) == NULL)
131
OpenErrorMessage (Filename);
113
136
/* ---------------------------------------------------------------------------
114
137
* opens a file for saving connection data
116
FILE *OpenConnectionDataFile(void)
119
Boolean result; /* not used */
121
filename = GetUserInput("enter filename to save connection data:", "");
122
return(CheckAndOpenFile(filename, True, False, &result));
140
OpenConnectionDataFile (void)
143
Boolean result; /* not used */
145
filename = GetUserInput ("enter filename to save connection data:", "");
146
return (CheckAndOpenFile (filename, True, False, &result));
149
/* ---------------------------------------------------------------------------
150
* save elements in the current buffer
153
SaveBufferElements (char *Filename)
159
result = WritePipe (Filename, False);
125
165
/* ---------------------------------------------------------------------------
128
int SavePCB(char *Filename)
169
SavePCB (char *Filename)
133
if (!(retcode = WritePCBPipe(Filename)))
135
/* thanks to Nick Bailey for the bug-fix;
136
* first of all make a copy of the passed filename because
137
* it might be identical to 'PCB->Filename'
139
copy = MyStrdup(Filename, "SavePCB()");
140
SaveFree(PCB->Filename);
141
PCB->Filename = copy;
142
SetChangedFlag(False);
174
if (!(retcode = WritePipe (Filename, True)))
176
/* thanks to Nick Bailey for the bug-fix;
177
* first of all make a copy of the passed filename because
178
* it might be identical to 'PCB->Filename'
180
copy = MyStrdup (Filename, "SavePCB()");
181
SaveFree (PCB->Filename);
182
PCB->Filename = copy;
183
SetChangedFlag (False);
147
188
/* ---------------------------------------------------------------------------
149
190
* parse the file with enabled 'PCB mode' (see parser)
150
191
* if successful, update some other stuff
152
int LoadPCB(char *Filename)
194
LoadPCB (char *Filename)
154
PCBTypePtr newPCB = CreateNewPCB(False);
157
/* new data isn't added to the undo list */
158
if (!ParsePCB(newPCB, Filename))
196
PCBTypePtr newPCB = CreateNewPCB (False);
198
/* new data isn't added to the undo list */
199
if (!ParsePCB (newPCB, Filename))
203
InitNetlistWindow (Output.Toplevel);
204
ResetStackAndVisibility ();
205
/* set the zoom first before the Xorig, Yorig */
208
/* update cursor location */
209
Crosshair.X = MAX (0, MIN (PCB->CursorX, (LocationType) PCB->MaxWidth));
210
Crosshair.Y = MAX (0, MIN (PCB->CursorY, (LocationType) PCB->MaxHeight));
212
Xorig = Crosshair.X - TO_PCB (Output.Width / 2);
213
Yorig = Crosshair.Y - TO_PCB (Output.Height / 2);
214
RedrawZoom (Output.Width / 2, Output.Height / 2);
216
/* update cursor confinement and output area (scrollbars) */
217
ChangePCBSize (PCB->MaxWidth, PCB->MaxHeight);
219
/* create default font if necessary */
220
if (!PCB->Font.Valid)
162
InitNetlistWindow(Output.Toplevel);
163
ResetStackAndVisibility();
165
/* update cursor location */
166
Crosshair.X = MIN(PCB->CursorX, (Position) PCB->MaxWidth);
167
Crosshair.Y = MIN(PCB->CursorY, (Position) PCB->MaxHeight);
169
/* update zoom information. Presetting it to a not allowed
170
* value makes sure that the routine is forced to
171
* initialize some things
172
* SetZoom() also calls CenterDisplay()
175
PCB->Zoom = MAX_ZOOM+1;
178
/* update cursor confinement and output area (scrollbars) */
179
ChangePCBSize(PCB->MaxWidth, PCB->MaxHeight);
181
/* create default font if necessary */
182
if (!PCB->Font.Valid)
184
Message("file '%s' has no font information\n"
185
" default font will be used\n", Filename);
189
/* clear 'changed flag' */
190
SetChangedFlag(False);
191
PCB->Filename = MyStrdup(Filename, "LoadPCB()");
192
UpdateSettingsOnScreen();
222
Message ("file '%s' has no font information\n"
223
" default font will be used\n", Filename);
224
CreateDefaultFont ();
196
/* release unused memory */
227
/* clear 'changed flag' */
228
SetChangedFlag (False);
229
PCB->Filename = MyStrdup (Filename, "LoadPCB()");
230
/* just in case a bad file saved file is loaded */
231
UpdatePIPFlags (NULL, NULL, NULL, False);
232
UpdateSettingsOnScreen ();
236
/* release unused memory */
201
241
/* ---------------------------------------------------------------------------
202
242
* writes the quoted string created by another subroutine
204
static void PrintQuotedString(FILE *FP, char *S)
245
PrintQuotedString (FILE * FP, char *S)
206
static DynamicStringType ds;
247
static DynamicStringType ds;
208
CreateQuotedString(&ds, S);
249
CreateQuotedString (&ds, S);
212
253
/* ---------------------------------------------------------------------------
213
254
* writes layout header information
214
255
* date, UID and name of user
216
static void WritePCBInfoHeader(FILE *FP)
258
WritePCBInfoHeader (FILE * FP)
218
struct passwd *pwentry;
219
struct hostent *hostentry;
260
struct passwd *pwentry;
261
struct hostent *hostentry;
223
/* write some useful comments */
224
currenttime = time(NULL);
225
pwentry = getpwuid(getuid());
226
fprintf(FP, "# release: %s "RELEASE"\n", Progname);
227
fprintf(FP, "# date: %s", asctime(localtime(¤ttime)));
228
fprintf(FP, "# user: %s (%s)\n", pwentry->pw_name, pwentry->pw_gecos);
229
if (gethostname(hostname, 255) != -1)
231
hostentry = gethostbyname(hostname);
232
fprintf(FP, "# host: %s\n",hostentry ? hostentry->h_name : hostname);
265
/* write some useful comments */
266
currenttime = time (NULL);
267
pwentry = getpwuid (getuid ());
268
fprintf (FP, "# release: %s " VERSION "\n", Progname);
269
fprintf (FP, "# date: %s", asctime (localtime (¤ttime)));
270
fprintf (FP, "# user: %s (%s)\n", pwentry->pw_name, pwentry->pw_gecos);
271
if (gethostname (hostname, 255) != -1)
273
hostentry = gethostbyname (hostname);
274
fprintf (FP, "# host: %s\n",
275
hostentry ? hostentry->h_name : hostname);
236
279
/* ---------------------------------------------------------------------------
238
281
* the name of the PCB, cursor location, zoom and grid
239
282
* layergroups and some flags
241
static void WritePCBDataHeader(FILE *FP)
285
WritePCBDataHeader (FILE * FP)
247
PrintQuotedString(FP, EMPTY(PCB->Name));
248
fprintf(FP, " %i %i)\n\n",
249
(int) PCB->MaxWidth, (int) PCB->MaxHeight);
250
fprintf(FP, "Grid(%i %i %i %i)\n",
251
(int) PCB->Grid, (int) PCB->GridOffsetX, (int) PCB->GridOffsetY, (int) Settings.DrawGrid);
252
fprintf(FP, "Cursor(%i %i %i)\n",
253
(int) Crosshair.X, (int) Crosshair.Y, PCB->Zoom);
254
fprintf(FP, "Flags(0x%08x)\n", (int) PCB->Flags);
255
fputs("Groups(\"", FP);
256
for (group = 0; group < MAX_LAYER; group++)
257
if (PCB->LayerGroups.Number[group])
259
for (entry = 0; entry < PCB->LayerGroups.Number[group]; entry++)
261
switch(PCB->LayerGroups.Entries[group][entry])
263
case MAX_LAYER +COMPONENT_LAYER:
267
case MAX_LAYER +SOLDER_LAYER:
273
PCB->LayerGroups.Entries[group][entry]+1);
276
if (entry != PCB->LayerGroups.Number[group]-1)
279
if (group != MAX_LAYER-1)
282
fputs("\")\nStyles(\"", FP);
283
for (group = 0; group < NUM_STYLES - 1; group++)
284
fprintf(FP, "%s,%i,%i,%i:", PCB->RouteStyle[group].Name,
285
PCB->RouteStyle[group].Thick,
286
PCB->RouteStyle[group].Diameter,
287
PCB->RouteStyle[group].Hole);
288
fprintf(FP, "%s,%i,%i,%i\")\n\n", PCB->RouteStyle[group].Name,
289
PCB->RouteStyle[group].Thick,
290
PCB->RouteStyle[group].Diameter,
291
PCB->RouteStyle[group].Hole);
287
Cardinal group, entry;
289
fputs ("\nPCB[", FP);
290
PrintQuotedString (FP, EMPTY (PCB->Name));
291
fprintf (FP, " %i %i]\n\n", (int) PCB->MaxWidth, (int) PCB->MaxHeight);
292
fprintf (FP, "Grid[%2.8f %i %i %i]\n",
293
PCB->Grid, (int) PCB->GridOffsetX, (int) PCB->GridOffsetY,
294
(int) Settings.DrawGrid);
295
fprintf (FP, "Cursor[%i %i %f]\n", (int) TO_PCB_X (Output.Width / 2),
296
(int) TO_PCB_Y (Output.Height / 2), PCB->Zoom);
297
fprintf (FP, "Thermal[%f]\n", PCB->ThermScale);
298
fprintf (FP, "DRC[%i %i %i %i]\n", Settings.Bloat, Settings.Shrink,
299
Settings.minWid, Settings.minSlk);
300
fprintf (FP, "Flags(0x%016x)\n", (int) PCB->Flags);
301
fputs ("Groups(\"", FP);
302
for (group = 0; group < MAX_LAYER; group++)
303
if (PCB->LayerGroups.Number[group])
305
for (entry = 0; entry < PCB->LayerGroups.Number[group]; entry++)
307
switch (PCB->LayerGroups.Entries[group][entry])
309
case MAX_LAYER + COMPONENT_LAYER:
313
case MAX_LAYER + SOLDER_LAYER:
319
PCB->LayerGroups.Entries[group][entry] + 1);
322
if (entry != PCB->LayerGroups.Number[group] - 1)
325
if (group != MAX_LAYER - 1)
328
fputs ("\")\nStyles[\"", FP);
329
for (group = 0; group < NUM_STYLES - 1; group++)
330
fprintf (FP, "%s,%i,%i,%i,%i:", PCB->RouteStyle[group].Name,
331
PCB->RouteStyle[group].Thick,
332
PCB->RouteStyle[group].Diameter,
333
PCB->RouteStyle[group].Hole, PCB->RouteStyle[group].Keepaway);
334
fprintf (FP, "%s,%i,%i,%i,%i\"]\n\n", PCB->RouteStyle[group].Name,
335
PCB->RouteStyle[group].Thick,
336
PCB->RouteStyle[group].Diameter,
337
PCB->RouteStyle[group].Hole, PCB->RouteStyle[group].Keepaway);
294
340
/* ---------------------------------------------------------------------------
295
341
* writes font data of non empty symbols
297
static void WritePCBFontData(FILE *FP)
344
WritePCBFontData (FILE * FP)
303
for (font = &PCB->Font, i = 0; i <= MAX_FONTPOSITION; i++)
305
if (!font->Symbol[i].Valid)
309
fprintf(FP, "Symbol('%c' %i)\n(\n",
310
(char) i, (int) font->Symbol[i].Delta);
312
fprintf(FP, "Symbol(%i %i)\n(\n", i, (int) font->Symbol[i].Delta);
314
line = font->Symbol[i].Line;
315
for (j = font->Symbol[i].LineN; j; j --, line++)
316
fprintf(FP, "\tSymbolLine(%i %i %i %i %i)\n",
317
(int) line->Point1.X, (int) line->Point1.Y,
318
(int) line->Point2.X, (int) line->Point2.Y,
319
(int) line->Thickness);
350
for (font = &PCB->Font, i = 0; i <= MAX_FONTPOSITION; i++)
352
if (!font->Symbol[i].Valid)
356
fprintf (FP, "Symbol['%c' %i]\n(\n",
357
(char) i, (int) font->Symbol[i].Delta);
359
fprintf (FP, "Symbol[%i %i]\n(\n", i, (int) font->Symbol[i].Delta);
361
line = font->Symbol[i].Line;
362
for (j = font->Symbol[i].LineN; j; j--, line++)
363
fprintf (FP, "\tSymbolLine[%i %i %i %i %i]\n",
364
line->Point1.X, line->Point1.Y,
365
line->Point2.X, line->Point2.Y, line->Thickness);
324
370
/* ---------------------------------------------------------------------------
325
371
* writes via data
327
static void WritePCBViaData(FILE *FP)
374
WriteViaData (FILE * FP, DataTypePtr Data)
329
/* write information about vias */
331
fprintf(FP, "Via(%i %i %i %i %i ",
332
(int) via->X, (int) via->Y,
333
(int) via->Thickness, (int) via->Clearance,
334
(int) via->DrillingHole);
335
PrintQuotedString(FP, EMPTY(via->Name));
336
fprintf(FP, " 0x%08x)\n", (int) via->Flags);
377
/* write information about vias */
378
for (n = 0; n < Data->ViaN; n++)
380
PinTypePtr via = &Data->Via[n];
381
fprintf (FP, "Via[%i %i %i %i %i %i ",
383
via->Thickness, via->Clearance, via->Mask, via->DrillingHole);
384
PrintQuotedString (FP, EMPTY (via->Name));
385
fprintf (FP, " 0x%08x]\n", (int) via->Flags);
340
389
/* ---------------------------------------------------------------------------
341
390
* writes rat-line data
343
static void WritePCBRatData(FILE *FP)
393
WritePCBRatData (FILE * FP)
345
/* write information about rats */
347
fprintf(FP, "Rat(%i %i %i %i %i %i ",
348
(int) line->Point1.X, (int) line->Point1.Y,
349
(int) line->group1, (int) line->Point2.X,
350
(int) line->Point2.Y, (int) line->group2);
351
fprintf(FP, " 0x%08x)\n", (int) line->Flags);
396
/* write information about rats */
397
for (n = 0; n < PCB->Data->RatN; n++)
399
RatTypePtr line = &PCB->Data->Rat[n];
400
fprintf (FP, "Rat[%i %i %i %i %i %i ",
401
(int) line->Point1.X, (int) line->Point1.Y,
402
(int) line->group1, (int) line->Point2.X,
403
(int) line->Point2.Y, (int) line->group2);
404
fprintf (FP, " 0x%08x]\n", (int) line->Flags);
355
408
/* ---------------------------------------------------------------------------
356
409
* writes netlist data
358
static void WritePCBNetlistData(FILE *FP)
412
WritePCBNetlistData (FILE * FP)
360
/* write out the netlist if it exists */
361
if (PCB->NetlistLib.MenuN)
414
/* write out the netlist if it exists */
415
if (PCB->NetlistLib.MenuN)
418
fprintf (FP, "NetList()\n(\n");
420
for (n = 0; n < PCB->NetlistLib.MenuN; n++)
363
fprintf(FP,"NetList()\n(\n");
364
MENU_LOOP(&PCB->NetlistLib,
365
fprintf(FP,"\tNet(\"%s\" \"%s\")\n\t(\n", &menu->Name[2],
366
UNKNOWN(menu->Style));
368
fprintf(FP, "\t\tConnect(\"%s\")\n", entry->ListEntry);
422
LibraryMenuTypePtr menu = &PCB->NetlistLib.Menu[n];
423
fprintf (FP, "\tNet(\"%s\" \"%s\")\n\t(\n", &menu->Name[2],
424
UNKNOWN (menu->Style));
425
for (p = 0; p < menu->EntryN; p++)
427
LibraryEntryTypePtr entry = &menu->Entry[p];
428
fprintf (FP, "\t\tConnect(\"%s\")\n", entry->ListEntry);
430
fprintf (FP, "\t)\n");
376
436
/* ---------------------------------------------------------------------------
377
437
* writes element data
379
static void WritePCBElementData(FILE *FP)
440
WriteElementData (FILE * FP, DataTypePtr Data)
381
ELEMENT_LOOP(PCB->Data,
382
/* only non empty elements */
383
if (!element->LineN && !element->PinN &&
384
!element->ArcN && !element->PadN)
387
/* the coordinates and text-flags are the same for
388
* both names of an element
390
fprintf(FP, "\nElement(0x%08x ", (int) element->Flags);
391
PrintQuotedString(FP, EMPTY(DESCRIPTION_NAME(element)));
393
PrintQuotedString(FP, EMPTY(NAMEONPCB_NAME(element)));
395
PrintQuotedString(FP, EMPTY(VALUE_NAME(element)));
396
fprintf(FP, " %i %i %i %i %i %i 0x%08x)\n(\n",
397
(int) element->MarkX, (int) element->MarkY,
398
(int) (DESCRIPTION_TEXT(element).X - element->MarkX),
399
(int) (DESCRIPTION_TEXT(element).Y - element->MarkY),
400
(int) DESCRIPTION_TEXT(element).Direction,
401
(int) DESCRIPTION_TEXT(element).Scale,
402
(int) DESCRIPTION_TEXT(element).Flags);
405
fprintf(FP, "\tPin(%i %i %i %i %i %i ",
406
(int) (pin->X - element->MarkX),
407
(int) (pin->Y - element->MarkY),
408
(int) pin->Thickness, (int) pin->Clearance,
409
(int) pin->Mask, (int) pin->DrillingHole);
410
PrintQuotedString(FP, EMPTY(pin->Name));
412
PrintQuotedString(FP, EMPTY(pin->Number));
413
fprintf(FP, " 0x%08x)\n", (int) pin->Flags);
416
fprintf(FP, "\tPad(%i %i %i %i %i %i %i ",
417
(int) (pad->Point1.X - element->MarkX),
418
(int) (pad->Point1.Y - element->MarkY),
419
(int) (pad->Point2.X - element->MarkX),
420
(int) (pad->Point2.Y - element->MarkY),
421
(int) pad->Thickness, (int) pad->Clearance,
423
PrintQuotedString(FP, EMPTY(pad->Name));
425
PrintQuotedString(FP, EMPTY(pad->Number));
426
fprintf(FP, " 0x%08x)\n", (int) pad->Flags);
429
ELEMENTLINE_LOOP(element,
430
fprintf(FP, "\tElementLine (%i %i %i %i %i)\n",
431
(int) (line->Point1.X - element->MarkX),
432
(int) (line->Point1.Y - element->MarkY),
433
(int) (line->Point2.X - element->MarkX),
434
(int) (line->Point2.Y - element->MarkY),
435
(int) line->Thickness);
439
fprintf(FP, "\tElementArc (%i %i %i %i %i %i %i)\n",
440
(int) (arc->X - element->MarkX),
441
(int) (arc->Y - element->MarkY),
442
(int) arc->Width, (int) arc->Height,
443
(int) arc->StartAngle, (int) arc->Delta,
444
(int) arc->Thickness);
446
fprintf(FP, "\t)\n");
443
for (n = 0; n < Data->ElementN; n++)
445
ElementTypePtr element = &Data->Element[n];
446
/* only non empty elements */
447
if (!element->LineN && !element->PinN && !element->ArcN
450
/* the coordinates and text-flags are the same for
451
* both names of an element
453
fprintf (FP, "\nElement[0x%08x ", (int) element->Flags);
454
PrintQuotedString (FP, EMPTY (DESCRIPTION_NAME (element)));
456
PrintQuotedString (FP, EMPTY (NAMEONPCB_NAME (element)));
458
PrintQuotedString (FP, EMPTY (VALUE_NAME (element)));
459
fprintf (FP, " %i %i %i %i %i %i 0x%08x]\n(\n",
460
(int) element->MarkX, (int) element->MarkY,
461
(int) (DESCRIPTION_TEXT (element).X -
463
(int) (DESCRIPTION_TEXT (element).Y -
465
(int) DESCRIPTION_TEXT (element).Direction,
466
(int) DESCRIPTION_TEXT (element).Scale,
467
(int) DESCRIPTION_TEXT (element).Flags);
468
for (p = 0; p < element->PinN; p++)
470
PinTypePtr pin = &element->Pin[p];
471
fprintf (FP, "\tPin[%i %i %i %i %i %i ",
472
(int) (pin->X - element->MarkX),
473
(int) (pin->Y - element->MarkY),
474
(int) pin->Thickness, (int) pin->Clearance,
475
(int) pin->Mask, (int) pin->DrillingHole);
476
PrintQuotedString (FP, EMPTY (pin->Name));
478
PrintQuotedString (FP, EMPTY (pin->Number));
479
fprintf (FP, " 0x%08x]\n", (int) pin->Flags);
481
for (p = 0; p < element->PadN; p++)
483
PadTypePtr pad = &element->Pad[p];
484
fprintf (FP, "\tPad[%i %i %i %i %i %i %i ",
485
(int) (pad->Point1.X - element->MarkX),
486
(int) (pad->Point1.Y - element->MarkY),
487
(int) (pad->Point2.X - element->MarkX),
488
(int) (pad->Point2.Y - element->MarkY),
489
(int) pad->Thickness, (int) pad->Clearance,
491
PrintQuotedString (FP, EMPTY (pad->Name));
493
PrintQuotedString (FP, EMPTY (pad->Number));
494
fprintf (FP, " 0x%08x]\n", (int) pad->Flags);
496
for (p = 0; p < element->LineN; p++)
498
LineTypePtr line = &element->Line[p];
500
"\tElementLine [%i %i %i %i %i]\n",
501
(int) (line->Point1.X -
503
(int) (line->Point1.Y -
505
(int) (line->Point2.X -
507
(int) (line->Point2.Y -
508
element->MarkY), (int) line->Thickness);
510
for (p = 0; p < element->ArcN; p++)
512
ArcTypePtr arc = &element->Arc[p];
514
"\tElementArc [%i %i %i %i %i %i %i]\n",
515
(int) (arc->X - element->MarkX),
516
(int) (arc->Y - element->MarkY),
517
(int) arc->Width, (int) arc->Height,
518
(int) arc->StartAngle, (int) arc->Delta,
519
(int) arc->Thickness);
521
fputs ("\n\t)\n", FP);
450
525
/* ---------------------------------------------------------------------------
451
526
* writes layer data
453
static void WritePCBLayerData(FILE *FP, Cardinal Number)
455
LayerTypePtr layer = &PCB->Data->Layer[Number];
457
/* write information about non empty layers */
458
if (layer->LineN || layer->ArcN || layer->TextN || layer->PolygonN ||
459
(layer->Name && *layer->Name))
461
fprintf(FP, "Layer(%i ", (int) Number+1);
462
PrintQuotedString(FP, EMPTY(layer->Name));
466
fprintf(FP, "\tLine(%i %i %i %i %i %i 0x%08x)\n",
467
(int) line->Point1.X, (int) line->Point1.Y,
468
(int) line->Point2.X, (int) line->Point2.Y,
469
(int) line->Thickness, (int) line->Clearance,
473
fprintf(FP, "\tArc(%i %i %i %i %i %i %i %i 0x%08x)\n",
474
(int) arc->X, (int) arc->Y, (int) arc->Width,
475
(int) arc->Height, (int) arc->Thickness,
476
(int) arc->Clearance, (int) arc->StartAngle,
477
(int) arc->Delta, (int) arc->Flags);
480
fprintf(FP, "\tText(%i %i %i %i ",
481
(int) text->X, (int) text->Y,
482
(int) text->Direction, (int) text->Scale);
483
PrintQuotedString(FP, EMPTY(text->TextString));
484
fprintf(FP, " 0x%08x)\n", (int) text->Flags);
490
fprintf(FP, "\tPolygon(0x%08x)\n\t(", polygon->Flags);
491
POLYGONPOINT_LOOP(polygon,
495
fprintf(FP, "(%i %i) ",
496
(int) point->X, (int) point->Y);
499
fputs("\n\t)\n", FP);
507
/* ---------------------------------------------------------------------------
510
static int WritePCB(FILE *FP)
514
WritePCBInfoHeader(FP);
515
WritePCBDataHeader(FP);
516
WritePCBFontData(FP);
518
WritePCBElementData(FP);
520
for (i = 0; i < MAX_LAYER + 2; i++)
521
WritePCBLayerData(FP, i);
522
WritePCBNetlistData(FP);
527
/* ---------------------------------------------------------------------------
530
static int WritePCBFile(char *Filename)
535
if ((fp = fopen(Filename, "w")) == NULL)
537
OpenErrorMessage(Filename);
538
return(STATUS_ERROR);
540
result = WritePCB(fp);
545
/* ---------------------------------------------------------------------------
546
* writes PCB to pipe using the command defined by Settings.SaveCommand
529
WriteLayerData (FILE * FP, Cardinal Number, LayerTypePtr layer)
532
/* write information about non empty layers */
533
if (layer->LineN || layer->ArcN || layer->TextN || layer->PolygonN ||
534
(layer->Name && *layer->Name))
536
fprintf (FP, "Layer(%i ", (int) Number + 1);
537
PrintQuotedString (FP, EMPTY (layer->Name));
538
fputs (")\n(\n", FP);
540
for (n = 0; n < layer->LineN; n++)
542
LineTypePtr line = &layer->Line[n];
543
fprintf (FP, "\tLine[%i %i %i %i %i %i 0x%08x]\n",
544
(int) line->Point1.X, (int) line->Point1.Y,
545
(int) line->Point2.X, (int) line->Point2.Y,
546
(int) line->Thickness, (int) line->Clearance,
549
for (n = 0; n < layer->ArcN; n++)
551
ArcTypePtr arc = &layer->Arc[n];
552
fprintf (FP, "\tArc[%i %i %i %i %i %i %i %i 0x%08x]\n",
553
(int) arc->X, (int) arc->Y, (int) arc->Width,
554
(int) arc->Height, (int) arc->Thickness,
555
(int) arc->Clearance, (int) arc->StartAngle,
556
(int) arc->Delta, (int) arc->Flags);
558
for (n = 0; n < layer->TextN; n++)
560
TextTypePtr text = &layer->Text[n];
561
fprintf (FP, "\tText[%i %i %i %i ",
562
(int) text->X, (int) text->Y,
563
(int) text->Direction, (int) text->Scale);
564
PrintQuotedString (FP, EMPTY (text->TextString));
565
fprintf (FP, " 0x%08x]\n", (int) text->Flags);
567
for (n = 0; n < layer->PolygonN; n++)
569
PolygonTypePtr polygon = &layer->Polygon[n];
571
fprintf (FP, "\tPolygon(0x%08x)\n\t(", (int) polygon->Flags);
572
for (p = 0; p < polygon->PointN; p++)
574
PointTypePtr point = &polygon->Points[p];
576
fputs ("\n\t\t", FP);
577
fprintf (FP, "[%i %i] ", (int) point->X, (int) point->Y);
579
fputs ("\n\t)\n", FP);
585
/* ---------------------------------------------------------------------------
586
* writes just the elements in the buffer to file
589
WriteBuffer (FILE * FP)
593
WriteViaData (FP, PASTEBUFFER->Data);
594
WriteElementData (FP, PASTEBUFFER->Data);
595
for (i = 0; i < MAX_LAYER + 2; i++)
596
WriteLayerData (FP, i, &(PASTEBUFFER->Data->Layer[i]));
600
/* ---------------------------------------------------------------------------
608
WritePCBInfoHeader (FP);
609
WritePCBDataHeader (FP);
610
WritePCBFontData (FP);
611
WriteViaData (FP, PCB->Data);
612
WriteElementData (FP, PCB->Data);
613
WritePCBRatData (FP);
614
for (i = 0; i < MAX_LAYER + 2; i++)
615
WriteLayerData (FP, i, &(PCB->Data->Layer[i]));
616
WritePCBNetlistData (FP);
621
/* ---------------------------------------------------------------------------
625
WritePCBFile (char *Filename)
630
if ((fp = fopen (Filename, "w")) == NULL)
632
OpenErrorMessage (Filename);
633
return (STATUS_ERROR);
635
result = WritePCB (fp);
640
/* ---------------------------------------------------------------------------
641
* writes to pipe using the command defined by Settings.SaveCommand
547
642
* %f are replaced by the passed filename
549
static int WritePCBPipe(char *Filename)
645
WritePipe (char *Filename, Boolean thePcb)
554
static DynamicStringType command;
556
/* setup commandline */
557
DSClearString(&command);
558
for (p = Settings.SaveCommand; *p; p++)
560
/* copy character if not special or add string to command */
561
if (!(*p == '%' && *(p+1) == 'f'))
562
DSAddCharacter(&command, *p);
565
DSAddString(&command, Filename);
567
/* skip the character */
571
DSAddCharacter(&command, '\0');
573
if ((fp = popen(command.Data, "w")) == NULL)
575
PopenErrorMessage(command.Data);
576
return(STATUS_ERROR);
578
result = WritePCB(fp);
579
return(pclose(fp) ? STATUS_ERROR : result);
650
static DynamicStringType command;
652
/* setup commandline */
653
DSClearString (&command);
654
for (p = Settings.SaveCommand; *p; p++)
656
/* copy character if not special or add string to command */
657
if (!(*p == '%' && *(p + 1) == 'f'))
658
DSAddCharacter (&command, *p);
661
DSAddString (&command, Filename);
663
/* skip the character */
667
DSAddCharacter (&command, '\0');
669
if ((fp = popen (command.Data, "w")) == NULL)
671
PopenErrorMessage (command.Data);
672
return (STATUS_ERROR);
675
result = WritePCB (fp);
677
result = WriteBuffer (fp);
678
return (pclose (fp) ? STATUS_ERROR : result);
582
681
#if defined(HAS_ON_EXIT)
583
682
/* ---------------------------------------------------------------------------
584
683
* just a glue function for systems with on_exit()
586
void GlueEmergencySave(int status, caddr_t arg)
686
GlueEmergencySave (int status, caddr_t arg)
645
748
* before LEX and YACC functions are called because they are able to abort
648
void SaveTMPData(void)
650
sprintf(TMPFilename, EMERGENCY_NAME, (int) getpid());
651
WritePCBFile(TMPFilename);
754
sprintf (TMPFilename, EMERGENCY_NAME, (int) getpid ());
755
WritePCBFile (TMPFilename);
654
758
/* ---------------------------------------------------------------------------
655
759
* removes the temporary copy of the data file
657
void RemoveTMPData(void)
764
unlink (TMPFilename);
768
/* ---------------------------------------------------------------------------
769
* parse the directory tree where additional library elements are found
772
ParseLibraryTree (void)
774
char path[MAXPATHLEN + 1];
775
char working[MAXPATHLEN + 1];
779
struct dirent *direntry, *e2;
780
LibraryMenuTypePtr menu = NULL;
781
LibraryEntryTypePtr entry;
783
memset (path, 0, sizeof path);
784
memset (working, 0, sizeof working);
786
/* save the current working directory */
787
GetWorkingDirectory (working);
789
/* Additional loop to allow for multiple 'newlib' style library directories */
790
libpaths = MyStrdup (Settings.LibraryTree, "ParseLibraryTree");
791
for (p = strtok (libpaths, ":"); p && *p; p = strtok (NULL, ":"))
793
strncpy (path, p, sizeof (path) - 1);
796
* start out in the working directory in case the path is a
801
if ((dir = opendir (path)) == NULL)
803
OpendirErrorMessage (path);
808
* change to the directory which is the top of the library tree
809
* and then extract that directory to ensure we have a full path
810
* name, not a relative path name.
813
GetWorkingDirectory (path);
815
/* read all entries */
816
while ((direntry = readdir (dir)) != NULL)
820
* ignore entries beginning with "." and CVS
823
if (!stat (direntry->d_name, &buffer)
824
&& S_ISDIR (buffer.st_mode) && direntry->d_name[0] != '.'
825
&& NSTRCMP (direntry->d_name, "CVS") != 0)
827
/* add directory name into menu */
828
menu = GetLibraryMenuMemory (&Library);
829
menu->Name = MyStrdup (direntry->d_name, "ParseLibraryTree()");
830
subdir = opendir (direntry->d_name);
831
chdir (direntry->d_name);
832
while (subdir && (e2 = readdir (subdir)))
834
if (!stat (e2->d_name, &buffer) && S_ISREG (buffer.st_mode)
835
&& e2->d_name[0] != '.'
836
&& NSTRCMP (e2->d_name, "CVS") != 0
837
&& NSTRCMP (e2->d_name, "Makefile") != 0
838
&& NSTRCMP (e2->d_name, "Makefile.am") != 0
839
&& NSTRCMP (e2->d_name, "Makefile.in") != 0 )
841
long len = strlen (path) + strlen (e2->d_name) +
842
strlen (direntry->d_name) + 3;
845
(e2->d_name + strlen (e2->d_name) - 4, ".lel") != 0)
848
entry = GetLibraryEntryMemory (menu);
849
entry->AllocatedMemory = MyCalloc (1, len,
850
"ParseLibraryTree()");
851
strcat (entry->AllocatedMemory, path);
852
strcat (entry->AllocatedMemory, "/");
853
strcat (entry->AllocatedMemory, direntry->d_name);
854
strcat (entry->AllocatedMemory, "/");
855
entry->ListEntry = entry->AllocatedMemory
856
+ strlen (entry->AllocatedMemory);
857
strcat (entry->AllocatedMemory, e2->d_name);
858
/* mark as directory tree library */
859
entry->Template = (char *) -1;
869
/* restore the original working directory */
663
873
/* ---------------------------------------------------------------------------
664
874
* read contents of the library description file
875
* also parse a special library directory tree
666
int ReadLibraryContents(void)
878
ReadLibraryContents (void)
668
static char *command = NULL;
669
char inputline[MAX_LIBRARY_LINE_LENGTH+1];
671
LibraryMenuTypePtr menu;
672
LibraryEntryTypePtr entry;
674
/* release old command string */
676
command = EvaluateFilename(Settings.LibraryContentsCommand,
677
Settings.LibraryPath, Settings.LibraryFilename, NULL);
679
/* open a pipe to the output of the command */
680
if ((resultFP = popen(command, "r")) == NULL)
682
PopenErrorMessage(command);
686
/* the library contents are seperated by colons;
687
* template : package : name : description
689
while(fgets(inputline, MAX_LIBRARY_LINE_LENGTH, resultFP))
691
size_t len = strlen(inputline);
693
/* check for maximum linelength */
697
if (inputline[len] != '\n')
698
Message("linelength (%i) exceeded; following characters will be ignored\n", MAX_LIBRARY_LINE_LENGTH);
700
inputline[len] = '\0';
703
/* if the line defines a menu */
704
if (!strncmp(inputline, "TYPE=", 5))
706
menu = GetLibraryMenuMemory(&Library);
707
menu->Name = MyStrdup(UNKNOWN(&inputline[5]),
708
"ReadLibraryDescription()");
712
/* allocate a new menu entry if not already done */
715
menu = GetLibraryMenuMemory(&Library);
716
menu->Name = MyStrdup(UNKNOWN((char *) NULL),
717
"ReadLibraryDescription()");
719
entry = GetLibraryEntryMemory(menu);
720
entry->AllocatedMemory = MyStrdup(inputline,
721
"ReadLibraryDescription()");
723
/* now break the line into pieces separated by colons */
724
if ((entry->Template = strtok(entry->AllocatedMemory, ":")) != NULL)
725
if ((entry->Package= strtok(NULL, ":")) != NULL)
726
if ((entry->Value = strtok(NULL, ":")) != NULL)
727
entry->Description = strtok(NULL, ":");
729
/* create the list entry */
730
len = strlen(EMPTY(entry->Value)) +
731
strlen(EMPTY(entry->Description)) +3;
732
entry->ListEntry = MyCalloc(len, sizeof(char),
733
"ReadLibraryDescription()");
734
sprintf(entry->ListEntry,
735
"%s, %s", EMPTY(entry->Value), EMPTY(entry->Description));
739
return(pclose(resultFP));
880
static char *command = NULL;
881
char inputline[MAX_LIBRARY_LINE_LENGTH + 1];
883
LibraryMenuTypePtr menu = NULL;
884
LibraryEntryTypePtr entry;
886
/* release old command string */
888
command = EvaluateFilename (Settings.LibraryContentsCommand,
889
Settings.LibraryPath, Settings.LibraryFilename,
892
/* open a pipe to the output of the command */
893
if ((resultFP = popen (command, "r")) == NULL)
895
PopenErrorMessage (command);
899
/* the library contents are seperated by colons;
900
* template : package : name : description
902
while (fgets (inputline, MAX_LIBRARY_LINE_LENGTH, resultFP))
904
size_t len = strlen (inputline);
906
/* check for maximum linelength */
910
if (inputline[len] != '\n')
912
("linelength (%i) exceeded; following characters will be ignored\n",
913
MAX_LIBRARY_LINE_LENGTH);
915
inputline[len] = '\0';
918
/* if the line defines a menu */
919
if (!strncmp (inputline, "TYPE=", 5))
921
menu = GetLibraryMenuMemory (&Library);
922
menu->Name = MyStrdup (UNKNOWN (&inputline[5]),
923
"ReadLibraryDescription()");
927
/* allocate a new menu entry if not already done */
930
menu = GetLibraryMenuMemory (&Library);
931
menu->Name = MyStrdup (UNKNOWN ((char *) NULL),
932
"ReadLibraryDescription()");
934
entry = GetLibraryEntryMemory (menu);
935
entry->AllocatedMemory = MyStrdup (inputline,
936
"ReadLibraryDescription()");
938
/* now break the line into pieces separated by colons */
939
if ((entry->Template = strtok (entry->AllocatedMemory, ":")) !=
941
if ((entry->Package = strtok (NULL, ":")) != NULL)
942
if ((entry->Value = strtok (NULL, ":")) != NULL)
943
entry->Description = strtok (NULL, ":");
945
/* create the list entry */
946
len = strlen (EMPTY (entry->Value)) +
947
strlen (EMPTY (entry->Description)) + 3;
948
entry->ListEntry = MyCalloc (len, sizeof (char),
949
"ReadLibraryDescription()");
950
sprintf (entry->ListEntry,
951
"%s, %s", EMPTY (entry->Value),
952
EMPTY (entry->Description));
956
return (pclose (resultFP));
742
959
#define BLANK(x) ((x) == ' ' || (x) == '\t' || (x) == '\n' \
745
962
/* ---------------------------------------------------------------------------
746
963
* Read in a netlist and store it in the netlist menu
749
int ReadNetlist(char *filename)
751
static char *command = NULL;
752
char inputline[MAX_NETLIST_LINE_LENGTH + 1];
753
char temp[MAX_NETLIST_LINE_LENGTH + 1];
755
LibraryMenuTypePtr menu;
756
LibraryEntryTypePtr entry;
757
int i, j, lines, kind;
761
return(1); /* nothing to do */
763
command = EvaluateFilename(Settings.RatCommand,
764
Settings.RatPath, filename, NULL);
766
/* open pipe to stdout of command */
767
if (*command == '\0' || (fp = popen(command, "r")) == NULL)
769
PopenErrorMessage(command);
773
/* kind = 0 is net name
774
* kind = 1 is route style name
775
* kind = 2 is connection
967
ReadNetlist (char *filename)
969
static char *command = NULL;
970
char inputline[MAX_NETLIST_LINE_LENGTH + 1];
971
char temp[MAX_NETLIST_LINE_LENGTH + 1];
973
LibraryMenuTypePtr menu = NULL;
974
LibraryEntryTypePtr entry;
975
int i, j, lines, kind;
979
return (1); /* nothing to do */
981
command = EvaluateFilename (Settings.RatCommand,
982
Settings.RatPath, filename, NULL);
984
/* open pipe to stdout of command */
985
if (*command == '\0' || (fp = popen (command, "r")) == NULL)
987
PopenErrorMessage (command);
991
/* kind = 0 is net name
992
* kind = 1 is route style name
993
* kind = 2 is connection
996
while (fgets (inputline, MAX_NETLIST_LINE_LENGTH, fp))
998
size_t len = strlen (inputline);
999
/* check for maximum length line */
1002
if (inputline[--len] != '\n')
1003
Message ("line length (%i) exceeded in netlist file.\n"
1004
"additional characters will be ignored.\n",
1005
MAX_NETLIST_LINE_LENGTH);
1007
inputline[len] = '\0';
1009
continued = (inputline[len - 1] == '\\') ? True : False;
1011
inputline[len - 1] = '\0';
1014
while (inputline[i] != '\0')
1017
/* skip leading blanks */
1018
while (inputline[i] != '\0' && BLANK (inputline[i]))
1022
/* add two spaces for included/unincluded */
1026
while (!BLANK (inputline[i]))
1027
temp[j++] = inputline[i++];
1029
while (inputline[i] != '\0' && BLANK (inputline[i]))
1033
menu = GetLibraryMenuMemory (&PCB->NetlistLib);
1034
menu->Name = MyStrdup (temp, "ReadNetlist()");
1039
if (kind == 1 && strchr (temp, '-') == NULL)
1042
menu->Style = MyStrdup (temp, "ReadNetlist()");
1046
entry = GetLibraryEntryMemory (menu);
1047
entry->ListEntry = MyStrdup (temp, "ReadNetlist()");
778
while (fgets(inputline, MAX_NETLIST_LINE_LENGTH, fp))
780
size_t len = strlen(inputline);
781
/* check for maximum length line */
784
if (inputline[--len] != '\n')
785
Message("line length (%i) exceeded in netlist file.\n"
786
"additional characters will be ignored.\n",
787
MAX_NETLIST_LINE_LENGTH);
789
inputline[len] = '\0';
791
continued = (inputline[len-1] == '\\') ? True : False;
793
inputline[len-1] = '\0';
796
while (inputline[i] != '\0')
799
/* skip leading blanks */
800
while(inputline[i] != '\0' && BLANK(inputline[i]))
804
/* add two spaces for included/unincluded */
808
while(!BLANK(inputline[i]))
809
temp[j++] = inputline[i++];
811
while(inputline[i] != '\0' && BLANK(inputline[i]))
815
menu = GetLibraryMenuMemory(&PCB->NetlistLib);
816
menu->Name = MyStrdup(temp, "ReadNetlist()");
821
if (kind == 1 && strchr(temp, '-') == NULL)
824
menu->Style = MyStrdup(temp, "ReadNetlist()");
828
entry = GetLibraryEntryMemory(menu);
829
entry->ListEntry = MyStrdup(temp, "ReadNetlist()");
838
Message("Empty netlist file!\n");
1056
Message ("Empty netlist file!\n");