Bumped versions to 1.1.2/20070818/30:2:0 for the next development snapshot
[geda-gaf/whiteaudio.git] / gschem / src / gschem.c
blobc0aab556aaae0474cea9faa6aa0480ae832cd611
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 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., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 #include <config.h>
22 #include <stdio.h>
23 #ifdef HAVE_STRING_H
24 #include <string.h>
25 #endif
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
30 #include <glib.h>
32 #include <libgeda/libgeda.h>
34 #include "../include/globals.h"
35 #include "../include/i_vars.h"
36 #include "../include/prototype.h"
38 #ifdef HAVE_LIBDMALLOC
39 #include <dmalloc.h>
40 #endif
42 #ifdef HAVE_LOCALE_H
43 #include <locale.h>
44 #endif
46 #ifdef HAS_LIBSTROKE
47 /* libstroke prototype */
48 void stroke_init(void);
49 #endif
51 typedef struct {
52 gschem_atexit_func func;
53 gpointer arg;
54 } gschem_atexit_struct;
56 static GList *exit_functions = NULL;
58 /*! \brief Register a function to be called on program exit
60 * \par Function Description
61 * This function registers a function to be called on
62 * program exit. Multiple functions will be executed in
63 * the order they are registered.
65 * \param [in] func a pointer to the function to be registered
66 * \param [in] data an arbitrary argument provided to the function
67 * when it is called
69 void gschem_atexit(gschem_atexit_func func, gpointer data)
71 gschem_atexit_struct *p;
73 p = g_new(gschem_atexit_struct, 1);
74 p->func = func;
75 p->arg = data;
76 exit_functions = g_list_append(exit_functions, p);
79 /*! \brief Cleanup gSchem on exit.
80 * \par Function Description
81 * This function cleans up all memory objects allocated during the
82 * gSchem runtime.
84 void gschem_quit(void)
86 GList *list;
87 gschem_atexit_struct *p;
89 /* Call all registered functions in order */
90 list = exit_functions;
91 while(list != NULL) {
92 p = (gschem_atexit_struct *) list->data;
93 p->func(p->arg);
94 g_free(p);
95 list = g_list_next(list);
97 g_list_free(exit_functions);
99 s_clib_free();
100 s_slib_free();
101 s_menu_free();
102 /* o_text_freeallfonts();*/
103 s_attrib_free();
104 s_papersizes_free();
105 x_stroke_free_all();
106 s_color_destroy_all();
107 o_undo_cleanup();
108 /* s_stroke_free(); no longer needed */
110 i_vars_freenames();
112 /* x_window_free_head(); can't do this since it causes a
113 * condition in which window_head->... is still being refered
114 * after this */
116 /* enable this to get more memory usage from glib */
117 /* You also have to enable something in glib I think */
118 /* g_mem_profile();*/
121 gtk_main_quit();
124 /*! \brief Main Scheme(GUILE) program function.
125 * \par Function Description
126 * This function is the main program called from scm_boot_guile.
127 * It handles initializing all libraries and gSchem variables
128 * and passes control to the gtk main loop.
130 void main_prog(void *closure, int argc, char *argv[])
132 int i;
133 char *cwd = NULL;
134 TOPLEVEL *w_current = NULL;
135 char *input_str = NULL;
136 int argv_index;
137 int first_page = 1;
138 char *geda_data = NULL;
139 char *filename;
140 gboolean save_grid;
142 #ifdef HAVE_GTHREAD
143 /* Gschem isn't threaded, but some of GTK's file chooser
144 * backends uses threading so we need to call g_thread_init().
145 * GLib requires threading be initialised before any other GLib
146 * functions are called. Do it now if its not already setup. */
147 if (!g_thread_supported ()) g_thread_init (NULL);
148 #endif
150 #if ENABLE_NLS
151 /* this should be equivalent to setlocale (LC_ALL, "") */
152 gtk_set_locale();
154 /* This must be the same for all locales */
155 setlocale(LC_NUMERIC, "POSIX");
157 /* Disable gtk's ability to set the locale. */
158 /* If gtk is allowed to set the locale, then it will override the */
159 /* setlocale for LC_NUMERIC (which is important for proper PS output. */
160 /* This may look funny here, given we make a call to gtk_set_locale() */
161 /* above. I don't know yet, if this is really the right thing to do. */
162 gtk_disable_setlocale();
164 #endif
166 gtk_init(&argc, &argv);
167 visual = gdk_visual_get_system();
169 argv_index = parse_commandline(argc, argv);
170 cwd = getcwd(NULL, 1024);
171 #ifdef __MINGW32__
172 u_basic_strip_trailing(cwd, G_DIR_SEPARATOR);
173 #endif
175 libgeda_init();
177 /*! \todo Probably the file name shuold be defined elsewhere */
178 /* create log file right away even if logging is enabled */
179 filename = g_build_path (G_DIR_SEPARATOR_S,
180 cwd,
181 "gschem.log",
182 NULL);
183 s_log_init (filename);
184 g_free (filename);
186 #ifdef HAS_LIBSTROKE
187 stroke_init(); /* libstroke function */
188 /* s_stroke_init(); no longer needed libgeda function */
189 #endif
191 s_log_message(
192 _("gEDA/gschem version %s%s.%s\n"), PREPEND_VERSION_STRING,
193 DOTTED_VERSION, DATE_VERSION);
194 s_log_message(
195 _("gEDA/gschem comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n"));
196 s_log_message(
197 _("This is free software, and you are welcome to redistribute it under certain\n"));
198 s_log_message(
199 _("conditions; please see the COPYING file for more details.\n\n"));
201 if (!quiet_mode) {
202 fprintf(stderr,
203 _("gEDA/gschem version %s%s.%s\n"), PREPEND_VERSION_STRING,
204 DOTTED_VERSION, DATE_VERSION);
205 fprintf(stderr,
206 _("gEDA/gschem comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n"));
207 fprintf(stderr,
208 _("This is free software, and you are welcome to redistribute it under certain\n"));
209 fprintf(stderr,
210 _("conditions; please see the COPYING file for more details.\n\n"));
213 #ifdef __MINGW32__
214 fprintf(stderr, _("This is the MINGW32 port.\n"));
215 #endif
217 #if DEBUG
218 fprintf(stderr, _("Current locale settings: %s\n"), setlocale(LC_ALL, NULL));
219 #endif
221 /* init global buffers */
222 o_buffer_init();
224 /* register guile (scheme) functions */
225 g_register_funcs();
227 o_undo_init();
229 geda_data = getenv("GEDADATA");
230 if (geda_data == NULL) {
231 fprintf(stderr, _("You must set the GEDADATA environment variable!\n"));
232 exit(-1);
235 /* Allocate w_current. */
236 w_current = s_toplevel_new ();
237 global_window_current = w_current;
239 /* Now read in RC files. */
240 g_rc_parse_gtkrc();
241 g_rc_parse(w_current, "gschemrc", rc_filename);
243 input_str = g_strdup_printf("%s%cgschem.scm", default_scheme_directory,
244 G_DIR_SEPARATOR);
245 if (g_read_file(input_str) != -1) {
246 s_log_message(_("Read init scm file [%s]\n"), input_str);
247 } else {
248 /*! \todo These two messages are the same. Should be
249 * integrated. */
250 s_log_message(_("Failed to read init scm file [%s]\n"),
251 input_str);
252 fprintf(stderr,
253 _("Failed to read init scm file [%s]\n"), input_str);
255 g_free(input_str);
257 /* Load recent files list. This must be done
258 * before calling x_window_setup(). */
259 recent_files_load();
260 gschem_atexit(recent_files_save, NULL);
262 /* At end, complete set up of window. */
263 colormap = gdk_colormap_get_system ();
264 x_window_setup_colors();
265 x_window_setup (w_current);
267 /* Repaint the background in-case we have to throw up a "restore backup?"
268 * dialog box. Disable grid drawing as there is no page loaded, hence no
269 * scale factor to draw the grid at. (gschem will segfault otherwise.)
271 save_grid = w_current->grid;
272 w_current->grid = FALSE;
273 x_repaint_background (w_current);
274 w_current->grid = save_grid;
276 i = argv_index;
277 while (argv[i] != NULL) {
279 #ifdef __MINGW32__
280 if (argv[i][1] == ':' && (argv[i][2] == G_DIR_SEPARATOR ||
281 argv[i][2] == OTHER_PATH_SEPARATER_CHAR))
282 #else
283 if (argv[i][0] == G_DIR_SEPARATOR)
284 #endif
286 /* Path is already absolute so no need to do any concat of cwd */
287 filename = g_strdup (argv[i]);
288 } else {
289 filename = g_strconcat (cwd, G_DIR_SEPARATOR_S, argv[i], NULL);
292 if ( first_page )
293 first_page = 0;
296 * SDB notes: at this point the filename might be unnormalized, like
297 * /path/to/foo/../bar/baz.sch. Bad filenames will be normalized in
298 * f_open (called by x_window_open_page). This works for Linux and MINGW32.
300 x_window_open_page(w_current, filename);
302 /* Go to the next argument */
303 i++;
306 free(cwd); /* allocated from getcwd, should be regular free */
308 /* If no page has been loaded (wasn't specified in the command line.) */
309 /* Then create an untitled page */
310 if ( first_page ) {
311 x_window_open_untitled_page( w_current );
314 /* Update the window to show the current page */
315 x_window_set_current_page( w_current, w_current->page_current );
318 #if DEBUG
319 scm_c_eval_string ("(display \"hello guile\n\")");
320 #endif
322 if (w_current->scheme_directory == NULL) {
323 fprintf(stderr, _("Scheme directory NOT set!\n"));
324 exit(-1);
328 /* Execute a script if it exists */
329 if (script_filename) {
330 s_log_message(_("Executing guile script [%s]\n"),
331 script_filename);
332 g_read_file(script_filename);
335 /* open up log window on startup */
336 if (w_current->log_window == MAP_ON_STARTUP) {
337 x_log_open ();
340 /* if there were any symbols which had major changes, put up an error */
341 /* dialog box */
342 major_changed_dialog(w_current);
344 /* enter main loop */
345 gtk_main();
348 /*! \brief Main executable entrance point.
349 * \par Function Description
350 * This is the main function for gSchem. It sets up the Scheme(GUILE)
351 * environment and passes control to via scm_boot_guile to
352 * the #main_prog function.
354 int main (int argc, char *argv[])
357 #if ENABLE_NLS
358 setlocale(LC_ALL, "");
359 setlocale(LC_NUMERIC, "POSIX");
360 bindtextdomain(PACKAGE, LOCALEDIR);
361 textdomain(PACKAGE);
362 bind_textdomain_codeset(PACKAGE, "UTF-8");
363 #endif
365 /* disable the deprecated warnings in guile 1.6.3 */
366 /* Eventually the warnings will need to be fixed */
367 if(getenv("GUILE_WARN_DEPRECATED") == NULL)
368 putenv("GUILE_WARN_DEPRECATED=no");
370 scm_boot_guile (argc, argv, main_prog, 0);
372 return 0;