gsch2pcb: Make --m4-file and -m4-pcbdir arguments work again.
[geda-gaf/peter-b.git] / gschem / src / gschem.c
blobd33d35ded6ee2183a9d6fb9e39512286a6b94963
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2011 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <config.h>
21 #include <version.h>
22 #include <missing.h>
24 #include <stdio.h>
25 #ifdef HAVE_STRING_H
26 #include <string.h>
27 #endif
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
32 #include <glib.h>
34 #include "gschem.h"
36 #ifdef HAVE_LIBDMALLOC
37 #include <dmalloc.h>
38 #endif
40 #ifdef HAVE_LOCALE_H
41 #include <locale.h>
42 #endif
44 /* These are generated by parse_commandline() */
45 extern SCM s_pre_load_expr;
46 extern SCM s_post_load_expr;
48 typedef struct {
49 gschem_atexit_func func;
50 gpointer arg;
51 } gschem_atexit_struct;
53 static GList *exit_functions = NULL;
55 /*! \brief Register a function to be called on program exit
57 * \par Function Description
58 * This function registers a function to be called on
59 * program exit. Multiple functions will be executed in
60 * the order they are registered.
62 * \param [in] func a pointer to the function to be registered
63 * \param [in] data an arbitrary argument provided to the function
64 * when it is called
66 void gschem_atexit(gschem_atexit_func func, gpointer data)
68 gschem_atexit_struct *p;
70 p = g_new(gschem_atexit_struct, 1);
71 p->func = func;
72 p->arg = data;
73 exit_functions = g_list_append(exit_functions, p);
76 /*! \brief Cleanup gSchem on exit.
77 * \par Function Description
78 * This function cleans up all memory objects allocated during the
79 * gSchem runtime.
81 void gschem_quit(void)
83 GList *list;
84 gschem_atexit_struct *p;
86 /* Call all registered functions in order */
87 list = exit_functions;
88 while(list != NULL) {
89 p = (gschem_atexit_struct *) list->data;
90 p->func(p->arg);
91 g_free(p);
92 list = g_list_next(list);
94 g_list_free(exit_functions);
96 s_clib_free();
97 s_slib_free();
98 s_menu_free();
99 /* o_text_freeallfonts();*/
100 s_attrib_free();
101 s_papersizes_free();
102 #ifdef HAVE_LIBSTROKE
103 x_stroke_free ();
104 #endif /* HAVE_LIBSTROKE */
105 o_undo_cleanup();
106 /* s_stroke_free(); no longer needed */
108 i_vars_freenames();
109 i_vars_libgeda_freenames();
111 /* x_window_free_head(); can't do this since it causes a
112 * condition in which window_head->... is still being refered
113 * after this */
115 /* enable this to get more memory usage from glib */
116 /* You also have to enable something in glib I think */
117 /* g_mem_profile();*/
120 gtk_main_quit();
123 /*! \brief Main Scheme(GUILE) program function.
124 * \par Function Description
125 * This function is the main program called from scm_boot_guile.
126 * It handles initializing all libraries and gSchem variables
127 * and passes control to the gtk main loop.
129 void main_prog(void *closure, int argc, char *argv[])
131 int i;
132 char *cwd = NULL;
133 GSCHEM_TOPLEVEL *w_current = NULL;
134 char *input_str = NULL;
135 int argv_index;
136 int first_page = 1;
137 char *filename;
138 SCM scm_tmp;
140 #ifdef HAVE_GTHREAD
141 /* Gschem isn't threaded, but some of GTK's file chooser
142 * backends uses threading so we need to call g_thread_init().
143 * GLib requires threading be initialised before any other GLib
144 * functions are called. Do it now if its not already setup. */
145 if (!g_thread_supported ()) g_thread_init (NULL);
146 #endif
148 #if ENABLE_NLS
149 /* this should be equivalent to setlocale (LC_ALL, "") */
150 gtk_set_locale();
152 /* This must be the same for all locales */
153 setlocale(LC_NUMERIC, "C");
155 /* Disable gtk's ability to set the locale. */
156 /* If gtk is allowed to set the locale, then it will override the */
157 /* setlocale for LC_NUMERIC (which is important for proper PS output. */
158 /* This may look funny here, given we make a call to gtk_set_locale() */
159 /* above. I don't know yet, if this is really the right thing to do. */
160 gtk_disable_setlocale();
162 #endif
164 gtk_init(&argc, &argv);
166 argv_index = parse_commandline(argc, argv);
167 cwd = g_get_current_dir();
169 libgeda_init();
171 /* create log file right away even if logging is enabled */
172 s_log_init ("gschem");
174 s_log_message(
175 _("gEDA/gschem version %s%s.%s\n"), PREPEND_VERSION_STRING,
176 PACKAGE_DOTTED_VERSION, PACKAGE_DATE_VERSION);
177 s_log_message(
178 _("gEDA/gschem comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n"));
179 s_log_message(
180 _("This is free software, and you are welcome to redistribute it under certain\n"));
181 s_log_message(
182 _("conditions; please see the COPYING file for more details.\n\n"));
184 #if defined(__MINGW32__) && defined(DEBUG)
185 fprintf(stderr, _("This is the MINGW32 port.\n"));
186 #endif
188 #if DEBUG
189 fprintf(stderr, _("Current locale settings: %s\n"), setlocale(LC_ALL, NULL));
190 #endif
192 /* init global buffers */
193 o_buffer_init();
195 /* register guile (scheme) functions */
196 g_register_funcs();
197 g_init_window ();
198 g_init_select ();
199 g_init_hook ();
200 g_init_attrib ();
201 g_init_keys ();
202 g_init_util ();
204 /* initialise color map (need to do this before reading rc files */
205 x_color_init ();
207 o_undo_init();
209 if (s_path_sys_data () == NULL) {
210 const gchar *message =
211 _("You must set the GEDADATA environment variable!\n\n"
212 "gschem cannot locate its data files. You must set the GEDADATA\n"
213 "environment variable to point to the correct location.\n");
214 GtkWidget* error_diag =
215 gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR,
216 GTK_BUTTONS_OK,
217 "%s", message);
218 gtk_dialog_run (GTK_DIALOG (error_diag));
219 g_error ("%s", message);
222 /* Allocate w_current */
223 w_current = gschem_toplevel_new ();
224 w_current->toplevel = s_toplevel_new ();
226 w_current->toplevel->load_newer_backup_func = x_fileselect_load_backup;
227 w_current->toplevel->load_newer_backup_data = w_current;
229 o_text_set_rendered_bounds_func (w_current->toplevel,
230 o_text_get_rendered_bounds, w_current);
232 /* Damage notifications should invalidate the object on screen */
233 o_add_change_notify (w_current->toplevel,
234 (ChangeNotifyFunc) o_invalidate,
235 (ChangeNotifyFunc) o_invalidate, w_current);
237 scm_dynwind_begin (0);
238 g_dynwind_window (w_current);
240 /* Run pre-load Scheme expressions */
241 g_scm_eval_protected (s_pre_load_expr, scm_current_module ());
243 /* By this point, libgeda should have setup the Guile load path, so
244 * we can take advantage of that. */
245 scm_tmp = scm_sys_search_load_path (scm_from_utf8_string ("gschem.scm"));
246 if (scm_is_false (scm_tmp)) {
247 s_log_message (_("Couldn't find init scm file [%s]\n"), "gschem.scm");
249 input_str = scm_to_utf8_string (scm_tmp);
250 if (g_read_file(w_current->toplevel, input_str, NULL)) {
251 s_log_message(_("Read init scm file [%s]\n"), input_str);
252 } else {
253 /*! \todo These two messages are the same. Should be
254 * integrated. */
255 s_log_message(_("Failed to read init scm file [%s]\n"),
256 input_str);
258 free (input_str); /* M'allocated by scm_to_utf8_string() */
259 scm_remember_upto_here_1 (scm_tmp);
261 /* Now read in RC files. */
262 g_rc_parse_gtkrc();
263 x_rc_parse_gschem (w_current, rc_filename);
265 /* Set default icon */
266 x_window_set_default_icon();
268 /* At end, complete set up of window. */
269 x_color_allocate();
270 x_window_setup (w_current);
272 #ifdef HAVE_LIBSTROKE
273 x_stroke_init ();
274 #endif /* HAVE_LIBSTROKE */
276 for (i = argv_index; i < argc; i++) {
278 if (g_path_is_absolute(argv[i]))
280 /* Path is already absolute so no need to do any concat of cwd */
281 filename = g_strdup (argv[i]);
282 } else {
283 filename = g_build_filename (cwd, argv[i], NULL);
286 if ( first_page )
287 first_page = 0;
290 * SDB notes: at this point the filename might be unnormalized, like
291 * /path/to/foo/../bar/baz.sch. Bad filenames will be normalized in
292 * f_open (called by x_window_open_page). This works for Linux and MINGW32.
294 x_window_open_page(w_current, filename);
295 g_free (filename);
298 g_free(cwd);
300 /* If no page has been loaded (wasn't specified in the command line.) */
301 /* Then create an untitled page */
302 if ( first_page ) {
303 x_window_open_page( w_current, NULL );
306 /* Update the window to show the current page */
307 x_window_set_current_page( w_current, w_current->toplevel->page_current );
310 #if DEBUG
311 scm_c_eval_string ("(display \"hello guile\n\")");
312 #endif
314 /* Run post-load expressions */
315 g_scm_eval_protected (s_post_load_expr, scm_current_module ());
317 /* open up log window on startup */
318 if (w_current->log_window == MAP_ON_STARTUP) {
319 x_log_open ();
322 /* if there were any symbols which had major changes, put up an error */
323 /* dialog box */
324 major_changed_dialog(w_current);
326 scm_dynwind_end ();
328 /* enter main loop */
329 gtk_main();
332 /*! \brief Main executable entrance point.
333 * \par Function Description
334 * This is the main function for gSchem. It sets up the Scheme(GUILE)
335 * environment and passes control to via scm_boot_guile to
336 * the #main_prog function.
338 int main (int argc, char *argv[])
341 #if ENABLE_NLS
342 setlocale(LC_ALL, "");
343 setlocale(LC_NUMERIC, "C");
344 bindtextdomain("geda-gschem", LOCALEDIR);
345 textdomain("geda-gschem");
346 bind_textdomain_codeset("geda-gschem", "UTF-8");
347 #endif
349 /* disable the deprecated warnings in guile 1.6.3 */
350 /* Eventually the warnings will need to be fixed */
351 if(getenv("GUILE_WARN_DEPRECATED") == NULL)
352 putenv("GUILE_WARN_DEPRECATED=no");
354 scm_boot_guile (argc, argv, main_prog, 0);
356 return 0;