Use strdup to copy environment strings into our settings structure.
[geda-pcb/gde.git] / src / main.c
blobbb79991e289066e0bf3ab5c665387b408cfb53cf
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>
44 #include "global.h"
45 #include "data.h"
46 #include "buffer.h"
47 #include "create.h"
48 #include "crosshair.h"
49 #include "draw.h"
50 #include "error.h"
51 #include "file.h"
52 #include "set.h"
53 #include "action.h"
54 #include "misc.h"
55 #include "lrealpath.h"
57 /* This next one is so we can print the help messages. */
58 #include "hid/hidint.h"
60 #ifdef HAVE_DBUS
61 #include "dbus.h"
62 #endif
64 #if ENABLE_NLS
65 #include <libintl.h>
66 #endif
68 #ifdef HAVE_LIBDMALLOC
69 #include <dmalloc.h>
70 #endif
72 RCSID ("$Id$");
75 #define PCBLIBPATH ".:" PCBLIBDIR
78 #ifdef HAVE_LIBSTROKE
79 extern void stroke_init (void);
80 #endif
83 /* ----------------------------------------------------------------------
84 * initialize signal and error handlers
86 static void
87 InitHandler (void)
90 signal(SIGHUP, CatchSignal);
91 signal(SIGQUIT, CatchSignal);
92 signal(SIGABRT, CatchSignal);
93 signal(SIGSEGV, CatchSignal);
94 signal(SIGTERM, CatchSignal);
95 signal(SIGINT, CatchSignal);
98 /* calling external program by popen() may cause a PIPE signal,
99 * so we ignore it
101 #ifdef SIGPIPE
102 signal (SIGPIPE, SIG_IGN);
103 #endif
107 /* ----------------------------------------------------------------------
108 | command line and rc file processing.
110 static char *command_line_pcb;
112 void
113 copyright (void)
115 printf ("\n"
116 " COPYRIGHT for %s version %s\n\n"
117 " PCB, interactive printed circuit board design\n"
118 " Copyright (C) 1994,1995,1996,1997 Thomas Nau\n"
119 " Copyright (C) 1998, 1999, 2000 Harry Eaton\n\n"
120 " This program is free software; you can redistribute it and/or modify\n"
121 " it under the terms of the GNU General Public License as published by\n"
122 " the Free Software Foundation; either version 2 of the License, or\n"
123 " (at your option) any later version.\n\n"
124 " This program is distributed in the hope that it will be useful,\n"
125 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
126 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
127 " GNU General Public License for more details.\n\n"
128 " You should have received a copy of the GNU General Public License\n"
129 " along with this program; if not, write to the Free Software\n"
130 " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n",
131 Progname, VERSION);
132 exit (0);
135 static inline void
136 u (const char *fmt, ...)
138 va_list ap;
139 va_start (ap, fmt);
140 vfprintf (stderr, fmt, ap);
141 fputc ('\n', stderr);
142 va_end (ap);
145 static void
146 usage_attr (HID_Attribute * a)
148 int i;
149 static char buf[200];
151 if (a->help_text == ATTR_UNDOCUMENTED)
152 return;
154 switch (a->type)
156 case HID_Label:
157 return;
158 case HID_Integer:
159 case HID_Real:
160 sprintf (buf, "--%s <num>", a->name);
161 break;
162 case HID_String:
163 sprintf (buf, "--%s <string>", a->name);
164 break;
165 case HID_Boolean:
166 sprintf (buf, "--%s", a->name);
167 break;
168 case HID_Mixed:
169 case HID_Enum:
170 sprintf (buf, "--%s ", a->name);
171 if (a->type == HID_Mixed)
172 strcat (buf, " <val>");
173 for (i = 0; a->enumerations[i]; i++)
175 strcat (buf, i ? "|" : "<");
176 strcat (buf, a->enumerations[i]);
178 strcat (buf, ">");
179 break;
180 case HID_Path:
181 sprintf (buf, "--%s <path>", a->name);
182 break;
185 if (strlen (buf) <= 30)
187 if (a->help_text)
188 fprintf (stderr, " %-30s\t%s\n", buf, a->help_text);
189 else
190 fprintf (stderr, " %-30s\n", buf);
192 else if (a->help_text && strlen (a->help_text) + strlen (buf) < 72)
193 fprintf (stderr, " %s\t%s\n", buf, a->help_text);
194 else if (a->help_text)
195 fprintf (stderr, " %s\n\t\t\t%s\n", buf, a->help_text);
196 else
197 fprintf (stderr, " %s\n", buf);
200 static void
201 usage_hid (HID * h)
203 HID_Attribute *e;
204 int i, n;
206 if (h->gui)
208 HID **hl = hid_enumerate ();
209 HID_AttrNode *ha;
210 fprintf (stderr, "\n%s gui options:\n", h->name);
211 for (ha = hid_attr_nodes; ha; ha = ha->next)
213 for (i = 0; hl[i]; i++)
214 if (ha->attributes == hl[i]->get_export_options (0))
215 goto skip_this_one;
216 for (i = 0; i < ha->n; i++)
217 usage_attr (ha->attributes + i);
218 skip_this_one:;
220 return;
222 fprintf (stderr, "\n%s options:\n", h->name);
223 exporter = h;
224 e = h->get_export_options (&n);
225 if (!e)
226 return;
227 for (i = 0; i < n; i++)
228 usage_attr (e + i);
229 exporter = NULL;
232 static void
233 usage (void)
235 HID **hl = hid_enumerate ();
236 int i;
237 int n_printer = 0, n_gui = 0, n_exporter = 0;
239 for (i = 0; hl[i]; i++)
241 if (hl[i]->gui)
242 n_gui++;
243 if (hl[i]->printer)
244 n_printer++;
245 if (hl[i]->exporter)
246 n_exporter++;
249 u ("PCB Printed Circuit Board editing program, http://pcb.sourceforge.net");
250 u ("%s [-h|-V|--copyright]\t\t\tHelp, version, copyright", Progname);
251 u ("%s [gui options] <pcb file>\t\tto edit", Progname);
252 u ("Available GUI hid%s:", n_gui == 1 ? "" : "s");
253 for (i = 0; hl[i]; i++)
254 if (hl[i]->gui)
255 fprintf (stderr, "\t%s\t%s\n", hl[i]->name, hl[i]->description);
256 u ("%s -p [printing options] <pcb file>\tto print", Progname);
257 u ("Available printing hid%s:", n_printer == 1 ? "" : "s");
258 for (i = 0; hl[i]; i++)
259 if (hl[i]->printer)
260 fprintf (stderr, "\t%s\t%s\n", hl[i]->name, hl[i]->description);
261 u ("%s -x hid [export options] <pcb file>\tto export", Progname);
262 u ("Available export hid%s:", n_exporter == 1 ? "" : "s");
263 for (i = 0; hl[i]; i++)
264 if (hl[i]->exporter)
265 fprintf (stderr, "\t%s\t%s\n", hl[i]->name, hl[i]->description);
267 for (i = 0; hl[i]; i++)
268 if (hl[i]->gui)
269 usage_hid (hl[i]);
270 for (i = 0; hl[i]; i++)
271 if (hl[i]->printer)
272 usage_hid (hl[i]);
273 for (i = 0; hl[i]; i++)
274 if (hl[i]->exporter)
275 usage_hid (hl[i]);
276 exit (1);
279 static void
280 print_defaults_1 (HID_Attribute * a, void *value)
282 int i;
283 double d;
284 char *s;
286 /* Remember, at this point we've parsed the command line, so they
287 may be in the global variable instead of the default_val. */
288 switch (a->type)
290 case HID_Integer:
291 i = value ? *(int *) value : a->default_val.int_value;
292 fprintf (stderr, "%s %d\n", a->name, i);
293 break;
294 case HID_Boolean:
295 i = value ? *(char *) value : a->default_val.int_value;
296 fprintf (stderr, "%s %s\n", a->name, i ? "yes" : "no");
297 break;
298 case HID_Real:
299 d = value ? *(double *) value : a->default_val.real_value;
300 fprintf (stderr, "%s %g\n", a->name, d);
301 break;
302 case HID_String:
303 case HID_Path:
304 s = value ? *(char **) value : a->default_val.str_value;
305 fprintf (stderr, "%s \"%s\"\n", a->name, s);
306 break;
307 case HID_Enum:
308 i = value ? *(int *) value : a->default_val.int_value;
309 fprintf (stderr, "%s %s\n", a->name, a->enumerations[i]);
310 break;
311 case HID_Mixed:
312 i = value ? *(int *) value : a->default_val.int_value;
313 d = value ? *(double *) value : a->default_val.real_value;
314 fprintf (stderr, "%s %g%s\n", a->name, d, a->enumerations[i]);
315 break;
316 case HID_Label:
317 break;
321 static void
322 print_defaults ()
324 HID **hl = hid_enumerate ();
325 HID_Attribute *e;
326 int i, n, hi;
328 for (hi = 0; hl[hi]; hi++)
330 HID *h = hl[hi];
331 if (h->gui)
333 HID_AttrNode *ha;
334 fprintf (stderr, "\ngui defaults:\n");
335 for (ha = hid_attr_nodes; ha; ha = ha->next)
336 for (i = 0; i < ha->n; i++)
337 print_defaults_1 (ha->attributes + i, ha->attributes[i].value);
339 else
341 fprintf (stderr, "\n%s defaults:\n", h->name);
342 e = h->get_export_options (&n);
343 if (e)
344 for (i = 0; i < n; i++)
345 print_defaults_1 (e + i, 0);
348 exit (1);
351 /* in hid/common/actions.c */
352 extern void print_actions ();
355 #define SSET(F,D,N,H) { N, H, \
356 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.F }
357 #define ISET(F,D,N,H) { N, H, \
358 HID_Integer, 0, 0, { D, 0, 0 }, 0, &Settings.F }
359 #define BSET(F,D,N,H) { N, H, \
360 HID_Boolean, 0, 0, { D, 0, 0 }, 0, &Settings.F }
361 #define RSET(F,D,N,H) { N, H, \
362 HID_Real, 0, 0, { 0, 0, D }, 0, &Settings.F }
364 #define COLOR(F,D,N,H) { N, H, \
365 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.F }
366 #define LAYERCOLOR(N,D) { "layer-color-" #N, "Color for layer " #N, \
367 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.LayerColor[N-1] }
368 #define LAYERNAME(N,D) { "layer-name-" #N, "Name for layer " #N, \
369 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.DefaultLayerName[N-1] }
370 #define LAYERSELCOLOR(N) { "layer-selected-color-" #N, "Color for layer " #N " when selected", \
371 HID_String, 0, 0, { 0, "#00ffff", 0 }, 0, &Settings.LayerSelectedColor[N-1] }
373 static int show_help = 0;
374 static int show_version = 0;
375 static int show_copyright = 0;
376 static int show_defaults = 0;
377 static int show_actions = 0;
378 static int do_dump_actions = 0;
380 HID_Attribute main_attribute_list[] = {
381 {"help", "Show Help", HID_Boolean, 0, 0, {0, 0, 0}, 0, &show_help},
382 {"version", "Show Version", HID_Boolean, 0, 0, {0, 0, 0}, 0, &show_version},
383 {"verbose", "Be verbose", HID_Boolean, 0, 0, {0, 0, 0}, 0,
384 &Settings.verbose},
385 {"copyright", "Show Copyright", HID_Boolean, 0, 0, {0, 0, 0}, 0,
386 &show_copyright},
387 {"show-defaults", "Show option defaults", HID_Boolean, 0, 0, {0, 0, 0}, 0,
388 &show_defaults},
389 {"show-actions", "Show actions", HID_Boolean, 0, 0, {0, 0, 0}, 0,
390 &show_actions},
391 {"dump-actions", "Dump actions (for documentation)", HID_Boolean, 0, 0,
392 {0, 0, 0}, 0,
393 &do_dump_actions},
395 BSET (grid_units_mm, 0, "grid-units-mm", 0),
397 COLOR (BlackColor, "#000000", "black-color", "color for black"),
398 COLOR (WhiteColor, "#ffffff", "white-color", "color for white"),
399 COLOR (BackgroundColor, "#e5e5e5", "background-color",
400 "color for background"),
401 COLOR (CrosshairColor, "#ff0000", "crosshair-color",
402 "color for the crosshair"),
403 COLOR (CrossColor, "#cdcd00", "cross-color", "color for cross"),
404 COLOR (ViaColor, "#7f7f7f", "via-color", "color for vias"),
405 COLOR (ViaSelectedColor, "#00ffff", "via-selected-color",
406 "color for selected vias"),
407 COLOR (PinColor, "#4d4d4d", "pin-color", "color for pins"),
408 COLOR (PinSelectedColor, "#00ffff", "pin-selected-color",
409 "color for selected pins"),
410 COLOR (PinNameColor, "#ff0000", "pin-name-color",
411 "color for pin names and numbers"),
412 COLOR (ElementColor, "#000000", "element-color", "color for elements"),
413 COLOR (RatColor, "#b8860b", "rat-color", "color for ratlines"),
414 COLOR (InvisibleObjectsColor, "#cccccc", "invisible-objects-color",
415 "color for invisible objects"),
416 COLOR (InvisibleMarkColor, "#cccccc", "invisible-mark-color",
417 "color for invisible marks"),
418 COLOR (ElementSelectedColor, "#00ffff", "element-selected-color",
419 "color for selected elements"),
420 COLOR (RatSelectedColor, "#00ffff", "rat-selected-color",
421 "color for selected rats"),
422 COLOR (ConnectedColor, "#00ff00", "connected-color",
423 "color for connections"),
424 COLOR (OffLimitColor, "#cccccc", "off-limit-color",
425 "color for off-limits areas"),
426 COLOR (GridColor, "#ff0000", "grid-color", "color for the grid"),
427 LAYERCOLOR (1, "#8b2323"),
428 LAYERCOLOR (2, "#3a5fcd"),
429 LAYERCOLOR (3, "#104e8b"),
430 LAYERCOLOR (4, "#cd3700"),
431 LAYERCOLOR (5, "#548b54"),
432 LAYERCOLOR (6, "#8b7355"),
433 LAYERCOLOR (7, "#00868b"),
434 LAYERCOLOR (8, "#228b22"),
435 LAYERCOLOR (9, "#8b2323"),
436 LAYERCOLOR (10, "#3a5fcd"),
437 LAYERCOLOR (11, "#104e8b"),
438 LAYERCOLOR (12, "#cd3700"),
439 LAYERCOLOR (13, "#548b54"),
440 LAYERCOLOR (14, "#8b7355"),
441 LAYERCOLOR (15, "#00868b"),
442 LAYERCOLOR (16, "#228b22"),
443 LAYERSELCOLOR (1),
444 LAYERSELCOLOR (2),
445 LAYERSELCOLOR (3),
446 LAYERSELCOLOR (4),
447 LAYERSELCOLOR (5),
448 LAYERSELCOLOR (6),
449 LAYERSELCOLOR (7),
450 LAYERSELCOLOR (8),
451 LAYERSELCOLOR (9),
452 LAYERSELCOLOR (10),
453 LAYERSELCOLOR (11),
454 LAYERSELCOLOR (12),
455 LAYERSELCOLOR (13),
456 LAYERSELCOLOR (14),
457 LAYERSELCOLOR (15),
458 LAYERSELCOLOR (16),
459 COLOR (WarnColor, "#ff8000", "warn-color", "color for warnings"),
460 COLOR (MaskColor, "#ff0000", "mask-color", "color for solder mask"),
462 ISET (ViaThickness, 6000, "via-thickness", 0),
463 ISET (ViaDrillingHole, 2800, "via-drilling-hole", 0),
464 ISET (LineThickness, 1000, "line-thickness",
465 "Initial thickness of new lines."),
466 ISET (RatThickness, 1000, "rat-thickness", 0),
467 ISET (Keepaway, 1000, "keepaway", 0),
468 ISET (MaxWidth, 600000, "default-PCB-width", 0),
469 ISET (MaxHeight, 500000, "default-PCB-height", 0),
470 ISET (TextScale, 100, "text-scale", 0),
471 ISET (AlignmentDistance, 200, "alignment-distance", 0),
472 ISET (Bloat, 1000, "bloat", 0),
473 ISET (Shrink, 1000, "shrink", 0),
474 ISET (minWid, 1000, "min-width", "DRC minimum copper spacing"),
475 ISET (minSlk, 1000, "min-silk", "DRC minimum silk width"),
476 ISET (minDrill, 1500, "min-drill", "DRC minimum drill diameter"),
477 ISET (minRing, 1000, "min-ring", "DRC minimum annular ring"),
479 RSET (Grid, 1000, "grid", 0),
480 RSET (grid_increment_mm, 0.1, "grid-increment-mm", 0),
481 RSET (grid_increment_mil, 5.0, "grid-increment-mil", 0),
482 RSET (size_increment_mm, 0.2, "size-increment-mm", 0),
483 RSET (size_increment_mil, 10.0, "size-increment-mil", 0),
484 RSET (line_increment_mm, 0.1, "line-increment-mm", 0),
485 RSET (line_increment_mil, 5.0, "line-increment-mil", 0),
486 RSET (clear_increment_mm, 0.05, "clear-increment-mm", 0),
487 RSET (clear_increment_mil, 2.0, "clear-increment-mil", 0),
488 RSET (IsleArea, 200000000, "minimum polygon area", 0),
490 ISET (BackupInterval, 60, "backup-interval", 0),
492 LAYERNAME (1, "component"),
493 LAYERNAME (2, "solder"),
494 LAYERNAME (3, "GND"),
495 LAYERNAME (4, "power"),
496 LAYERNAME (5, "signal1"),
497 LAYERNAME (6, "signal2"),
498 LAYERNAME (7, "signal3"),
499 LAYERNAME (8, "signal4"),
501 SSET (FontCommand, "",
502 "font-command", 0),
503 SSET (FileCommand, "", "file-command", "Command to read a file."),
504 SSET (ElementCommand,
505 "M4PATH='%p';export M4PATH;echo 'include(%f)' | " GNUM4,
506 "element-command", 0),
507 SSET (PrintFile, "%f.output", "print-file", 0),
508 SSET (LibraryCommandDir, PCBLIBDIR, "lib-command-dir", 0),
509 SSET (LibraryCommand, "QueryLibrary.sh '%p' '%f' %a",
510 "lib-command", 0),
511 SSET (LibraryContentsCommand, "ListLibraryContents.sh '%p' '%f'",
512 "lib-contents-command", 0),
513 SSET (LibraryTree, PCBTREEPATH, "lib-newlib",
514 "Top level directory for the newlib style library"),
515 SSET (SaveCommand, "", "save-command", 0),
516 SSET (LibraryFilename, LIBRARYFILENAME, "lib-name", 0),
517 SSET (FontFile, "default_font", "default-font",
518 "File name of default font."),
519 SSET (Groups, "1,c:2,s:3:4:5:6:7:8", "groups", 0),
520 SSET (Routes, "Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000"
521 ":Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600", "route-styles",
523 SSET (FilePath, "", "file-path", 0),
524 SSET (RatCommand, "", "rat-command", 0),
525 SSET (FontPath, PCBLIBPATH, "font-path", 0),
526 SSET (ElementPath, PCBLIBPATH, "element-path", 0),
527 SSET (LibraryPath, PCBLIBPATH, "lib-path", 0),
528 SSET (MenuFile, "pcb-menu.res", "menu-file", 0),
529 SSET (ScriptFilename, 0, "action-script",
530 "If set, this file is executed at startup."),
531 SSET (ActionString, 0, "action-string",
532 "If set, this is executed at startup."),
533 SSET (FabAuthor, "", "fab-author", 0),
534 SSET (InitialLayerStack, "", "layer-stack",
535 "Initial layer stackup, for setting up an export."),
537 SSET (MakeProgram, NULL, "make-program",
538 "Sets the name and optionally full path to a make(3) program"),
539 SSET (GnetlistProgram, NULL, "gnetlist",
540 "Sets the name and optionally full path to the gnetlist(3) program"),
542 ISET (PinoutOffsetX, 100, "pinout-offset-x", 0),
543 ISET (PinoutOffsetY, 100, "pinout-offset-y", 0),
544 ISET (PinoutTextOffsetX, 800, "pinout-text-offset-x", 0),
545 ISET (PinoutTextOffsetY, -100, "pinout-text-offset-y", 0),
547 BSET (DrawGrid, 0, "draw-grid", "default to drawing the grid at startup"),
548 BSET (ClearLine, 1, "clear-line", 0),
549 BSET (FullPoly, 0, "full-poly", 0),
550 BSET (UniqueNames, 1, "unique-names", 0),
551 BSET (SnapPin, 1, "snap-pin", 0),
552 BSET (SaveLastCommand, 0, "save-last-command", 0),
553 BSET (SaveInTMP, 0, "save-in-tmp", 0),
554 BSET (AllDirectionLines, 0, "all-direction-lines", 0),
555 BSET (ShowNumber, 0, "show-number", 0),
556 BSET (ResetAfterElement, 1, "reset-after-element", 0),
557 BSET (RingBellWhenFinished, 0, "ring-bell-finished", 0),
560 REGISTER_ATTRIBUTES (main_attribute_list)
561 /* ----------------------------------------------------------------------
562 * post-process settings.
564 static void settings_post_process ()
566 char *tmps;
568 if (Settings.LibraryCommand[0] != PCB_DIR_SEPARATOR_C && Settings.LibraryCommand[0] != '.')
570 Settings.LibraryCommand
572 Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
573 Settings.LibraryCommand,
574 NULL);
576 if (Settings.LibraryContentsCommand[0] != PCB_DIR_SEPARATOR_C
577 && Settings.LibraryContentsCommand[0] != '.')
579 Settings.LibraryContentsCommand
581 Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
582 Settings.LibraryContentsCommand, NULL);
585 if (Settings.LineThickness > MAX_LINESIZE
586 || Settings.LineThickness < MIN_LINESIZE)
587 Settings.LineThickness = 1000;
589 if (Settings.ViaThickness > MAX_PINORVIASIZE
590 || Settings.ViaThickness < MIN_PINORVIASIZE)
591 Settings.ViaThickness = 4000;
593 if (Settings.ViaDrillingHole <= 0)
594 Settings.ViaDrillingHole =
595 DEFAULT_DRILLINGHOLE * Settings.ViaThickness / 100;
597 Settings.MaxWidth = MIN (MAX_COORD, MAX (Settings.MaxWidth, MIN_SIZE));
598 Settings.MaxHeight = MIN (MAX_COORD, MAX (Settings.MaxHeight, MIN_SIZE));
600 ParseRouteString (Settings.Routes, &Settings.RouteStyle[0], 1);
603 * Make sure we have settings for some various programs we may wish
604 * to call
606 if (Settings.MakeProgram == NULL) {
607 tmps = getenv ("PCB_MAKE_PROGRAM");
608 if (tmps != NULL)
609 Settings.MakeProgram = strdup (tmps);
611 if (Settings.MakeProgram == NULL) {
612 Settings.MakeProgram = strdup ("make");
615 if (Settings.GnetlistProgram == NULL) {
616 tmps = getenv ("PCB_GNETLIST");
617 if (tmps != NULL)
618 Settings.GnetlistProgram = strdup (tmps);
620 if (Settings.GnetlistProgram == NULL) {
621 Settings.GnetlistProgram = strdup ("gnetlist");
627 /* ----------------------------------------------------------------------
628 * Print help or version messages.
631 static void
632 print_version ()
634 printf ("PCB version %s\n", VERSION);
635 exit (0);
638 /* ----------------------------------------------------------------------
639 * Figure out the canonical name of the executed program
640 * and fix up the defaults for various paths
642 char *bindir = NULL;
643 char *exec_prefix = NULL;
644 char *pcblibdir = NULL;
645 char *pcblibpath = NULL;
646 char *pcbtreedir = NULL;
647 char *pcbtreepath = NULL;
648 char *homedir = NULL;
650 static void
651 InitPaths (char *argv0)
653 size_t l;
654 int i;
655 int haspath;
656 char *t1, *t2;
657 int found_bindir = 0;
659 /* see if argv0 has enough of a path to let lrealpath give the
660 * real path. This should be the case if you invoke pcb with
661 * something like /usr/local/bin/pcb or ./pcb or ./foo/pcb
662 * but if you just use pcb and it exists in your path, you'll
663 * just get back pcb again.
666 haspath = 0;
667 for (i = 0; i < strlen (argv0) ; i++)
669 if (argv0[i] == PCB_DIR_SEPARATOR_C)
670 haspath = 1;
673 #ifdef DEBUG
674 printf ("InitPaths (%s): haspath = %d\n", argv0, haspath);
675 #endif
677 if (haspath)
679 bindir = strdup (lrealpath (argv0));
680 found_bindir = 1;
682 else
684 char *path, *p, *tmps;
685 struct stat sb;
686 int r;
688 tmps = getenv ("PATH");
690 if (tmps != NULL)
692 path = strdup (tmps);
694 /* search through the font path for a font file */
695 for (p = strtok (path, PCB_PATH_DELIMETER); p && *p;
696 p = strtok (NULL, PCB_PATH_DELIMETER))
698 #ifdef DEBUG
699 printf ("Looking for %s in %s\n", argv0, p);
700 #endif
701 if ( (tmps = malloc ( (strlen (argv0) + strlen (p) + 2) * sizeof (char))) == NULL )
703 fprintf (stderr, "InitPaths(): malloc failed\n");
704 exit (1);
706 sprintf (tmps, "%s%s%s", p, PCB_DIR_SEPARATOR_S, argv0);
707 r = stat (tmps, &sb);
708 if (r == 0)
710 #ifdef DEBUG
711 printf ("Found it: \"%s\"\n", tmps);
712 #endif
713 bindir = lrealpath (tmps);
714 found_bindir = 1;
715 free (tmps);
716 break;
718 free (tmps);
720 free (path);
724 #ifdef DEBUG
725 printf ("InitPaths(): bindir = \"%s\"\n", bindir);
726 #endif
728 if (found_bindir)
730 /* strip off the executible name leaving only the path */
731 t2 = NULL;
732 t1 = strchr (bindir, PCB_DIR_SEPARATOR_C);
733 while (t1 != NULL && *t1 != '\0')
735 t2 = t1;
736 t1 = strchr (t2 + 1, PCB_DIR_SEPARATOR_C);
738 if (t2 != NULL)
739 *t2 = '\0';
741 #ifdef DEBUG
742 printf ("After stripping off the executible name, we found\n");
743 printf ("bindir = \"%s\"\n", bindir);
744 #endif
746 else
748 /* we have failed to find out anything from argv[0] so fall back to the original
749 * install prefix
751 bindir = strdup (BINDIR);
754 /* now find the path to exec_prefix */
755 l = strlen (bindir) + 1 + strlen (BINDIR_TO_EXECPREFIX) + 1;
756 if ( (exec_prefix = (char *) malloc (l * sizeof (char) )) == NULL )
758 fprintf (stderr, "InitPaths(): malloc failed\n");
759 exit (1);
761 sprintf (exec_prefix, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
762 BINDIR_TO_EXECPREFIX);
764 /* now find the path to PCBLIBDIR */
765 l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBLIBDIR) + 1;
766 if ( (pcblibdir = (char *) malloc (l * sizeof (char) )) == NULL )
768 fprintf (stderr, "InitPaths(): malloc failed\n");
769 exit (1);
771 sprintf (pcblibdir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
772 BINDIR_TO_PCBLIBDIR);
774 /* and the path to PCBTREEDIR */
775 l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBTREEDIR) + 1;
776 if ( (pcbtreedir = (char *) malloc (l * sizeof (char) )) == NULL )
778 fprintf (stderr, "InitPaths(): malloc failed\n");
779 exit (1);
781 sprintf (pcbtreedir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
782 BINDIR_TO_PCBTREEDIR);
784 /* and the search path including PCBLIBDIR */
785 l = strlen (pcblibdir) + 3;
786 if ( (pcblibpath = (char *) malloc (l * sizeof (char) )) == NULL )
788 fprintf (stderr, "InitPaths(): malloc failed\n");
789 exit (1);
791 sprintf (pcblibpath, ".%s%s", PCB_PATH_DELIMETER, pcblibdir);
793 /* and the newlib search path */
794 l = strlen (pcblibdir) + 1 + strlen (pcbtreedir)
795 + strlen ("pcblib-newlib") + 2;
796 if ( (pcbtreepath = (char *) malloc (l * sizeof (char) )) == NULL )
798 fprintf (stderr, "InitPaths(): malloc failed\n");
799 exit (1);
801 sprintf (pcbtreepath, "%s%s%s%spcblib-newlib", pcbtreedir,
802 PCB_PATH_DELIMETER, pcblibdir,
803 PCB_DIR_SEPARATOR_S);
805 #ifdef DEBUG
806 printf ("bindir = %s\n", bindir);
807 printf ("pcblibdir = %s\n", pcblibdir);
808 printf ("pcblibpath = %s\n", pcblibpath);
809 printf ("pcbtreedir = %s\n", pcbtreedir);
810 printf ("pcbtreepath = %s\n", pcbtreepath);
811 #endif
813 l = sizeof (main_attribute_list) / sizeof (main_attribute_list[0]);
814 for (i = 0; i < l ; i++)
816 if (NSTRCMP (main_attribute_list[i].name, "lib-command-dir") == 0)
818 main_attribute_list[i].default_val.str_value = pcblibdir;
821 if ( (NSTRCMP (main_attribute_list[i].name, "font-path") == 0)
822 || (NSTRCMP (main_attribute_list[i].name, "element-path") == 0)
823 || (NSTRCMP (main_attribute_list[i].name, "lib-path") == 0) )
825 main_attribute_list[i].default_val.str_value = pcblibpath;
828 if (NSTRCMP (main_attribute_list[i].name, "lib-newlib") == 0)
830 main_attribute_list[i].default_val.str_value = pcbtreepath;
836 char *tmps;
838 tmps = getenv ("HOME");
840 if (tmps == NULL) {
841 tmps = getenv ("USERPROFILE");
844 if (tmps != NULL) {
845 homedir = strdup (tmps);
846 } else {
847 homedir = NULL;
853 /* ----------------------------------------------------------------------
854 * main program
857 char *program_name = 0;
858 char *program_basename = 0;
859 char *program_directory = 0;
861 #include "dolists.h"
864 main (int argc, char *argv[])
866 int i;
868 /* init application:
869 * - make program name available for error handlers
870 * - evaluate special options
871 * - initialize toplevel shell and resources
872 * - create an empty PCB with default symbols
873 * - initialize all other widgets
874 * - update screen and get size of drawing area
875 * - evaluate command-line arguments
876 * - register 'call on exit()' function
879 #include "core_lists.h"
880 setbuf (stdout, 0);
881 InitPaths (argv[0]);
883 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
884 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
886 hid_init ();
888 hid_load_settings ();
890 program_name = argv[0];
891 program_basename = strrchr (program_name, PCB_DIR_SEPARATOR_C);
892 if (program_basename)
894 program_directory = strdup (program_name);
895 *strrchr (program_directory, PCB_DIR_SEPARATOR_C) = 0;
896 program_basename++;
898 else
900 program_directory = ".";
901 program_basename = program_name;
903 Progname = program_basename;
905 if (argc > 1 && strcmp (argv[1], "-h") == 0)
906 usage ();
907 if (argc > 1 && strcmp (argv[1], "-V") == 0)
908 print_version ();
909 if (argc > 1 && strcmp (argv[1], "-p") == 0)
911 exporter = gui = hid_find_printer ();
912 argc--;
913 argv++;
915 else if (argc > 2 && strcmp (argv[1], "-x") == 0)
917 exporter = gui = hid_find_exporter (argv[2]);
918 argc -= 2;
919 argv += 2;
921 else
922 gui = hid_find_gui ();
924 if (!gui)
925 exit (1);
927 for (i = 0; i < MAX_LAYER; i++)
929 char buf[20];
930 sprintf (buf, "signal%d", i + 1);
931 Settings.DefaultLayerName[i] = MyStrdup (buf, "DefaultLayerNames");
932 Settings.LayerColor[i] = "#c49350";
933 Settings.LayerSelectedColor[i] = "#00ffff";
936 gui->parse_arguments (&argc, &argv);
938 if (show_help || (argc > 1 && argv[1][0] == '-'))
939 usage ();
940 if (show_version)
941 print_version ();
942 if (show_defaults)
943 print_defaults ();
944 if (show_copyright)
945 copyright ();
947 Output.bgGC = gui->make_gc ();
948 Output.fgGC = gui->make_gc ();
949 Output.pmGC = gui->make_gc ();
950 Output.GridGC = gui->make_gc ();
952 settings_post_process ();
955 if (show_actions)
957 print_actions ();
958 exit (0);
961 if (do_dump_actions)
963 extern void dump_actions (void);
964 dump_actions ();
965 exit (0);
968 PCB = CreateNewPCB (True);
969 PCB->Data->LayerN = DEF_LAYER;
970 ParseGroupString (Settings.Groups, &PCB->LayerGroups, DEF_LAYER);
971 CreateNewPCBPost (PCB, 1);
972 if (argc > 1)
973 command_line_pcb = argv[1];
975 ResetStackAndVisibility ();
977 CreateDefaultFont ();
978 if (gui->gui)
979 InitCrosshair ();
980 InitHandler ();
981 InitBuffers ();
982 SetMode (ARROW_MODE);
984 if (command_line_pcb)
986 /* keep filename even if initial load command failed;
987 * file might not exist
989 if (LoadPCB (command_line_pcb))
990 PCB->Filename = MyStrdup (command_line_pcb, "main()");
993 if (Settings.InitialLayerStack
994 && Settings.InitialLayerStack[0])
996 LayerStringToLayerStack (Settings.InitialLayerStack);
999 if (gui->printer || gui->exporter)
1001 gui->do_export (0);
1002 exit (0);
1005 /* FIX_ME
1006 LoadBackgroundImage (Settings.BackgroundImage); */
1008 /* Register a function to be called when the program terminates.
1009 * This makes sure that data is saved even if LEX/YACC routines
1010 * abort the program.
1011 * If the OS doesn't have at least one of them,
1012 * the critical sections will be handled by parse_l.l
1014 atexit (EmergencySave);
1016 /* read the library file and display it if it's not empty
1018 if (!ReadLibraryContents () && Library.MenuN)
1019 hid_action ("LibraryChanged");
1021 #ifdef HAVE_LIBSTROKE
1022 stroke_init ();
1023 #endif
1025 * Set this flag to zero. Then if we have a startup
1026 * action which includes Quit(), the flag will be set
1027 * to -1 and we can avoid ever calling gtk_main();
1029 Settings.init_done = 0;
1031 if (Settings.ScriptFilename)
1033 Message (_("Executing startup script file %s\n"),
1034 Settings.ScriptFilename);
1035 hid_actionl ("ExecuteFile", Settings.ScriptFilename, NULL);
1037 if (Settings.ActionString)
1039 Message (_("Executing startup action %s\n"), Settings.ActionString);
1040 hid_parse_actions (Settings.ActionString, 0);
1043 if (Settings.init_done == 0)
1045 Settings.init_done = 1;
1046 #if HAVE_DBUS
1047 pcb_dbus_setup();
1048 #endif
1050 EnableAutosave ();
1052 #ifdef DEBUG
1053 printf ("Settings.LibraryCommandDir = \"%s\"\n",
1054 Settings.LibraryCommandDir);
1055 printf ("Settings.FontPath = \"%s\"\n",
1056 Settings.FontPath);
1057 printf ("Settings.ElementPath = \"%s\"\n",
1058 Settings.ElementPath);
1059 printf ("Settings.LibraryPath = \"%s\"\n",
1060 Settings.LibraryPath);
1061 printf ("Settings.LibraryTree = \"%s\"\n",
1062 Settings.LibraryTree);
1063 printf ("Settings.MakeProgram = \"%s\"\n",
1064 UNKNOWN (Settings.MakeProgram));
1065 printf ("Settings.GnetlistProgram = \"%s\"\n",
1066 UNKNOWN (Settings.GnetlistProgram));
1067 #endif
1069 gui->do_export (0);
1070 #if HAVE_DBUS
1071 pcb_dbus_finish();
1072 #endif
1075 return (0);