/* PSPPIRE - a graphical user interface for PSPP.
Copyright (C) 2004, 2005, 2006, 2010, 2011, 2012 Free Software Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include "ui/gui/psppire.h"
#include
#include
#include "language/lexer/include-path.h"
#include "libpspp/argv-parser.h"
#include "libpspp/array.h"
#include "libpspp/assertion.h"
#include "libpspp/cast.h"
#include "libpspp/copyleft.h"
#include "libpspp/str.h"
#include "libpspp/string-array.h"
#include "libpspp/version.h"
#include "ui/source-init-opts.h"
#include "gl/configmake.h"
#include "gl/progname.h"
#include "gl/relocatable.h"
#include "gl/version-etc.h"
#include "gl/xalloc.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
/* Arguments to be interpreted before the X server gets initialised */
enum
{
OPT_HELP,
OPT_VERSION,
OPT_NO_SPLASH,
OPT_MEASURE_STARTUP,
N_STARTUP_OPTIONS
};
static const struct argv_option startup_options[N_STARTUP_OPTIONS] =
{
{"help", 'h', no_argument, OPT_HELP},
{"version", 'V', no_argument, OPT_VERSION},
{"no-splash", 'q', no_argument, OPT_NO_SPLASH},
{"measure-startup", 0, no_argument, OPT_MEASURE_STARTUP},
};
/* --measure-startup: Prints the elapsed time to start up and load any file
specified on the command line. */
static gboolean measure_startup;
static GTimer *startup;
static void
usage (void)
{
char *inc_path = string_array_join (include_path_default (), " ");
GOptionGroup *gtk_options;
GOptionContext *ctx;
gchar *gtk_help_base, *gtk_help;
/* Get help text for GTK+ options. */
ctx = g_option_context_new ("psppire");
gtk_options = gtk_get_option_group (FALSE);
gtk_help_base = g_option_context_get_help (ctx, FALSE, gtk_options);
g_option_context_free (ctx);
/* The GTK+ help text starts with usage instructions that we don't want,
followed by a blank line. Trim off everything up to and including the
first blank line. */
gtk_help = strstr (gtk_help_base, "\n\n");
gtk_help = gtk_help != NULL ? gtk_help + 2 : gtk_help_base;
printf (_("\
PSPPIRE, a GUI for PSPP, a program for statistical analysis of sample data.\n\
Usage: %s [OPTION]... FILE\n\
\n\
Arguments to long options also apply to equivalent short options.\n\
\n\
GUI options:\n\
-q, --no-splash don't show splash screen during startup\n\
\n\
%s\
Language options:\n\
-I, --include=DIR append DIR to search path\n\
-I-, --no-include clear search path\n\
-a, --algorithm={compatible|enhanced}\n\
set to `compatible' if you want output\n\
calculated from broken algorithms\n\
-x, --syntax={compatible|enhanced}\n\
set to `compatible' to disable PSPP extensions\n\
-i, --interactive interpret syntax in interactive mode\n\
-s, --safer don't allow some unsafe operations\n\
Default search path: %s\n\
\n\
Informative output:\n\
-h, --help display this help and exit\n\
-V, --version output version information and exit\n\
\n\
A non-option argument is interpreted as a .sav file, a .por file or a syntax\n\
file to load.\n"),
program_name, gtk_help, inc_path);
free (inc_path);
g_free (gtk_help_base);
emit_bug_reporting_address ();
exit (EXIT_SUCCESS);
}
static void
startup_option_callback (int id, void *show_splash_)
{
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gboolean *show_splash = show_splash_;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
switch (id)
{
case OPT_HELP:
usage ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
break;
case OPT_VERSION:
version_etc (stdout, "psppire", PACKAGE_NAME, PACKAGE_VERSION,
"Ben Pfaff", "John Darrington", "Jason Stover",
NULL_SENTINEL);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
exit (EXIT_SUCCESS);
case OPT_NO_SPLASH:
*show_splash = FALSE;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
break;
case OPT_MEASURE_STARTUP:
measure_startup = TRUE;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
break;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
default:
NOT_REACHED ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
}
}
static GtkWidget *
create_splash_window (void)
{
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
GtkWidget *splash ;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
GtkWidget *image;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_window_set_auto_startup_notification (FALSE);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
splash = gtk_window_new (GTK_WINDOW_POPUP);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_window_set_position (GTK_WINDOW (splash),
GTK_WIN_POS_CENTER_ALWAYS);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_window_set_type_hint (GTK_WINDOW (splash),
GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
image = gtk_image_new_from_file (relocate (PKGDATADIR "/splash.png"));
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_container_add (GTK_CONTAINER (splash), image);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_widget_show (image);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
return splash;
}
static gboolean
hide_splash_window (gpointer data)
{
GtkWidget *splash = data;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_widget_destroy (splash);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_window_set_auto_startup_notification (TRUE);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
return FALSE;
}
static gboolean
print_startup_time (gpointer data)
{
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_timer_stop (startup);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
printf ("%.3f seconds elapsed\n", g_timer_elapsed (startup, NULL));
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_timer_destroy (startup);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
startup = NULL;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
return FALSE;
}
static gboolean
quit_one_loop (gpointer data)
{
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_main_quit ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
return FALSE;
}
struct initialisation_parameters
{
const char *data_file;
GtkWidget *splash_window;
};
static gboolean
run_inner_loop (gpointer data)
{
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
struct initialisation_parameters *ip = data;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
initialize (ip->data_file);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_timeout_add (500, hide_splash_window, ip->splash_window);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
if (measure_startup)
{
GSource *source = g_idle_source_new ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_source_set_priority (source, G_PRIORITY_LOW);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_source_set_callback (source, print_startup_time, NULL, NULL);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_source_attach (source, NULL);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_source_unref (source);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
}
gtk_main ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
de_initialize ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
return FALSE;
}
static GMemVTable vtable =
{
xmalloc,
xrealloc,
free,
xcalloc,
malloc,
realloc
};
#ifdef __APPLE__
/* Searches ARGV for the -psn_xxxx option that the desktop application
launcher passes in, and removes it if it finds it. Returns the new value
of ARGC. */
static int
remove_psn (int argc, char **argv)
{
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
int i;
for (i = 0; i < argc; i++)
{
if (!strncmp(argv[i], "-psn", 4))
{
remove_element (argv, argc + 1, sizeof *argv, i);
return argc - 1;
}
}
return argc;
}
#endif /* __APPLE__ */
int
main (int argc, char *argv[])
{
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
struct initialisation_parameters init_p;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gboolean show_splash = TRUE;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
struct argv_parser *parser;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
const gchar *vers;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
set_program_name (argv[0]);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_mem_set_vtable (&vtable);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_thread_init (NULL);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_disable_setlocale ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
startup = g_timer_new ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_timer_start (startup);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
if ( ! gtk_parse_args (&argc, &argv) )
{
perror ("Error parsing arguments");
exit (1);
}
if ( (vers = gtk_check_version (GTK_MAJOR_VERSION,
GTK_MINOR_VERSION,
GTK_MICRO_VERSION)) )
{
g_warning ("%s", vers);
}
#ifdef __APPLE__
argc = remove_psn (argc, argv);
#endif
/* Parse our own options.
This must come BEFORE gdk_init otherwise options such as
--help --version which ought to work without an X server, won't.
*/
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
parser = argv_parser_create ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
argv_parser_add_options (parser, startup_options, N_STARTUP_OPTIONS,
startup_option_callback, &show_splash);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
source_init_register_argv_parser (parser);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
if (!argv_parser_run (parser, argc, argv))
exit (EXIT_FAILURE);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
argv_parser_destroy (parser);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
/* Initialise GDK. Theoretically this call can remove options from argc,argv if
it thinks they are gdk options.
However there shouldn't be any here because of the gtk_parse_args call above. */
gdk_init (&argc, &argv);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
init_p.splash_window = create_splash_window ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
init_p.data_file = optind < argc ? argv[optind] : NULL;
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
if ( show_splash )
gtk_widget_show (init_p.splash_window);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
g_idle_add (quit_one_loop, 0);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_quit_add (0, run_inner_loop, &init_p);
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
gtk_main ();
printf ("%s:%d %s\n", __FILE__, __LINE__, setlocale (LC_NUMERIC, NULL));
return 0;
}