Logo Search packages:      
Sourcecode: kazehakase version File versions

main.c

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2002 Hiroyuki Ikezoe
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  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, 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <glib/gi18n.h>

#include "kazehakase.h"
#include "kz-icons.h"
#include "kz-window.h"
#include "kz-actions-tab.h"
#include "kz-xbel.h"
#include "locale.h"
#include "utils.h"
#include "estsearch.h"
#include "mozilla.h"
#if (GLIB_MAJOR_VERSION == 2) && ((GLIB_MINOR_VERSION < 5) || \
            ((GLIB_MINOR_VERSION >= 5) && (GLIB_MICRO_VERSION < 4)))
#include "goption.h"
#endif

KzProfile      *kz_global_profile = NULL;
KzProfile      *kz_proxy          = NULL;
KzRootBookmark *kz_bookmarks      = NULL;
#if USE_MIGEMO
Migemo         *migemo            = NULL;
#endif

static gchar** action_array;
static gchar* geometry_string;
static gboolean show_version;

static GOptionEntry entries[] = {
      { "action", 'a', 0, G_OPTION_ARG_STRING_ARRAY, &action_array, "Execute action", NULL},
      { "geometry", 'g', 0, G_OPTION_ARG_STRING, &geometry_string, " Position the window on the screen", NULL },
      { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, "Show this version", NULL },
      { NULL }
};

static const gchar parameter_string[] = "URI ...";

static GOptionContext *context;
static GOptionGroup *main_group;

gboolean is_restoring_session = FALSE;

gboolean exists_estindex = FALSE;
gchar   *estversion;

static void activate_action(const gchar *text);

/******************************************************************************
 *                                                                            *
 *                                 UI Level                                   *
 *                                                                            *
 ******************************************************************************/
KzUILevel
kz_ui_level (void)
{
      KzUILevel val;
      gchar level[16];

      g_return_val_if_fail(KZ_IS_PROFILE(kz_global_profile),
                       KZ_UI_LEVEL_BEGINNER);

      level[0] = '\0';
      kz_profile_get_value(kz_global_profile,
                       "Global", "ui_level",
                       level, sizeof(level),
                       KZ_PROFILE_VALUE_TYPE_STRING);

      val = kz_ui_level_from_str(level);
      if (!val)
            return KZ_UI_LEVEL_BEGINNER;

      return val;
}


KzUILevel
kz_ui_level_from_str (const gchar *level)
{
      if (!level || !*level)
            return KZ_UI_LEVEL_INVALID;

      if (!strcmp(level, "custom"))
            return KZ_UI_LEVEL_CUSTOM;
      else if (!strcmp(level, "expert"))
            return KZ_UI_LEVEL_EXPERT;
      else if (!strcmp(level, "medium"))
            return KZ_UI_LEVEL_MEDIUM;
      else if (!strcmp(level, "beginner"))
            return KZ_UI_LEVEL_BEGINNER;

      return KZ_UI_LEVEL_INVALID;
}


const gchar *
kz_ui_level_to_str (KzUILevel level)
{
      switch (level)
      {
      case KZ_UI_LEVEL_CUSTOM:
            return "custom";
      case KZ_UI_LEVEL_EXPERT:
            return "expert";
      case KZ_UI_LEVEL_MEDIUM:
            return "medium";
      case KZ_UI_LEVEL_BEGINNER:
            return "beginner";
      default:
            break;
      }

      return NULL;
}


/******************************************************************************
 *                                                                            *
 *                       arguments parser                                     *
 *                                                                            *
 ******************************************************************************/
/* split_string is taken from glib/tests/option-test.c */

static gchar **
split_string (const char *str, int *argc)
{
      gchar **argv;
      int len;
  
      argv = g_strsplit (str, "\n", -1);

      for (len = 0; argv[len] != NULL; len++);
      
      if (argc)
            *argc = len;
      
      return argv;
}

static gboolean
pre_parse_cb (GOptionContext *context,
            GOptionGroup   *group,
            gpointer           data,
            GError        **error)
{
#if 0
      if(action_array)
      {
                /* free action_array before using */
            g_strfreev (action_array);
            action_array = NULL;
      }
#endif
      return TRUE;
}

