GUI: Dead kittens.
[gnumeric.git] / src / main-application.c
blob86ec06d1adafb772373d123c5b705b0c81da59b1
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * main-application.c: Main entry point for the Gnumeric application
5 * Author:
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>
15 #include "gnumeric.h"
16 #include "libgnumeric.h"
17 #ifdef G_OS_WIN32
18 #define _WIN32_WINNT 0x0501
19 #include <windows.h>
20 #include <io.h>
21 #endif
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"
30 #include "workbook.h"
31 #include "gui-file.h"
32 #include "gnumeric-conf.h"
33 #include "gnumeric-paths.h"
34 #include "session.h"
35 #include "sheet.h"
36 #include "gutils.h"
37 #include "gnm-plugin.h"
38 #include "application.h"
39 #include "func.h"
41 #include <gtk/gtk.h>
42 #include <glib/gstdio.h>
44 #include <sys/types.h>
45 #include <time.h>
46 #include <string.h>
47 #include <locale.h>
49 #ifdef HAVE_FPU_CONTROL_H
50 #include <fpu_control.h>
51 #endif
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 /*********************************
61 * Public Variables */
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"),
70 NULL
73 /*********************************
74 * Hidden Actions */
76 "quit", 0,
77 G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &immediate_exit_flag,
78 N_("Exit immediately after loading the selected books"),
79 NULL
81 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &startup_files, NULL, NULL },
82 { NULL }
86 static void
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;
97 static void
98 gnumeric_arg_shutdown (void)
100 if (program) {
101 g_object_unref (program);
102 program = NULL;
106 static void
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);
120 #endif
122 g_option_context_add_group (ocontext, gtk_get_option_group (TRUE));
123 g_option_context_parse (ocontext, &argc, &argv, &error);
125 if (ocontext)
126 g_option_context_free (ocontext);
128 if (error) {
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);
132 exit (1);
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"
144 static void
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);
152 static gboolean
153 cb_kill_wbcg (WBCGtk *wbcg)
155 gboolean still_open = wbc_gtk_close (wbcg);
156 g_assert (!still_open);
157 return FALSE;
160 static void
161 cb_workbook_removed (void)
163 if (gnm_app_workbook_list () == NULL) {
164 gtk_main_quit ();
168 static void
169 cpu_sanity_check (void)
171 #if (defined(i386) || defined(__i386__) || defined(__i386) || defined(__x86_64__) || defined(__x86_64)) && HAVE_FPU_CONTROL_H
172 fpu_control_t state;
173 const fpu_control_t mask = _FPU_EXTENDED | _FPU_DOUBLE | _FPU_SINGLE;
175 _FPU_GETCW (state);
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;
181 _FPU_SETCW (state);
183 #else
184 // Hope for the best
185 #endif
190 main (int argc, char const **argv)
192 gboolean opened_workbook = FALSE;
193 GOIOContext *ioc;
194 WorkbookView *wbv;
195 GSList *wbcgs_to_kill = NULL;
196 GOCmdContext *cc;
197 gboolean any_error = FALSE;
199 #ifdef G_OS_WIN32
200 gboolean has_console;
201 #endif
203 /* No code before here, we need to init threads */
204 argv = gnm_pre_parse_init (argc, argv);
206 cpu_sanity_check ();
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);
216 #ifdef G_OS_WIN32
217 has_console = FALSE;
219 typedef BOOL (CALLBACK* LPFNATTACHCONSOLE)(DWORD);
220 LPFNATTACHCONSOLE MyAttachConsole;
221 HMODULE hmod;
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);
230 has_console = TRUE;
234 #endif
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]);
242 gnm_init ();
244 cc = gnm_cmd_context_stderr_new ();
245 go_component_set_default_command_context (cc);
246 g_object_unref (cc);
248 cc = g_object_new (GNM_TYPE_IO_CONTEXT_GTK,
249 "show-splash", !gnumeric_no_splash,
250 "show-warnings", !gnumeric_no_warnings,
251 NULL);
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));
259 if (startup_files) {
260 int i, N;
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]);
267 if (uri == NULL) {
268 g_warning ("Ignoring invalid URI.");
269 any_error = TRUE;
270 continue;
273 go_io_context_processing_file (ioc, uri);
274 wbv = workbook_view_new_from_uri (uri, NULL, ioc, NULL);
275 g_free (uri);
277 if (go_io_error_occurred (ioc) ||
278 go_io_warning_occurred (ioc)) {
279 if (go_io_error_occurred (ioc))
280 any_error = TRUE;
281 go_io_error_display (ioc);
282 go_io_error_clear (ioc);
284 if (wbv != NULL) {
285 WBCGtk *wbcg;
287 workbook_update_history (wb_view_get_workbook (wbv), GNM_FILE_SAVE_AS_STYLE_SAVE);
289 wbcg = wbc_gtk_new (wbv, NULL, NULL, geometry);
290 geometry = NULL;
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,
297 wbcg);
299 /* cheesy attempt to keep the ui from freezing during
300 load */
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 */
307 g_object_unref (cc);
308 cc = NULL;
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.)
313 if (opened_workbook)
314 any_error = FALSE;
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);
320 } else {
321 initial_workbook_open_complete = TRUE;
322 if (!opened_workbook) {
323 gint n_of_sheets = gnm_conf_get_core_workbook_n_sheet ();
324 wbc_gtk_new (NULL,
325 workbook_new_with_sheets (n_of_sheets),
326 NULL, geometry);
329 if (immediate_exit_flag) {
330 GSList *l;
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 (),
336 "workbook_removed",
337 G_CALLBACK (cb_workbook_removed),
338 NULL);
340 gnm_io_context_gtk_discharge_splash (GNM_IO_CONTEXT_GTK (ioc));
341 g_object_unref (ioc);
343 gtk_main ();
346 g_slist_free (wbcgs_to_kill);
347 gnumeric_arg_shutdown ();
348 store_plugin_state ();
349 gnm_shutdown ();
351 #if defined(G_OS_WIN32)
352 if (has_console) {
353 close(1);
354 close(2);
355 FreeConsole();
357 #endif
359 gnm_pre_parse_shutdown ();
360 go_component_set_default_command_context (NULL);
363 * This helps finding leaks. We might want it in developent
364 * only.
366 if (gnm_debug_flag ("close-displays")) {
367 GSList *displays;
369 gdk_flush();
370 while (g_main_context_iteration (NULL, FALSE))
371 ;/* nothing */
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;