gschem
|
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 }