Logo Search packages:      
Sourcecode: gaby version File versions  Download package

main.c

/*  Gaby
 *  Copyright (C) 1998-2000 Frederic Peters
 *
 *  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
 *  (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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#define APPNAME_DECLARED
#define LISTS_DECLARED
#define EVERY_WINS_DECLARED
#define DEBUG_MODE_DECLARED
#define LANGUAGE_DECLARED

#include "gaby.h"
#include "files.h"
#include "tables.h"
#include "windows.h"
#include "actions.h"
#include "gtk_main.h"
/*#include "menu.h"*/

/** global variables **/

/* it holds the name of the desc file (gaby, gcd, ...) */
char *appname;

GList *list_tables = NULL;
GList *list_subtables = NULL;
GList *list_views = NULL;
GList *list_actions = NULL;
GList *list_windows = NULL;
GList *list_print_plugins = NULL;

int debug_mode;

char language[3];

#ifdef COMPATIBILITY
void try_to_read_old_config(gchar *name);
#endif

void fatal_error(char *message);

/*
 * init_gaby
 *
 * Description:
 * This functions creates the required directory (~/.gaby/) and checks if
 * plug-ins are installed (it exits if they're not found).
 *
 * Returns: TRUE if ~/.gaby/ existed, FALSE otherwise
 */
gboolean init_gaby()
{
      char str[PATH_MAX];
      DIR *dir;
      
#ifndef FOLLOW_MIGUEL
      dir = opendir(PLUGINS_DIR);
      if ( dir == NULL ) {
            fatal_error(
                  _("You forgot to install the plug-ins, aborting.\n"
                    "You should run 'make install' to fix this."));
            exit(1);
      }
      closedir(dir);
#endif
      /* filling the language variable
       * it could be much better if I allowed such things as
       * LANGUAGE=fr_FR:fr in a real way (no arbitrary cut!)
       * it should also be a good candidate for a 'init_gaby'
       * shared among executables...
       */
      strcpy(language, "en");
      if ( getenv("LANGUAGE") || getenv("LANG") ) {
            char *t = g_strdup_printf("%s", getenv("LANGUAGE") ?
                                          getenv("LANGUAGE")
                                          : getenv("LANG")   );
            t[2] = 0;
            strcpy(language, t);
            g_free(t);
      }
      
      
      /* checking ~/.gaby/ (creating it if necessary) */
      sprintf(str, "%s/.gaby", g_get_home_dir());
      dir = opendir(str);
      if ( dir == NULL ) {
            /* we let everybody read our files.
             * Should this be configurable ? */
            if ( mkdir(str, 0755) == 0 ) return FALSE;
            gaby_message = g_strdup(_("Unable to create ~/.gaby/; aborting."));
            gaby_errno = CUSTOM_ERROR;
            gaby_perror_in_a_box();
            exit(7);
      } else {
            closedir(dir);
            return TRUE;
      }
}