static gboolean
post_parse_cb (GOptionContext *context,
             GOptionGroup   *group,
             gpointer     data,
             GError        **error)
{
        /* XXX: Is there anything to do? */
      return TRUE;
}

static void
parse_error_cb (GOptionContext *context,
             GOptionGroup   *group,
             gpointer     data,
             GError        **error)
{
      fprintf (stderr, "%s\n", (*error)->message);
      g_error_free (*error);
      return;
}

static void
free_goption()
{
      g_free (geometry_string);
      g_strfreev (action_array);
      g_option_context_free (context);
}

/* XXX: This function has side effect! */
static void
process_args(int argc, char** argv)
{
      int i;
      static int count = 0;
      GList* list;
      KzWindow *kz;

#warning This function has side effect!

      list = kz_window_get_window_list();
      if (!list || !list->data || !KZ_IS_WINDOW(list->data))
            return;

      if(action_array)
      {
                /* show actions */
            for(; action_array[count] != NULL; count++)
            {
                  activate_action(action_array[count]);
            }
      }
      
      kz = KZ_WINDOW(list->data);
      for(i = 1; i < argc; i++)
      {
            gchar *uri = complement_scheme(argv[i]);
            gdk_window_raise(GTK_WIDGET(kz)->window);

            kz_window_open_new_tab(kz, uri);
            g_free(uri);
      }
}

/******************************************************************************
 *                                                                            *
 *                       Kazehakase process checker                           *
 *                                                                            *
 ******************************************************************************/
/*
 *  Based on Text maid 2.3.0
 *  copyright (c) 1998-2003 Kazuki IWAMOTO http://www.maid.org/ iwm@maid.org
 */
enum {
      TARGET_STRING
};

static GtkTargetEntry targets[]={
      {"STRING", 0, TARGET_STRING},
};
static GdkAtom  atom_kz0;  /* for checking process  */
static GdkAtom  atom_kz1;  /* for sending arguments */
static gchar   *arg_text = NULL;
static gint     instance = -1;


static void
cb_selection_get(GtkWidget *widget,
             GtkSelectionData *data,
             guint info,
             guint time,
             GtkWidget *window)
{
      gchar *text = NULL;
      gint length = 0;

      if (data->selection == atom_kz0)
      {
            text = "Kazehakase Selection";
            length = strlen(text);
            gtk_selection_convert(window, atom_kz1,
                              GDK_SELECTION_TYPE_STRING,
                              GDK_CURRENT_TIME);
      }
      else if (data->selection == atom_kz1 && arg_text != NULL)
      {
            text = arg_text;
            arg_text = NULL;
            length = strlen(text);
      }

      if (text != NULL)
      {
            gtk_selection_data_set_text(data, text, length);
            if (data->selection == atom_kz1)
                  g_free(text);
      }
}


