Revert "adding osx application bundler scripts"
[pspp] / src / ui / gui / psppire.c
index 6e7c6e0a5ea05d25e149bea74eef9415fc031f5b..1532cbd316fca466ad9f6ef5169db23f353cfb39 100644 (file)
@@ -1,11 +1,9 @@
-/* 
-   PSPPIRE --- A Graphical User Interface for PSPP
-   Copyright (C) 2004, 2005, 2006  Free Software Foundation
-   Written by John Darrington
+/* PSPPIRE - a graphical user interface for PSPP.
+   Copyright (C) 2004, 2005, 2006, 2009, 2010, 2011, 2012, 2013, 2014, 2016  Free Software Foundation
 
-   This program is free software; you can redistribute it and/or modify
+   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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#include <assert.h>
-#include <libintl.h>
+#include <config.h>
 
-#include <libpspp/version.h>
-#include <libpspp/copyleft.h>
-#include <data/settings.h>
 
-#include <getopt.h>
-#include <gtk/gtk.h>
+#include <assert.h>
+#include <gsl/gsl_errno.h>
 #include <gtk/gtk.h>
-#include <glade/glade.h>
-#include "menu-actions.h"
-#include "psppire-dict.h"
-#include "psppire-var-store.h"
-#include "psppire-data-store.h"
-#include "helper.h"
-#include "data-sheet.h"
-#include "var-sheet.h"
-#include "message-dialog.h"
-
-GladeXML *xml;
-
-
-PsppireDict *the_dictionary = 0;
-
-PsppireDataStore *data_store = 0;
-
-
-static bool parse_command_line (int *argc, char ***argv, 
-                               gchar **filename, GError **err);
-
+#include <libintl.h>
+#include <unistd.h>
+
+#include "data/any-reader.h"
+#include "data/casereader.h"
+#include "data/dataset.h"
+#include "data/datasheet.h"
+#include "data/file-handle-def.h"
+#include "data/session.h"
+#include "data/settings.h"
+
+#include "language/lexer/lexer.h"
+#include "libpspp/i18n.h"
+#include "libpspp/message.h"
+#include "libpspp/version.h"
+
+#include "output/driver.h"
+#include "output/journal.h"
+#include "output/message-item.h"
+
+#include "ui/gui/dict-display.h"
+#include "ui/gui/executor.h"
+#include "ui/gui/psppire-data-store.h"
+#include "ui/gui/psppire-data-window.h"
+#include "ui/gui/psppire-dict.h"
+#include "ui/gui/psppire.h"
+#include "ui/gui/psppire-output-window.h"
+#include "ui/gui/psppire-syntax-window.h"
+#include "ui/gui/psppire-selector.h"
+#include "ui/gui/psppire-var-view.h"
+#include "ui/gui/psppire-means-layer.h"
+#include "ui/gui/psppire-window-register.h"
+#include "ui/gui/widgets.h"
+#include "ui/source-init-opts.h"
+#include "ui/syntax-gen.h"
+
+#include "ui/gui/icons/icon-names.h"
+
+
+#include "gl/configmake.h"
+#include "gl/xalloc.h"
+#include "gl/relocatable.h"
+
+static void create_icon_factory (void);
 
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 
-static void
-give_help(void)
-{
-  static struct msg m = {
-    MSG_GENERAL, 
-    MSG_NOTE,
-    {0, -1},
-    0, 
-  };
-
-  if (! m.text) 
-    m.text=g_strdup(_("Sorry. The help system hasn't yet been implemented."));
-
-  popup_message(&m);
-}
-
-PsppireVarStore *var_store = 0;
 
-int 
-main(int argc, char *argv[]) 
+bool
+initialize (const struct init_source *is)
 {
-
-  GtkWidget *data_editor ;
-  GtkSheet *var_sheet ; 
-  GtkSheet *data_sheet ;
-
-  gchar *filename=0;
-  GError *err = 0;
-  gchar *vers;
-
-  gtk_init(&argc, &argv);
-  if ( (vers = gtk_check_version(GTK_MAJOR_VERSION, 
-                                GTK_MINOR_VERSION, 
-                                GTK_MICRO_VERSION)) )
-    {
-      g_critical(vers);
-    }
-       
-
-  /* gtk_init messes with the locale. 
-     So unset the bits we want to control ourselves */
-  setlocale (LC_NUMERIC, "C");
-
-  bindtextdomain (PACKAGE, locale_dir);
-
-  textdomain (PACKAGE);
-
-  if ( ! parse_command_line(&argc, &argv, &filename, &err) ) 
+  switch (is->state)
     {
-      g_clear_error(&err);
-      return 1;
+    case 0:
+      i18n_init ();
+      break;
+    case 1:
+      preregister_widgets ();
+      break;
+    case 2:
+      gsl_set_error_handler_off ();
+      break;
+    case 3:
+      output_engine_push ();
+      break;
+    case 4:
+      settings_init ();
+      break;
+    case 5:
+      fh_init ();
+      break;
+    case 6:
+      psppire_set_lexer (NULL);
+      break;
+    case 7:
+      bind_textdomain_codeset (PACKAGE, "UTF-8");
+      break;
+    case 8:
+      if ( ! gtk_parse_args (is->argc, is->argv) )
+       {
+         perror ("Error parsing arguments");
+         exit (1);
+       }
+      break;
+    case 9:
+      create_icon_factory ();
+      break;
+    case 10:
+      psppire_output_window_setup ();
+      break;
+    case 11:
+      journal_init ();
+      break;
+    case 12:
+      textdomain (PACKAGE);
+      break;
+    case 13:
+      /* FIXME: This should be implemented with a GtkInterface */
+      psppire_selector_set_default_selection_func (GTK_TYPE_ENTRY, insert_source_row_into_entry);
+      psppire_selector_set_default_selection_func (PSPPIRE_VAR_VIEW_TYPE, insert_source_row_into_tree_view);
+      psppire_selector_set_default_selection_func (GTK_TYPE_TREE_VIEW, insert_source_row_into_tree_view);
+      psppire_selector_set_default_selection_func (PSPPIRE_TYPE_MEANS_LAYER, insert_source_row_into_layers);
+      break;
+    case 14:
+      {
+      if (is->filename_arg != -1)
+       {
+#ifndef G_OS_WIN32
+         const char *file = (*is->argv)[is->filename_arg];
+         const gchar *local_encoding = NULL;
+         g_get_charset (&local_encoding);
+#else
+         char **as = g_win32_get_command_line ();
+         const char *file = as[is->filename_arg];
+         const gchar *local_encoding = "UTF-8";
+#endif   
+
+         struct file_handle *fh = fh_create_file (NULL,
+                                                  file,
+                                                  local_encoding,
+                                                  fh_default_properties ());
+         
+         const char *filename = fh_get_file_name (fh);
+
+         int retval = any_reader_detect (fh, NULL);
+
+         /* Check to see if the file is a .sav or a .por file.  If not
+            assume that it is a syntax file */
+         if (retval == 1)
+           open_data_window (NULL, filename, NULL, NULL);
+         else if (retval == 0)
+           {
+             create_data_window ();
+             open_syntax_window (filename, NULL);
+           }
+
+         fh_unref (fh);
+       }
+      else
+       {
+         create_data_window ();
+       }
+      return TRUE;
+      }
+      break;
+    default:
+      return TRUE;
+      break;
     }
