/* $Id: main.c,v 1.20 2006/03/05 22:24:59 dj Exp $ */ /* * COPYRIGHT * * PCB, interactive printed circuit board design * Copyright (C) 1994,1995,1996, 2004 Thomas Nau * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Contact addresses for paper mail and Email: * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany * Thomas.Nau@rz.uni-ulm.de * */ /* main program, initializes some stuff and handles user input */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #ifdef HAVE_STRING_H #include #endif #include #include #include "global.h" #include "data.h" #include "buffer.h" #include "create.h" #include "crosshair.h" #include "draw.h" #include "error.h" #include "file.h" #include "set.h" #include "action.h" #include "misc.h" /* This next one is so we can print the help messages. */ #include "hid/hidint.h" RCSID("$Id: main.c,v 1.20 2006/03/05 22:24:59 dj Exp $"); #ifdef HAVE_LIBSTROKE extern void stroke_init (void); #endif /* ---------------------------------------------------------------------- * initialize signal and error handlers */ static void InitHandler (void) { /* signal(SIGHUP, CatchSignal); signal(SIGQUIT, CatchSignal); signal(SIGABRT, CatchSignal); signal(SIGSEGV, CatchSignal); signal(SIGTERM, CatchSignal); signal(SIGINT, CatchSignal); */ /* calling external program by popen() may cause a PIPE signal, * so we ignore it */ signal (SIGPIPE, SIG_IGN); } /* --------------------------------------------------------------------------- * init device drivers for printing */ static void InitDeviceDriver (void) { #ifdef FIXME DeviceInfoTypePtr ptr = PrintingDevice; while (ptr->Query) { ptr->Info = ptr->Query (); ptr++; } #endif } /* ---------------------------------------------------------------------- | command line and rc file processing. */ static char *command_line_pcb; void copyright (void) { printf ("\n" " COPYRIGHT for %s version %s\n\n" " PCB, interactive printed circuit board design\n" " Copyright (C) 1994,1995,1996,1997 Thomas Nau\n" " Copyright (C) 1998, 1999, 2000 Harry Eaton\n\n" " This program is free software; you can redistribute it and/or modify\n" " it under the terms of the GNU General Public License as published by\n" " the Free Software Foundation; either version 2 of the License, or\n" " (at your option) any later version.\n\n" " This program is distributed in the hope that it will be useful,\n" " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" " GNU General Public License for more details.\n\n" " You should have received a copy of the GNU General Public License\n" " along with this program; if not, write to the Free Software\n" " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n", Progname, VERSION); exit (0); } static inline void u(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); fputc('\n', stderr); va_end(ap); } static void usage_attr (HID_Attribute *a) { int i; char *help; static char buf[200]; switch (a->type) { case HID_Label: return; case HID_Integer: case HID_Real: sprintf(buf, "--%s ", a->name); break; case HID_String: sprintf(buf, "--%s ", a->name); break; case HID_Boolean: sprintf(buf, "--%s", a->name); break; case HID_Mixed: case HID_Enum: sprintf(buf, "--%s ", a->name); if (a->type == HID_Mixed) strcat(buf, " "); for (i=0; a->enumerations[i]; i++) { strcat(buf, i ? "|" : "<"); strcat(buf, a->enumerations[i]); } strcat(buf, ">"); break; case HID_Path: sprintf(buf, "--%s ", a->name); break; } if (strlen(buf) <= 30) { if (a->help_text) fprintf(stderr, " %-30s\t%s\n", buf, a->help_text); else fprintf(stderr, " %-30s\n", buf); } else if (a->help_text && strlen(a->help_text) + strlen(buf) < 72) fprintf(stderr, " %s\t%s\n", buf, a->help_text); else if (a->help_text) fprintf(stderr, " %s\n\t\t\t%s\n", buf, a->help_text); else fprintf(stderr, " %s\n", buf); } static void usage_hid (HID *h) { HID_Attribute *e; int i, n; if (h->gui) { HID **hl = hid_enumerate(); HID_AttrNode *ha; fprintf(stderr, "\ngui options:\n"); for (ha=hid_attr_nodes; ha; ha=ha->next) { for (i=0; hl[i]; i++) if (ha->attributes == hl[i]->get_export_options(0)) goto skip_this_one; for (i=0; in; i++) usage_attr (ha->attributes+i); skip_this_one: ; } return; } fprintf(stderr, "\n%s options:\n", h->name); e = h->get_export_options(&n); if (!e) return; for (i=0; igui) n_gui++; if (hl[i]->printer) n_printer++; if (hl[i]->exporter) n_exporter++; } u("PCB Printed Circuit Board editing program, http://pcb.sourceforge.net"); u("%s [-h|-V|--copyright]\t\t\tHelp, version, copyright", Progname); u("%s [gui options] \t\tto edit", Progname); u("Available GUI hid%s:", n_gui == 1 ? "" : "s"); for (i=0; hl[i]; i++) if (hl[i]->gui) fprintf(stderr, "\t%s\t%s\n", hl[i]->name, hl[i]->description); u("%s -p [printing options] \tto print", Progname); u("Available printing hid%s:", n_printer == 1 ? "" : "s"); for (i=0; hl[i]; i++) if (hl[i]->printer) fprintf(stderr, "\t%s\t%s\n", hl[i]->name, hl[i]->description); u("%s -x hid [export options] \tto export", Progname); u("Available export hid%s:", n_exporter == 1 ? "" : "s"); for (i=0; hl[i]; i++) if (hl[i]->exporter) fprintf(stderr, "\t%s\t%s\n", hl[i]->name, hl[i]->description); for (i=0; hl[i]; i++) if (hl[i]->gui) usage_hid(hl[i]); for (i=0; hl[i]; i++) if (hl[i]->printer) usage_hid(hl[i]); for (i=0; hl[i]; i++) if (hl[i]->exporter) usage_hid(hl[i]); exit(1); } static void print_defaults_1 (HID_Attribute *a, void *value) { int i; double d; char *s; HID_Attr_Val ha; /* Remember, at this point we've parsed the command line, so they may be in the global variable instead of the default_val. */ switch (a->type) { case HID_Integer: i = value ? *(int *)value : a->default_val.int_value; fprintf(stderr, "%s %d\n", a->name, i); break; case HID_Boolean: i = value ? *(char *)value : a->default_val.int_value; fprintf(stderr, "%s %s\n", a->name, i ? "yes" : "no"); break; case HID_Real: d = value ? *(double *)value : a->default_val.real_value; fprintf(stderr, "%s %g\n", a->name, d); break; case HID_String: case HID_Path: s = value ? *(char **)value : a->default_val.str_value; fprintf(stderr, "%s \"%s\"\n", a->name, s); break; case HID_Enum: i = value ? *(int *)value : a->default_val.int_value; fprintf(stderr, "%s %s\n", a->name, a->enumerations[i]); break; case HID_Mixed: i = value ? *(int *)value : a->default_val.int_value; d = value ? *(double *)value : a->default_val.real_value; fprintf(stderr, "%s %g%s\n", a->name, d, a->enumerations[i]); break; } } static void print_defaults () { HID **hl = hid_enumerate(); HID_Attribute *e; int i, n, hi; for (hi=0; hl[hi]; hi++) { HID *h = hl[hi]; if (h->gui) { HID_AttrNode *ha; fprintf(stderr, "\ngui defaults:\n"); for (ha=hid_attr_nodes; ha; ha=ha->next) for (i=0; in; i++) print_defaults_1 (ha->attributes+i, ha->attributes[i].value); } else { fprintf(stderr, "\n%s defaults:\n", h->name); e = h->get_export_options(&n); if (e) for (i=0; i '%f'", "save-command", 0), SSET(LibraryFilename, LIBRARYFILENAME, "lib-name", 0), SSET(FontFile, "default_font", "default-font", "File name of default font."), SSET(Groups, "1,c:2,s:3:4:5:6:7:8", "groups", 0), SSET(Routes, "Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000" ":Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600", "route-styles", 0), SSET(FilePath, "", "file-path", 0), SSET(RatCommand, "cat %f", "rat-command", 0), SSET(FontPath, ".:" PCBLIBDIR, "font-path", 0), SSET(ElementPath, ".:" PCBLIBDIR, "element-path", 0), SSET(LibraryPath, ".:" PCBLIBDIR, "lib-path", 0), SSET(MenuFile, "pcb-menu.res", "menu-file", 0), SSET(ScriptFilename, 0, "action-script", "If set, this file is executed at startup."), SSET(ActionString, 0, "action-string", "If set, this is executed at startup."), SSET(FabAuthor, "", "fab-author", 0), ISET(PinoutOffsetX, 100, "pinout-offset-x", 0), ISET(PinoutOffsetY, 100, "pinout-offset-y", 0), ISET(PinoutTextOffsetX, 800, "pinout-text-offset-x", 0), ISET(PinoutTextOffsetY, -100, "pinout-text-offset-y", 0), BSET(ClearLine, 1, "clear-line", 0), BSET(UniqueNames, 1, "unique-names", 0), BSET(SnapPin, 1, "snap-pin", 0), BSET(SaveLastCommand, 0, "save-last-command", 0), BSET(SaveInTMP, 0, "save-in-tmp", 0), BSET(AllDirectionLines, 0, "all-direction-lines", 0), BSET(ShowNumber, 0, "show-number", 0), BSET(ResetAfterElement, 1, "reset-after-element", 0), BSET(RingBellWhenFinished, 0, "ring-bell-finished", 0), }; REGISTER_ATTRIBUTES(main_attribute_list) /* ---------------------------------------------------------------------- * post-process settings. */ static void settings_post_process() { if (Settings.LibraryCommand[0] != '/' && Settings.LibraryCommand[0] != '.') { Settings.LibraryCommand = strdup(Concat(Settings.LibraryCommandDir, "/", Settings.LibraryCommand, 0)); } if (Settings.LibraryContentsCommand[0] != '/' && Settings.LibraryContentsCommand[0] != '.') { Settings.LibraryContentsCommand = strdup(Concat(Settings.LibraryCommandDir, "/", Settings.LibraryContentsCommand, 0)); } if (Settings.LineThickness > MAX_LINESIZE || Settings.LineThickness < MIN_LINESIZE) Settings.LineThickness = 1000; if (Settings.ViaThickness > MAX_PINORVIASIZE || Settings.ViaThickness < MIN_PINORVIASIZE) Settings.ViaThickness = 4000; if (Settings.ViaDrillingHole <= 0) Settings.ViaDrillingHole = DEFAULT_DRILLINGHOLE * Settings.ViaThickness / 100; Settings.MaxWidth = MIN(MAX_COORD, MAX(Settings.MaxWidth, MIN_SIZE)); Settings.MaxHeight = MIN(MAX_COORD, MAX(Settings.MaxHeight, MIN_SIZE)); ParseGroupString (Settings.Groups, &Settings.LayerGroups); ParseRouteString (Settings.Routes, &Settings.RouteStyle[0], 1); } /* ---------------------------------------------------------------------- * Print help or version messages. */ static void print_version () { printf ("PCB version %s\n", VERSION); exit (0); } /* ---------------------------------------------------------------------- * main program */ char *program_name = 0; char *program_basename = 0; char *program_directory = 0; #include "dolists.h" int main (int argc, char *argv[]) { /* GdkRectangle Big;*/ /* init application: * - make program name available for error handlers * - evaluate special options * - initialize toplevel shell and resources * - create an empty PCB with default symbols * - initialize all other widgets * - update screen and get size of drawing area * - evaluate command-line arguments * - register 'call on exit()' function */ #include "core_lists.h" setbuf(stdout,0); hid_init(); program_name = argv[0]; program_basename = strrchr(program_name, '/'); if (program_basename) { program_directory = strdup (program_name); *strrchr(program_directory, '/') = 0; program_basename ++; } else { program_directory = "."; program_basename = program_name; } Progname = program_basename; if (argc > 1 && strcmp (argv[1], "-h") == 0) usage(); if (argc > 1 && strcmp (argv[1], "-V") == 0) print_version(); if (argc > 1 && strcmp (argv[1], "-p") == 0) { gui = hid_find_printer (); argc --; argv ++; } else if (argc > 2 && strcmp (argv[1], "-x") == 0) { gui = hid_find_exporter (argv[2]); argc -= 2; argv += 2; } else gui = hid_find_gui (); if (!gui) exit(1); gui->parse_arguments (&argc, &argv); if (show_help || (argc > 1 && argv[1][0] == '-')) usage(); if (show_version) print_version(); if (show_defaults) print_defaults(); if (show_copyright) copyright(); Output.bgGC = gui->make_gc (); Output.fgGC = gui->make_gc (); Output.pmGC = gui->make_gc (); Output.GridGC = gui->make_gc (); settings_post_process(); if (show_actions) { print_actions (); exit(0); } PCB = CreateNewPCB (True); if (argc > 1) command_line_pcb = argv[1]; ResetStackAndVisibility (); CreateDefaultFont (); InitCrosshair (); InitHandler (); InitBuffers (); SetMode (ARROW_MODE); /* update zoom and grid... */ UpdateSettingsOnScreen (); #ifdef FIXME gdk_window_get_geometry(NULL, NULL, NULL, &Settings.w_display, &Settings.h_display, NULL); #endif #ifdef FIXME FullRegion = gdk_region_new(); Big.x = Big.y = 0; Big.width = Big.height = TO_SCREEN(MAX_COORD); gdk_region_union_with_rect(FullRegion, &Big); #endif if (command_line_pcb) { /* keep filename even if initial load command failed; * file might not exist */ if (LoadPCB (command_line_pcb)) PCB->Filename = MyStrdup (command_line_pcb, "main()"); } if (gui->printer || gui->exporter) { gui->do_export (0); exit(0); } /* FIX_ME LoadBackgroundImage (Settings.BackgroundImage); */ /* Register a function to be called when the program terminates. * This makes sure that data is saved even if LEX/YACC routines * abort the program. * If the OS doesn't have at least one of them, * the critical sections will be handled by parse_l.l */ atexit(EmergencySave); /* read the library file and display it if it's not empty */ if (!ReadLibraryContents () && Library.MenuN) hid_action("LibraryChanged"); #ifdef HAVE_LIBSTROKE stroke_init (); #endif /* * Set this flag to zero. Then if we have a startup * action which includes Quit(), the flag will be set * to -1 and we can avoid ever calling gtk_main(); */ Settings.init_done = 0; if (Settings.ScriptFilename) { Message(_("Executing startup script file %s\n"), Settings.ScriptFilename); hid_actionl("ExecuteFile", Settings.ScriptFilename, 0); } if (Settings.ActionString) { char *param[1]; Message(_("Executing startup action %s\n"), Settings.ActionString); hid_parse_actions(Settings.ActionString, 0); } if( Settings.init_done == 0 ) { Settings.init_done = 1; gui->do_export (0); } #ifdef FIXME if (Settings.config_modified) config_file_write(); #endif return (0); }