select.c: Remove Draw() call from SelectConnection
[geda-pcb/leaky.git] / src / main.c
blob735fde7b651fd2fce92e764bf34cbc6aab39ac1a
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"
56 #include "free_atexit.h"
58 #include "hid/common/actions.h"
60 /* This next one is so we can print the help messages. */
61 #include "hid/hidint.h"
63 #ifdef HAVE_DBUS
64 #include "dbus.h"
65 #endif
67 #if ENABLE_NLS
68 #include <libintl.h>
69 #endif
71 #ifdef HAVE_LIBDMALLOC
72 #include <dmalloc.h>
73 #endif
75 RCSID ("$Id$");
78 #define PCBLIBPATH ".:" PCBLIBDIR
81 #ifdef HAVE_LIBSTROKE
82 extern void stroke_init (void);
83 #endif
86 /* ----------------------------------------------------------------------
87 * initialize signal and error handlers
89 static void
90 InitHandler (void)
93 signal(SIGHUP, CatchSignal);
94 signal(SIGQUIT, CatchSignal);
95 signal(SIGABRT, CatchSignal);
96 signal(SIGSEGV, CatchSignal);
97 signal(SIGTERM, CatchSignal);
98 signal(SIGINT, CatchSignal);
101 /* calling external program by popen() may cause a PIPE signal,
102 * so we ignore it
104 #ifdef SIGPIPE
105 signal (SIGPIPE, SIG_IGN);
106 #endif
110 /* ----------------------------------------------------------------------
111 | command line and rc file processing.
113 static char *command_line_pcb;
115 void
116 copyright (void)
118 printf ("\n"
119 " COPYRIGHT for %s version %s\n\n"
120 " PCB, interactive printed circuit board design\n"
121 " Copyright (C) 1994,1995,1996,1997 Thomas Nau\n"
122 " Copyright (C) 1998, 1999, 2000 Harry Eaton\n\n"
123 " This program is free software; you can redistribute it and/or modify\n"
124 " it under the terms of the GNU General Public License as published by\n"
125 " the Free Software Foundation; either version 2 of the License, or\n"
126 " (at your option) any later version.\n\n"
127 " This program is distributed in the hope that it will be useful,\n"
128 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
129 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
130 " GNU General Public License for more details.\n\n"
131 " You should have received a copy of the GNU General Public License\n"
132 " along with this program; if not, write to the Free Software\n"
133 " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n",
134 Progname, VERSION);
135 exit (0);
138 static inline void
139 u (const char *fmt, ...)
141 va_list ap;
142 va_start (ap, fmt);
143 vfprintf (stderr, fmt, ap);
144 fputc ('\n', stderr);
145 va_end (ap);
148 typedef struct UsageNotes {
149 struct UsageNotes *next;
150 HID_Attribute *seen;
151 } UsageNotes;
153 static UsageNotes *usage_notes = NULL;
155 static void
156 usage_attr (HID_Attribute * a)
158 int i;
159 static char buf[200];
161 if (a->help_text == ATTR_UNDOCUMENTED)
162 return;
164 switch (a->type)
166 case HID_Label:
167 return;
168 case HID_Integer:
169 case HID_Real:
170 sprintf (buf, "--%s <num>", a->name);
171 break;
172 case HID_String:
173 sprintf (buf, "--%s <string>", a->name);
174 break;
175 case HID_Boolean:
176 sprintf (buf, "--%s", a->name);
177 break;
178 case HID_Mixed:
179 case HID_Enum:
180 sprintf (buf, "--%s ", a->name);
181 if (a->type == HID_Mixed)
182 strcat (buf, " <val>");
183 for (i = 0; a->enumerations[i]; i++)
185 strcat (buf, i ? "|" : "<");
186 strcat (buf, a->enumerations[i]);
188 strcat (buf, ">");
189 break;
190 case HID_Path:
191 sprintf (buf, "--%s <path>", a->name);
192 break;
195 if (strlen (buf) <= 30)
197 if (a->help_text)
198 fprintf (stderr, " %-30s\t%s\n", buf, a->help_text);
199 else
200 fprintf (stderr, " %-30s\n", buf);
202 else if (a->help_text && strlen (a->help_text) + strlen (buf) < 72)
203 fprintf (stderr, " %s\t%s\n", buf, a->help_text);
204 else if (a->help_text)
205 fprintf (stderr, " %s\n\t\t\t%s\n", buf, a->help_text);
206 else
207 fprintf (stderr, " %s\n", buf);
210 static void
211 usage_hid (HID * h)
213 HID_Attribute *attributes;
214 int i, n_attributes = 0;
215 UsageNotes *note;
217 if (h->gui)
219 fprintf (stderr, "\n%s gui options:\n", h->name);
220 attributes = h->get_export_options (&n_attributes);
222 else
224 fprintf (stderr, "\n%s options:\n", h->name);
225 exporter = h;
226 attributes = exporter->get_export_options (&n_attributes);
227 exporter = NULL;
230 note = malloc (sizeof (UsageNotes));
231 note->next = usage_notes;
232 note->seen = attributes;
233 usage_notes = note;
235 for (i = 0; i < n_attributes; i++)
236 usage_attr (attributes + i);
239 static void
240 usage (void)
242 HID **hl = hid_enumerate ();
243 HID_AttrNode *ha;
244 UsageNotes *note;
245 int i;
246 int n_printer = 0, n_gui = 0, n_exporter = 0;
248 for (i = 0; hl[i]; i++)
250 if (hl[i]->gui)
251 n_gui++;
252 if (hl[i]->printer)
253 n_printer++;
254 if (hl[i]->exporter)
255 n_exporter++;
258 u ("PCB Printed Circuit Board editing program, http://pcb.gpleda.org");
259 u ("%s [-h|-V|--copyright]\t\t\tHelp, version, copyright", Progname);
260 u ("%s [gui options] <pcb file>\t\tto edit", Progname);
261 u ("Available GUI hid%s:", n_gui == 1 ? "" : "s");
262 for (i = 0; hl[i]; i++)
263 if (hl[i]->gui)
264 fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
265 u ("%s -p [printing options] <pcb file>\tto print", Progname);
266 u ("Available printing hid%s:", n_printer == 1 ? "" : "s");
267 for (i = 0; hl[i]; i++)
268 if (hl[i]->printer)
269 fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
270 u ("%s -x hid [export options] <pcb file>\tto export", Progname);
271 u ("Available export hid%s:", n_exporter == 1 ? "" : "s");
272 for (i = 0; hl[i]; i++)
273 if (hl[i]->exporter)
274 fprintf (stderr, "\t%-8s %s\n", hl[i]->name, hl[i]->description);
276 for (i = 0; hl[i]; i++)
277 if (hl[i]->gui)
278 usage_hid (hl[i]);
279 for (i = 0; hl[i]; i++)
280 if (hl[i]->printer)
281 usage_hid (hl[i]);
282 for (i = 0; hl[i]; i++)
283 if (hl[i]->exporter)
284 usage_hid (hl[i]);
286 u ("\nCommon options:");
287 for (ha = hid_attr_nodes; ha; ha = ha->next)
289 for (note = usage_notes; note && note->seen != ha->attributes; note = note->next)
291 if (note)
292 continue;
293 for (i = 0; i < ha->n; i++)
295 usage_attr (ha->attributes + i);
299 exit (1);
302 static void
303 print_defaults_1 (HID_Attribute * a, void *value)
305 int i;
306 double d;
307 char *s;
309 /* Remember, at this point we've parsed the command line, so they
310 may be in the global variable instead of the default_val. */
311 switch (a->type)
313 case HID_Integer:
314 i = value ? *(int *) value : a->default_val.int_value;
315 fprintf (stderr, "%s %d\n", a->name, i);
316 break;
317 case HID_Boolean:
318 i = value ? *(char *) value : a->default_val.int_value;
319 fprintf (stderr, "%s %s\n", a->name, i ? "yes" : "no");
320 break;
321 case HID_Real:
322 d = value ? *(double *) value : a->default_val.real_value;
323 fprintf (stderr, "%s %g\n", a->name, d);
324 break;
325 case HID_String:
326 case HID_Path:
327 s = value ? *(char **) value : a->default_val.str_value;
328 fprintf (stderr, "%s \"%s\"\n", a->name, s);
329 break;
330 case HID_Enum:
331 i = value ? *(int *) value : a->default_val.int_value;
332 fprintf (stderr, "%s %s\n", a->name, a->enumerations[i]);
333 break;
334 case HID_Mixed:
335 i = value ?
336 ((HID_Attr_Val*)value)->int_value : a->default_val.int_value;
337 d = value ?
338 ((HID_Attr_Val*)value)->real_value : a->default_val.real_value;
339 fprintf (stderr, "%s %g%s\n", a->name, d, a->enumerations[i]);
340 break;
341 case HID_Label:
342 break;
346 static void
347 print_defaults ()
349 HID **hl = hid_enumerate ();
350 HID_Attribute *e;
351 int i, n, hi;
353 for (hi = 0; hl[hi]; hi++)
355 HID *h = hl[hi];
356 if (h->gui)
358 HID_AttrNode *ha;
359 fprintf (stderr, "\ngui defaults:\n");
360 for (ha = hid_attr_nodes; ha; ha = ha->next)
361 for (i = 0; i < ha->n; i++)
362 print_defaults_1 (ha->attributes + i, ha->attributes[i].value);
364 else
366 fprintf (stderr, "\n%s defaults:\n", h->name);
367 exporter = h;
368 e = exporter->get_export_options (&n);
369 exporter = NULL;
370 if (e)
371 for (i = 0; i < n; i++)
372 print_defaults_1 (e + i, 0);
375 exit (1);
378 #define SSET(F,D,N,H) { N, H, \
379 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.F }
380 #define ISET(F,D,N,H) { N, H, \
381 HID_Integer, 0, 0, { D, 0, 0 }, 0, &Settings.F }
382 #define BSET(F,D,N,H) { N, H, \
383 HID_Boolean, 0, 0, { D, 0, 0 }, 0, &Settings.F }
384 #define RSET(F,D,N,H) { N, H, \
385 HID_Real, 0, 0, { 0, 0, D }, 0, &Settings.F }
387 #define COLOR(F,D,N,H) { N, H, \
388 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.F }
389 #define LAYERCOLOR(N,D) { "layer-color-" #N, "Color for layer " #N, \
390 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.LayerColor[N-1] }
391 #define LAYERNAME(N,D) { "layer-name-" #N, "Name for layer " #N, \
392 HID_String, 0, 0, { 0, D, 0 }, 0, &Settings.DefaultLayerName[N-1] }
393 #define LAYERSELCOLOR(N) { "layer-selected-color-" #N, "Color for layer " #N " when selected", \
394 HID_String, 0, 0, { 0, "#00ffff", 0 }, 0, &Settings.LayerSelectedColor[N-1] }
396 static int show_help = 0;
397 static int show_version = 0;
398 static int show_copyright = 0;
399 static int show_defaults = 0;
400 static int show_actions = 0;
401 static int do_dump_actions = 0;
403 HID_Attribute main_attribute_list[] = {
404 {"help", "Show Help", HID_Boolean, 0, 0, {0, 0, 0}, 0, &show_help},
405 {"version", "Show Version", HID_Boolean, 0, 0, {0, 0, 0}, 0, &show_version},
406 {"verbose", "Be verbose", HID_Boolean, 0, 0, {0, 0, 0}, 0,
407 &Settings.verbose},
408 {"copyright", "Show Copyright", HID_Boolean, 0, 0, {0, 0, 0}, 0,
409 &show_copyright},
410 {"show-defaults", "Show option defaults", HID_Boolean, 0, 0, {0, 0, 0}, 0,
411 &show_defaults},
412 {"show-actions", "Show actions", HID_Boolean, 0, 0, {0, 0, 0}, 0,
413 &show_actions},
414 {"dump-actions", "Dump actions (for documentation)", HID_Boolean, 0, 0,
415 {0, 0, 0}, 0,
416 &do_dump_actions},
418 BSET (grid_units_mm, 0, "grid-units-mm", 0),
420 COLOR (BlackColor, "#000000", "black-color", "color for black"),
421 COLOR (WhiteColor, "#ffffff", "white-color", "color for white"),
422 COLOR (BackgroundColor, "#e5e5e5", "background-color",
423 "color for background"),
424 COLOR (CrosshairColor, "#ff0000", "crosshair-color",
425 "color for the crosshair"),
426 COLOR (CrossColor, "#cdcd00", "cross-color", "color for cross"),
427 COLOR (ViaColor, "#7f7f7f", "via-color", "color for vias"),
428 COLOR (ViaSelectedColor, "#00ffff", "via-selected-color",
429 "color for selected vias"),
430 COLOR (PinColor, "#4d4d4d", "pin-color", "color for pins"),
431 COLOR (PinSelectedColor, "#00ffff", "pin-selected-color",
432 "color for selected pins"),
433 COLOR (PinNameColor, "#ff0000", "pin-name-color",
434 "color for pin names and numbers"),
435 COLOR (ElementColor, "#000000", "element-color", "color for elements"),
436 COLOR (RatColor, "#b8860b", "rat-color", "color for ratlines"),
437 COLOR (InvisibleObjectsColor, "#cccccc", "invisible-objects-color",
438 "color for invisible objects"),
439 COLOR (InvisibleMarkColor, "#cccccc", "invisible-mark-color",
440 "color for invisible marks"),
441 COLOR (ElementSelectedColor, "#00ffff", "element-selected-color",
442 "color for selected elements"),
443 COLOR (RatSelectedColor, "#00ffff", "rat-selected-color",
444 "color for selected rats"),
445 COLOR (ConnectedColor, "#00ff00", "connected-color",
446 "color for connections"),
447 COLOR (OffLimitColor, "#cccccc", "off-limit-color",
448 "color for off-limits areas"),
449 COLOR (GridColor, "#ff0000", "grid-color", "color for the grid"),
450 LAYERCOLOR (1, "#8b2323"),
451 LAYERCOLOR (2, "#3a5fcd"),
452 LAYERCOLOR (3, "#104e8b"),
453 LAYERCOLOR (4, "#cd3700"),
454 LAYERCOLOR (5, "#548b54"),
455 LAYERCOLOR (6, "#8b7355"),
456 LAYERCOLOR (7, "#00868b"),
457 LAYERCOLOR (8, "#228b22"),
458 LAYERCOLOR (9, "#8b2323"),
459 LAYERCOLOR (10, "#3a5fcd"),
460 LAYERCOLOR (11, "#104e8b"),
461 LAYERCOLOR (12, "#cd3700"),
462 LAYERCOLOR (13, "#548b54"),
463 LAYERCOLOR (14, "#8b7355"),
464 LAYERCOLOR (15, "#00868b"),
465 LAYERCOLOR (16, "#228b22"),
466 LAYERSELCOLOR (1),
467 LAYERSELCOLOR (2),
468 LAYERSELCOLOR (3),
469 LAYERSELCOLOR (4),
470 LAYERSELCOLOR (5),
471 LAYERSELCOLOR (6),
472 LAYERSELCOLOR (7),
473 LAYERSELCOLOR (8),
474 LAYERSELCOLOR (9),
475 LAYERSELCOLOR (10),
476 LAYERSELCOLOR (11),
477 LAYERSELCOLOR (12),
478 LAYERSELCOLOR (13),
479 LAYERSELCOLOR (14),
480 LAYERSELCOLOR (15),
481 LAYERSELCOLOR (16),
482 COLOR (WarnColor, "#ff8000", "warn-color", "color for warnings"),
483 COLOR (MaskColor, "#ff0000", "mask-color", "color for solder mask"),
485 ISET (ViaThickness, 6000, "via-thickness", 0),
486 ISET (ViaDrillingHole, 2800, "via-drilling-hole", 0),
487 ISET (LineThickness, 1000, "line-thickness",
488 "Initial thickness of new lines."),
489 ISET (RatThickness, 1000, "rat-thickness", 0),
490 ISET (Keepaway, 1000, "keepaway", 0),
491 ISET (MaxWidth, 600000, "default-PCB-width", 0),
492 ISET (MaxHeight, 500000, "default-PCB-height", 0),
493 ISET (TextScale, 100, "text-scale", 0),
494 ISET (AlignmentDistance, 200, "alignment-distance", 0),
495 ISET (Bloat, 1000, "bloat", 0),
496 ISET (Shrink, 1000, "shrink", 0),
497 ISET (minWid, 1000, "min-width", "DRC minimum copper spacing"),
498 ISET (minSlk, 1000, "min-silk", "DRC minimum silk width"),
499 ISET (minDrill, 1500, "min-drill", "DRC minimum drill diameter"),
500 ISET (minRing, 1000, "min-ring", "DRC minimum annular ring"),
502 RSET (Grid, 1000, "grid", 0),
503 RSET (grid_increment_mm, 0.1, "grid-increment-mm", 0),
504 RSET (grid_increment_mil, 5.0, "grid-increment-mil", 0),
505 RSET (size_increment_mm, 0.2, "size-increment-mm", 0),
506 RSET (size_increment_mil, 10.0, "size-increment-mil", 0),
507 RSET (line_increment_mm, 0.1, "line-increment-mm", 0),
508 RSET (line_increment_mil, 5.0, "line-increment-mil", 0),
509 RSET (clear_increment_mm, 0.05, "clear-increment-mm", 0),
510 RSET (clear_increment_mil, 2.0, "clear-increment-mil", 0),
511 RSET (IsleArea, 200000000, "minimum polygon area", 0),
513 ISET (BackupInterval, 60, "backup-interval", 0),
515 LAYERNAME (1, "component"),
516 LAYERNAME (2, "solder"),
517 LAYERNAME (3, "GND"),
518 LAYERNAME (4, "power"),
519 LAYERNAME (5, "signal1"),
520 LAYERNAME (6, "signal2"),
521 LAYERNAME (7, "signal3"),
522 LAYERNAME (8, "signal4"),
524 SSET (FontCommand, "",
525 "font-command", 0),
526 SSET (FileCommand, "", "file-command", "Command to read a file."),
527 SSET (ElementCommand,
528 "M4PATH='%p';export M4PATH;echo 'include(%f)' | " GNUM4,
529 "element-command", 0),
530 SSET (PrintFile, "%f.output", "print-file", 0),
531 SSET (LibraryCommandDir, PCBLIBDIR, "lib-command-dir", 0),
532 SSET (LibraryCommand, "QueryLibrary.sh '%p' '%f' %a",
533 "lib-command", 0),
534 SSET (LibraryContentsCommand, "ListLibraryContents.sh '%p' '%f'",
535 "lib-contents-command", 0),
536 SSET (LibraryTree, PCBTREEPATH, "lib-newlib",
537 "Top level directory for the newlib style library"),
538 SSET (SaveCommand, "", "save-command", 0),
539 SSET (LibraryFilename, LIBRARYFILENAME, "lib-name", 0),
540 SSET (FontFile, "default_font", "default-font",
541 "File name of default font."),
542 SSET (Groups, "1,c:2,s:3:4:5:6:7:8", "groups", 0),
543 SSET (Routes, "Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000"
544 ":Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600", "route-styles",
546 SSET (FilePath, "", "file-path", 0),
547 SSET (RatCommand, "", "rat-command", 0),
548 SSET (FontPath, PCBLIBPATH, "font-path", 0),
549 SSET (ElementPath, PCBLIBPATH, "element-path", 0),
550 SSET (LibraryPath, PCBLIBPATH, "lib-path", 0),
551 SSET (MenuFile, "pcb-menu.res", "menu-file", 0),
552 SSET (ScriptFilename, 0, "action-script",
553 "If set, this file is executed at startup."),
554 SSET (ActionString, 0, "action-string",
555 "If set, this is executed at startup."),
556 SSET (FabAuthor, "", "fab-author", 0),
557 SSET (InitialLayerStack, "", "layer-stack",
558 "Initial layer stackup, for setting up an export."),
560 SSET (MakeProgram, NULL, "make-program",
561 "Sets the name and optionally full path to a make(3) program"),
562 SSET (GnetlistProgram, NULL, "gnetlist",
563 "Sets the name and optionally full path to the gnetlist(3) program"),
565 ISET (PinoutOffsetX, 100, "pinout-offset-x", 0),
566 ISET (PinoutOffsetY, 100, "pinout-offset-y", 0),
567 ISET (PinoutTextOffsetX, 800, "pinout-text-offset-x", 0),
568 ISET (PinoutTextOffsetY, -100, "pinout-text-offset-y", 0),
570 BSET (DrawGrid, 0, "draw-grid", "default to drawing the grid at startup"),
571 BSET (ClearLine, 1, "clear-line", 0),
572 BSET (FullPoly, 0, "full-poly", 0),
573 BSET (UniqueNames, 1, "unique-names", 0),
574 BSET (SnapPin, 1, "snap-pin", 0),
575 BSET (SaveLastCommand, 0, "save-last-command", 0),
576 BSET (SaveInTMP, 0, "save-in-tmp", 0),
577 BSET (AllDirectionLines, 0, "all-direction-lines", 0),
578 BSET (ShowNumber, 0, "show-number", 0),
579 BSET (ResetAfterElement, 1, "reset-after-element", 0),
580 BSET (RingBellWhenFinished, 0, "ring-bell-finished", 0),
583 REGISTER_ATTRIBUTES (main_attribute_list)
584 /* ----------------------------------------------------------------------
585 * post-process settings.
587 static void settings_post_process ()
589 char *tmps;
591 if (Settings.LibraryCommand[0] != PCB_DIR_SEPARATOR_C && Settings.LibraryCommand[0] != '.')
593 Settings.LibraryCommand
595 Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
596 Settings.LibraryCommand,
597 NULL);
599 if (Settings.LibraryContentsCommand[0] != PCB_DIR_SEPARATOR_C
600 && Settings.LibraryContentsCommand[0] != '.')
602 Settings.LibraryContentsCommand
604 Concat (Settings.LibraryCommandDir, PCB_DIR_SEPARATOR_S,
605 Settings.LibraryContentsCommand, NULL);
608 if (Settings.LineThickness > MAX_LINESIZE
609 || Settings.LineThickness < MIN_LINESIZE)
610 Settings.LineThickness = 1000;
612 if (Settings.ViaThickness > MAX_PINORVIASIZE
613 || Settings.ViaThickness < MIN_PINORVIASIZE)
614 Settings.ViaThickness = 4000;
616 if (Settings.ViaDrillingHole <= 0)
617 Settings.ViaDrillingHole =
618 DEFAULT_DRILLINGHOLE * Settings.ViaThickness / 100;
620 Settings.MaxWidth = MIN (MAX_COORD, MAX (Settings.MaxWidth, MIN_SIZE));
621 Settings.MaxHeight = MIN (MAX_COORD, MAX (Settings.MaxHeight, MIN_SIZE));
623 ParseRouteString (Settings.Routes, &Settings.RouteStyle[0], 1);
626 * Make sure we have settings for some various programs we may wish
627 * to call
629 if (Settings.MakeProgram == NULL) {
630 tmps = getenv ("PCB_MAKE_PROGRAM");
631 if (tmps != NULL)
632 Settings.MakeProgram = strdup (tmps);
634 if (Settings.MakeProgram == NULL) {
635 Settings.MakeProgram = strdup ("make");
638 if (Settings.GnetlistProgram == NULL) {
639 tmps = getenv ("PCB_GNETLIST");
640 if (tmps != NULL)
641 Settings.GnetlistProgram = strdup (tmps);
643 if (Settings.GnetlistProgram == NULL) {
644 Settings.GnetlistProgram = strdup ("gnetlist");
650 /* ----------------------------------------------------------------------
651 * Print help or version messages.
654 static void
655 print_version ()
657 printf ("PCB version %s\n", VERSION);
658 exit (0);
661 /* ----------------------------------------------------------------------
662 * Figure out the canonical name of the executed program
663 * and fix up the defaults for various paths
665 char *bindir = NULL;
666 char *exec_prefix = NULL;
667 char *pcblibdir = NULL;
668 char *pcblibpath = NULL;
669 char *pcbtreedir = NULL;
670 char *pcbtreepath = NULL;
671 char *homedir = NULL;
673 static void
674 InitPaths (char *argv0)
676 size_t l;
677 int i;
678 int haspath;
679 char *t1, *t2;
680 int found_bindir = 0;
682 /* see if argv0 has enough of a path to let lrealpath give the
683 * real path. This should be the case if you invoke pcb with
684 * something like /usr/local/bin/pcb or ./pcb or ./foo/pcb
685 * but if you just use pcb and it exists in your path, you'll
686 * just get back pcb again.
689 haspath = 0;
690 for (i = 0; i < strlen (argv0) ; i++)
692 if (argv0[i] == PCB_DIR_SEPARATOR_C)
693 haspath = 1;
696 #ifdef DEBUG
697 printf ("InitPaths (%s): haspath = %d\n", argv0, haspath);
698 #endif
700 if (haspath)
702 bindir = strdup (lrealpath (argv0));
703 found_bindir = 1;
705 else
707 char *path, *p, *tmps;
708 struct stat sb;
709 int r;
711 tmps = getenv ("PATH");
713 if (tmps != NULL)
715 path = strdup (tmps);
717 /* search through the font path for a font file */
718 for (p = strtok (path, PCB_PATH_DELIMETER); p && *p;
719 p = strtok (NULL, PCB_PATH_DELIMETER))
721 #ifdef DEBUG
722 printf ("Looking for %s in %s\n", argv0, p);
723 #endif
724 if ( (tmps = malloc ( (strlen (argv0) + strlen (p) + 2) * sizeof (char))) == NULL )
726 fprintf (stderr, "InitPaths(): malloc failed\n");
727 exit (1);
729 sprintf (tmps, "%s%s%s", p, PCB_DIR_SEPARATOR_S, argv0);
730 r = stat (tmps, &sb);
731 if (r == 0)
733 #ifdef DEBUG
734 printf ("Found it: \"%s\"\n", tmps);
735 #endif
736 bindir = lrealpath (tmps);
737 found_bindir = 1;
738 free (tmps);
739 break;
741 free (tmps);
743 free (path);
747 #ifdef DEBUG
748 printf ("InitPaths(): bindir = \"%s\"\n", bindir);
749 #endif
751 if (found_bindir)
753 /* strip off the executible name leaving only the path */
754 t2 = NULL;
755 t1 = strchr (bindir, PCB_DIR_SEPARATOR_C);
756 while (t1 != NULL && *t1 != '\0')
758 t2 = t1;
759 t1 = strchr (t2 + 1, PCB_DIR_SEPARATOR_C);
761 if (t2 != NULL)
762 *t2 = '\0';
764 #ifdef DEBUG
765 printf ("After stripping off the executible name, we found\n");
766 printf ("bindir = \"%s\"\n", bindir);
767 #endif
769 else
771 /* we have failed to find out anything from argv[0] so fall back to the original
772 * install prefix
774 bindir = strdup (BINDIR);
777 /* now find the path to exec_prefix */
778 l = strlen (bindir) + 1 + strlen (BINDIR_TO_EXECPREFIX) + 1;
779 if ( (exec_prefix = (char *) malloc (l * sizeof (char) )) == NULL )
781 fprintf (stderr, "InitPaths(): malloc failed\n");
782 exit (1);
784 sprintf (exec_prefix, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
785 BINDIR_TO_EXECPREFIX);
787 /* now find the path to PCBLIBDIR */
788 l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBLIBDIR) + 1;
789 if ( (pcblibdir = (char *) malloc (l * sizeof (char) )) == NULL )
791 fprintf (stderr, "InitPaths(): malloc failed\n");
792 exit (1);
794 sprintf (pcblibdir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
795 BINDIR_TO_PCBLIBDIR);
797 /* and the path to PCBTREEDIR */
798 l = strlen (bindir) + 1 + strlen (BINDIR_TO_PCBTREEDIR) + 1;
799 if ( (pcbtreedir = (char *) malloc (l * sizeof (char) )) == NULL )
801 fprintf (stderr, "InitPaths(): malloc failed\n");
802 exit (1);
804 sprintf (pcbtreedir, "%s%s%s", bindir, PCB_DIR_SEPARATOR_S,
805 BINDIR_TO_PCBTREEDIR);
807 /* and the search path including PCBLIBDIR */
808 l = strlen (pcblibdir) + 3;
809 if ( (pcblibpath = (char *) malloc (l * sizeof (char) )) == NULL )
811 fprintf (stderr, "InitPaths(): malloc failed\n");
812 exit (1);
814 sprintf (pcblibpath, ".%s%s", PCB_PATH_DELIMETER, pcblibdir);
816 /* and the newlib search path */
817 l = strlen (pcblibdir) + 1 + strlen (pcbtreedir)
818 + strlen ("pcblib-newlib") + 2;
819 if ( (pcbtreepath = (char *) malloc (l * sizeof (char) )) == NULL )
821 fprintf (stderr, "InitPaths(): malloc failed\n");
822 exit (1);
824 sprintf (pcbtreepath, "%s%s%s%spcblib-newlib", pcbtreedir,
825 PCB_PATH_DELIMETER, pcblibdir,
826 PCB_DIR_SEPARATOR_S);
828 #ifdef DEBUG
829 printf ("bindir = %s\n", bindir);
830 printf ("pcblibdir = %s\n", pcblibdir);
831 printf ("pcblibpath = %s\n", pcblibpath);
832 printf ("pcbtreedir = %s\n", pcbtreedir);
833 printf ("pcbtreepath = %s\n", pcbtreepath);
834 #endif
836 l = sizeof (main_attribute_list) / sizeof (main_attribute_list[0]);
837 for (i = 0; i < l ; i++)
839 if (NSTRCMP (main_attribute_list[i].name, "lib-command-dir") == 0)
841 main_attribute_list[i].default_val.str_value = pcblibdir;
844 if ( (NSTRCMP (main_attribute_list[i].name, "font-path") == 0)
845 || (NSTRCMP (main_attribute_list[i].name, "element-path") == 0)
846 || (NSTRCMP (main_attribute_list[i].name, "lib-path") == 0) )
848 main_attribute_list[i].default_val.str_value = pcblibpath;
851 if (NSTRCMP (main_attribute_list[i].name, "lib-newlib") == 0)
853 main_attribute_list[i].default_val.str_value = pcbtreepath;
859 char *tmps;
861 tmps = getenv ("HOME");
863 if (tmps == NULL) {
864 tmps = getenv ("USERPROFILE");
867 if (tmps != NULL) {
868 homedir = strdup (tmps);
869 } else {
870 homedir = NULL;
876 /* ----------------------------------------------------------------------
877 * main program
880 char *program_name = 0;
881 char *program_basename = 0;
882 char *program_directory = 0;
884 #include "dolists.h"
887 main (int argc, char *argv[])
889 int i;
891 /* init application:
892 * - make program name available for error handlers
893 * - evaluate special options
894 * - initialize toplevel shell and resources
895 * - create an empty PCB with default symbols
896 * - initialize all other widgets
897 * - update screen and get size of drawing area
898 * - evaluate command-line arguments
899 * - register 'call on exit()' function
902 #include "core_lists.h"
903 setbuf (stdout, 0);
904 InitPaths (argv[0]);
906 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
907 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
909 hid_init ();
911 hid_load_settings ();
913 program_name = argv[0];
914 program_basename = strrchr (program_name, PCB_DIR_SEPARATOR_C);
915 if (program_basename)
917 program_directory = strdup (program_name);
918 *strrchr (program_directory, PCB_DIR_SEPARATOR_C) = 0;
919 program_basename++;
921 else
923 program_directory = ".";
924 program_basename = program_name;
926 Progname = program_basename;
928 /* Print usage or version if requested. Then exit. */
929 if (argc > 1 && strcmp (argv[1], "-h") == 0)
930 usage ();
931 if (argc > 1 && strcmp (argv[1], "-V") == 0)
932 print_version ();
933 /* Export pcb from command line if requested. */
934 if (argc > 1 && strcmp (argv[1], "-p") == 0)
936 exporter = gui = hid_find_printer ();
937 argc--;
938 argv++;
940 else if (argc > 2 && strcmp (argv[1], "-x") == 0)
942 exporter = gui = hid_find_exporter (argv[2]);
943 argc -= 2;
944 argv += 2;
946 /* Otherwise start GUI. */
947 else
948 gui = hid_find_gui ();
950 /* Exit with error if GUI failed to start. */
951 if (!gui)
952 exit (1);
954 /* Set up layers. */
955 for (i = 0; i < MAX_LAYER; i++)
957 char buf[20];
958 sprintf (buf, "signal%d", i + 1);
959 Settings.DefaultLayerName[i] = strdup (buf);
960 Settings.LayerColor[i] = "#c49350";
961 Settings.LayerSelectedColor[i] = "#00ffff";
964 gui->parse_arguments (&argc, &argv);
966 if (show_help || (argc > 1 && argv[1][0] == '-'))
967 usage ();
968 if (show_version)
969 print_version ();
970 if (show_defaults)
971 print_defaults ();
972 if (show_copyright)
973 copyright ();
975 Output.bgGC = gui->make_gc ();
976 Output.fgGC = gui->make_gc ();
977 Output.pmGC = gui->make_gc ();
978 Output.GridGC = gui->make_gc ();
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);