static void
activate_action(const gchar *text)
{
      KzWindow *kz;
      KzTabLabel *kztab;
      GList *window_list;
      GtkWidget *widget;
      GtkAction *action;
      gchar *action_name;
      gint action_type;
      enum {
            WINDOW_ACTION,
            TAB_ACTION
      };
      gint window_id = 0, tab_id = -1 /* -1 is current tab */;

      window_list = kz_window_get_window_list();
      
      if (!strncmp(text, "KzWindowTabPopup", 16))
      {
            gchar *p1, *p2, *p3;
            action_type = TAB_ACTION;
            
            p1 = (gchar *)(text + 17);

            p2 = strchr(p1, ' ');
            if (!p2)
            {
                  window_id = 1;
                  action_name = g_strdup(p1);
            }
            else
            {
                  window_id = atoi(p2 + 1);
                  action_name = g_strndup(p1, p2 - p1);
                  p3 = strchr(p2 + 1, ' ');
                  if (p3)
                        tab_id = atoi(p3 + 1);
            }
            tab_id = !tab_id ? -1 : tab_id;
      }
      else /*if (!strncmp(action, "KzWindow", 8))*/
      {
            gchar *p1, *p2;
            action_type = WINDOW_ACTION;

            p1 = strchr(text, '/');
            if (!p1)
                  p1 = (gchar*)text;
            else
                  p1++;

            p2 = strchr(p1, ' ');
            if (!p2)
            {
                  window_id = 1;
                  action_name = g_strdup(p1);
            }
            else
            {
                  window_id = atoi(p2 + 1);
                  action_name = g_strndup(p1, p2 - p1);
            }
      }
      window_id = !window_id ? 1 : window_id;

      kz = g_list_nth_data(window_list, window_id - 1);     
      /* if not exists indicated window, use first one  */
      if (!kz)
            kz = window_list->data;

      /* activate actions */
      switch (action_type)
      {
       case TAB_ACTION:
            if (tab_id == -1)
                  widget = KZ_WINDOW_CURRENT_PAGE(kz);
            else
                  widget = KZ_WINDOW_NTH_PAGE(kz, tab_id - 1);
            if (!widget)
                  widget = KZ_WINDOW_CURRENT_PAGE(kz);
            if (!widget)
                  break;
            kztab = KZ_TAB_LABEL(gtk_notebook_get_tab_label(GTK_NOTEBOOK(kz->notebook)
                                                , widget));

            action = gtk_action_group_get_action(kz->tabpop_actions,
                                         action_name);
            if (action)
                  kz_actions_tab_activate_action(kztab, action);
            break;
       case WINDOW_ACTION:
       default:
            action = gtk_action_group_get_action(kz->actions,
                                         action_name);
            if (action)
                  gtk_action_activate(action);
            break;
      }

      g_free(action_name);
}

static void
cb_selection_received(GtkWidget *widget,
                  GtkSelectionData *data,
                  guint time,
                  gpointer user_data)
{
      if (data->selection == atom_kz0)
      {
            instance = MAX(data->length, 0);
      }
      else if (data->selection == atom_kz1 && data->length > 0) 
      {
            gint argc;
            gchar **argv;
            gboolean retval;
            GError *error = NULL;


            /* open URL */
            argv = split_string(data->data, &argc);

            retval = g_option_context_parse (context, &argc, &argv, &error);
            if(retval)
                  process_args(argc, argv);

            g_strfreev(argv);
      }
}


static GtkWidget *
check_kazehakase_process (int argc, char *argv[])
{
      GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gint i, length = 0;

      gtk_widget_realize(window);

      atom_kz0 = gdk_atom_intern("Kazehakase InterProcess communication 0",
                           FALSE);
      atom_kz1 = gdk_atom_intern("Kazehakase InterProcess communication 1",
                           FALSE);

      gtk_selection_add_targets(window, atom_kz0, targets, 1);
      gtk_selection_add_targets(window, atom_kz1, targets, 1);
      g_signal_connect (window, "selection-get",
                    G_CALLBACK(cb_selection_get), window);
      g_signal_connect (window, "selection-received",
                    G_CALLBACK(cb_selection_received), window);

      for (i = 0; i < argc; i++)
      {
            gint len;

            len = strlen(argv[i]) * sizeof(gchar);
            arg_text = g_realloc(arg_text,
                             length + len + sizeof(gchar));
            g_memmove(arg_text + length, argv[i], len);
            length += len;
            arg_text[length++] = '\n';
      }
      if (length > 0)
      {
            arg_text[length - 1] = '\0';
            gtk_selection_owner_set(window, atom_kz1, GDK_CURRENT_TIME);
      }
      gtk_selection_convert(window,atom_kz0,
                        GDK_SELECTION_TYPE_STRING,
                        GDK_CURRENT_TIME);
      while (instance < 0)
            while (gtk_events_pending())
                  gtk_main_iteration();
      if (instance > 0)
      {
            /* Kazehakase process is already exists */
            while (arg_text != NULL)
                  while (gtk_events_pending())
                        gtk_main_iteration();
            gtk_widget_destroy(window);
            return NULL;
      }
      g_free(arg_text);
      arg_text = NULL;
      gtk_selection_owner_set(window, atom_kz0, GDK_CURRENT_TIME);

      return window;
}


