gschem

gschem.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2011 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 #include <config.h>
00021 #include <version.h>
00022 #include <missing.h>
00023 
00024 #include <stdio.h>
00025 #ifdef HAVE_STRING_H
00026 #include <string.h>
00027 #endif
00028 #ifdef HAVE_UNISTD_H
00029 #include <unistd.h>
00030 #endif
00031 
00032 #include <glib.h>
00033 
00034 #include "gschem.h"
00035 
00036 #ifdef HAVE_LIBDMALLOC
00037 #include <dmalloc.h>
00038 #endif
00039 
00040 #ifdef HAVE_LOCALE_H
00041 #include <locale.h>
00042 #endif
00043 
00044 /* These are generated by parse_commandline() */
00045 extern SCM s_pre_load_expr;
00046 extern SCM s_post_load_expr;
00047 
00048 typedef struct {
00049   gschem_atexit_func func;
00050   gpointer arg;
00051 } gschem_atexit_struct;
00052 
00053 static GList *exit_functions = NULL;
00054 
00066 void gschem_atexit(gschem_atexit_func func, gpointer data)
00067 {
00068   gschem_atexit_struct *p;
00069 
00070   p = g_new(gschem_atexit_struct, 1);
00071   p->func = func;
00072   p->arg = data;
00073   exit_functions = g_list_append(exit_functions, p);
00074 }
00075 
00081 void gschem_quit(void)
00082 {
00083   GList *list;
00084   gschem_atexit_struct *p;
00085 
00086   /* Call all registered functions in order */
00087   list = exit_functions;
00088   while(list != NULL) {
00089     p = (gschem_atexit_struct *) list->data;
00090     p->func(p->arg);
00091     g_free(p);
00092     list = g_list_next(list);
00093   }
00094   g_list_free(exit_functions);
00095 
00096   s_clib_free();
00097   s_slib_free();
00098   s_menu_free();
00099   /* o_text_freeallfonts();*/
00100   s_attrib_free();
00101   s_papersizes_free();
00102 #ifdef HAVE_LIBSTROKE
00103   x_stroke_free ();
00104 #endif /* HAVE_LIBSTROKE */
00105   o_undo_cleanup();
00106   /* s_stroke_free(); no longer needed */
00107 
00108   i_vars_freenames();
00109   i_vars_libgeda_freenames();
00110 
00111   /* x_window_free_head(); can't do this since it causes a
00112    * condition in which window_head->... is still being refered
00113    * after this */
00114 
00115   /* enable this to get more memory usage from glib */
00116   /* You also have to enable something in glib I think */
00117   /* g_mem_profile();*/
00118      
00119 
00120   gtk_main_quit();
00121 }
00122 
00129 void main_prog(void *closure, int argc, char *argv[])
00130 {
00131   int i;
00132   char *cwd = NULL;
00133   GSCHEM_TOPLEVEL *w_current = NULL;
00134   char *input_str = NULL;
00135   int argv_index;
00136   int first_page = 1;
00137   char *filename;
00138   SCM scm_tmp;
00139 
00140 #ifdef HAVE_GTHREAD
00141   /* Gschem isn't threaded, but some of GTK's file chooser
00142    * backends uses threading so we need to call g_thread_init().
00143    * GLib requires threading be initialised before any other GLib
00144    * functions are called. Do it now if its not already setup.  */
00145   if (!g_thread_supported ()) g_thread_init (NULL);
00146 #endif
00147 
00148 #if ENABLE_NLS
00149   /* this should be equivalent to setlocale (LC_ALL, "") */
00150   gtk_set_locale();
00151 
00152   /* This must be the same for all locales */
00153   setlocale(LC_NUMERIC, "C");
00154 
00155   /* Disable gtk's ability to set the locale. */ 
00156   /* If gtk is allowed to set the locale, then it will override the     */
00157   /* setlocale for LC_NUMERIC (which is important for proper PS output. */
00158   /* This may look funny here, given we make a call to gtk_set_locale() */
00159   /* above.  I don't know yet, if this is really the right thing to do. */
00160   gtk_disable_setlocale(); 
00161 
00162 #endif
00163 
00164   gtk_init(&argc, &argv);
00165 
00166   argv_index = parse_commandline(argc, argv);
00167   cwd = g_get_current_dir();
00168   
00169   libgeda_init();
00170 
00171   /* create log file right away even if logging is enabled */
00172   s_log_init ("gschem");
00173 
00174   s_log_message(
00175                 _("gEDA/gschem version %s%s.%s\n"), PREPEND_VERSION_STRING,
00176                 PACKAGE_DOTTED_VERSION, PACKAGE_DATE_VERSION);
00177   s_log_message(
00178                 _("gEDA/gschem comes with ABSOLUTELY NO WARRANTY; see COPYING for more details.\n"));
00179   s_log_message(
00180                 _("This is free software, and you are welcome to redistribute it under certain\n"));
00181   s_log_message(
00182                 _("conditions; please see the COPYING file for more details.\n\n")); 
00183 
00184 #if defined(__MINGW32__) && defined(DEBUG)
00185   fprintf(stderr, _("This is the MINGW32 port.\n"));
00186 #endif  
00187 
00188 #if DEBUG
00189   fprintf(stderr, _("Current locale settings: %s\n"), setlocale(LC_ALL, NULL));
00190 #endif
00191 
00192   /* init global buffers */
00193   o_buffer_init();
00194 
00195   /* register guile (scheme) functions */
00196   g_register_funcs();
00197   g_init_window ();
00198   g_init_select ();
00199   g_init_hook ();
00200   g_init_attrib ();
00201   g_init_keys ();
00202   g_init_util ();
00203 
00204   /* initialise color map (need to do this before reading rc files */
00205   x_color_init ();
00206 
00207   o_undo_init(); 
00208 
00209   if (s_path_sys_data () == NULL) {
00210     const gchar *message = 
00211       _("You must set the GEDADATA environment variable!\n\n"
00212         "gschem cannot locate its data files. You must set the GEDADATA\n"
00213         "environment variable to point to the correct location.\n");
00214     GtkWidget* error_diag =
00215       gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR,
00216                               GTK_BUTTONS_OK,
00217                               "%s", message);
00218     gtk_dialog_run (GTK_DIALOG (error_diag));
00219     g_error ("%s", message);
00220   }
00221 
00222   /* Allocate w_current */
00223   w_current = gschem_toplevel_new ();
00224 
00225   gschem_toplevel_alloc_libgeda_toplevel (w_current);
00226 
00227   w_current->toplevel->load_newer_backup_func = x_fileselect_load_backup;
00228   w_current->toplevel->load_newer_backup_data = w_current;
00229 
00230   o_text_set_rendered_bounds_func (w_current->toplevel,
00231                                    o_text_get_rendered_bounds, w_current);
00232 
00233   /* Damage notifications should invalidate the object on screen */
00234   o_add_change_notify (w_current->toplevel,
00235                        (ChangeNotifyFunc) o_invalidate,
00236                        (ChangeNotifyFunc) o_invalidate, w_current);
00237 
00238   scm_dynwind_begin (0);
00239   g_dynwind_window (w_current);
00240 
00241   /* Run pre-load Scheme expressions */
00242   g_scm_eval_protected (s_pre_load_expr, scm_current_module ());
00243 
00244   /* By this point, libgeda should have setup the Guile load path, so
00245    * we can take advantage of that.  */
00246   scm_tmp = scm_sys_search_load_path (scm_from_utf8_string ("gschem.scm"));
00247   if (scm_is_false (scm_tmp)) {
00248     s_log_message (_("Couldn't find init scm file [%s]\n"), "gschem.scm");
00249   }
00250   input_str = scm_to_utf8_string (scm_tmp);
00251   if (g_read_file(w_current->toplevel, input_str, NULL)) {
00252     s_log_message(_("Read init scm file [%s]\n"), input_str);
00253   } else {
00256     s_log_message(_("Failed to read init scm file [%s]\n"),
00257                   input_str);
00258   }
00259   free (input_str); /* M'allocated by scm_to_utf8_string() */
00260   scm_remember_upto_here_1 (scm_tmp);
00261 
00262   /* Now read in RC files. */
00263   g_rc_parse_gtkrc();
00264   x_rc_parse_gschem (w_current, rc_filename);
00265 
00266   /* Set default icon */
00267   x_window_set_default_icon();
00268 
00269   /* At end, complete set up of window. */
00270   x_color_allocate();
00271   x_window_setup (w_current);
00272 
00273 #ifdef HAVE_LIBSTROKE
00274   x_stroke_init ();
00275 #endif /* HAVE_LIBSTROKE */
00276 
00277   for (i = argv_index; i < argc; i++) {
00278 
00279     if (g_path_is_absolute(argv[i]))
00280     {
00281       /* Path is already absolute so no need to do any concat of cwd */
00282       filename = g_strdup (argv[i]);
00283     } else {
00284       filename = g_build_filename (cwd, argv[i], NULL);
00285     }
00286 
00287     if ( first_page )
00288       first_page = 0;
00289 
00290     /*
00291      * SDB notes:  at this point the filename might be unnormalized, like
00292      * /path/to/foo/../bar/baz.sch.  Bad filenames will be normalized in
00293      * f_open (called by x_window_open_page). This works for Linux and MINGW32.
00294      */
00295     x_window_open_page(w_current, filename);
00296     g_free (filename);
00297   }
00298 
00299   g_free(cwd);
00300 
00301   /* If no page has been loaded (wasn't specified in the command line.) */
00302   /* Then create an untitled page */
00303   if ( first_page ) {
00304     x_window_open_page( w_current, NULL );
00305   }
00306 
00307   /* Update the window to show the current page */
00308   x_window_set_current_page( w_current, w_current->toplevel->page_current );
00309 
00310 
00311 #if DEBUG
00312   scm_c_eval_string ("(display \"hello guile\n\")");
00313 #endif
00314 
00315   /* Run post-load expressions */
00316   g_scm_eval_protected (s_post_load_expr, scm_current_module ());
00317 
00318   /* open up log window on startup */
00319   if (w_current->log_window == MAP_ON_STARTUP) {
00320     x_log_open ();
00321   }
00322 
00323   /* if there were any symbols which had major changes, put up an error */
00324   /* dialog box */
00325   major_changed_dialog(w_current);
00326 
00327   scm_dynwind_end ();
00328 
00329   /* enter main loop */
00330   gtk_main();
00331 }
00332 
00339 int main (int argc, char *argv[])
00340 {
00341 
00342 #if ENABLE_NLS
00343   setlocale(LC_ALL, "");
00344   setlocale(LC_NUMERIC, "C");
00345   bindtextdomain("geda-gschem", LOCALEDIR);
00346   textdomain("geda-gschem");
00347   bind_textdomain_codeset("geda-gschem", "UTF-8");
00348 #endif
00349 
00350   /* disable the deprecated warnings in guile 1.6.3 */
00351   /* Eventually the warnings will need to be fixed */
00352   if(getenv("GUILE_WARN_DEPRECATED") == NULL)
00353     putenv("GUILE_WARN_DEPRECATED=no");
00354 
00355   scm_boot_guile (argc, argv, main_prog, 0);
00356   
00357   return 0;
00358 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines