1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * main-application.c: Main entry point for the Gnumeric application
6 * Jon Kåre Hellan <hellan@acm.org>
7 * Morten Welinder <terra@gnome.org>
8 * Jody Goldberg <jody@gnome.org>
10 * Copyright (C) 2002-2004, Jon Kåre Hellan
13 #include <gnumeric-config.h>
14 #include <glib/gi18n.h>
16 #include "libgnumeric.h"
18 #define _WIN32_WINNT 0x0501
23 #include "command-context.h"
24 #include <goffice/goffice.h>
25 #include "io-context-gtk.h"
26 /* TODO: Get rid of this one */
27 #include "command-context-stderr.h"
28 #include "wbc-gtk-impl.h"
29 #include "workbook-view.h"
32 #include "gnumeric-conf.h"
33 #include "gnumeric-paths.h"
37 #include "gnm-plugin.h"
38 #include "application.h"
42 #include <glib/gstdio.h>
44 #include <sys/types.h>
49 #ifdef HAVE_FPU_CONTROL_H
50 #include <fpu_control.h>
53 static gboolean immediate_exit_flag
= FALSE
;
54 static gboolean gnumeric_no_splash
= FALSE
;
55 static gboolean gnumeric_no_warnings
= FALSE
;
56 static gchar
*geometry
= NULL
;
57 static gchar
**startup_files
;
59 static const GOptionEntry gnumeric_options
[] = {
60 /*********************************
62 { "geometry", 'g', 0, G_OPTION_ARG_STRING
, &geometry
,
63 N_("Specify the size and location of the initial window"),
64 N_("WIDTHxHEIGHT+XOFF+YOFF")
66 { "no-splash", 0, 0, G_OPTION_ARG_NONE
, &gnumeric_no_splash
,
67 N_("Don't show splash screen"), NULL
},
68 { "no-warnings", 0, 0, G_OPTION_ARG_NONE
, &gnumeric_no_warnings
,
69 N_("Don't display warning dialogs when importing"),
73 /*********************************
77 G_OPTION_FLAG_HIDDEN
, G_OPTION_ARG_NONE
, &immediate_exit_flag
,
78 N_("Exit immediately after loading the selected books"),
81 { G_OPTION_REMAINING
, 0, 0, G_OPTION_ARG_FILENAME_ARRAY
, &startup_files
, NULL
, NULL
},
87 handle_paint_events (void)
89 /* FIXME: we need to mask input events correctly here */
90 /* Show something coherent */
91 while (gtk_events_pending () && !initial_workbook_open_complete
)
92 gtk_main_iteration_do (FALSE
);
95 static GObject
*program
= NULL
;
98 gnumeric_arg_shutdown (void)
101 g_object_unref (program
);
107 gnumeric_arg_parse (int argc
, char **argv
)
109 GOptionContext
*ocontext
;
110 GError
*error
= NULL
;
112 ocontext
= g_option_context_new (_("[FILE ...]"));
113 g_option_context_add_main_entries (ocontext
, gnumeric_options
, GETTEXT_PACKAGE
);
114 g_option_context_add_group (ocontext
, gnm_get_option_group ());
116 #if defined(G_OS_WIN32)
117 /* we have already translated to utf8, do not do it again.
118 * http://bugzilla.gnome.org/show_bug.cgi?id=361321 */
119 g_option_context_set_delocalize (ocontext
, FALSE
);
122 g_option_context_add_group (ocontext
, gtk_get_option_group (TRUE
));
123 g_option_context_parse (ocontext
, &argc
, &argv
, &error
);
126 g_option_context_free (ocontext
);
129 g_printerr (_("%s\nRun '%s --help' to see a full list of available command line options.\n"),
130 error
->message
, argv
[0]);
131 g_error_free (error
);
135 gtk_init (&argc
, &argv
);
139 * WARNING WARNING WARNING
140 * This does not belong here
141 * but it is expedient for now to get things to compile
143 #warning "REMOVE REMOVE REMOVE"
145 store_plugin_state (void)
147 GSList
*active_plugins
= go_plugins_get_active_plugins ();
148 gnm_conf_set_plugins_active (active_plugins
);
149 g_slist_free (active_plugins
);
153 cb_kill_wbcg (WBCGtk
*wbcg
)
155 gboolean still_open
= wbc_gtk_close (wbcg
);
156 g_assert (!still_open
);
161 cb_workbook_removed (void)
163 if (gnm_app_workbook_list () == NULL
) {
169 cpu_sanity_check (void)
171 #if (defined(i386) || defined(__i386__) || defined(__i386) || defined(__x86_64__) || defined(__x86_64)) && HAVE_FPU_CONTROL_H
173 const fpu_control_t mask
= _FPU_EXTENDED
| _FPU_DOUBLE
| _FPU_SINGLE
;
176 if ((state
& mask
) != _FPU_EXTENDED
) {
177 // Evidently currentlly happinging when Windows runs Linux
178 // binaries. See bug 794515.
179 g_warning ("Sanity check failed! The cpu is not in \"extended\" mode as it should be. Attempting to fix, but expect trouble.");
180 state
= (state
& ~mask
) | _FPU_EXTENDED
;
190 main (int argc
, char const **argv
)
192 gboolean opened_workbook
= FALSE
;
195 GSList
*wbcgs_to_kill
= NULL
;
197 gboolean any_error
= FALSE
;
200 gboolean has_console
;
203 /* No code before here, we need to init threads */
204 argv
= gnm_pre_parse_init (argc
, argv
);
209 * Attempt to disable Ubuntu's funky, non-working scroll
210 * bars. This needs to be done before gtk starts loading
211 * modules. Note: the following call will not replace
212 * an existing setting, so you can run with =1 if you like.
214 g_setenv ("LIBOVERLAY_SCROLLBAR", "0", FALSE
);
219 typedef BOOL (CALLBACK
* LPFNATTACHCONSOLE
)(DWORD
);
220 LPFNATTACHCONSOLE MyAttachConsole
;
223 if ((hmod
= GetModuleHandle("kernel32.dll"))) {
224 MyAttachConsole
= (LPFNATTACHCONSOLE
) GetProcAddress(hmod
, "AttachConsole");
225 if (MyAttachConsole
&& MyAttachConsole(ATTACH_PARENT_PROCESS
)) {
226 freopen("CONOUT$", "w", stdout
);
227 freopen("CONOUT$", "w", stderr
);
228 dup2(fileno(stdout
), 1);
229 dup2(fileno(stderr
), 2);
236 gnumeric_arg_parse (argc
, (char **)argv
);
237 bind_textdomain_codeset (GETTEXT_PACKAGE
, "UTF-8");
238 bind_textdomain_codeset (GETTEXT_PACKAGE
"-functions", "UTF-8");
240 gnm_session_init (argv
[0]);
244 cc
= gnm_cmd_context_stderr_new ();
245 go_component_set_default_command_context (cc
);
248 cc
= g_object_new (GNM_TYPE_IO_CONTEXT_GTK
,
249 "show-splash", !gnumeric_no_splash
,
250 "show-warnings", !gnumeric_no_warnings
,
252 ioc
= GO_IO_CONTEXT (g_object_ref (cc
));
253 handle_paint_events ();
255 /* Keep in sync with .desktop file */
256 g_set_application_name (_("Gnumeric Spreadsheet"));
257 gnm_plugins_init (GO_CMD_CONTEXT (ioc
));
262 N
= g_strv_length (startup_files
);
263 go_io_context_set_num_files (ioc
, N
);
264 for (i
= 0; i
< N
&& !initial_workbook_open_complete
; i
++) {
265 char *uri
= go_shell_arg_to_uri (startup_files
[i
]);
268 g_warning ("Ignoring invalid URI.");
273 go_io_context_processing_file (ioc
, uri
);
274 wbv
= workbook_view_new_from_uri (uri
, NULL
, ioc
, NULL
);
277 if (go_io_error_occurred (ioc
) ||
278 go_io_warning_occurred (ioc
)) {
279 if (go_io_error_occurred (ioc
))
281 go_io_error_display (ioc
);
282 go_io_error_clear (ioc
);
287 workbook_update_history (wb_view_get_workbook (wbv
), GNM_FILE_SAVE_AS_STYLE_SAVE
);
289 wbcg
= wbc_gtk_new (wbv
, NULL
, NULL
, geometry
);
291 sheet_update (wb_view_cur_sheet (wbv
));
292 opened_workbook
= TRUE
;
293 gnm_io_context_gtk_set_transient_for (GNM_IO_CONTEXT_GTK (ioc
),
294 wbcg_toplevel (wbcg
));
295 if (immediate_exit_flag
)
296 wbcgs_to_kill
= g_slist_prepend (wbcgs_to_kill
,
299 /* cheesy attempt to keep the ui from freezing during
301 handle_paint_events ();
302 if (gnm_io_context_gtk_get_interrupted (GNM_IO_CONTEXT_GTK (ioc
)))
303 break; /* Don't load any more workbooks */
310 // If we actually opened a workbook, we are not about to exit so
311 // suppress the error. (Returning an error when the GUI exits
312 // down the line is not helpful.)
316 // If we were intentionally short circuited exit now
317 if (any_error
|| initial_workbook_open_complete
) {
318 g_object_unref (ioc
);
319 g_slist_foreach (wbcgs_to_kill
, (GFunc
)cb_kill_wbcg
, NULL
);
321 initial_workbook_open_complete
= TRUE
;
322 if (!opened_workbook
) {
323 gint n_of_sheets
= gnm_conf_get_core_workbook_n_sheet ();
325 workbook_new_with_sheets (n_of_sheets
),
329 if (immediate_exit_flag
) {
331 for (l
= wbcgs_to_kill
; l
; l
= l
->next
)
332 g_idle_add ((GSourceFunc
)cb_kill_wbcg
, l
->data
);
335 g_signal_connect (gnm_app_get_app (),
337 G_CALLBACK (cb_workbook_removed
),
340 gnm_io_context_gtk_discharge_splash (GNM_IO_CONTEXT_GTK (ioc
));
341 g_object_unref (ioc
);
346 g_slist_free (wbcgs_to_kill
);
347 gnumeric_arg_shutdown ();
348 store_plugin_state ();
351 #if defined(G_OS_WIN32)
359 gnm_pre_parse_shutdown ();
360 go_component_set_default_command_context (NULL
);
363 * This helps finding leaks. We might want it in developent
366 if (gnm_debug_flag ("close-displays")) {
370 while (g_main_context_iteration (NULL
, FALSE
))
373 displays
= gdk_display_manager_list_displays
374 (gdk_display_manager_get ());
375 g_slist_foreach (displays
, (GFunc
)gdk_display_close
, NULL
);
376 g_slist_free (displays
);
379 return any_error
? 1 : 0;