static void
clean_history_cache (void)
{
      gchar *history_dir;
      guint limit_days = 30;
      gboolean limit = FALSE;
      time_t limit_seconds;
      
      KZ_CONF_GET("History", "limit_days", limit_days, INT);
      KZ_CONF_GET("History", "limit_cache", limit, BOOL);
      if (limit)
      {
            GSList *purge_list = NULL;
            gchar **purge_files = NULL;

            limit_seconds = limit_days * 86400;
            history_dir = g_build_filename(g_get_home_dir(),
                                     HISTORY_DIR,
                                     NULL); 
            purge_list = purge_history_file(history_dir, limit_seconds);
            g_free(history_dir);

            if (purge_list)
            {
                  GSList *slist;
                  gint n = g_slist_length(purge_list);
                  purge_files = g_new0 (gchar*, n + 1);

                  purge_files[n--] = NULL;
                  for (slist = purge_list; slist; slist = slist->next)
                        purge_files[n--] = slist->data;

                  /* optimize and purge history index */
                  if (exists_estindex)
                        estsearch_purge_index(purge_files);
             
                  g_strfreev(purge_files);
                  g_slist_free(purge_list);
            }
      }
}

static void
prepare_dir (void)
{
      /* for thumbnails */
      make_thumbnails_dir();
      
      /* for favicon */
      make_dir("favicon");

      /* for popup */
      make_dir("popup");

      /* for smart bookmark input history */
      make_dir("smartbookmark_history");
      
      /* for storing form data */
      make_dir("form_data");
}

/******************************************************************************
 *                                                                            *
 *                                  Main                                      *
 *                                                                            *
 ******************************************************************************/
static void
open_app_info (void)
{
      gchar *sysconf_file, *conf_file;
      gchar *bookmark_file, *sys_bookmark_file;
      gchar *clip_file, *current_session_file;
      gchar *bookmark_bar_file, *sys_bookmark_bar_file;
      gchar *smartbookmark_file, *sys_smartbookmark_file;
      gchar *accel_prefs_file;
      gchar *proxy_file, *sysproxy_file;
      gchar *estindex;

      /* load prefs */
      sysconf_file = g_strdup(KZ_SYSCONFDIR "/kzrc");
      conf_file = g_build_filename(g_get_home_dir(),
                             "."PACKAGE,
                             "kzrc", NULL);
      
      kz_global_profile = kz_profile_open(conf_file, sysconf_file);

      /* load bookmarks */
      bookmark_file         = g_build_filename(g_get_home_dir(),
                                     "."PACKAGE,
                                     "bookmarks.xml",
                                     NULL);
      sys_bookmark_file     = g_build_filename(KZ_SYSCONFDIR,
                                     "bookmarks.xml",
                                     NULL);

        bookmark_bar_file     = g_build_filename(g_get_home_dir(),
                                     "."PACKAGE,
                                     "bookmarkbar.xml",
                                     NULL);
      sys_bookmark_bar_file = g_build_filename(KZ_SYSCONFDIR,
                                     "bookmarkbar.xml",
                                     NULL);
      clip_file             = g_build_filename(g_get_home_dir(),
                                     "."PACKAGE,
                                     "clip.xml",
                                     NULL);
        smartbookmark_file    = g_build_filename(g_get_home_dir(),
                                     "."PACKAGE,
                                     "smartbookmarks.xml",
                                     NULL);
      sys_smartbookmark_file= g_build_filename(KZ_SYSCONFDIR,
                                     "smartbookmarks.xml",
                                     NULL);
      current_session_file  = g_build_filename(g_get_home_dir(),
                                     "."PACKAGE,
                                     "current_session.xml",
                                     NULL);
      
      kz_bookmarks = kz_root_bookmark_new(bookmark_file, sys_bookmark_file,
                                  clip_file, NULL);

      kz_root_bookmark_add_smartbookmark_file(kz_bookmarks,
                                    smartbookmark_file,
                                    sys_smartbookmark_file);
      kz_root_bookmark_add_bookmark_bar_file(kz_bookmarks,
                                     bookmark_bar_file,
                                     sys_bookmark_bar_file);
      kz_root_bookmark_add_current_session_file(kz_bookmarks,
                                      current_session_file);

      /* Load other prefs... */
      accel_prefs_file = g_build_filename (g_get_home_dir(),
                                   "."PACKAGE,
                                   "keyaccelrc",
                                   NULL);
      gtk_accel_map_load (accel_prefs_file);

      sysproxy_file = g_build_filename(KZ_SYSCONFDIR, "proxyrc", NULL);
      proxy_file = g_build_filename (g_get_home_dir(),
                               "."PACKAGE,
                               "proxyrc", NULL);
      kz_proxy = kz_profile_open(proxy_file, sysproxy_file);

      kz_icons_init();
      mozilla_init();

      /* check existence of estindex */
      estindex = g_find_program_in_path("estindex");
      
      if (estindex)
      {
            exists_estindex = TRUE;
            g_free(estindex);
            /* check estraier version */
            estversion = estsearch_get_version();
      }

      /* make dirs */
      prepare_dir();

      g_free(sysconf_file);
      g_free(conf_file);
      g_free(bookmark_file);
      g_free(sys_bookmark_file);
      g_free(clip_file);
      g_free(current_session_file);
      g_free(bookmark_bar_file);
      g_free(sys_bookmark_bar_file);
      g_free(smartbookmark_file);
      g_free(sys_smartbookmark_file);
      g_free(accel_prefs_file);
      g_free(sysproxy_file);
      g_free(proxy_file);
}