+  return FALSE;
+}
 
 
-  glade_init();
-
-
-  settings_init();
-
-  /* 
-  set_pspp_locale("da_DK");
-  */
+void
+de_initialize (void)
+{
+  settings_done ();
+  output_engine_pop ();
+  i18n_done ();
+}
 
-  message_dialog_init();
+void
+psppire_quit (void)
+{
+  gtk_main_quit ();
+}
 
-  the_dictionary = psppire_dict_new();
+struct icon_size
+{
+  int resolution;  /* The dimension of the images which will be used */
+  size_t n_sizes;  /* The number of items in the array below. */
+  const GtkIconSize *usage; /* An array determining for what the icon set is used */
+};
 
-  bind_textdomain_codeset(PACKAGE, "UTF-8");
+static const GtkIconSize menus[] = {GTK_ICON_SIZE_MENU};
+static const GtkIconSize large_toolbar[] = {GTK_ICON_SIZE_LARGE_TOOLBAR};
+static const GtkIconSize small_toolbar[] = {GTK_ICON_SIZE_SMALL_TOOLBAR};
 
-  /* Create the model for the var_sheet */
-  var_store = psppire_var_store_new(the_dictionary);
 
-  data_store = psppire_data_store_new(the_dictionary);
+/* We currently have three icon sets viz: 16x16, 24x24 and 32x32
+   We use the 16x16 for menus, the 32x32 for the large_toolbars and 
+   the 24x24 for small_toolbars.
 
-  /* load the interface */
-  xml = glade_xml_new(PKGDATADIR "/psppire.glade", NULL, NULL);
+   The order of this array is pertinent.  The icons in the sets occuring
+   earlier in the array will be used a the wildcard (default) icon size,
+   if such an icon exists.
+*/
+static const struct icon_size sizemap[] = 
+{
+  {24,  sizeof (small_toolbar) / sizeof (GtkIconSize), small_toolbar},
+  {16,  sizeof (menus) / sizeof (GtkIconSize), menus},
+  {32,  sizeof (large_toolbar) / sizeof (GtkIconSize), large_toolbar}
+};
 
