hid/gtk: Clean up ghid_pan_fixup ()
[geda-pcb/pcjc2.git] / src / main.c
blob0e6852ff73443f971964607300e4133152d7f147
1 /* $Id$ */
3 /*
4 * COPYRIGHT
6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996, 2004 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
30 /* main program, initializes some stuff and handles user input
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
36 #include <stdlib.h>
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
40 #include <signal.h>
41 #include <unistd.h>
42 #include <sys/stat.h>
43 #include <time.h> /* Seed for srand() */
45 #include "global.h"
46 #include "data.h"
47 #include "buffer.h"
48 #include "create.h"
49 #include "crosshair.h"
50 #include "draw.h"
51 #include "error.h"
52 #include "file.h"
53 #include "set.h"
54 #include "action.h"
55 #include "misc.h"
56 #include "lrealpath.h"
57 #include "free_atexit.h"
58 #include "polygon.h"
60 #include "hid/common/actions.h"
62 /* This next one is so we can print the help messages. */
63 #include "hid/hidint.h"
65 #ifdef HAVE_DBUS
66 #include "dbus.h"
67 #endif
69 #if ENABLE_NLS
70 #include <libintl.h>
71 #endif
73 #ifdef HAVE_LIBDMALLOC
74 #include <dmalloc.h>
75 #endif
77 RCSID ("$Id$");
80 #define PCBLIBPATH ".:" PCBLIBDIR
83 #ifdef HAVE_LIBSTROKE
84 extern void stroke_init (void);
85 #endif
88 /* ----------------------------------------------------------------------
89 * initialize signal and error handlers
91 static void
92 InitHandler (void)
95 signal(SIGHUP, CatchSignal);
96 signal(SIGQUIT, CatchSignal);
97 signal(SIGABRT, CatchSignal);
98 signal(SIGSEGV, CatchSignal);
99 signal(SIGTERM, CatchSignal);
100 signal(SIGINT, CatchSignal);
103 /* calling external program by popen() may cause a PIPE signal,
104 * so we ignore it
106 #ifdef SIGPIPE
107 signal (SIGPIPE, SIG_IGN);
108 #endif
112 /* ----------------------------------------------------------------------
113 | command line and rc file processing.
115 static char *command_line_pcb;
117 void
118 copyright (void)
120 printf ("\n"
121 " COPYRIGHT for %s version %s\n\n"
122 " PCB, interactive printed circuit board design\n"
123 " Copyright (C) 1994,1995,1996,1997 Thomas Nau\n"
124 " Copyright (C) 1998, 1999, 2000 Harry Eaton\n\n"
125 " This program is free software; you can redistribute it and/or modify\n"
126 " it under the terms of the GNU General Public License as published by\n"
127 " the Free Software Foundation; either version 2 of the License, or\n"
128 " (at your option) any later version.\n\n"
129 " This program is distributed in the hope that it will be useful,\n"
130 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
131 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
132 " GNU General Public License for more details.\n\n"
133 " You should have received a copy of the GNU General Public License\n"
134 " along with this program; if not, write to the Free Software\n"
135 " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n",
136 Progname, VERSION);
137 exit (0);
140 static inline void
141 u (const char *fmt, ...)
143 va_list ap;
144 va_start (ap, fmt);
145 vfprintf (stderr, fmt, ap);
146 fputc ('\n', stderr);
147 va_end (ap);
150 typedef struct UsageNotes {
151 struct UsageNotes *next;
152 HID_Attribute *seen;
153 } UsageNotes;
155 static UsageNotes *usage_notes = NULL;
157 static void
158 usage_attr (HID_Attribute * a)
160 int i;
161 static char buf[200];
163 if (a->help_text == ATTR_UNDOCUMENTED)
164 return;
166 switch (a->type)
168 case HID_Label:
169 return;
170 case HID_Integer:
171 case HID_Real:
172 sprintf (buf, "--%s <num>", a->name);
173 break;
174 case HID_String:
175 sprintf (buf, "--%s <string>", a->name);
176 break;
177 case HID_Boolean:
178 sprintf (buf, "--%s", a->name);
179 break;
180 case HID_Mixed:
181 case HID_Enum:
182 sprintf (buf, "--%s ", a->name);
183 if (a->type == HID_Mixed)
184 strcat (buf, " <val>");
185 for (i = 0; a->enumerations[i]; i++)
187 strcat (buf, i ? "|" : "<");
188 strcat (buf, a->enumerations[i]);
190 strcat (buf, ">");
191 break;
192 case HID_Path:
193 sprintf (buf, "--%s <path>", a->name);
194 break;
197 if (strlen (buf) <= 30)
199 if (a->help_text)
200 fprintf (stderr, " %-30s\t%s\n", buf, a->help_text);
201 else
202 fprintf (stderr, " %-30s\n", buf);
204 else if (a->help_text && strlen (a->help_text) + strlen (buf) < 72)
205 fprintf (stderr, " %s\t%s\n", buf, a->help_text);
206 else if (a->help_text)
207 fprintf (stderr, " %s\n\t\t\t%s\n", buf, a->help_text);
208 else
209 fprintf (stderr, " %s\n", buf);
212 static void
213 usage_hid (HID * h)
215 HID_Attribute *attributes;
216 int i, n_attributes = 0;
217 UsageNotes *note;
219 if (h->gui)
221 fprintf (stderr, "\n%s gui options:\n", h->name);
222 attributes = h->get_export_options (&n_attributes);
224 else
226 fprintf (stderr, "\n%s options:\n", h->name);
227 exporter = h;
228 attributes = exporter->get_export_options (&n_attributes);
229 exporter = NULL;
232 note = (UsageNotes *)malloc (sizeof (UsageNotes));
233 note->next = usage_notes;
234 note->seen = attributes;
235 usage_notes = note;
237 for (i = 0; i < n_attributes; i++)
238 usage_attr (attributes + i);
241 static void
242 usage (void)
244 HID **hl = hid_enumerate ();
245 HID_AttrNode *ha;
246 UsageNotes *note;
247 int i;
248 int n_printer = 0, n_gui = 0, n_exporter = 0;
250 for (i = 0; hl[i]; i++)
252 if (hl[i]->gui)
253 n_gui++;
254 if (hl[i]->printer)
255 n_printer++;
256 if (hl[i]->exporter)
257 n_exporter++;
260 u ("PCB Printed Circuit Board editing program, http://pcb.gpleda.org");
261 u ("%s [-h|-V|--copyright]\t\t\tHelp, version, copyright", Progname);
262 u ("%s [gui options] <pcb file>\t\tto edit", Progname);
263 u ("Available GUI hid%s:", n_gui == 1 ? "" : "s");
264 for (i = 0; hl[i]; i++)
265 if (hl[i]->gui)
266 fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
267 u ("%s -p [printing options] <pcb file>\tto print", Progname);
268 u ("Available printing hid%s:", n_printer == 1 ? "" : "s");
269 for (i = 0; hl[i]; i++)
270 if (hl[i]->printer)
271 fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
272 u ("%s -x hid [export options] <pcb file>\tto export", Progname);
273 u ("Available export hid%s:", n_exporter == 1 ? "" : "s");
274 for (i = 0; hl[i]; i++)
275 if (hl[i]->exporter)
276 fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
278 for (i = 0; hl[i]; i++)
279 if (hl[i]->gui)
280 usage_hid (hl[i]);
281 for (i = 0; hl[i]; i++)
282 if (hl[i]->printer)
283 usage_hid (hl[i]);
284 for (i = 0; hl[i]; i++)
285 if (hl[i]->exporter)
286 usage_hid (hl[i]);
288 u ("\nCommon options:");
289 for (ha = hid_attr_nodes; ha; ha = ha->next)
291 for (note = usage_notes; note && note->seen != ha->attributes; note = note->next)
293 if (note)
294 continue;
295 for (i = 0; i < ha->n; i++)
297 usage_attr (ha->attributes + i);
301 exit (1);
304 static void
305 print_defaults_1 (HID_Attribute * a, void *value)
307 int i;
308 double d;
309 char *s;
311 /* Remember, at this point we've parsed the command line, so they
312 may be in the global variable instead of the default_val. */
313 switch (a->type)
315 case HID_Integer:
316 i = value ? *(int *) value : a->default_val.int_value;
317 fprintf (stderr, "%s %d\n", a->name, i);
318 break;
319 case HID_Boolean:
320 i = value ? *(char *) value : a->default_val.int_value;
321 fprintf (stderr, "%s %s\n", a->name, i ? "yes" : "no");
322 break;
323 case HID_Real:
324 d = value ? *(double *) value : a->default_val.real_value;
325 fprintf (stderr, "%s %g\n", a->name, d);
326 break;
327 case HID_String:
328 case HID_Path:
329 s = value ? *(char **) value : a->default_val.str_value;
330 fprintf (stderr, "%s \"%s\"\n", a->name, s);
331 break;
332 case HID_Enum:
333 i = value ? *(int *) value : a->default_val.int_value;
334 fprintf (stderr, "%s %s\n", a->name, a->enumerations[i]);
335 break;
336 case HID_Mixed:
337 i = value ?
338 ((HID_Attr_Val*)value)->int_value : a->default_val.int_value;
339 d = value ?
340 ((HID_Attr_Val*)value)->real_value : a->default_val.real_value;
341 fprintf (stderr, "%s %g%s\n", a->name, d, a->enumerations[i]);
342 break;
343 case HID_Label:
344 break;
348 static void
349 print_defaults ()
351 HID **hl = hid_enumerate ();
352 HID_Attribute *e;
353 int i, n, hi;
355 for (hi = 0; hl[hi]; hi++)
357 HID *h = hl[hi];
358 if (h->gui)
360 HID_AttrNode *ha;
361 fprintf (stderr, "\ngui defaults:\n");
362 for (ha = hid_attr_nodes; ha; ha = ha->next)
363 for (i = 0; i < ha->n; i++)
364 print_defaults_1 (ha->attributes + i, ha->attributes[i].value);
366 else
368 fprintf (stderr, "\n%s defaults:\n", h->name);
369 exporter = h;
370 e = exporter->get_export_options (&n);
371 exporter = NULL;
372 if (e)
373 for (i = 0; i < n; i++)
374 print_defaults_1 (e + i, 0);
377 exit (1);
380 #define SSET(F,D,N,H) { N, H, \
381 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.F }
382 #define ISET(F,D,N,H) { N, H, \
383 HID_Integer, 0, 0, { D, 0, 0 }, 0, &Settings.F }
384 #define BSET(F,D,N,H) { N, H, \
385 HID_Boolean, 0, 0, { D, 0, 0 }, 0, &Settings.F }
386 #define RSET(F,D,N,H) { N, H, \
387 HID_Real, 0, 0, { 0, 0, D }, 0, &Settings.F }
389 #define COLOR(F,D,N,H) { N, H, \
390 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.F }
391 #define LAYERCOLOR(N,D) { "layer-color-" #N, "Color for layer " #N, \
392 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.LayerColor[N-1] }
393 #define LAYERNAME(N,D) { "layer-name-" #N, "Name for layer " #N, \
394 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.DefaultLayerName[N-1] }
395 #define LAYERSELCOLOR(N) { "layer-selected-color-" #N, "Color for layer " #N " when selected", \
396 HID_String, 0, 0, { 0, "#00ffff", 0 }, 0, &Settings.LayerSelectedColor[N-1] }
398 static int show_help = 0;
399 static int show_version = 0;
400 static int show_copyright = 0;
401 static int show_defaults = 0;
402 static int show_actions = 0;
403 static int do_dump_actions = 0;
405 HID_Attribute main_attribute_list[] = {
406 {"help", "Show Help", HID_Boolean, 0, 0, {0, 0, 0}, 0, &show_help},
407 {"version", "Show Version", HID_Boolean, 0, 0, {0, 0, 0}, 0, &show_version},
408 {"verbose", "Be verbose", HID_Boolean, 0, 0, {0, 0, 0}, 0,
409 &Settings.verbose},
410 {"copyright", "Show Copyright", HID_Boolean, 0, 0, {0, 0, 0}, 0,
411 &show_copyright},
412 {"show-defaults", "Show option defaults", HID_Boolean, 0, 0, {0, 0, 0}, 0,
413 &show_defaults},
414 {"show-actions", "Show actions", HID_Boolean, 0, 0, {0, 0, 0}, 0,
415 &show_actions},
416 {"dump-actions", "Dump actions (for documentation)", HID_Boolean, 0, 0,
417 {0, 0, 0}, 0,
418 &do_dump_actions},
420 BSET (grid_units_mm, 0, "grid-units-mm", 0),
422 COLOR (BlackColor, "#000000", "black-color", "color for black"),
423 COLOR (WhiteColor, "#ffffff", "white-color", "color for white"),
424 COLOR (BackgroundColor, "#e5e5e5", "background-color",
425 "color for background"),
426 COLOR (CrosshairColor, "#ff0000", "crosshair-color",
427 "color for the crosshair"),
428 COLOR (CrossColor, "#cdcd00", "cross-color", "color for cross"),
429 COLOR (ViaColor, "#7f7f7f", "via-color", "color for vias"),
430 COLOR (ViaSelectedColor, "#00ffff", "via-selected-color",
431 "color for selected vias"),
432 COLOR (PinColor, "#4d4d4d", "pin-color", "color for pins"),
433 COLOR (PinSelectedColor, "#00ffff", "pin-selected-color",
434 "color for selected pins"),
435 COLOR (PinNameColor, "#ff0000", "pin-name-color",
436 "color for pin names and numbers"),
437 COLOR (ElementColor, "#000000", "element-color", "color for elements"),
438 COLOR (RatColor, "#b8860b", "rat-color", "color for ratlines"),
439 COLOR (InvisibleObjectsColor, "#cccccc", "invisible-objects-color",
440 "color for invisible objects"),
441 COLOR (InvisibleMarkColor, "#cccccc", "invisible-mark-color",
442 "color for invisible marks"),
443 COLOR (ElementSelectedColor, "#00ffff", "element-selected-color",
444 "color for selected elements"),
445 COLOR (RatSelectedColor, "#00ffff", "rat-selected-color",
446 "color for selected rats"),
447 COLOR (ConnectedColor, "#00ff00", "connected-color",
448 "color for connections"),
449 COLOR (OffLimitColor, "#cccccc", "off-limit-color",
450 "color for off-limits areas"),
451 COLOR (GridColor, "#ff0000", "grid-color", "color for the grid"),
452 LAYERCOLOR (1, "#8b2323"),
453 LAYERCOLOR (2, "#3a5fcd"),
454 LAYERCOLOR (3, "#104e8b"),
455 LAYERCOLOR (4, "#cd3700"),
456 LAYERCOLOR (5, "#548b54"),
457 LAYERCOLOR (6, "#8b7355"),
458 LAYERCOLOR (7, "#00868b"),
459 LAYERCOLOR (8, "#228b22"),
460 LAYERCOLOR (9, "#8b2323"),
461 LAYERCOLOR (10, "#3a5fcd"),
462 LAYERCOLOR (11, "#104e8b"),
463 LAYERCOLOR (12, "#cd3700"),
464 LAYERCOLOR (13, "#548b54"),
465 LAYERCOLOR (14, "#8b7355"),
466 LAYERCOLOR (15, "#00868b"),
467 LAYERCOLOR (16, "#228b22"),
468 LAYERSELCOLOR (1),
469 LAYERSELCOLOR (2),
470 LAYERSELCOLOR (3),
471 LAYERSELCOLOR (4),
472 LAYERSELCOLOR (5),
473 LAYERSELCOLOR (6),
474 LAYERSELCOLOR (7),
475 LAYERSELCOLOR (8),
476 LAYERSELCOLOR (9),
477 LAYERSELCOLOR (10),
478 LAYERSELCOLOR (11),
479 LAYERSELCOLOR (12),
480 LAYERSELCOLOR (13),
481 LAYERSELCOLOR (14),
482 LAYERSELCOLOR (15),
483 LAYERSELCOLOR (16),
484 COLOR (WarnColor, "#ff8000", "warn-color", "color for warnings"),
485 COLOR (MaskColor, "#ff0000", "mask-color", "color for solder mask"),
487 ISET (ViaThickness, MIL_TO_COORD(60), "via-thickness", 0),
488 ISET (ViaDrillingHole, MIL_TO_COORD(28), "via-drilling-hole", 0),
489 ISET (LineThickness, MIL_TO_COORD(10), "line-thickness",
490 "Initial thickness of new lines."),
491 ISET (RatThickness, MIL_TO_COORD(10), "rat-thickness", 0),
492 ISET (Keepaway, MIL_TO_COORD(10), "keepaway", 0),
493 ISET (MaxWidth, MIL_TO_COORD(MIL_TO_COORD(60)), "default-PCB-width", 0),
494 ISET (MaxHeight, MIL_TO_COORD(MIL_TO_COORD(50)), "default-PCB-height", 0),
495 ISET (TextScale, 100, "text-scale", 0),
496 ISET (AlignmentDistance, MIL_TO_COORD(2), "alignment-distance", 0),
497 ISET (Bloat, MIL_TO_COORD(10), "bloat", 0),
498 ISET (Shrink, MIL_TO_COORD(10), "shrink", 0),
499 ISET (minWid, MIL_TO_COORD(10), "min-width", "DRC minimum copper spacing"),
500 ISET (minSlk, MIL_TO_COORD(10), "min-silk", "DRC minimum silk width"),
501 ISET (minDrill, MIL_TO_COORD(15), "min-drill", "DRC minimum drill diameter"),
502 ISET (minRing, MIL_TO_COORD(10), "min-ring", "DRC minimum annular ring"),
504 RSET (Grid, MIL_TO_COORD(10), "grid", 0),
505 RSET (grid_increment_mm, 0.1, "grid-increment-mm", 0),
506 RSET (grid_increment_mil, 5.0, "grid-increment-mil", 0),
507 RSET (size_increment_mm, 0.2, "size-increment-mm", 0),
508 RSET (size_increment_mil, 10.0, "size-increment-mil", 0),
509 RSET (line_increment_mm, 0.1, "line-increment-mm", 0),
510 RSET (line_increment_mil, 5.0, "line-increment-mil", 0),
511 RSET (clear_increment_mm, 0.05, "clear-increment-mm", 0),
512 RSET (clear_increment_mil, 2.0, "clear-increment-mil", 0),
513 RSET (IsleArea, MIL_TO_COORD(1400) * MIL_TO_COORD(1400), "minimum polygon area", 0),
515 ISET (BackupInterval, 60, "backup-interval", 0),
517 LAYERNAME (1, "top"),
518 LAYERNAME (2, "ground"),
519 LAYERNAME (3, "signal2"),
520 LAYERNAME (4, "signal3"),
521 LAYERNAME (5, "power"),
522 LAYERNAME (6, "bottom"),
523 LAYERNAME (7, "outline"),
524 LAYERNAME (8, "spare"),
525 SSET (Groups, "1,c:2:3:4:5:6,s:7:8", "groups", 0),
527 SSET (FontCommand, "",
528 "font-command", 0),
529 SSET (FileCommand, "", "file-command", "Command to read a file."),
530 SSET (ElementCommand,
531 "M4PATH='%p';export M4PATH;echo 'include(%f)' | " GNUM4,
532 "element-command", 0),
533 SSET (PrintFile, "%f.output", "print-file", 0),
534 SSET (LibraryCommandDir, PCBLIBDIR, "lib-command-dir", 0),
535 SSET (LibraryCommand, "QueryLibrary.sh '%p' '%f' %a",
536 "lib-command", 0),
537 SSET (LibraryContentsCommand, "ListLibraryContents.sh '%p' '%f'",
538 "lib-contents-command", 0),
539 SSET (LibraryTree, PCBTREEPATH, "lib-newlib",
540 "Top level directory for the newlib style library"),
541 SSET (SaveCommand, "", "save-command", 0),
542 SSET (LibraryFilename, LIBRARYFILENAME, "lib-name", 0),
543 SSET (FontFile, "default_font", "default-font",
544 "File name of default font."),
545 SSET (Routes, "Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000"
546 ":Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600", "route-styles",
548 SSET (FilePath, "", "file-path", 0),
549 SSET (RatCommand, "", "rat-command", 0),
550 SSET (FontPath, PCBLIBPATH, "font-path", 0),
551 SSET (ElementPath, PCBLIBPATH, "element-path", 0),
552 SSET (LibraryPath, PCBLIBPATH, "lib-path", 0),
553 SSET (MenuFile, "pcb-menu.res", "menu-file", 0),
554 SSET (ScriptFilename, 0, "action-script",
555 "If set, this file is executed at startup."),
556 SSET (ActionString, 0, "action-string",
557 "If set, this is executed at startup."),
558 SSET (FabAuthor, "", "fab-author", 0),
559 SSET (InitialLayerStack, "", "layer-stack",
560 "Initial layer stackup, for setting up an export."),
562 SSET (MakeProgram, NULL, "make-program",
563 "Sets the name and optionally full path to a make(3) program"),
564 SSET (GnetlistProgram, NULL, "gnetlist",
565 "Sets the name and optionally full path to the gnetlist(3) program"),
567 ISET (PinoutOffsetX, MIL_TO_COORD(1), "pinout-offset-x", 0),
568 ISET (PinoutOffsetY, MIL_TO_COORD(1), "pinout-offset-y", 0),
569 ISET (PinoutTextOffsetX, MIL_TO_COORD(8), "pinout-text-offset-x", 0),
570 ISET (PinoutTextOffsetY, MIL_TO_COORD(-1), "pinout-text-offset-y", 0),
572 BSET (DrawGrid, 0, "draw-grid", "default to drawing the grid at startup"),
573 BSET (ClearLine, 1, "clear-line", 0),
574 BSET (FullPoly, 0, "full-poly", 0),
575 BSET (UniqueNames, 1, "unique-names", 0),
576 BSET (SnapPin, 1, "snap-pin", 0),
577 BSET (SaveLastCommand, 0, "save-last-command", 0),
578 BSET (SaveInTMP, 0, "save-in-tmp", 0),
579 BSET (AllDirectionLines, 0, "all-direction-lines", 0),
580 BSET (ShowNumber, 0, "show-number", 0),
581 BSET (ResetAfterElement, 1, "reset-after-element", 0),
582 BSET (RingBellWhenFinished, 0, "ring-bell-finished", 0),
585 REGISTER_ATTRIBUTES (main_attribute_list)
586 /* ----------------------------------------------------------------------
587 * post-process settings.
589 static void settings_post_process ()
591 char *tmps;
593 if (Settings.LibraryCommand[0] != PCB_DIR_SEPARATOR_C && Settings.LibraryCommand[0] != '.')
595 Settings.LibraryCommand
597 Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
598 Settings.LibraryCommand,
599 NULL);
601 if (Settings.LibraryContentsCommand[0] != PCB_DIR_SEPARATOR_C
602 && Settings.LibraryContentsCommand[0] != '.')
604 Settings.LibraryContentsCommand
606 Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
607 Settings.LibraryContentsCommand, NULL);
610 if (Settings.LineThickness > MAX_LINESIZE
611 || Settings.LineThickness < MIN_LINESIZE)
612 Settings.LineThickness = MIL_TO_COORD(10);
614 if (Settings.ViaThickness > MAX_PINORVIASIZE
615 || Settings.ViaThickness < MIN_PINORVIASIZE)
616 Settings.ViaThickness = MIL_TO_COORD(40);
618 if (Settings.ViaDrillingHole <= 0)
619 Settings.ViaDrillingHole =
620 DEFAULT_DRILLINGHOLE * Settings.ViaThickness / 100;
622 Settings.MaxWidth = MIN (MAX_COORD, MAX (Settings.MaxWidth, MIN_SIZE));
623 Settings.MaxHeight = MIN (MAX_COORD, MAX (Settings.MaxHeight, MIN_SIZE));
625 ParseRouteString (Settings.Routes, &Settings.RouteStyle[0], "cmil");
628 * Make sure we have settings for some various programs we may wish
629 * to call
631 if (Settings.MakeProgram == NULL) {
632 tmps = getenv ("PCB_MAKE_PROGRAM");
633 if (tmps != NULL)
634 Settings.MakeProgram = strdup (tmps);
636 if (Settings.MakeProgram == NULL) {
637 Settings.MakeProgram = strdup ("make");
640 if (Settings.GnetlistProgram == NULL) {
641 tmps = getenv ("PCB_GNETLIST");
642 if (tmps != NULL)
643 Settings.GnetlistProgram = strdup (tmps);
645 if (Settings.GnetlistProgram == NULL) {
646 Settings.GnetlistProgram = strdup ("gnetlist");
652 /* ----------------------------------------------------------------------
653 * Print help or version messages.
656 static void
657 print_version ()
659 printf ("PCB version %s\n", VERSION);
660 exit (0);
663 /* ----------------------------------------------------------------------
664 * Figure out the canonical name of the executed program
665 * and fix up the defaults for various paths
667 char *bindir = NULL;
668 char *exec_prefix = NULL;
669 char *pcblibdir = NULL;
670 char *pcblibpath = NULL;
671 char *pcbtreedir = NULL;
672 char *pcbtreepath = NULL;
673 char *homedir = NULL;
675 static void
676 InitPaths (char *argv0)
678 size_t l;
679 int i;
680 int haspath;
681 char *t1, *t2;
682 int found_bindir = 0;
684 /* see if argv0 has enough of a path to let lrealpath give the
685 * real path. This should be the case if you invoke pcb with
686 * something like /usr/local/bin/pcb or ./pcb or ./foo/pcb
687 * but if you just use pcb and it exists in your path, you'll
688 * just get back pcb again.
691 haspath = 0;
692 for (i = 0; i < strlen (argv0) ; i++)
694 if (argv0[i] == PCB_DIR_SEPARATOR_C)
695 haspath = 1;
698 #ifdef DEBUG
699 printf ("InitPaths (%s): haspath = %d\n", argv0, haspath);
700 #endif
702 if (haspath)
704 bindir = strdup (lrealpath (argv0));
705 found_bindir = 1;
707 else
709 char *path, *p, *tmps;
710 struct stat sb;
711 int r;
713 tmps = getenv ("PATH");
715 if (tmps != NULL)
717 path = strdup (tmps);
719 /* search through the font path for a font file */
720 for (p = strtok (path, PCB_PATH_DELIMETER); p && *p;
721 p = strtok (NULL, PCB_PATH_DELIMETER))
723 #ifdef DEBUG
724 printf ("Looking for %s in %s\n", argv0, p);
725 #endif
726 if ( (tmps = (char *)malloc ( (strlen (argv0) + strlen (p) + 2) * sizeof (char))) == NULL )
728 fprintf (stderr, "InitPaths(): malloc failed\n");
729 exit (1);
731 sprintf (tmps, "%s%s%s", p, PCB_DIR_SEPARATOR_S, argv0);
732 r = stat (tmps, &sb);
733 if (r == 0)
735 #ifdef DEBUG
736 printf ("Found it: \"%s\"\n", tmps);
737 #endif
738 bindir = lrealpath (tmps);
739 found_bindir = 1;
740 free (tmps);
741 break;
743 free (tmps);
745 free (path);
749 #ifdef DEBUG
750 printf ("InitPaths(): bindir = \"%s\"\n", bindir);
751 #endif
753 if (found_bindir)
755 /* strip off the executible name leaving only the path */
756 t2 = NULL;
757 t1 = strchr (bindir, PCB_DIR_SEPARATOR_C);
758 while (t1 != NULL && *t1 != '\0')
760 t2 = t1;
761 t1 = strchr (t2 + 1, PCB_DIR_SEPARATOR_C);
763 if (t2 != NULL)
764 *t2 = '\0';
766 #ifdef DEBUG
767 printf ("After stripping off the executible name, we found\n");
768 printf ("bindir = \"%s\"\n", bindir);
769 #endif
771 else
773 /* we have failed to find out anything from argv[0] so fall back to the original
774 * install prefix
776 bindir = strdup (BINDIR);
779 /* now find the path to exec_prefix */
780 l = strlen (bindir) + 1 + strlen (BINDIR_TO_EXECPREFIX) + 1;
781 if ( (exec_prefix = (char *) malloc (l * sizeof (char) )) == NULL )
783 fprintf (stderr, "InitPaths(): malloc failed\n");
784 exit (1);
786 sprintf (exec_prefix, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
787 BINDIR_TO_EXECPREFIX);
789 /* now find the path to PCBLIBDIR */
790 l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBLIBDIR) + 1;
791 if ( (pcblibdir = (char *) malloc (l * sizeof (char) )) == NULL )
793 fprintf (stderr, "InitPaths(): malloc failed\n");
794 exit (1);
796 sprintf (pcblibdir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
797 BINDIR_TO_PCBLIBDIR);
799 /* and the path to PCBTREEDIR */
800 l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBTREEDIR) + 1;
801 if ( (pcbtreedir = (char *) malloc (l * sizeof (char) )) == NULL )
803 fprintf (stderr, "InitPaths(): malloc failed\n");
804 exit (1);
806 sprintf (pcbtreedir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
807 BINDIR_TO_PCBTREEDIR);
809 /* and the search path including PCBLIBDIR */
810 l = strlen (pcblibdir) + 3;
811 if ( (pcblibpath = (char *) malloc (l * sizeof (char) )) == NULL )
813 fprintf (stderr, "InitPaths(): malloc failed\n");
814 exit (1);
816 sprintf (pcblibpath, ".%s%s", PCB_PATH_DELIMETER, pcblibdir);
818 /* and the newlib search path */
819 l = strlen (pcblibdir) + 1 + strlen (pcbtreedir)
820 + strlen ("pcblib-newlib") + 2;
821 if ( (pcbtreepath = (char *) malloc (l * sizeof (char) )) == NULL )
823 fprintf (stderr, "InitPaths(): malloc failed\n");
824 exit (1);
826 sprintf (pcbtreepath, "%s%s%s%spcblib-newlib", pcbtreedir,
827 PCB_PATH_DELIMETER, pcblibdir,
828 PCB_DIR_SEPARATOR_S);
830 #ifdef DEBUG
831 printf ("bindir = %s\n", bindir);
832 printf ("pcblibdir = %s\n", pcblibdir);
833 printf ("pcblibpath = %s\n", pcblibpath);
834 printf ("pcbtreedir = %s\n", pcbtreedir);
835 printf ("pcbtreepath = %s\n", pcbtreepath);
836 #endif
838 l = sizeof (main_attribute_list) / sizeof (main_attribute_list[0]);
839 for (i = 0; i < l ; i++)
841 if (NSTRCMP (main_attribute_list[i].name, "lib-command-dir") == 0)
843 main_attribute_list[i].default_val.str_value = pcblibdir;
846 if ( (NSTRCMP (main_attribute_list[i].name, "font-path") == 0)
847 || (NSTRCMP (main_attribute_list[i].name, "element-path") == 0)
848 || (NSTRCMP (main_attribute_list[i].name, "lib-path") == 0) )
850 main_attribute_list[i].default_val.str_value = pcblibpath;
853 if (NSTRCMP (main_attribute_list[i].name, "lib-newlib") == 0)
855 main_attribute_list[i].default_val.str_value = pcbtreepath;
861 char *tmps;
863 tmps = getenv ("HOME");
865 if (tmps == NULL) {
866 tmps = getenv ("USERPROFILE");
869 if (tmps != NULL) {
870 homedir = strdup (tmps);
871 } else {
872 homedir = NULL;
878 /* ----------------------------------------------------------------------
879 * main program
882 char *program_name = 0;
883 char *program_basename = 0;
884 char *program_directory = 0;
886 #include "dolists.h"
889 main (int argc, char *argv[])
891 int i;
893 /* init application:
894 * - make program name available for error handlers
895 * - evaluate special options
896 * - initialize toplevel shell and resources
897 * - create an empty PCB with default symbols
898 * - initialize all other widgets
899 * - update screen and get size of drawing area
900 * - evaluate command-line arguments
901 * - register 'call on exit()' function
904 #include "core_lists.h"
905 setbuf (stdout, 0);
906 InitPaths (argv[0]);
908 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
909 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
911 srand ( time(NULL) ); /* Set seed for rand() */
913 polygon_init ();
914 hid_init ();
916 hid_load_settings ();
918 program_name = argv[0];
919 program_basename = strrchr (program_name, PCB_DIR_SEPARATOR_C);
920 if (program_basename)
922 program_directory = strdup (program_name);
923 *strrchr (program_directory, PCB_DIR_SEPARATOR_C) = 0;
924 program_basename++;
926 else
928 program_directory = ".";
929 program_basename = program_name;
931 Progname = program_basename;
933 /* Print usage or version if requested. Then exit. */
934 if (argc > 1 && strcmp (argv[1], "-h") == 0)
935 usage ();
936 if (argc > 1 && strcmp (argv[1], "-V") == 0)
937 print_version ();
938 /* Export pcb from command line if requested. */
939 if (argc > 1 && strcmp (argv[1], "-p") == 0)
941 exporter = gui = hid_find_printer ();
942 argc--;
943 argv++;
945 else if (argc > 2 && strcmp (argv[1], "-x") == 0)
947 exporter = gui = hid_find_exporter (argv[2]);
948 argc -= 2;
949 argv += 2;
951 /* Otherwise start GUI. */
952 else
953 gui = hid_find_gui ();
955 /* Exit with error if GUI failed to start. */
956 if (!gui)
957 exit (1);
959 /* Set up layers. */
960 for (i = 0; i < MAX_LAYER; i++)
962 char buf[20];
963 sprintf (buf, "signal%d", i + 1);
964 Settings.DefaultLayerName[i] = strdup (buf);
965 Settings.LayerColor[i] = "#c49350";
966 Settings.LayerSelectedColor[i] = "#00ffff";
969 gui->parse_arguments (&argc, &argv);
971 if (show_help || (argc > 1 && argv[1][0] == '-'))
972 usage ();
973 if (show_version)
974 print_version ();
975 if (show_defaults)
976 print_defaults ();
977 if (show_copyright)
978 copyright ();
980 settings_post_process ();
983 if (show_actions)
985 print_actions ();
986 exit (0);
989 if (do_dump_actions)
991 extern void dump_actions (void);
992 dump_actions ();
993 exit (0);
996 /* Create a new PCB object in memory */
997 PCB = CreateNewPCB (true);
998 PCB->Data->LayerN = DEF_LAYER;
999 ParseGroupString (Settings.Groups, &PCB->LayerGroups, DEF_LAYER);
1000 /* Add silk layers to newly created PCB */
1001 CreateNewPCBPost (PCB, 1);
1002 if (argc > 1)
1003 command_line_pcb = argv[1];
1005 ResetStackAndVisibility ();
1007 CreateDefaultFont ();
1008 if (gui->gui)
1009 InitCrosshair ();
1010 InitHandler ();
1011 InitBuffers ();
1012 SetMode (ARROW_MODE);
1014 if (command_line_pcb)
1016 /* keep filename even if initial load command failed;
1017 * file might not exist
1019 if (LoadPCB (command_line_pcb))
1020 PCB->Filename = strdup (command_line_pcb);
1023 if (Settings.InitialLayerStack
1024 && Settings.InitialLayerStack[0])
1026 LayerStringToLayerStack (Settings.InitialLayerStack);
1029 /* FIX_ME
1030 LoadBackgroundImage (Settings.BackgroundImage); */
1032 /* This must be called before any other atexit functions
1033 * are registered, as it configures an atexit function to
1034 * clean up and free various items of allocated memory,
1035 * and must be the last last atexit function to run.
1037 leaky_init ();
1039 /* Register a function to be called when the program terminates.
1040 * This makes sure that data is saved even if LEX/YACC routines
1041 * abort the program.
1042 * If the OS doesn't have at least one of them,
1043 * the critical sections will be handled by parse_l.l
1045 atexit (EmergencySave);
1047 /* read the library file and display it if it's not empty
1049 if (!ReadLibraryContents () && Library.MenuN)
1050 hid_action ("LibraryChanged");
1052 #ifdef HAVE_LIBSTROKE
1053 stroke_init ();
1054 #endif
1056 if (Settings.ScriptFilename)
1058 Message (_("Executing startup script file %s\n"),
1059 Settings.ScriptFilename);
1060 hid_actionl ("ExecuteFile", Settings.ScriptFilename, NULL);
1062 if (Settings.ActionString)
1064 Message (_("Executing startup action %s\n"), Settings.ActionString);
1065 hid_parse_actions (Settings.ActionString);
1068 if (gui->printer || gui->exporter)
1070 gui->do_export (0);
1071 exit (0);
1074 #if HAVE_DBUS
1075 pcb_dbus_setup();
1076 #endif
1078 EnableAutosave ();
1080 #ifdef DEBUG
1081 printf ("Settings.LibraryCommandDir = \"%s\"\n",
1082 Settings.LibraryCommandDir);
1083 printf ("Settings.FontPath = \"%s\"\n",
1084 Settings.FontPath);
1085 printf ("Settings.ElementPath = \"%s\"\n",
1086 Settings.ElementPath);
1087 printf ("Settings.LibraryPath = \"%s\"\n",
1088 Settings.LibraryPath);
1089 printf ("Settings.LibraryTree = \"%s\"\n",
1090 Settings.LibraryTree);
1091 printf ("Settings.MakeProgram = \"%s\"\n",
1092 UNKNOWN (Settings.MakeProgram));
1093 printf ("Settings.GnetlistProgram = \"%s\"\n",
1094 UNKNOWN (Settings.GnetlistProgram));
1095 #endif
1097 gui->do_export (0);
1098 #if HAVE_DBUS
1099 pcb_dbus_finish();
1100 #endif
1102 return (0);