Introduce POLYGONHOLE_MODE for creating holes in polygons
[geda-pcb/gde.git] / src / main.c
blob3340c7fc6c672548f4b929013d5238d2a1d6e45e
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 *attributes;
204 int i, n_attributes = 0;
206 if (h->gui)
208 fprintf (stderr, "\n%s gui options:\n", h->name);
209 attributes = h->get_export_options (&n_attributes);
211 else
213 fprintf (stderr, "\n%s options:\n", h->name);
214 exporter = h;
215 attributes = exporter->get_export_options (&n_attributes);
216 exporter = NULL;
219 for (i = 0; i < n_attributes; i++)
220 usage_attr (attributes + i);
223 static void
224 usage (void)
226 HID **hl = hid_enumerate ();
227 int i;
228 int n_printer = 0, n_gui = 0, n_exporter = 0;
230 for (i = 0; hl[i]; i++)
232 if (hl[i]->gui)
233 n_gui++;
234 if (hl[i]->printer)
235 n_printer++;
236 if (hl[i]->exporter)
237 n_exporter++;
240 u ("PCB Printed Circuit Board editing program, http://pcb.gpleda.org");
241 u ("%s [-h|-V|--copyright]\t\t\tHelp, version, copyright", Progname);
242 u ("%s [gui options] <pcb file>\t\tto edit", Progname);
243 u ("Available GUI hid%s:", n_gui == 1 ? "" : "s");
244 for (i = 0; hl[i]; i++)
245 if (hl[i]->gui)
246 fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
247 u ("%s -p [printing options] <pcb file>\tto print", Progname);
248 u ("Available printing hid%s:", n_printer == 1 ? "" : "s");
249 for (i = 0; hl[i]; i++)
250 if (hl[i]->printer)
251 fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
252 u ("%s -x hid [export options] <pcb file>\tto export", Progname);
253 u ("Available export hid%s:", n_exporter == 1 ? "" : "s");
254 for (i = 0; hl[i]; i++)
255 if (hl[i]->exporter)
256 fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
258 for (i = 0; hl[i]; i++)
259 if (hl[i]->gui)
260 usage_hid (hl[i]);
261 for (i = 0; hl[i]; i++)
262 if (hl[i]->printer)
263 usage_hid (hl[i]);
264 for (i = 0; hl[i]; i++)
265 if (hl[i]->exporter)
266 usage_hid (hl[i]);
267 exit (1);
270 static void
271 print_defaults_1 (HID_Attribute * a, void *value)
273 int i;
274 double d;
275 char *s;
277 /* Remember, at this point we've parsed the command line, so they
278 may be in the global variable instead of the default_val. */
279 switch (a->type)
281 case HID_Integer:
282 i = value ? *(int *) value : a->default_val.int_value;
283 fprintf (stderr, "%s %d\n", a->name, i);
284 break;
285 case HID_Boolean:
286 i = value ? *(char *) value : a->default_val.int_value;
287 fprintf (stderr, "%s %s\n", a->name, i ? "yes" : "no");
288 break;
289 case HID_Real:
290 d = value ? *(double *) value : a->default_val.real_value;
291 fprintf (stderr, "%s %g\n", a->name, d);
292 break;
293 case HID_String:
294 case HID_Path:
295 s = value ? *(char **) value : a->default_val.str_value;
296 fprintf (stderr, "%s \"%s\"\n", a->name, s);
297 break;
298 case HID_Enum:
299 i = value ? *(int *) value : a->default_val.int_value;
300 fprintf (stderr, "%s %s\n", a->name, a->enumerations[i]);
301 break;
302 case HID_Mixed:
303 i = value ?
304 ((HID_Attr_Val*)value)->int_value : a->default_val.int_value;
305 d = value ?
306 ((HID_Attr_Val*)value)->real_value : a->default_val.real_value;
307 fprintf (stderr, "%s %g%s\n", a->name, d, a->enumerations[i]);
308 break;
309 case HID_Label:
310 break;
314 static void
315 print_defaults ()
317 HID **hl = hid_enumerate ();
318 HID_Attribute *e;
319 int i, n, hi;
321 for (hi = 0; hl[hi]; hi++)
323 HID *h = hl[hi];
324 if (h->gui)
326 HID_AttrNode *ha;
327 fprintf (stderr, "\ngui defaults:\n");
328 for (ha = hid_attr_nodes; ha; ha = ha->next)
329 for (i = 0; i < ha->n; i++)
330 print_defaults_1 (ha->attributes + i, ha->attributes[i].value);
332 else
334 fprintf (stderr, "\n%s defaults:\n", h->name);
335 exporter = h;
336 e = exporter->get_export_options (&n);
337 exporter = NULL;
338 if (e)
339 for (i = 0; i < n; i++)
340 print_defaults_1 (e + i, 0);
343 exit (1);
346 /* in hid/common/actions.c */
347 extern void print_actions ();
350 #define SSET(F,D,N,H) { N, H, \
351 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.F }
352 #define ISET(F,D,N,H) { N, H, \
353 HID_Integer, 0, 0, { D, 0, 0 }, 0, &Settings.F }
354 #define BSET(F,D,N,H) { N, H, \
355 HID_Boolean, 0, 0, { D, 0, 0 }, 0, &Settings.F }
356 #define RSET(F,D,N,H) { N, H, \
357 HID_Real, 0, 0, { 0, 0, D }, 0, &Settings.F }
359 #define COLOR(F,D,N,H) { N, H, \
360 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.F }
361 #define LAYERCOLOR(N,D) { "layer-color-" #N, "Color for layer " #N, \
362 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.LayerColor[N-1] }
363 #define LAYERNAME(N,D) { "layer-name-" #N, "Name for layer " #N, \
364 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.DefaultLayerName[N-1] }
365 #define LAYERSELCOLOR(N) { "layer-selected-color-" #N, "Color for layer " #N " when selected", \
366 HID_String, 0, 0, { 0, "#00ffff", 0 }, 0, &Settings.LayerSelectedColor[N-1] }
368 static int show_help = 0;
369 static int show_version = 0;
370 static int show_copyright = 0;
371 static int show_defaults = 0;
372 static int show_actions = 0;
373 static int do_dump_actions = 0;
375 HID_Attribute main_attribute_list[] = {
376 {"help", "Show Help", HID_Boolean, 0, 0, {0, 0, 0}, 0, &show_help},
377 {"version", "Show Version", HID_Boolean, 0, 0, {0, 0, 0}, 0, &show_version},
378 {"verbose", "Be verbose", HID_Boolean, 0, 0, {0, 0, 0}, 0,
379 &Settings.verbose},
380 {"copyright", "Show Copyright", HID_Boolean, 0, 0, {0, 0, 0}, 0,
381 &show_copyright},
382 {"show-defaults", "Show option defaults", HID_Boolean, 0, 0, {0, 0, 0}, 0,
383 &show_defaults},
384 {"show-actions", "Show actions", HID_Boolean, 0, 0, {0, 0, 0}, 0,
385 &show_actions},
386 {"dump-actions", "Dump actions (for documentation)", HID_Boolean, 0, 0,
387 {0, 0, 0}, 0,
388 &do_dump_actions},
390 BSET (grid_units_mm, 0, "grid-units-mm", 0),
392 COLOR (BlackColor, "#000000", "black-color", "color for black"),
393 COLOR (WhiteColor, "#ffffff", "white-color", "color for white"),
394 COLOR (BackgroundColor, "#e5e5e5", "background-color",
395 "color for background"),
396 COLOR (CrosshairColor, "#ff0000", "crosshair-color",
397 "color for the crosshair"),
398 COLOR (CrossColor, "#cdcd00", "cross-color", "color for cross"),
399 COLOR (ViaColor, "#7f7f7f", "via-color", "color for vias"),
400 COLOR (ViaSelectedColor, "#00ffff", "via-selected-color",
401 "color for selected vias"),
402 COLOR (PinColor, "#4d4d4d", "pin-color", "color for pins"),
403 COLOR (PinSelectedColor, "#00ffff", "pin-selected-color",
404 "color for selected pins"),
405 COLOR (PinNameColor, "#ff0000", "pin-name-color",
406 "color for pin names and numbers"),
407 COLOR (ElementColor, "#000000", "element-color", "color for elements"),
408 COLOR (RatColor, "#b8860b", "rat-color", "color for ratlines"),
409 COLOR (InvisibleObjectsColor, "#cccccc", "invisible-objects-color",
410 "color for invisible objects"),
411 COLOR (InvisibleMarkColor, "#cccccc", "invisible-mark-color",
412 "color for invisible marks"),
413 COLOR (ElementSelectedColor, "#00ffff", "element-selected-color",
414 "color for selected elements"),
415 COLOR (RatSelectedColor, "#00ffff", "rat-selected-color",
416 "color for selected rats"),
417 COLOR (ConnectedColor, "#00ff00", "connected-color",
418 "color for connections"),
419 COLOR (OffLimitColor, "#cccccc", "off-limit-color",
420 "color for off-limits areas"),
421 COLOR (GridColor, "#ff0000", "grid-color", "color for the grid"),
422 LAYERCOLOR (1, "#8b2323"),
423 LAYERCOLOR (2, "#3a5fcd"),
424 LAYERCOLOR (3, "#104e8b"),
425 LAYERCOLOR (4, "#cd3700"),
426 LAYERCOLOR (5, "#548b54"),
427 LAYERCOLOR (6, "#8b7355"),
428 LAYERCOLOR (7, "#00868b"),
429 LAYERCOLOR (8, "#228b22"),
430 LAYERCOLOR (9, "#8b2323"),
431 LAYERCOLOR (10, "#3a5fcd"),
432 LAYERCOLOR (11, "#104e8b"),
433 LAYERCOLOR (12, "#cd3700"),
434 LAYERCOLOR (13, "#548b54"),
435 LAYERCOLOR (14, "#8b7355"),
436 LAYERCOLOR (15, "#00868b"),
437 LAYERCOLOR (16, "#228b22"),
438 LAYERSELCOLOR (1),
439 LAYERSELCOLOR (2),
440 LAYERSELCOLOR (3),
441 LAYERSELCOLOR (4),
442 LAYERSELCOLOR (5),
443 LAYERSELCOLOR (6),
444 LAYERSELCOLOR (7),
445 LAYERSELCOLOR (8),
446 LAYERSELCOLOR (9),
447 LAYERSELCOLOR (10),
448 LAYERSELCOLOR (11),
449 LAYERSELCOLOR (12),
450 LAYERSELCOLOR (13),
451 LAYERSELCOLOR (14),
452 LAYERSELCOLOR (15),
453 LAYERSELCOLOR (16),
454 COLOR (WarnColor, "#ff8000", "warn-color", "color for warnings"),
455 COLOR (MaskColor, "#ff0000", "mask-color", "color for solder mask"),
457 ISET (ViaThickness, 6000, "via-thickness", 0),
458 ISET (ViaDrillingHole, 2800, "via-drilling-hole", 0),
459 ISET (LineThickness, 1000, "line-thickness",
460 "Initial thickness of new lines."),
461 ISET (RatThickness, 1000, "rat-thickness", 0),
462 ISET (Keepaway, 1000, "keepaway", 0),
463 ISET (MaxWidth, 600000, "default-PCB-width", 0),
464 ISET (MaxHeight, 500000, "default-PCB-height", 0),
465 ISET (TextScale, 100, "text-scale", 0),
466 ISET (AlignmentDistance, 200, "alignment-distance", 0),
467 ISET (Bloat, 1000, "bloat", 0),
468 ISET (Shrink, 1000, "shrink", 0),
469 ISET (minWid, 1000, "min-width", "DRC minimum copper spacing"),
470 ISET (minSlk, 1000, "min-silk", "DRC minimum silk width"),
471 ISET (minDrill, 1500, "min-drill", "DRC minimum drill diameter"),
472 ISET (minRing, 1000, "min-ring", "DRC minimum annular ring"),
474 RSET (Grid, 1000, "grid", 0),
475 RSET (grid_increment_mm, 0.1, "grid-increment-mm", 0),
476 RSET (grid_increment_mil, 5.0, "grid-increment-mil", 0),
477 RSET (size_increment_mm, 0.2, "size-increment-mm", 0),
478 RSET (size_increment_mil, 10.0, "size-increment-mil", 0),
479 RSET (line_increment_mm, 0.1, "line-increment-mm", 0),
480 RSET (line_increment_mil, 5.0, "line-increment-mil", 0),
481 RSET (clear_increment_mm, 0.05, "clear-increment-mm", 0),
482 RSET (clear_increment_mil, 2.0, "clear-increment-mil", 0),
483 RSET (IsleArea, 200000000, "minimum polygon area", 0),
485 ISET (BackupInterval, 60, "backup-interval", 0),
487 LAYERNAME (1, "component"),
488 LAYERNAME (2, "solder"),
489 LAYERNAME (3, "GND"),
490 LAYERNAME (4, "power"),
491 LAYERNAME (5, "signal1"),
492 LAYERNAME (6, "signal2"),
493 LAYERNAME (7, "signal3"),
494 LAYERNAME (8, "signal4"),
496 SSET (FontCommand, "",
497 "font-command", 0),
498 SSET (FileCommand, "", "file-command", "Command to read a file."),
499 SSET (ElementCommand,
500 "M4PATH='%p';export M4PATH;echo 'include(%f)' | " GNUM4,
501 "element-command", 0),
502 SSET (PrintFile, "%f.output", "print-file", 0),
503 SSET (LibraryCommandDir, PCBLIBDIR, "lib-command-dir", 0),
504 SSET (LibraryCommand, "QueryLibrary.sh '%p' '%f' %a",
505 "lib-command", 0),
506 SSET (LibraryContentsCommand, "ListLibraryContents.sh '%p' '%f'",
507 "lib-contents-command", 0),
508 SSET (LibraryTree, PCBTREEPATH, "lib-newlib",
509 "Top level directory for the newlib style library"),
510 SSET (SaveCommand, "", "save-command", 0),
511 SSET (LibraryFilename, LIBRARYFILENAME, "lib-name", 0),
512 SSET (FontFile, "default_font", "default-font",
513 "File name of default font."),
514 SSET (Groups, "1,c:2,s:3:4:5:6:7:8", "groups", 0),
515 SSET (Routes, "Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000"
516 ":Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600", "route-styles",
518 SSET (FilePath, "", "file-path", 0),
519 SSET (RatCommand, "", "rat-command", 0),
520 SSET (FontPath, PCBLIBPATH, "font-path", 0),
521 SSET (ElementPath, PCBLIBPATH, "element-path", 0),
522 SSET (LibraryPath, PCBLIBPATH, "lib-path", 0),
523 SSET (MenuFile, "pcb-menu.res", "menu-file", 0),
524 SSET (ScriptFilename, 0, "action-script",
525 "If set, this file is executed at startup."),
526 SSET (ActionString, 0, "action-string",
527 "If set, this is executed at startup."),
528 SSET (FabAuthor, "", "fab-author", 0),
529 SSET (InitialLayerStack, "", "layer-stack",
530 "Initial layer stackup, for setting up an export."),
532 SSET (MakeProgram, NULL, "make-program",
533 "Sets the name and optionally full path to a make(3) program"),
534 SSET (GnetlistProgram, NULL, "gnetlist",
535 "Sets the name and optionally full path to the gnetlist(3) program"),
537 ISET (PinoutOffsetX, 100, "pinout-offset-x", 0),
538 ISET (PinoutOffsetY, 100, "pinout-offset-y", 0),
539 ISET (PinoutTextOffsetX, 800, "pinout-text-offset-x", 0),
540 ISET (PinoutTextOffsetY, -100, "pinout-text-offset-y", 0),
542 BSET (DrawGrid, 0, "draw-grid", "default to drawing the grid at startup"),
543 BSET (ClearLine, 1, "clear-line", 0),
544 BSET (FullPoly, 0, "full-poly", 0),
545 BSET (UniqueNames, 1, "unique-names", 0),
546 BSET (SnapPin, 1, "snap-pin", 0),
547 BSET (SaveLastCommand, 0, "save-last-command", 0),
548 BSET (SaveInTMP, 0, "save-in-tmp", 0),
549 BSET (AllDirectionLines, 0, "all-direction-lines", 0),
550 BSET (ShowNumber, 0, "show-number", 0),
551 BSET (ResetAfterElement, 1, "reset-after-element", 0),
552 BSET (RingBellWhenFinished, 0, "ring-bell-finished", 0),
555 REGISTER_ATTRIBUTES (main_attribute_list)
556 /* ----------------------------------------------------------------------
557 * post-process settings.
559 static void settings_post_process ()
561 char *tmps;
563 if (Settings.LibraryCommand[0] != PCB_DIR_SEPARATOR_C && Settings.LibraryCommand[0] != '.')
565 Settings.LibraryCommand
567 Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
568 Settings.LibraryCommand,
569 NULL);
571 if (Settings.LibraryContentsCommand[0] != PCB_DIR_SEPARATOR_C
572 && Settings.LibraryContentsCommand[0] != '.')
574 Settings.LibraryContentsCommand
576 Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
577 Settings.LibraryContentsCommand, NULL);
580 if (Settings.LineThickness > MAX_LINESIZE
581 || Settings.LineThickness < MIN_LINESIZE)
582 Settings.LineThickness = 1000;
584 if (Settings.ViaThickness > MAX_PINORVIASIZE
585 || Settings.ViaThickness < MIN_PINORVIASIZE)
586 Settings.ViaThickness = 4000;
588 if (Settings.ViaDrillingHole <= 0)
589 Settings.ViaDrillingHole =
590 DEFAULT_DRILLINGHOLE * Settings.ViaThickness / 100;
592 Settings.MaxWidth = MIN (MAX_COORD, MAX (Settings.MaxWidth, MIN_SIZE));
593 Settings.MaxHeight = MIN (MAX_COORD, MAX (Settings.MaxHeight, MIN_SIZE));
595 ParseRouteString (Settings.Routes, &Settings.RouteStyle[0], 1);
598 * Make sure we have settings for some various programs we may wish
599 * to call
601 if (Settings.MakeProgram == NULL) {
602 tmps = getenv ("PCB_MAKE_PROGRAM");
603 if (tmps != NULL)
604 Settings.MakeProgram = strdup (tmps);
606 if (Settings.MakeProgram == NULL) {
607 Settings.MakeProgram = strdup ("make");
610 if (Settings.GnetlistProgram == NULL) {
611 tmps = getenv ("PCB_GNETLIST");
612 if (tmps != NULL)
613 Settings.GnetlistProgram = strdup (tmps);
615 if (Settings.GnetlistProgram == NULL) {
616 Settings.GnetlistProgram = strdup ("gnetlist");
622 /* ----------------------------------------------------------------------
623 * Print help or version messages.
626 static void
627 print_version ()
629 printf ("PCB version %s\n", VERSION);
630 exit (0);
633 /* ----------------------------------------------------------------------
634 * Figure out the canonical name of the executed program
635 * and fix up the defaults for various paths
637 char *bindir = NULL;
638 char *exec_prefix = NULL;
639 char *pcblibdir = NULL;
640 char *pcblibpath = NULL;
641 char *pcbtreedir = NULL;
642 char *pcbtreepath = NULL;
643 char *homedir = NULL;
645 static void
646 InitPaths (char *argv0)
648 size_t l;
649 int i;
650 int haspath;
651 char *t1, *t2;
652 int found_bindir = 0;
654 /* see if argv0 has enough of a path to let lrealpath give the
655 * real path. This should be the case if you invoke pcb with
656 * something like /usr/local/bin/pcb or ./pcb or ./foo/pcb
657 * but if you just use pcb and it exists in your path, you'll
658 * just get back pcb again.
661 haspath = 0;
662 for (i = 0; i < strlen (argv0) ; i++)
664 if (argv0[i] == PCB_DIR_SEPARATOR_C)
665 haspath = 1;
668 #ifdef DEBUG
669 printf ("InitPaths (%s): haspath = %d\n", argv0, haspath);
670 #endif
672 if (haspath)
674 bindir = strdup (lrealpath (argv0));
675 found_bindir = 1;
677 else
679 char *path, *p, *tmps;
680 struct stat sb;
681 int r;
683 tmps = getenv ("PATH");
685 if (tmps != NULL)
687 path = strdup (tmps);
689 /* search through the font path for a font file */
690 for (p = strtok (path, PCB_PATH_DELIMETER); p && *p;
691 p = strtok (NULL, PCB_PATH_DELIMETER))
693 #ifdef DEBUG
694 printf ("Looking for %s in %s\n", argv0, p);
695 #endif
696 if ( (tmps = malloc ( (strlen (argv0) + strlen (p) + 2) * sizeof (char))) == NULL )
698 fprintf (stderr, "InitPaths(): malloc failed\n");
699 exit (1);
701 sprintf (tmps, "%s%s%s", p, PCB_DIR_SEPARATOR_S, argv0);
702 r = stat (tmps, &sb);
703 if (r == 0)
705 #ifdef DEBUG
706 printf ("Found it: \"%s\"\n", tmps);
707 #endif
708 bindir = lrealpath (tmps);
709 found_bindir = 1;
710 free (tmps);
711 break;
713 free (tmps);
715 free (path);
719 #ifdef DEBUG
720 printf ("InitPaths(): bindir = \"%s\"\n", bindir);
721 #endif
723 if (found_bindir)
725 /* strip off the executible name leaving only the path */
726 t2 = NULL;
727 t1 = strchr (bindir, PCB_DIR_SEPARATOR_C);
728 while (t1 != NULL && *t1 != '\0')
730 t2 = t1;
731 t1 = strchr (t2 + 1, PCB_DIR_SEPARATOR_C);
733 if (t2 != NULL)
734 *t2 = '\0';
736 #ifdef DEBUG
737 printf ("After stripping off the executible name, we found\n");
738 printf ("bindir = \"%s\"\n", bindir);
739 #endif
741 else
743 /* we have failed to find out anything from argv[0] so fall back to the original
744 * install prefix
746 bindir = strdup (BINDIR);
749 /* now find the path to exec_prefix */
750 l = strlen (bindir) + 1 + strlen (BINDIR_TO_EXECPREFIX) + 1;
751 if ( (exec_prefix = (char *) malloc (l * sizeof (char) )) == NULL )
753 fprintf (stderr, "InitPaths(): malloc failed\n");
754 exit (1);
756 sprintf (exec_prefix, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
757 BINDIR_TO_EXECPREFIX);
759 /* now find the path to PCBLIBDIR */
760 l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBLIBDIR) + 1;
761 if ( (pcblibdir = (char *) malloc (l * sizeof (char) )) == NULL )
763 fprintf (stderr, "InitPaths(): malloc failed\n");
764 exit (1);
766 sprintf (pcblibdir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
767 BINDIR_TO_PCBLIBDIR);
769 /* and the path to PCBTREEDIR */
770 l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBTREEDIR) + 1;
771 if ( (pcbtreedir = (char *) malloc (l * sizeof (char) )) == NULL )
773 fprintf (stderr, "InitPaths(): malloc failed\n");
774 exit (1);
776 sprintf (pcbtreedir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
777 BINDIR_TO_PCBTREEDIR);
779 /* and the search path including PCBLIBDIR */
780 l = strlen (pcblibdir) + 3;
781 if ( (pcblibpath = (char *) malloc (l * sizeof (char) )) == NULL )
783 fprintf (stderr, "InitPaths(): malloc failed\n");
784 exit (1);
786 sprintf (pcblibpath, ".%s%s", PCB_PATH_DELIMETER, pcblibdir);
788 /* and the newlib search path */
789 l = strlen (pcblibdir) + 1 + strlen (pcbtreedir)
790 + strlen ("pcblib-newlib") + 2;
791 if ( (pcbtreepath = (char *) malloc (l * sizeof (char) )) == NULL )
793 fprintf (stderr, "InitPaths(): malloc failed\n");
794 exit (1);
796 sprintf (pcbtreepath, "%s%s%s%spcblib-newlib", pcbtreedir,
797 PCB_PATH_DELIMETER, pcblibdir,
798 PCB_DIR_SEPARATOR_S);
800 #ifdef DEBUG
801 printf ("bindir = %s\n", bindir);
802 printf ("pcblibdir = %s\n", pcblibdir);
803 printf ("pcblibpath = %s\n", pcblibpath);
804 printf ("pcbtreedir = %s\n", pcbtreedir);
805 printf ("pcbtreepath = %s\n", pcbtreepath);
806 #endif
808 l = sizeof (main_attribute_list) / sizeof (main_attribute_list[0]);
809 for (i = 0; i < l ; i++)
811 if (NSTRCMP (main_attribute_list[i].name, "lib-command-dir") == 0)
813 main_attribute_list[i].default_val.str_value = pcblibdir;
816 if ( (NSTRCMP (main_attribute_list[i].name, "font-path") == 0)
817 || (NSTRCMP (main_attribute_list[i].name, "element-path") == 0)
818 || (NSTRCMP (main_attribute_list[i].name, "lib-path") == 0) )
820 main_attribute_list[i].default_val.str_value = pcblibpath;
823 if (NSTRCMP (main_attribute_list[i].name, "lib-newlib") == 0)
825 main_attribute_list[i].default_val.str_value = pcbtreepath;
831 char *tmps;
833 tmps = getenv ("HOME");
835 if (tmps == NULL) {
836 tmps = getenv ("USERPROFILE");
839 if (tmps != NULL) {
840 homedir = strdup (tmps);
841 } else {
842 homedir = NULL;
848 /* ----------------------------------------------------------------------
849 * main program
852 char *program_name = 0;
853 char *program_basename = 0;
854 char *program_directory = 0;
856 #include "dolists.h"
859 main (int argc, char *argv[])
861 int i;
863 /* init application:
864 * - make program name available for error handlers
865 * - evaluate special options
866 * - initialize toplevel shell and resources
867 * - create an empty PCB with default symbols
868 * - initialize all other widgets
869 * - update screen and get size of drawing area
870 * - evaluate command-line arguments
871 * - register 'call on exit()' function
874 #include "core_lists.h"
875 setbuf (stdout, 0);
876 InitPaths (argv[0]);
878 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
879 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
881 hid_init ();
883 hid_load_settings ();
885 program_name = argv[0];
886 program_basename = strrchr (program_name, PCB_DIR_SEPARATOR_C);
887 if (program_basename)
889 program_directory = strdup (program_name);
890 *strrchr (program_directory, PCB_DIR_SEPARATOR_C) = 0;
891 program_basename++;
893 else
895 program_directory = ".";
896 program_basename = program_name;
898 Progname = program_basename;
900 /* Print usage or version if requested. Then exit. */
901 if (argc > 1 && strcmp (argv[1], "-h") == 0)
902 usage ();
903 if (argc > 1 && strcmp (argv[1], "-V") == 0)
904 print_version ();
905 /* Export pcb from command line if requested. */
906 if (argc > 1 && strcmp (argv[1], "-p") == 0)
908 exporter = gui = hid_find_printer ();
909 argc--;
910 argv++;
912 else if (argc > 2 && strcmp (argv[1], "-x") == 0)
914 exporter = gui = hid_find_exporter (argv[2]);
915 argc -= 2;
916 argv += 2;
918 /* Otherwise start GUI. */
919 else
920 gui = hid_find_gui ();
922 /* Exit with error if GUI failed to start. */
923 if (!gui)
924 exit (1);
926 /* Set up layers. */
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 /* Create a new PCB object in memory */
969 PCB = CreateNewPCB (true);
970 PCB->Data->LayerN = DEF_LAYER;
971 ParseGroupString (Settings.Groups, &PCB->LayerGroups, DEF_LAYER);
972 /* Add silk layers to newly created PCB */
973 CreateNewPCBPost (PCB, 1);
974 if (argc > 1)
975 command_line_pcb = argv[1];
977 ResetStackAndVisibility ();
979 CreateDefaultFont ();
980 if (gui->gui)
981 InitCrosshair ();
982 InitHandler ();
983 InitBuffers ();
984 SetMode (ARROW_MODE);
986 if (command_line_pcb)
988 /* keep filename even if initial load command failed;
989 * file might not exist
991 if (LoadPCB (command_line_pcb))
992 PCB->Filename = MyStrdup (command_line_pcb, "main()");
995 if (Settings.InitialLayerStack
996 && Settings.InitialLayerStack[0])
998 LayerStringToLayerStack (Settings.InitialLayerStack);
1001 /* FIX_ME
1002 LoadBackgroundImage (Settings.BackgroundImage); */
1004 /* Register a function to be called when the program terminates.
1005 * This makes sure that data is saved even if LEX/YACC routines
1006 * abort the program.
1007 * If the OS doesn't have at least one of them,
1008 * the critical sections will be handled by parse_l.l
1010 atexit (EmergencySave);
1012 /* read the library file and display it if it's not empty
1014 if (!ReadLibraryContents () && Library.MenuN)
1015 hid_action ("LibraryChanged");
1017 #ifdef HAVE_LIBSTROKE
1018 stroke_init ();
1019 #endif
1021 if (Settings.ScriptFilename)
1023 Message (_("Executing startup script file %s\n"),
1024 Settings.ScriptFilename);
1025 hid_actionl ("ExecuteFile", Settings.ScriptFilename, NULL);
1027 if (Settings.ActionString)
1029 Message (_("Executing startup action %s\n"), Settings.ActionString);
1030 hid_parse_actions (Settings.ActionString);
1033 if (gui->printer || gui->exporter)
1035 gui->do_export (0);
1036 exit (0);
1039 #if HAVE_DBUS
1040 pcb_dbus_setup();
1041 #endif
1043 EnableAutosave ();
1045 #ifdef DEBUG
1046 printf ("Settings.LibraryCommandDir = \"%s\"\n",
1047 Settings.LibraryCommandDir);
1048 printf ("Settings.FontPath = \"%s\"\n",
1049 Settings.FontPath);
1050 printf ("Settings.ElementPath = \"%s\"\n",
1051 Settings.ElementPath);
1052 printf ("Settings.LibraryPath = \"%s\"\n",
1053 Settings.LibraryPath);
1054 printf ("Settings.LibraryTree = \"%s\"\n",
1055 Settings.LibraryTree);
1056 printf ("Settings.MakeProgram = \"%s\"\n",
1057 UNKNOWN (Settings.MakeProgram));
1058 printf ("Settings.GnetlistProgram = \"%s\"\n",
1059 UNKNOWN (Settings.GnetlistProgram));
1060 #endif
1062 gui->do_export (0);
1063 #if HAVE_DBUS
1064 pcb_dbus_finish();
1065 #endif
1067 return (0);