char* parse_options(int argc, char *argv[], gboolean opt[])
{
      int c;
      char *name;
      
#ifdef GETOPTLONG_AVAILABLE
      static struct option long_options[] = {
            { "as"                        , 1, 0, 'a' },
            { "debug"               , 0, 0, 'd' },
            { "disable-other-windows"     , 0, 0, 'w' },
            { "skip-startup-actions"      , 0, 0, 's' },
            { "version"                   , 0, 0, 'V' },
            { "help"                      , 0, 0, 'h' },
            {   0                         , 0, 0,  0  }
      };
#endif

      opt[0] = FALSE;         /* disable-other-windows */
      opt[1] = FALSE;         /* skip-startup-scripts */

      if ( strchr(argv[0], '/') == NULL ) {
            name = argv[0];
      } else {
            name = strrchr(argv[0], '/')+1;
      }

      /* this allows to rename gaby symlinks to gaby-<real name> or
       * <real name>-gaby . This idea came from Matti Koskimies (Finnish
       * translations) and Anthony Fok (Debian non-maintainer) 'cause there
       * are apps with names like gcd, gnomecard, videobase, ... and they
       * will overwrite the symlinks without wondering about Gaby (which is
       * kind enough to not overwrite them if they exist). As a side effect
       * you can now launch gaby (using desc.gaby) with a symlink named
       * gaby-gaby-gaby. Useful :)
       */
      if ( strncmp(name, "gaby-", 5) == 0 )
            name += 5;
      if ( strncmp(name+strlen(name)-5, "-gaby", 5) == 0 ) 
            name[strlen(name)-5] = 0;
      
#ifndef GETOPT_AVAILABLE
      /* we don't have getopt, we only implement --as <name> */
      if ( argc == 3 && strcmp(argv[1], "--as") == 0 ) {
            name = argv[2];
      }
      return name;
#else /* GETOPT_AVAILABLE */
      opterr = 0;

      while (1) {
#ifdef GETOPTLONG_AVAILABLE
            c = getopt_long(argc, argv, "a:dwsVh", long_options, NULL);
#else
            c = getopt(argc, argv, "a:dwsVh");
#endif
            if ( c == -1 ) break;
            switch ( c ) {
                  case 'a':
                  {
                        name = optarg;
                  } break;
                  case 'w':
                  {
                        opt[0] = TRUE;
                  } break;
                  case 's':
                  {
                        opt[1] = TRUE;
                  } break;
                  case 'd':
                  {
                        debug_mode++;
                  } break;
                  case 'V':
                  {
                        g_print(_("Gaby %s [%s]\n"), VERSION, CODENAME);
                        g_print(_("Copyright (c) 1998-2001 Frederic Peters\n"));
                        g_print(_("\nCompile options\n"));
                        g_print(_("  Plug-ins directory : %s\n"), PLUGINS_DIR);
                        g_print(_("  Use Gnome : "));
#ifdef USE_GNOME
                        g_print(_("yes\n"));
#else
                        g_print(_("no\n"));
#endif
                        g_print("  SYSCONF_DIR : %s\n", SYSCONF_DIR);

                        g_print(_("  Other flags : "));
#ifdef SUPERFLUOUS
                        g_print("SUPERFLUOUS ");
#endif
#ifdef DEBUG_GABY
                        g_print("DEBUG ");
#endif
#ifdef FOLLOW_MIGUEL
                        g_print("MIGUEL_WISHES ");
#endif
                        g_print("\n");
                        g_print(_("  Interpreters : "));
#ifdef USE_PYTHON
                        g_print("Python ");
#endif
#ifdef USE_PERL
                        g_print("Perl ");
#endif
#ifdef USE_GUILE
                        g_print("Guile ");
#endif
                        g_print("\n");
                        return NULL;
                  } break;
                  case '?':
                  case 'h':
                  {
                        g_print(_("Command line options :\n"));
                        g_print(_("  -a, --as NAME          \tlaunch gaby with the desc.NAME descfile\n"));
                        g_print(_("  -d, --debug            \tturn on verbose debugging\n"));
                        g_print(_("  --disable-other-windows\tdoesn't load additional windows\n"));
                        g_print(_("  --skip-startup-actions \tdoesn't launch startup actions\n"));
                        g_print(_("  -V, --version          \tshow gaby version number\n"));
                        g_print(_("  -h, --help             \tshow this help screen\n"));
                        return NULL;
                  } break;
            }
      }

      return name;
#endif /* GETOPT_AVAILABLE */
}

#ifdef USE_GNOME

/* TODO (post-2.0) : session management
 * delayed since that is not really necessary */

static gint save_yourself (GnomeClient *client, gint phase,
                     GnomeSaveStyle save_style, gint is_shutdown,
                     GnomeInteractStyle interact_style, gint is_fast,
                     gpointer client_data)
{
      gchar* args[4] = { "rm", "-r", NULL, NULL };
      
      if ( is_fast ) return TRUE; /* really fast :) */

      gnome_config_push_prefix (gnome_client_get_config_prefix (client));
      
      args[2] = gnome_config_get_real_path ( 
                        gnome_client_get_config_prefix (client) );
      debug_print("[save_yourself] %s\n", args[2] );
      gnome_client_set_discard_command (client, 3, args);
      
      return TRUE;
}