-  if ( !xml ) return 1;
 
-  data_editor = get_widget_assert(xml, "data_editor");
-  gtk_window_set_icon_from_file(GTK_WINDOW(data_editor), 
-                               PKGDATADIR "/psppicon.png",0);
+static void
+create_icon_factory (void)
+{
+  gint c;
+  GtkIconFactory *factory = gtk_icon_factory_new ();
+  struct icon_context ctx[2];
+  ctx[0] = action_icon_context;
+  ctx[1] = category_icon_context;
+  for (c = 0 ; c < 2 ; ++c)
+  {
+    const struct icon_context *ic = &ctx[c];
+    gint i;
+    for (i = 0 ; i < ic->n_icons ; ++i)
+      {
+       gboolean wildcarded = FALSE;
+       GtkIconSet *icon_set = gtk_icon_set_new ();
+       int r;
+       for (r = 0 ; r < sizeof (sizemap) / sizeof (sizemap[0]); ++r)
+         {
+           int s;
+           GtkIconSource *source = gtk_icon_source_new ();
+           gchar *filename = g_strdup_printf ("%s/%s/%dx%d/%s.png", PKGDATADIR,
+                                              ic->context_name,
+                                              sizemap[r].resolution, sizemap[r].resolution,
+                                              ic->icon_name[i]);
+           const char *relocated_filename = relocate (filename);
+           GFile *gf = g_file_new_for_path (relocated_filename);
+           if (g_file_query_exists (gf, NULL))
+             {
+               gtk_icon_source_set_filename (source, relocated_filename);
+               if (!wildcarded)
+                 {
+                   gtk_icon_source_set_size_wildcarded (source, TRUE);
+                   wildcarded = TRUE;
+                 }
+             }
+           g_object_unref (gf);
+
+           for (s = 0 ; s < sizemap[r].n_sizes ; ++s)
+             gtk_icon_source_set_size (source, sizemap[r].usage[s]);
+           if (filename != relocated_filename)
+             free (CONST_CAST (char *, relocated_filename));
+           g_free (filename);
+
+           if ( gtk_icon_source_get_filename (source))
+             gtk_icon_set_add_source (icon_set, source);
+
+           gtk_icon_source_free (source);
+         }
+      
+       gtk_icon_factory_add (factory, ic->icon_name[i], icon_set);
+    }
+  }
 
-  /* connect the signals in the interface */
-  glade_xml_signal_autoconnect(xml);
+  {
+    struct iconmap
+    {
+      const gchar *gtk_id;
+      gchar *pspp_id;
+    };
 
-  var_sheet  = GTK_SHEET(get_widget_assert(xml, "variable_sheet"));
-  data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet"));
+    /* We have our own icons for some things.
+       But we want the Stock Item to be identical to the Gtk standard
+       ones in all other respects.
+    */
+    const struct iconmap map[] = {
+      {GTK_STOCK_NEW,    "file-new-document"},
+      {GTK_STOCK_QUIT,   "file-quit"},
+      {GTK_STOCK_SAVE,   "file-save-document"},
+      {GTK_STOCK_CUT,    "edit-cut"},
+      {GTK_STOCK_COPY,   "edit-copy"},
+      {GTK_STOCK_PASTE,  "edit-paste"},
+      {GTK_STOCK_UNDO,   "edit-undo"},
+      {GTK_STOCK_REDO,   "edit-redo"},
+      {GTK_STOCK_DELETE, "edit-delete"},
+      {GTK_STOCK_ABOUT,  "help-about"},
+      {GTK_STOCK_PRINT,  "file-print-document"}
+    };
 
-  gtk_sheet_set_model(var_sheet, G_SHEET_MODEL(var_store));
-  
-  gtk_sheet_set_model(data_sheet, G_SHEET_MODEL(data_store));
+    GtkStockItem customised[sizeof (map) / sizeof (map[0])];
+    int i;
 
-  if (filename)
-    gtk_init_add((GtkFunction)load_system_file, filename);
-  else
-    gtk_init_add((GtkFunction)clear_file, 0);
+    for (i = 0; i < sizeof (map) / sizeof (map[0]); ++i)
+    {
+      gtk_stock_lookup (map[i].gtk_id, &customised[i]);
+      customised[i].stock_id =  map[i].pspp_id;
+    }
 
-  var_data_selection_init();
 
-  {
-  GList *helps = glade_xml_get_widget_prefix(xml, "help_button_");
 
-  GList *i;
-  for ( i = g_list_first(helps); i ; i = g_list_next(i))
-      g_signal_connect(GTK_WIDGET(i->data), "clicked", give_help, 0);
+    gtk_stock_add (customised, sizeof (map) / sizeof (map[0]));
   }
 
+  {
+    /* Create our own "pspp-stock-reset" item, using the
+       GTK_STOCK_REFRESH icon set */
+    GtkStockItem items[2] = {
+      {"pspp-stock-reset", N_("_Reset"), 0, 0, PACKAGE},
+      {"pspp-stock-select", N_("_Select"), 0, 0, PACKAGE}
+    };
 
-  /* start the event loop */
-  gtk_main();
+    gtk_stock_add (items, 2);
 
-  message_dialog_done();
+    gtk_icon_factory_add (factory, "pspp-stock-reset",
+                         gtk_icon_factory_lookup_default (GTK_STOCK_REFRESH)
+                         );
 
-  settings_done();
+    gtk_icon_factory_add (factory, "pspp-stock-select",
+                         gtk_icon_factory_lookup_default (GTK_STOCK_INDEX)
+                         );
+  }
 
-  return 0;
+  gtk_icon_factory_add_default (factory);
 }
 
+\f
 
-/* Parses the command line specified by ARGC and ARGV as received by
-   main().  Returns true if normal execution should proceed,
-   false if the command-line indicates that PSPP should exit. */
-static bool
-parse_command_line (int *argc, char ***argv, gchar **filename, GError **err)
+static void
+handle_msg (const struct msg *m_, void *lexer_)
 {
-  static struct option long_options[] =
-    {
-      {"help", no_argument, NULL, 'h'},
-      {"version", no_argument, NULL, 'V'},
-      {0, 0, 0, 0},
-    };
+  struct lexer *lexer = lexer_;
+  struct msg m = *m_;
 
-  int c;
-
-  for (;;)
+  if (lexer != NULL && m.file_name == NULL)
     {
-      c = getopt_long (*argc, *argv, "hV", long_options, NULL);
-      if (c == -1)
-       break;
-
-      switch (c)
-       {
-       case 'h':
-         g_printerr("Usage: psppire {|--help|--version}\n");
-          return false;
-       case 'V':
-         g_print(version);
-         g_print("\n");
-         g_print(legal);
-         return false;
-       default:
-         return false;
-       }
-    }
-
-  if ( optind < *argc) 
-    {
-      *filename = (*argv)[optind];
+      m.file_name = CONST_CAST (char *, lex_get_file_name (lexer));
+      m.first_line = lex_get_first_line_number (lexer, 0);
+      m.last_line = lex_get_last_line_number (lexer, 0);
+      m.first_column = lex_get_first_column (lexer, 0);
+      m.last_column = lex_get_last_column (lexer, 0);
     }
 
-  return true;
+  message_item_submit (message_item_create (&m));
 }
 
-
+void
+psppire_set_lexer (struct lexer *lexer)
+{
+  msg_set_handler (handle_msg, lexer);
+}