static void
close_app_info (void)
{
      gchar *accel_prefs_file;

      accel_prefs_file = g_build_filename (g_get_home_dir(),
                                   "."PACKAGE,
                                   "keyaccelrc",
                                   NULL);

      gtk_accel_map_save(accel_prefs_file);
      g_free(accel_prefs_file);

      mozilla_exit();

      /* clean history cache */
      clean_history_cache();

      kz_root_bookmark_save_all(kz_bookmarks);
      g_object_unref(G_OBJECT(kz_bookmarks));

      kz_profile_close(kz_global_profile);
      kz_profile_close(kz_proxy);

      if (estversion)
      {
            g_free(estversion);
            estversion = NULL;
      }
      
#if USE_MIGEMO
      if (migemo)
      {
            migemo_exit();
            migemo = NULL;
      }
#endif      
      kz_global_profile = NULL;
      kz_proxy          = NULL;
      kz_bookmarks      = NULL;
      
      free_goption();
}

static gboolean
restore_session (void)
{
      GList *list, *node;
      gint pos = 0;
      gchar *current_session;
      KzBookmarkFile *tmp_bookmark;

      /* reload from current session file */
      current_session  = g_build_filename(g_get_home_dir(),
                                  "."PACKAGE,
                                  "current_session.xml",
                                   NULL);
      if (!g_file_test(current_session, G_FILE_TEST_EXISTS))
      {
            g_free(current_session);
            return FALSE;
      }
      tmp_bookmark = kz_bookmark_file_new(current_session,
                                 _("Current Session"),
                                 "XBEL");
      g_free(current_session);
      kz_bookmark_file_load(tmp_bookmark);
      
      list = kz_bookmark_get_children(KZ_BOOKMARK(tmp_bookmark));
      if (!g_list_length(list))
      {
            g_list_free(list);
            g_object_unref(tmp_bookmark);
            return FALSE;
      }
      
      /* remove old entry from kz_bookmarks->current_session */
      kz_bookmark_remove_all(kz_bookmarks->current_session);

      is_restoring_session = TRUE;
      /* windows */
      for (node = list; node; node = g_list_next(node))
      {
            GList *tabs, *tabnode;
            KzWindow *window;
            KzBookmark *window_bookmark = KZ_BOOKMARK(node->data);
            tabs = kz_bookmark_get_children(window_bookmark);

            window = KZ_WINDOW(kz_window_new(NULL));
                  /* 
             * gtk_window_pargse_geometry() needs to be called 
             * before gtk_widget_show().
             */ 
            if(geometry_string)
            {
                  gtk_window_parse_geometry(GTK_WINDOW(window),
                                      geometry_string);
            }
            gtk_widget_show(GTK_WIDGET(window));
      
            /* tabs */
            for (tabnode = tabs; tabnode; tabnode = g_list_next(tabnode))
            {
                  GtkWidget *widget;
                  KzTabLabel *kztab;
                  KzBookmark *child = KZ_BOOKMARK(tabnode->data);
                  widget = kz_window_open_new_tab_at_tail(window, NULL);
                  kztab = KZ_TAB_LABEL(gtk_notebook_get_tab_label(
                                   GTK_NOTEBOOK(window->notebook),
                                   widget));
                  kz_tab_label_set_history(KZ_TAB_LABEL(kztab), child);

                  if (kz_bookmark_get_lock(child))
                  {
                        kz_tab_label_set_lock(kztab, TRUE);
                  }
                  if (kz_bookmark_get_auto_refresh(child))
                  {
                        kz_tab_label_set_auto_refresh(kztab, TRUE);
                  }
            }
            g_list_free(tabs);
            pos = kz_bookmark_get_current(window_bookmark);
            gtk_notebook_set_current_page(GTK_NOTEBOOK(window->notebook), pos);
      }

      g_list_free(list);
      g_object_unref(tmp_bookmark);

      is_restoring_session = FALSE;

      return TRUE;
}