void init_session_management()
{
      /* it should return useful stuffs */
      GnomeClient *client;

      client = gnome_master_client();
      

      gtk_signal_connect (GTK_OBJECT (client), "save_yourself",
                        GTK_SIGNAL_FUNC (save_yourself), NULL);
      gtk_signal_connect (GTK_OBJECT (client), "die", 
                  GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
      
      gnome_config_push_prefix (gnome_client_get_config_prefix (client));
      
      gnome_config_pop_prefix ();
      
}

#endif

guint free_actions_plugins(gpointer null)
{
      GList *actions;
      action *a;

      debug_print("[free_actions_plugins] --\n");
      if ( ! list_actions ) return 0;
      actions = g_list_first(list_actions);
      
      while ( actions != NULL ) {
            a = actions->data;
            actions = g_list_next(actions);
            
            if ( a == NULL ) continue;
            if ( a->type != PLUG_IN ) continue;
            if ( a->what.plugin == NULL ) continue;
            if ( a->what.plugin->handle == NULL ) continue;
            if ( a->what.plugin->loaded > 0 ) continue;

            debug_print("Unloading %s actions plug-in.\n", 
                                    a->what.plugin->name);

            g_module_close(a->what.plugin->handle);
            a->what.plugin->handle = NULL;
            a->what.plugin->get_function_by_name = NULL;
            
      }

      return TRUE;
}

void fatal_error(char *message)
{
#ifdef USE_GNOME
      GtkWidget *dlg;
      char *argv[] = { "gaby", NULL };
      
      gnome_init(_("Gaby"), VERSION, 1, argv);
      
      dlg = gnome_error_dialog (message);
      gtk_signal_connect(GTK_OBJECT(dlg), "clicked", gtk_main_quit, NULL);
      gtk_widget_show(dlg);
      gtk_main();
#else
      GtkWidget *dialog, *vbox, *label, *button;
      
      dialog = gtk_dialog_new();
      gtk_window_set_title(GTK_WINDOW(dialog), _("Fatal error"));
      vbox = GTK_DIALOG(dialog)->vbox;
      gtk_container_set_border_width(GTK_CONTAINER(vbox), 5 );
      label = gtk_label_new(message);
      gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0 );
      gtk_widget_show(label);
      
      button = gtk_button_new_with_label(_("OK"));
      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), 
                              button, TRUE, TRUE, 5 );
      gtk_signal_connect(GTK_OBJECT(button), "clicked", gtk_main_quit, NULL);
      gtk_widget_show(button);
      
      gtk_widget_show(dialog);
      gtk_main();
#endif
}

#if 0
guint free_print_plugins()
{
      PrintPluginData *ppd;
      GList *print_plugins = list_print_plugins;

#ifdef DEBUG_GABY
      debug_print("[free_print_plugins] --\n");
#endif
      
      while ( print_plugins != NULL ) {
            ppd = print_plugins->data;
            print_plugins = g_list_next(print_plugins);
            
            if ( ppd == NULL ) continue;
            if ( ppd->handle == NULL ) continue;
            if ( ppd->loaded > 0 ) continue;

#ifdef DEBUG_GABY
            debug_print("Unloading %s print plug-in.\n", ppd->i18n_name);
#endif

            g_module_close(ppd->handle);
            ppd->handle = NULL;
            
      }

      return TRUE;
}
#endif

#if 0
void load_interpreters(GList *tables, GList *subtables, GList *views,
                   GList *actions )
{
      action *act;
      char int_name[100];
      
      if ( actions == NULL ) return;

      actions = g_list_first(actions);

      while ( actions != NULL ) {
            act = actions->data;
            actions = g_list_next(actions);
            if ( act == NULL ) continue;
            if ( act->type != SCRIPT_FU ) continue;
            
            strchr(act->what.script, ':')[0] = 0;
            strcpy(int_name, act->what.script);
            act->what.script[strlen(act->what.script)] = ':';
             
            get_interpreter(int_name);
      }
}
#endif

int main ( int argc, char *argv[] )
{
      GList *view_plugins = NULL;
      gchar *name;
      gboolean first_time;
      gboolean options[2];
#ifndef FOLLOW_MIGUEL
      gboolean f__plugins = FALSE;
#endif
      GList *t;

      setlocale (LC_ALL, "");
      bindtextdomain (PACKAGE, LOCALEDIR);
      textdomain (PACKAGE);

      gtk_set_locale();

      name = parse_options(argc, argv, options);
      if ( name == NULL ) exit(-1);
      appname = g_strdup(name);

      first_time = ! init_gaby();
      
      /*g_print("Gaby %s [%s]\n", VERSION, name);*/
      
      gtk_init(&argc, &argv);
      gtk_rc_init();

#ifdef COMPATIBILITY
      try_to_read_old_config(name);
#endif
      
      if ( ! tables_load_struct(name) ) {
            fatal_error(_("Error loading tables structure! Aborting.\n"));
            exit(1);
      }
      tables_load ();
#ifndef FOLLOW_MIGUEL
      if ( gaby_errno == CUSTOM_ERROR ) {
            f__plugins = TRUE;
            gaby_errno = NO_ERROR;
      } 
#endif
      
      view_plugins = viewplugins_load(name);
#ifndef FOLLOW_MIGUEL
      if ( gaby_errno == CUSTOM_ERROR && f__plugins == TRUE ) {
            putchar(7);
            /* this may be put in a dialog box */
            fatal_error(_("\n\n\tWarning!!!\n"
  "\nGaby plug-ins don't seem to work on your system.\n"
  "Those errors are hardly predictable and hardly solvable\n"
  "but you should definitely mail the author with information\n"
  "regarding your system.\n"
  "Meanwhile you may want to bypass Gaby design and create a huge\n"
  "monolithic app: to do so:\n"
  "   ./configure --enable-miguel-wishes\n\n"));
            exit(42);
      }
#endif
      if ( view_plugins->data == NULL ) {
            fatal_error(_("Error loading view plug-ins! Aborting.\n"));
            exit(1);
      }
      
      if ( ! st_load_struct(view_plugins, name ) ) {
            fatal_error(_("Error loading subtables structure! Aborting.\n"));
            exit(1);
      }

      actions_load(name);

      list_print_plugins = printplugins_load();
      
#ifdef USE_GNOME
      /* we don't want a error message if we provide our options */
      
      argv[0] = name;
      gnome_init(_("Gaby"), VERSION, 1, argv);

      init_session_management();
#endif

#if 0 /* disabled since they are now only loaded when we need them */
      load_interpreters(tables, subtables, views, actions);
#endif
      
      debug_print("[main] create_main_window\n");
      create_main_window (view_plugins);

      gtk_main_iteration(); /* trick to fake a fast start :) */
      /* (i'm not even sure that works) */
      
      if ( options[0] == FALSE ) {
            debug_print("[main] crate_other_defaults_windows\n");
            create_other_defaults_windows (view_plugins);
      }

#ifndef FOLLOW_MIGUEL
      gtk_timeout_add(1000*60*1, (GtkFunction)free_actions_plugins, NULL);
/*    gtk_timeout_add(1000*60*10, (GtkFunction)free_print_plugins, NULL);*/
#endif /* ! FOLLOW_MIGUEL */

      if ( options[1] == FALSE ) {
            debug_print("[main] Launching startup scripts\n");
            launch_startup_scripts(first_time);
      }

      t = load_window_bindings(name, view_plugins);
      if ( t ) {
            set_window_binding(t);
            g_list_free(t);
      }
      
      g_list_free(view_plugins);
      
      gtk_main();
      
      return 0;
}


Generated by  Doxygen 1.6.0   Back to index