int
main (int argc, char *argv[])
{
      KzWindow *kz = NULL;
      GtkWidget *dupl_check_server = NULL;
      gchar **argv_copy;
      gint argc_copy = argc;
      gboolean retval;
      GError *error = NULL;
      gboolean restore = FALSE;

        /* initialize */
      setlocale(LC_ALL, "");
      bindtextdomain(PACKAGE, LOCALEDIR);
      bind_textdomain_codeset(PACKAGE, "UTF-8");
      textdomain(PACKAGE);

        /* initialize goption */
      context = g_option_context_new (parameter_string);
      g_option_context_add_main_entries (context, entries, NULL);
      main_group = g_option_context_get_main_group (context);

        /* set hooks */
      g_option_group_set_parse_hooks (main_group,
                              pre_parse_cb, post_parse_cb);
      g_option_group_set_error_hook (main_group,
                               parse_error_cb);
        /* set to ignore unknown options */
      g_option_context_set_ignore_unknown_options (context, TRUE);

      gtk_init(&argc, &argv);

        /* copy argv (ant argc) so as to preserve original arguments */
      argv_copy = g_strdupv(argv);

        /* g_option_context_parse changes argc_copy and argv_copy so as to
         process remaining arguments */
      retval = g_option_context_parse (context, &argc_copy, &argv_copy, &error);
      if(retval && show_version)
      {
              /* show version number and exit */
            g_print("%s %s\n", PACKAGE, VERSION);
            free_goption();
            g_strfreev(argv_copy);
            exit(0);
      }

      /* find kazehakase process */
      dupl_check_server = check_kazehakase_process(argc, argv);
      if (!dupl_check_server)
      {
            free_goption();
            g_strfreev(argv_copy);
            /* FIXME! show message */
            return 0;   /* found kazehakase process */
      }

      /* Load preference */
      open_app_info();
      
      /* restore session */
      KZ_CONF_GET("Session", "restore",
                restore, BOOL);
      if (restore)
      {
            GList *window_list;
            restore = restore_session();
            window_list = kz_window_get_window_list();
            if (window_list)
                  kz = KZ_WINDOW(window_list->data);
      }
      if (!restore)
      {
            /* create window */     
            kz = KZ_WINDOW(kz_window_new(NULL));

                  /* 
             * gtk_window_pargse_geometry() needs to be called 
             * before gtk_widget_show().
             */ 
            if(geometry_string)
            {
                  gtk_window_parse_geometry(GTK_WINDOW(kz),
                                      geometry_string);
            }
            gtk_widget_show(GTK_WIDGET(kz));
      }

      /* process arguments */
      process_args(argc_copy, argv_copy);
      g_strfreev (argv_copy);

      /* event loop */
      gtk_main();

      /* exit */
      gtk_widget_destroy(dupl_check_server);
      dupl_check_server = NULL;

      close_app_info();

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index