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

widgets_gtk.c

/*
 *  widgets_gtk.c - main gtk widgets for xarchive 
 *  Copyright (C) 2005 Lee Bigelow <ligelowbee@yahoo.com> 
 *
 *  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
 */
#include"widgets_gtk.h"

#ifndef HAVE_CANONICALIZE_FILE_NAME
/* from main.c */
char *
canonicalize_file_name(char *path);
#endif
#ifndef HAVE_GETLINE
ssize_t
getline(char **lineptr, size_t *n, FILE *stream);
#endif
/***********************/
/* tree view functions */
/***********************/
void
start_myfc_onDragDataRecived(GtkWidget *widget,
                       GdkDragContext *context,
                       int x, int y,
                       GtkSelectionData *seldata,
                       guint info, guint time,
                       gpointer userdata)
{
  GtkListStore *myfc_ls;
  GtkTreeIter iter;
  gchar **uri_list;
  gchar *hostname;
  gchar *filename;
  gint i;
  
  myfc_ls = make_myfc_ls();
  uri_list = gtk_selection_data_get_uris(seldata);
  for(i=0; uri_list[i] != NULL; i++)
  {
    filename = g_filename_from_uri(uri_list[i], &hostname, NULL);
    if ( filename != NULL && g_file_test(filename, G_FILE_TEST_EXISTS) )
       myfc_add_foreach_func(filename, myfc_ls);
    g_free(filename);
  }
  
  if (uri_list != NULL) g_strfreev(uri_list);
  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(myfc_ls), &iter) == TRUE)
    add_cb(NULL, (gpointer) myfc_ls);
  else
    g_object_unref(myfc_ls);
  
}

gboolean
my_search_equal_func(GtkTreeModel *model,
             gint column,
             const gchar *key,
             GtkTreeIter *iter,
             gpointer search_data)
{
  gchar *haystack;
  gboolean res;
  
  gtk_tree_model_get(model, iter, COL_DFILE, &haystack, -1);

  res = (strcasestr(haystack, key) == NULL);
  g_free(haystack);
  
  return res;
}

void 
render_cols(GtkTreeView *view, gchar *title, gint mcol)
{
  /* mcol is the liststore model coluumn. 
   * tvcol is the treeview column. 
   * Make a renderer to link the two, set the col header,
   * and make the column sortable.
   */

  GtkTreeViewColumn   *tvcol; 
  GtkCellRenderer     *renderer;

  tvcol = gtk_tree_view_column_new();
  if (mcol == COL_DFILE)
  {
    renderer = gtk_cell_renderer_pixbuf_new();
    gtk_tree_view_column_pack_start(tvcol, renderer, FALSE);
    gtk_tree_view_column_add_attribute(tvcol, renderer, 
                                       "stock-id", COL_ICON);
  }
  renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(tvcol, renderer, TRUE);
  gtk_tree_view_column_add_attribute(tvcol, renderer, "text", mcol);
  gtk_tree_view_column_set_title(tvcol, title);

  switch ( mcol ) 
  {
    case COL_DFILE:
      gtk_tree_view_column_set_sizing(tvcol, GTK_TREE_VIEW_COLUMN_FIXED);
      gtk_tree_view_column_set_fixed_width(tvcol, 300);
      break;
    case COL_LINK:
      gtk_tree_view_column_set_sizing(tvcol, GTK_TREE_VIEW_COLUMN_FIXED);
      gtk_tree_view_column_set_fixed_width(tvcol, 60);
      break;
  }

  gtk_tree_view_column_set_resizable(tvcol, TRUE);
  gtk_tree_view_append_column(view, tvcol);

  gtk_tree_view_column_set_sort_column_id(tvcol, mcol); 
}

GtkListStore *
make_liststore(void)
{
  GtkListStore *liststore;

  /* icon, file, dfile, size, attr, user, group, time, link */ 
  liststore = gtk_list_store_new(NUM_COLS, G_TYPE_STRING, G_TYPE_STRING, 
                                 G_TYPE_STRING, G_TYPE_ULONG, 
                                 G_TYPE_STRING, G_TYPE_STRING,
                                 G_TYPE_STRING, G_TYPE_STRING,
                                 G_TYPE_STRING);

  return liststore;
}

GtkWidget *
make_tree(GtkListStore *liststore)
{
  /* Make an empty treeview attached to liststore.
   * Then attach a renderer to each column in the view.*/
  GtkTreeView *treeview;
  GtkTreeSelection *sel; 
  enum { TARGET_URI };
  GtkTargetEntry targetentries[] =
    {
      { "text/uri-list", 0, TARGET_URI },
    };

  treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore)));

  gtk_tree_view_set_rules_hint(treeview, TRUE);

  sel = gtk_tree_view_get_selection(treeview);
  gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
  gtk_tree_selection_set_select_function(sel,
                                         (GtkTreeSelectionFunc)test_selection_func,
                                         NULL, NULL);
  render_cols(treeview, "File", COL_DFILE);
  render_cols(treeview, "SymLink", COL_LINK);
  render_cols(treeview, "Size", COL_SIZE);
  render_cols(treeview, "Permissions", COL_ATTR);
  render_cols(treeview, "User", COL_USER);
  render_cols(treeview, "Group", COL_GROUP);
  render_cols(treeview, "Time", COL_TIME);

  gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(liststore), 
                                       COL_DFILE, GTK_SORT_ASCENDING);
  gtk_tree_view_set_search_column(treeview, COL_DFILE);
  gtk_tree_view_set_enable_search(treeview, TRUE);
  gtk_tree_view_set_search_equal_func(treeview,
                              (GtkTreeViewSearchEqualFunc) my_search_equal_func,
                              NULL, NULL);
  /* setup drag and drop attributes */
  gtk_drag_dest_set(GTK_WIDGET(treeview),
                GTK_DEST_DEFAULT_ALL,
                targetentries, 1,
                GDK_ACTION_COPY|GDK_ACTION_MOVE);
  g_signal_connect(GTK_WIDGET(treeview),
               "drag_data_received",
               G_CALLBACK(start_myfc_onDragDataRecived),
               NULL);
  return GTK_WIDGET(treeview);
}

GtkTreeView *
get_current_tree(void)
{
  /* current notebook page contains a scrollwindow,
   * from which we get the current treeview.
   */
  gint page;
  GtkWidget *scrollwin;
  GtkWidget *treeview;
    
  if ( (page = gtk_notebook_get_current_page(NOTEBOOK)) < 0) return NULL;
  scrollwin = gtk_notebook_get_nth_page(NOTEBOOK, page); 
  treeview = gtk_bin_get_child(GTK_BIN(scrollwin)); 
    
  return GTK_TREE_VIEW(treeview);
}

gchar *
get_current_archive(void)
{
  /* current notebook page contains scrollwindow,
   * the archive path from it's label */
  GtkTreeView *treeview;
  GtkTreeModel *liststore;
  gchar *archive;
    
  if ( (treeview = get_current_tree()) != NULL)
  { 
    liststore = gtk_tree_view_get_model(treeview);
    archive = (gchar *) g_object_get_data(G_OBJECT(liststore), 
                                          "archive_path");
    return archive;
  }
  return NULL;
}
    
void 
add_row(GtkListStore *liststore, gchar **ent)
{
  /* add a row to the liststore model attached to the treeview on 
   * the current notebook page.
   */
  enum {name=0,size,attr,user,group,date,time,link,num_ent};
  GtkTreeIter iter;
  gchar *icon = GTK_STOCK_FILE;
  gchar *dfname;
  gchar time_string[20];
  
  sprintf(time_string, "%s %s", ent[date], ent[time]);
  
  dfname = g_filename_display_name(ent[name]);
  if (g_str_has_prefix(ent[attr],"d") == TRUE)
  {
    icon=GTK_STOCK_DIRECTORY;
  } 
    
  gtk_list_store_append(liststore, &iter);
  gtk_list_store_set(liststore, &iter,
                     COL_ICON, icon,
                     COL_FILE, ent[name],
                     COL_DFILE, dfname,
                     COL_SIZE, strtoul(ent[size],NULL,10),
                     COL_ATTR, ent[attr],
                     COL_USER, ent[user],
                     COL_GROUP, ent[group],
                     COL_TIME, time_string,
                     COL_LINK, ent[link],
                     -1); 
  g_free(dfname);
}

void 
reload_current_tree(GtkTreeView *treeview)
{
  /* clear liststore, then reload
   * data from archive */
  GtkTreeModel *liststore;
  gchar *argv[4]; /* wrapper, option, archive, NULL */

  argv[ARCHIVE_INDEX] = g_strdup(get_current_archive());
  argv[ARCHIVE_INDEX + 1] = NULL;
  liststore = gtk_tree_view_get_model(treeview); 
  gtk_list_store_clear(GTK_LIST_STORE(liststore));
  /* reload archive data */
  if (wrapper_cmd(AR_OPEN, argv, NULL) < 0) 
  {
    close_cb(NULL, NULL);
  }
}

gboolean
treeview_button_press(GtkWidget  *container,
                      GdkEventButton *event,
                      GtkUIManager *uimanager)
{
  gtk_widget_grab_focus (container);
      
  if (event->button == 3 && event->type == GDK_BUTTON_PRESS) 
  {
    GtkWidget *menu = gtk_ui_manager_get_widget(uimanager, 
                                                "/treeview_popup");
    if (GTK_IS_MENU (menu)) 
    {
      gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, 
                      container, 3, event->time);
      return TRUE;
    }
  }
  else if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
    double_click_cb();

  return FALSE;
}

/**********************/
/* notebook functions */
/**********************/
void 
make_notebook_widgets(GtkWidget *container)
{
  NOTEBOOK = GTK_NOTEBOOK(gtk_notebook_new());
  get_default_handler();
  get_lastdir();
  gtk_box_pack_end(GTK_BOX(container), GTK_WIDGET(NOTEBOOK),TRUE,TRUE,0);
  gtk_notebook_set_tab_pos(NOTEBOOK, GTK_POS_TOP);
  gtk_notebook_set_show_tabs(NOTEBOOK, TRUE);
  gtk_notebook_set_scrollable(NOTEBOOK, TRUE);
  gtk_notebook_popup_enable(NOTEBOOK); 
}

void 
add_page(gchar *archive)
{
  /* Add a page to the end of the notebook and make it active.
   * Page contains a scrolled window with a treeview in it.
   * Then get the data for the treeview model.
   */ 

  GtkWidget *label, *image, *hbox, *button, *scrollw, *treeview;
  GtkListStore *liststore;
  GtkTooltips *button_tips = gtk_tooltips_new();
  gchar *archive_path;
  gchar *archive_disp;
  gchar **argv;

  /* hide empty page and show notebook if neccessary */
  if (gtk_notebook_get_current_page(NOTEBOOK) < 0)
  {
    gtk_widget_hide(EMPTY);
    gtk_widget_show(GTK_WIDGET(NOTEBOOK));
  }
  
  archive_path = g_strdup(archive);
  archive_disp = g_filename_display_name(archive_path);
  /* make scrollw and it's label, then append to notebook and make
   * it the current active page */
  scrollw = gtk_scrolled_window_new(NULL, NULL);
  gtk_widget_show(scrollw);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollw),
                                 GTK_POLICY_AUTOMATIC,
                                 GTK_POLICY_AUTOMATIC);

  hbox = gtk_hbox_new(FALSE, 2);

  label = gtk_label_new(archive_disp);
  g_free(archive_disp);
  gtk_label_set_max_width_chars(GTK_LABEL(label), 50);
  gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_START);
  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

  button = gtk_button_new();
  gtk_tooltips_set_tip(button_tips, button,
                       "Close Archive", NULL);
  g_signal_connect(G_OBJECT(button), "clicked", 
                   G_CALLBACK(close_button_cb), (gpointer) scrollw);
  image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU);
  gtk_widget_set_size_request(image, 8, 8);
  gtk_container_add(GTK_CONTAINER(button), image);
  gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
  gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
  gtk_widget_show_all(hbox);

  gtk_notebook_append_page(NOTEBOOK, scrollw, hbox); 
  gtk_notebook_set_current_page(NOTEBOOK, -1);

  /* make treeview with attached liststore model and add to scrollw */
  liststore = make_liststore();
  g_object_set_data(G_OBJECT(liststore), "archive_path", 
                    (gpointer) archive_path);
  treeview = make_tree(liststore);
  g_object_unref(liststore);
  gtk_container_add(GTK_CONTAINER(scrollw), treeview);
  gtk_widget_show(treeview);
  g_signal_connect(treeview, "button_press_event", 
                   G_CALLBACK(treeview_button_press),
                   UIMANAGER);

  /* read in archive data, or close the page if it fails */
  argv = g_new(gchar *, 4); /* wrapper, option, archive, NULL */
  argv[ARCHIVE_INDEX] = g_strdup(archive_path);
  argv[FIRST_FILE_INDEX] = NULL;
  
  if (wrapper_cmd(AR_OPEN, argv, NULL) < 0) 
  {
    close_cb(NULL, NULL);
  }
  else
  {
    gchar *lastdir, *lastdir_path;
    FILE *lastdir_file;

    lastdir = (gchar *) g_object_get_data(G_OBJECT(NOTEBOOK), "lastdir");
    lastdir_path = (gchar *) g_object_get_data(G_OBJECT(NOTEBOOK), 
                                               "lastdir_path");
    g_free(lastdir);
    lastdir = g_path_get_dirname(archive_path);
    g_object_set_data(G_OBJECT(NOTEBOOK), "lastdir", (gpointer) g_path_get_dirname(archive_path));
    lastdir_file = g_fopen(lastdir_path, "w");
    fputs(lastdir, lastdir_file);
    fputs("\n", lastdir_file);
    fclose(lastdir_file);
  }
  g_strfreev(argv);
} 
   
/************************************/
/* emtpy page and message functions */
/************************************/
void
setup_opening_progress_bar(GtkWidget *pbwin, GtkWidget *pbar, gboolean *stopit)
{
  GtkWidget *vbox, *label, *button;

  g_signal_connect(G_OBJECT(pbwin), "delete_event", 
                   G_CALLBACK(gtk_true), NULL);
  gtk_window_set_modal(GTK_WINDOW(pbwin), TRUE);
  gtk_window_set_transient_for(GTK_WINDOW(pbwin), GTK_WINDOW(MAIN_WINDOW));
  gtk_window_set_title(GTK_WINDOW(pbwin), "Reading...");
    
  vbox = gtk_vbox_new(FALSE, 2);
  gtk_container_add(GTK_CONTAINER(pbwin), vbox);
  
  label = gtk_label_new("Please wait, reading file...");
  gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
  
  gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(pbar), 0.2);
  gtk_box_pack_start(GTK_BOX(vbox), pbar, TRUE, TRUE, 0);
  
  button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
  g_signal_connect(G_OBJECT(button), "clicked", 
                   G_CALLBACK(open_cancel_cb),
                   (gpointer) stopit);
  gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);

  gtk_widget_show_all(pbwin);
}  

void
wait_with_progress_bar(GPid pid, gint *wrapper_status, gint ar_func)
{
  GtkWidget *pbwin, *pbar, *label, *button, *vbox;
  gchar *msg;
  gint process_status = 0;
  gboolean waiting = TRUE;
  
  pbwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  g_signal_connect(G_OBJECT(pbwin), "delete_event",
                 G_CALLBACK(gtk_true),
                 NULL);
  gtk_window_set_modal(GTK_WINDOW(pbwin), TRUE);
  gtk_window_set_transient_for(GTK_WINDOW(pbwin), GTK_WINDOW(MAIN_WINDOW));
  gtk_window_set_title(GTK_WINDOW(pbwin), "Working...");
  
  switch (ar_func)
  {
    case AR_ADD:
      msg = "Please wait, adding files...";
      break;
    case AR_NEW:
      msg = "Please wait, creating new archive...";
      break;
    case AR_REMOVE:
      msg = "Please wait, removing files...";
      break;
    case AR_EXTRACT:
      msg = "Please wait, extracting files...";
      break;
    default:
      msg = "Busy, Please wait...";
      break;
  }
  vbox = gtk_vbox_new(FALSE, 2);
  gtk_container_add(GTK_CONTAINER(pbwin), vbox);
  
  label = gtk_label_new(msg);
  gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
  
  pbar = gtk_progress_bar_new();
  gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(pbar), 0.2);
  gtk_box_pack_start(GTK_BOX(vbox), pbar, TRUE, TRUE, 0);
  
  button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
  g_signal_connect(G_OBJECT(button), "clicked", 
                   G_CALLBACK(process_cancel_cb),
                   GINT_TO_POINTER(pid));
  gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
  
  gtk_widget_show_all(pbwin);
  
  while (waiting)
  { 
    process_status = waitpid((pid_t)pid, wrapper_status, WNOHANG);
    if (process_status < 0)
    {
      waiting = FALSE;
    }
    else 
    {
      gtk_progress_bar_pulse(GTK_PROGRESS_BAR(pbar));
      while (gtk_events_pending())
        gtk_main_iteration();
      g_usleep(200000);
    }
  }
  gtk_widget_destroy(pbwin);
  while (gtk_events_pending())
    gtk_main_iteration();
}

GtkWidget *
make_info_widget(gchar *msg)
{
  GtkWidget *scrollw, *label;
    
  scrollw = gtk_scrolled_window_new(0,0);
  gtk_container_set_border_width(GTK_CONTAINER(scrollw), 10);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollw),
                                 GTK_POLICY_AUTOMATIC,
                                 GTK_POLICY_AUTOMATIC);
  gtk_widget_show(scrollw);
    
  label = gtk_label_new(msg);
  gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollw), label);
  gtk_widget_show(label);

  return scrollw;
}

void 
make_empty_page(GtkWidget *container)
{
  gchar *wrapinf;

  wrapinf = wrapper_info();
  EMPTY = make_info_widget(wrapinf);
  g_free(wrapinf);
  gtk_box_pack_end(GTK_BOX(container), EMPTY, TRUE, TRUE, 0);
}

gboolean 
message(GtkWidget *parentwin, gint type, gchar *text)
{
  GtkWidget *md;

  md = gtk_message_dialog_new(GTK_WINDOW(parentwin), 
                              GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
                              type,
                              GTK_BUTTONS_NONE,
                              text);
  if ( type == GTK_MESSAGE_WARNING || type == GTK_MESSAGE_QUESTION) 
  {
    gtk_dialog_add_button(GTK_DIALOG(md),
                          GTK_STOCK_CANCEL, 
                          GTK_RESPONSE_CANCEL);
    gtk_dialog_add_button(GTK_DIALOG(md),
                          GTK_STOCK_OK, 
                          GTK_RESPONSE_OK);
    gtk_dialog_set_alternative_button_order(GTK_DIALOG(md), GTK_RESPONSE_OK,
                                            GTK_RESPONSE_CANCEL, -1);
  }
  else
  {
    gtk_dialog_add_button(GTK_DIALOG(md),
                          GTK_STOCK_OK, 
                          GTK_RESPONSE_OK);
  }
  if( gtk_dialog_run(GTK_DIALOG(md)) == GTK_RESPONSE_OK ) 
  {
    gtk_widget_destroy(md);
    return TRUE;
  }
  gtk_widget_destroy(md);
  return FALSE;
}

/******************************/
/* treeview foreach functions */
/******************************/
void 
selected_foreach_func(GtkTreeModel *model,
                      GtkTreePath *path,
                      GtkTreeIter *iter,
                      WrapperData *wrapper)
{
  gchar *fname;
  gchar *esc_fname;

  gtk_tree_model_get(model, iter, COL_FILE, &fname, -1);
  esc_fname = g_strdup(fname);

  wrapper->argv[wrapper->index] = esc_fname;
  wrapper->index++;
  wrapper->argv[wrapper->index] = NULL;

  g_free(fname);
}

gboolean 
sel_subdir_foreach_func(GtkTreeModel *model,
                        GtkTreePath *path,
                        GtkTreeIter *iter,
                        SelectionData *seld)
{
  gchar *fname;

  gtk_tree_model_get(model, iter, COL_FILE, &fname, -1); 
  if ( g_str_has_prefix(fname, seld->dname) == TRUE ) 
  {
    gtk_tree_selection_select_iter(seld->sel, iter);
  }

  g_free(fname);
  return FALSE;
}

gboolean 
unsel_subdir_foreach_func(GtkTreeModel *model,
                        GtkTreePath *path,
                        GtkTreeIter *iter,
                        SelectionData *seld)
{
  gchar *fname;

  gtk_tree_model_get(model, iter, COL_FILE, &fname, -1); 
  if ( g_str_has_prefix(fname, seld->dname) == TRUE ) 
  {
    gtk_tree_selection_unselect_iter(seld->sel, iter);
  }

  g_free(fname);
  return FALSE;
}

gboolean
test_selection_func(GtkTreeSelection *selection,
                    GtkTreeModel *model,
                    GtkTreePath *path,
                    gboolean path_currently_selected,
                    gpointer data)
{
  GtkTreeIter iter;
  SelectionData seld;
  gchar *icon, *fname, *dname=NULL;
  static gboolean skipit = FALSE;

  if (skipit == TRUE) 
    return TRUE;

  gtk_tree_model_get_iter(model, &iter, path);
  seld.sel = selection;
  
  gtk_tree_model_get(model, &iter, COL_ICON, &icon, COL_FILE, &fname, -1);
  if (g_str_has_prefix(icon, GTK_STOCK_DIRECTORY) == TRUE)
  {
    if (g_str_has_suffix(fname, "/") == FALSE)
      dname = g_strdup_printf("%s/", fname);
    else
      dname = g_strdup(fname);
    seld.dname = dname;
    seld.dirs = TRUE;
    skipit = TRUE;
    if (path_currently_selected == FALSE)
      gtk_tree_model_foreach(model,
                             (GtkTreeModelForeachFunc)sel_subdir_foreach_func,
                             &seld);
    else
      gtk_tree_model_foreach(model,
                             (GtkTreeModelForeachFunc)unsel_subdir_foreach_func,
                             &seld);
  }
  
  skipit = FALSE;
  g_free(icon);

  if (dname != NULL && strcmp(fname,dname) == 0)
  {
    g_free(fname);
    g_free(dname);
    return FALSE;
  }
  
  g_free(fname);
  if (dname != NULL) g_free(dname);
  
  return TRUE;
}

gboolean 
add_foreach_func(GtkTreeModel *model, GtkTreePath *path, 
                 GtkTreeIter *iter, WrapperData *wrapper)
{
  selected_foreach_func(model, path, iter, wrapper);
  return FALSE;
}

gboolean 
file_filter_func(const GtkFileFilterInfo *filter_info, gpointer data)
{
  gchar *fname;
    
  fname = g_strdup(filter_info->filename);
  if ( get_wrapper(fname) != NULL ) return TRUE;
  g_free(fname);
  return FALSE;
}

/*******************/
/* chooser widgets */
/*******************/
gchar *
askfor_existing_archive(void)
{
  GtkWidget *fc;
  GtkFileFilter *filter;
  gchar *archive = NULL, *lastdir;

  fc = gtk_file_chooser_dialog_new("Open File",
                                   GTK_WINDOW(MAIN_WINDOW),
                                   GTK_FILE_CHOOSER_ACTION_OPEN,
                                   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                   NULL);
  gtk_dialog_set_alternative_button_order(GTK_DIALOG(fc), GTK_RESPONSE_ACCEPT,
                                          GTK_RESPONSE_CANCEL, -1);
  lastdir = (gchar *)g_object_get_data(G_OBJECT(NOTEBOOK), "lastdir");
  printf("lastdir: %s\n", lastdir);
  gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fc), lastdir);
  filter = gtk_file_filter_new();
  gtk_file_filter_set_name(filter, "Only Supported");
  gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME, 
                             file_filter_func, NULL, g_free);
  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fc), filter);
  filter = gtk_file_filter_new();
  gtk_file_filter_set_name(filter, "All");
  gtk_file_filter_add_pattern(filter, "*");
  gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fc), filter);

  if (gtk_dialog_run(GTK_DIALOG(fc)) == GTK_RESPONSE_ACCEPT) 
    archive = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));

  gtk_widget_destroy(fc);
  
  return archive;
}

gchar *
askfor_new_archive(gchar *name)
{
  gchar *archive = NULL;
  gboolean again = TRUE;
  GtkWidget *fc_new;
  gchar *msg;
  
  fc_new = gtk_file_chooser_dialog_new("Enter New Archive Name", 
                                       GTK_WINDOW(MAIN_WINDOW),
                                       GTK_FILE_CHOOSER_ACTION_SAVE,
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                       GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                       NULL);
  gtk_dialog_set_default_response(GTK_DIALOG(fc_new), GTK_RESPONSE_ACCEPT);
  gtk_dialog_set_alternative_button_order(GTK_DIALOG(fc_new),
                                          GTK_RESPONSE_ACCEPT,
                                          GTK_RESPONSE_CANCEL, -1);
  if (name == NULL) 
    name = "somename.tar.gz";
  gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc_new), 
                                    name);
  while (again == TRUE)
  {
    if (gtk_dialog_run(GTK_DIALOG(fc_new)) == GTK_RESPONSE_ACCEPT) 
    {
      archive = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc_new));
      /* if no wrapper for archive type exits try again */
      if (get_wrapper(archive) == NULL)
      {
        message(fc_new,
            GTK_MESSAGE_ERROR, 
                "Sorry, archive type not supported.\n\n"
                "Please use an archive name with an\n"
                "extenstion that you have a wrapper for.\n\n"
                "For example:\n"
                "If you have tar-wrap.sh:\n"
                "\tsomename.tar.gz\n"
                "If you have zip-wrap.sh:\n"
                "\tsomename.zip\n");
        g_free(archive);
        archive = NULL;
      }
      /* if it already exists try again */
      else if (g_file_test(archive, G_FILE_TEST_EXISTS) == TRUE)
      {
        msg = g_strdup_printf("Archive %s\n"
                              "already exists.\n\n"
                              "Please pick another name, or\n"
                              "put archive in a different directory\n",
                              archive);
        message(fc_new,
            GTK_MESSAGE_ERROR, msg);
        g_free(msg);
        g_free(archive);
        archive = NULL;
      }
      else again = FALSE;
    }
    else
    {
      again = FALSE;
      archive = NULL;
    }
  }
  
  gtk_widget_destroy(GTK_WIDGET(fc_new));
  return archive;
}

gboolean
multi_file_chooser(gchar *archive, GtkListStore *filelist)
{
  GtkTreeIter iter;
  GtkDialog *myfc;
  gboolean accept = FALSE, again = TRUE;

  myfc = make_myfc(archive, filelist);
  while (again == TRUE)
  {
    if (gtk_dialog_run(myfc) == GTK_RESPONSE_ACCEPT) 
    {
      /* if no first entry, redisplay the file selector */
      if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filelist), 
                                        &iter) == FALSE) 
        message(GTK_WIDGET(myfc),
            GTK_MESSAGE_ERROR, 
                "No files added to list.\n\n"
                "Please try again, or cancel.");
      else 
      {
        again = FALSE;
        accept = TRUE;
      }
    }
    else 
    {
      again = FALSE;
      accept = FALSE;
    }
  }

  gtk_widget_destroy(GTK_WIDGET(myfc));
  return accept;
}

void
select_extract_dir(GtkWidget *widget, GtkWidget *entry)
{
  GtkWidget *fc;

  fc = gtk_file_chooser_dialog_new("Select Directory To Extract To", 
                                   GTK_WINDOW(MAIN_WINDOW),
                                   GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
                                   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                   NULL);
  gtk_dialog_set_alternative_button_order(GTK_DIALOG(fc), GTK_RESPONSE_ACCEPT, 
                                          GTK_RESPONSE_CANCEL, -1);
  gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(fc), 
                                  gtk_entry_get_text(GTK_ENTRY(entry)));
  if (gtk_dialog_run(GTK_DIALOG(fc)) == GTK_RESPONSE_ACCEPT) 
  {
    gtk_entry_set_text(GTK_ENTRY(entry), 
                       gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc)));
  }

  gtk_widget_destroy(fc);
}

gchar *
askfor_extract_dir(void)
{
  gchar *dir = NULL, *mesg;
  GtkWidget *idialog, *hbox, *label, *entry, *choose_button;
  gboolean again = TRUE;

  idialog = gtk_dialog_new_with_buttons("Extraction Directory",
                                        GTK_WINDOW(MAIN_WINDOW),
                                        GTK_DIALOG_MODAL | 
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
                                        GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
                                        GTK_STOCK_OK,GTK_RESPONSE_ACCEPT,
                                        NULL);
  gtk_dialog_set_default_response(GTK_DIALOG(idialog), GTK_RESPONSE_ACCEPT);
  gtk_dialog_set_alternative_button_order(GTK_DIALOG(idialog), GTK_RESPONSE_ACCEPT, 
                                          GTK_RESPONSE_REJECT, -1);
  label = gtk_label_new("Enter Directory To Extract To:");
  hbox = gtk_hbox_new(FALSE, 1);
  entry = gtk_entry_new();
  gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
  gtk_entry_set_text(GTK_ENTRY(entry), 
                     g_path_get_dirname(get_current_archive()));
  gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE,1);
  choose_button = gtk_button_new_with_label("Choose");
  g_signal_connect(G_OBJECT(choose_button), "clicked", 
                   G_CALLBACK(select_extract_dir), entry);
  gtk_box_pack_start(GTK_BOX(hbox), choose_button, TRUE, TRUE,1);
  
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(idialog)->vbox), label, TRUE, TRUE,1);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(idialog)->vbox), hbox, TRUE, TRUE,1);
  gtk_widget_show_all(GTK_DIALOG(idialog)->vbox);
  
  while(again == TRUE)
  {
    if (gtk_dialog_run(GTK_DIALOG(idialog)) == GTK_RESPONSE_ACCEPT) 
    {
      dir = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
      if (g_file_test(dir,G_FILE_TEST_IS_DIR) == FALSE)
      {  
      mesg = g_strdup_printf("Directory\n%s\nDoes not exist.\n\n"
                               "Shall I create it?", dir);
      if (message(idialog,
                GTK_MESSAGE_QUESTION, mesg))
      {
        if (g_mkdir(dir, S_IRWXU|S_IRWXG) != 0)
          message(idialog,
                GTK_MESSAGE_INFO, 
                "Sorry, could not create directory.\n\n"
                "If you need to create a parent dir and\n"
                "a subdir, create the parent first."
                );
      }
      g_free(mesg);
      }
      else    
        again = FALSE;
    }
    else
    {
      dir = NULL;
      again = FALSE;
    }
  }
  gtk_widget_destroy(idialog);
  return dir;
}

/******************************************/
/* openwith and default handler functions */
/******************************************/

GtkListStore *
get_openwith_cmdlist(gchar *cmdlist_path)
{
  gchar *cmd;
  gchar *line = NULL;
  FILE *cmdlist_file;
  size_t linesize = 0;
  int length;
  GtkListStore *cmdlist;
  GtkTreeIter iter;

  if (g_file_test(cmdlist_path, G_FILE_TEST_EXISTS) == FALSE)
  {
    cmdlist_file = g_fopen(cmdlist_path, "w");
    fputs("xarchive\n", cmdlist_file);
    fclose(cmdlist_file);
  }
  cmdlist = gtk_list_store_new(1, G_TYPE_STRING); 

  cmdlist_file = g_fopen(cmdlist_path, "r");
  while ( (length = getline(&line, &linesize, cmdlist_file)) > 0)
  {
    /* strip newline from line to get command */
    cmd = g_strndup(line, length-1);
    gtk_list_store_append(cmdlist, &iter);
    gtk_list_store_set(cmdlist, &iter, 0, cmd, -1);
    g_free(cmd);
  }
  fclose(cmdlist_file);

  g_free(line);

  return cmdlist;
}

void
add_to_cmdlist(GtkListStore *cmdlist, gchar *command, gchar *cmdlist_path)
{
  GtkTreeIter iter;
  gchar *list_entry = NULL;
  gboolean found = FALSE;
  FILE *cmdlist_file;

  if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(cmdlist), &iter) == TRUE)
  {
    do
    {
      gtk_tree_model_get(GTK_TREE_MODEL(cmdlist), &iter, 
                         0, &list_entry, -1);
      if (strcmp(list_entry,command) == 0) 
      {
        found = TRUE;
        gtk_list_store_move_after(cmdlist, &iter, NULL);
        break;
      }
      g_free(list_entry);
    } 
    while (gtk_tree_model_iter_next(GTK_TREE_MODEL(cmdlist), &iter));        
        
    if (found == FALSE)
    {
      gtk_list_store_prepend(cmdlist, &iter);
      gtk_list_store_set(cmdlist, &iter, 0, command, -1);
    }

    /* save list */
    gtk_tree_model_get_iter_first(GTK_TREE_MODEL(cmdlist), &iter);
    cmdlist_file = g_fopen(cmdlist_path, "w");
    do
    {
      gtk_tree_model_get(GTK_TREE_MODEL(cmdlist), &iter,
                         0, &list_entry, -1);
      fputs(list_entry,cmdlist_file);
      fputs("\n",cmdlist_file);
      g_free(list_entry);
    }
    while (gtk_tree_model_iter_next(GTK_TREE_MODEL(cmdlist), &iter));
    fclose(cmdlist_file);
  }
}

void
get_lastdir(void)
{
  gchar *lastdir_path, *lastdir;
  gchar *line = NULL;
  FILE *lastdir_file;
  size_t linesize = 0;
  int length;

  lastdir_path = g_strdup_printf("%s/.xarchive/lastdir",getenv("HOME"));
  g_object_set_data(G_OBJECT(NOTEBOOK),"lastdir_path",(gpointer)lastdir_path);
  if (g_file_test(lastdir_path, G_FILE_TEST_EXISTS) == TRUE)
  {
    lastdir_file = g_fopen(lastdir_path, "r");
    length = getline(&line, &linesize, lastdir_file);
    while (line[length-1] == '\n' || line[length-1] == ' ')
    {
      line[length-1] = '\0';
      length--;
    }
    fclose(lastdir_file);
    g_object_set_data(G_OBJECT(NOTEBOOK),"lastdir",(gpointer)line);
  }
  else
  {
    lastdir = g_strdup_printf("%s",getenv("HOME"));
    lastdir_file = g_fopen(lastdir_path, "w");
    fputs(lastdir, lastdir_file);
    fputs("\n", lastdir_file);
    fclose(lastdir_file);
    g_object_set_data(G_OBJECT(NOTEBOOK),"lastdir", (gpointer)lastdir);
  }
}

void
get_default_handler(void)
{
  gchar *defhand_path;
  gchar *line = NULL;
  FILE *defhand_file;
  size_t linesize = 0;
  int length;

  defhand_path = g_strdup_printf("%s/.xarchive/default_handler",
                                 getenv("HOME"));
  g_object_set_data(G_OBJECT(NOTEBOOK),"defhand_path",(gpointer)defhand_path);
  if (g_file_test(defhand_path, G_FILE_TEST_EXISTS) == FALSE)
    return;

  defhand_file = g_fopen(defhand_path, "r");
  length = getline(&line, &linesize, defhand_file);
  /* strip trailing whitespace from line to get command */
  /* isspace would be better if you want to #include ctype.h */
  while (line[length-1] == '\n' || line[length-1] == ' ')
  {
    line[length-1] = '\0';
    length--;
  }

  fclose(defhand_file);

  g_object_set_data(G_OBJECT(NOTEBOOK),"defhand_cmd",(gpointer)line);
}

void
set_default_handler(gchar *command)
{
  gchar *defhand_path;
  gchar *defhand_old_cmd;
  gchar *defhand_new_cmd;
  FILE *defhand_file;
  
  defhand_path = (gchar *)g_object_get_data(G_OBJECT(NOTEBOOK),"defhand_path");
  defhand_old_cmd=(gchar *)g_object_get_data(G_OBJECT(NOTEBOOK),"defhand_cmd");
  /* the passed command gets freed, so we'll store a copy */
  defhand_new_cmd = g_strdup(command);

  printf("setting default handler to file %s\n", defhand_path);
  defhand_file = g_fopen(defhand_path, "w");
  fputs(command, defhand_file);
  fputs("\n", defhand_file);
  fclose(defhand_file);
  
  g_free(defhand_old_cmd);
  g_object_set_data(G_OBJECT(NOTEBOOK),"defhand_cmd",(gpointer)defhand_new_cmd);
  return;
}

void 
open_one_file(WrapperData *wrapper, gchar *command)
{
  gchar *fname;

  if (wrapper_cmd(AR_EXTRACT, wrapper->argv, wrapper->dir) == 0)
  {
    fname = my_strescape(wrapper->argv[FIRST_FILE_INDEX]);
    gchar *viewcmd = g_strconcat(command, " ", wrapper->dir,
                                 "/", fname, NULL);
    g_free(fname);
    printf("viewcmd: %s\n",viewcmd);
    system(viewcmd);
    g_free(viewcmd);
  }
}

void 
default_handler_foreach_func(GtkTreeModel *model,
                             GtkTreePath  *path,
                             GtkTreeIter  *iter,
                             WrapperData  *wrapper)
{
  gchar *fname;
  gchar *defhand_cmd;
  
  defhand_cmd = (gchar *)g_object_get_data(G_OBJECT(NOTEBOOK),"defhand_cmd");
 
  /* if no cmd is set, pass off to open with dialog for setting */
  if (defhand_cmd == NULL)
  {
    message(MAIN_WINDOW,
          GTK_MESSAGE_WARNING,
            "Double-clicking doesn't work until you\n"
            "set your default handler using the\n"
            "'set double-click default handler' flag\n"
            "in the 'open with..' dialog.\n\n");
    openwith_foreach_func(model, path, iter, wrapper);
    return;
  }

  gtk_tree_model_get(model, iter, COL_FILE, &fname, -1);

  wrapper->argv = g_new(gchar *, 5); /*wrapper, option, archive, file, NULL*/
  wrapper->argv[ARCHIVE_INDEX] = g_strdup(get_current_archive());
  wrapper->argv[FIRST_FILE_INDEX] = g_strdup(fname);
  wrapper->argv[FIRST_FILE_INDEX + 1] = NULL;

  open_one_file(wrapper, defhand_cmd);
  
  g_strfreev(wrapper->argv);
  g_free(fname);
}

gchar *
askfor_openwith_command(gchar *fname)
{
  GtkWidget *dialog, *label, *combobox, *checkbox;
  GtkEntryCompletion *completion;
  static gchar *cmdlist_path = NULL;
  static GtkListStore *cmdlist = NULL;
  gchar *command = NULL, *msg;
  
  if (cmdlist_path == NULL)
    cmdlist_path = g_strdup_printf("%s/.xarchive/cmd_history",getenv("HOME"));
  if (cmdlist == NULL)
    cmdlist = get_openwith_cmdlist(cmdlist_path);
  
  dialog = gtk_dialog_new_with_buttons("Open With...",
                                       GTK_WINDOW(MAIN_WINDOW),
                                       GTK_DIALOG_DESTROY_WITH_PARENT,
                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                       GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
                                       NULL);
  gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog), 
                                          GTK_RESPONSE_ACCEPT,
                                          GTK_RESPONSE_CANCEL, -1);
  gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
  msg = g_strdup_printf("Open \"%s\" with...", fname); 
  label = gtk_label_new(msg);
  g_free(msg);
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE,TRUE,0);

  combobox = gtk_combo_box_entry_new_with_model(GTK_TREE_MODEL(cmdlist), 0);
  gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 0);
  gtk_widget_show(combobox);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),combobox,TRUE,TRUE,0);
  
  gtk_entry_set_activates_default(GTK_ENTRY(GTK_BIN(combobox)->child), 
                                  TRUE);
  completion = gtk_entry_completion_new();
  gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(cmdlist));
  gtk_entry_completion_set_text_column(completion, 0);
  gtk_entry_completion_set_popup_completion(completion, TRUE);
  gtk_entry_set_completion(GTK_ENTRY(GTK_BIN(combobox)->child), 
                           completion);
  
  checkbox = gtk_check_button_new_with_label("set as default double-click handler");
  gtk_widget_show(checkbox);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),checkbox,TRUE,TRUE,0);

  msg = g_strdup_printf("Current default handler: %s", 
                        (gchar *)g_object_get_data(G_OBJECT(NOTEBOOK), 
                                                   "defhand_cmd"));
  label = gtk_label_new(msg);
  gtk_widget_show(label);
  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),label,TRUE,TRUE,0);
  g_free(msg);

  if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
  {         
    command = g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_BIN(combobox)->child)));
    add_to_cmdlist(cmdlist, command, cmdlist_path);
    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox)) == TRUE) 
      set_default_handler(command);
  }
  
  gtk_widget_destroy(dialog);
  return command;
}

void 
openwith_foreach_func(GtkTreeModel *model,
                      GtkTreePath  *path,
                      GtkTreeIter  *iter,
                      WrapperData  *wrapper)
{
  gchar *fname, *command;
      
  /* see if cancel button pressed (xarchive set to null) */
  if (wrapper->index == FALSE) return;

  /* esc file name */
  gtk_tree_model_get(model, iter, COL_FILE, &fname, -1);
   
  /* display dialog asking to exatract and open fname with app */
  command = askfor_openwith_command(fname);
  if (command != NULL && strcmp(command, GTK_STOCK_NO) == 0)
    wrapper->index = TRUE;
  else if (command != NULL)
  {
    wrapper->argv = g_new(gchar *, 5); /*wrapper, option, archive, file, NULL*/
    wrapper->argv[ARCHIVE_INDEX] = g_strdup(get_current_archive());
    wrapper->argv[FIRST_FILE_INDEX] = g_strdup(fname);
    wrapper->argv[FIRST_FILE_INDEX + 1] = NULL;

    open_one_file(wrapper, command);

    g_strfreev(wrapper->argv);
  }
  else
  {
    wrapper->index = FALSE;
  }

  g_free(command);
  g_free(fname);
}

/**********************/
/* callback functions */
/**********************/
void
dummy_cb(GtkWidget *widget, gpointer data)
{
  return;
}

void 
open_cb(GtkWidget *widget, gpointer data)
{
  gchar *archive;

  archive = askfor_existing_archive();
  if (archive == NULL) return;
  
  add_page(archive);
  g_free(archive);
  
}

void 
new_cb(GtkWidget *widget, gpointer data)
{
  WrapperData wrapper;
  gchar *archive;
  GtkListStore *myfc_ls; /*file chooser liststore*/
  GtkTreeIter iter;
  gchar *name;
  gint error, size;

  /* now get the files that are to be added to the new archive */
  if (data == NULL)
  {
    archive = askfor_new_archive(NULL);
    if (archive == NULL) return;
    myfc_ls = make_myfc_ls();
  }
  else
  {
    myfc_ls = (GtkListStore *) data;
    name = g_object_get_data(G_OBJECT(myfc_ls), "name");
    archive = askfor_new_archive(name);
    g_free(name);
    if (archive == NULL)
    {
      g_object_unref(myfc_ls);
      return;
    }
  }

  if (multi_file_chooser(archive, myfc_ls) == TRUE) 
  {
    /* set up cmd array */
    /* adding 4 to list size for wrapper,option,archive, and null */
    size = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(myfc_ls), NULL) + 4;
    wrapper.argv = g_new(gchar *, size);
    wrapper.index = FIRST_FILE_INDEX;
    wrapper.argv[ARCHIVE_INDEX] = g_strdup(archive);                    
    /* create new archive with first item by calling
     * foreach func by hand */
    gtk_tree_model_get_iter_first(GTK_TREE_MODEL(myfc_ls), &iter); 
    add_foreach_func(GTK_TREE_MODEL(myfc_ls), NULL, &iter, &wrapper); 
    error = wrapper_cmd(AR_NEW, wrapper.argv, NULL);
    gtk_list_store_remove(myfc_ls, &iter);
    if (error != 0 )
    {
      g_free(archive);
      g_strfreev(wrapper.argv);
      g_object_unref(myfc_ls);
      return;
    }
    
    /* then add the rest, if any, to new archive */
    if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(myfc_ls), &iter) != FALSE)
    {
      gtk_tree_model_foreach(GTK_TREE_MODEL(myfc_ls), 
                             (GtkTreeModelForeachFunc) add_foreach_func,
                             &wrapper);
      error = wrapper_cmd(AR_ADD, wrapper.argv, NULL);
      if (error != 0) {
        g_free(archive);
        g_strfreev(wrapper.argv);
        g_object_unref(myfc_ls);
        return;
      }
    }
    
    g_strfreev(wrapper.argv);
    /* now load up the archive in the notebook */
    add_page(archive);
  }
  
  g_free(archive);
  g_object_unref(myfc_ls);
}

void 
close_cb(GtkWidget *widget, gpointer data)
{
  gint page;
  gchar *archive;
  GtkWidget *scrollw;

  if ( data != NULL)
  {
    scrollw = GTK_WIDGET(data);
    page = gtk_notebook_page_num(NOTEBOOK, scrollw);
    gtk_notebook_set_current_page(NOTEBOOK, page);
  }
  archive = get_current_archive();
  g_free(archive);
  page = gtk_notebook_get_current_page(NOTEBOOK);
  gtk_notebook_remove_page(NOTEBOOK, page);
  gtk_widget_queue_draw(GTK_WIDGET(NOTEBOOK));

  page = gtk_notebook_get_current_page(NOTEBOOK);
  if (page < 0) 
  {
    gtk_widget_hide(GTK_WIDGET(NOTEBOOK));
    gtk_widget_show(EMPTY);
  }
}

void
close_button_cb(GtkWidget *widget, gpointer data)
{
  GtkWidget *current_scrollw;
  gint page;

  current_scrollw = gtk_notebook_get_nth_page(NOTEBOOK, 
                            gtk_notebook_get_current_page(NOTEBOOK));
  close_cb(widget, data);
  page = gtk_notebook_page_num(NOTEBOOK, current_scrollw);
  if (page != -1)
    gtk_notebook_set_current_page(NOTEBOOK, page);
}

void 
extract_cb(GtkWidget *widget, gpointer data)
{
  /* get selections from current treeview and a destdir.
   * create a gchar pointer array with selected files and send
   * to wrapper_cmd to process. */
  static WrapperData wrapper;
  SelectionData seld;
  GtkTreeView *treeview;
  GtkTreeModel *liststore;
  gint sort_column;
  GtkSortType sort_order;
  gchar *msg;
  gint error;

  if ( (treeview = get_current_tree()) == NULL ) return; 
  liststore = gtk_tree_view_get_model(treeview);
  /* if selection contains directories notify user */
  seld.sel = gtk_tree_view_get_selection(treeview);

  /* if nothing selected ask to select all */
  if (gtk_tree_selection_count_selected_rows(seld.sel) < 1) 
  {
    if (message(MAIN_WINDOW,
            GTK_MESSAGE_WARNING, 
                "No files selected,\n\n"
                "assuming you want to extract all") == TRUE) 
      gtk_tree_selection_select_all(seld.sel);
    else return;
  }

  wrapper.dir = askfor_extract_dir();
  if (wrapper.dir == NULL) return;
  
  /* if all is selected don't send any files, just extract the whole thing */
  if ( gtk_tree_selection_count_selected_rows(seld.sel) == 
       gtk_tree_model_iter_n_children(liststore, NULL) )
  {
    /* need an array for 4 gchar pointers. wrapper option archive null. */ 
    wrapper.argv = g_new(gchar *, 4);
    wrapper.argv[ARCHIVE_INDEX] = g_strdup(get_current_archive());
    wrapper.argv[FIRST_FILE_INDEX] = NULL;
  }
  else
  {
    /* need an array for 4 gchar pointers plus the number of selected files.
     * Array will contain: wrapper option archive files... null 
     */
    wrapper.argv = g_new(gchar *, 
                         (4 + 
                          gtk_tree_selection_count_selected_rows(seld.sel)));
    wrapper.argv[ARCHIVE_INDEX] = g_strdup(get_current_archive());
    wrapper.index = FIRST_FILE_INDEX;
  
    /* for extracting we need the DFILE column sorted descending so that
     * the directories are extracted before the children.  Tar
     * hiccups if not. So change to that if it's not then
     * change back to what ever it was */
    gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(liststore),
                                         &sort_column, &sort_order);
    if ( ! (sort_column == COL_DFILE && sort_order == GTK_SORT_DESCENDING) ) 
    {
      gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(liststore), 
                                           COL_DFILE, GTK_SORT_DESCENDING);
    }

    gtk_tree_selection_selected_foreach(seld.sel, 
                                        (GtkTreeSelectionForeachFunc)
                                        selected_foreach_func, &wrapper);

    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(liststore),
                                         sort_column, sort_order);
  }
  error = wrapper_cmd(AR_EXTRACT, wrapper.argv, wrapper.dir); 
  if (error == 0)
  {
    msg = g_strconcat("Done extracting files to:\n\n",
                      wrapper.dir, NULL);
    message(MAIN_WINDOW,
          GTK_MESSAGE_INFO, msg);
    g_free(msg);
  }
  g_strfreev(wrapper.argv);
  g_free(wrapper.dir);
} 

void
openwith_cb(GtkWidget *widget, gpointer data)
{
  open_selected_files(FALSE);
}

void
double_click_cb()
{
  open_selected_files(TRUE);
}

void
open_selected_files(gboolean use_default_handler)
{
  static WrapperData wrapper;
  SelectionData seld;
  GtkTreeView *treeview;
  GtkTreeSelectionForeachFunc foreach_func = (GtkTreeSelectionForeachFunc)
    ((use_default_handler)
     ? default_handler_foreach_func
     : openwith_foreach_func);
  gchar *tdir, *rm_command;
  const gchar *tpath = NULL;
        

  if ( (treeview = get_current_tree()) == NULL ) return;
    
  seld.sel = gtk_tree_view_get_selection(treeview);

  /* if nothing selected do nothing */
  if ( gtk_tree_selection_count_selected_rows(seld.sel) < 1 ) return; 

  tpath = g_get_tmp_dir();
  tdir = g_strconcat(tpath,"/xarchiveXXXXXX", NULL); 
  wrapper.dir = mkdtemp(tdir);
  wrapper.index = TRUE; /* use index to check for a cancel */
  gtk_tree_selection_selected_foreach(seld.sel, foreach_func, &wrapper);
  
  /* remove temp dir tdir */
  rm_command = g_strconcat("rm -fr ", tdir, NULL);
  printf("rm_command: %s\n", rm_command);
  system(rm_command);
  g_free(rm_command);
  g_free(tdir);
}

void 
add_cb(GtkWidget *widget, gpointer data)
{
  WrapperData wrapper;
  GtkListStore *myfc_ls; /*file chooser liststore*/
  gchar *archive_disp, *archive;
  gint error;

  if ( (archive = get_current_archive()) == NULL ) return; 
  
  if (data != NULL)
    myfc_ls = (GtkListStore *) data;
  else
    myfc_ls = make_myfc_ls();
  
  archive_disp = g_filename_display_name(archive);
  if (multi_file_chooser(archive_disp, myfc_ls) == TRUE) 
  {
    /* need a gchar pointer array for 4 pointers plus the number
     * of files on the list (wrapper, option, archive, files.., null)
     */
    wrapper.argv = g_new(gchar *,
                         4 + 
                         gtk_tree_model_iter_n_children(GTK_TREE_MODEL(myfc_ls),NULL));
    wrapper.index = FIRST_FILE_INDEX;
    wrapper.argv[ARCHIVE_INDEX] = g_strdup(archive);
    gtk_tree_model_foreach( GTK_TREE_MODEL(myfc_ls),
                            (GtkTreeModelForeachFunc) 
                            add_foreach_func,
                            &wrapper);
    error = wrapper_cmd(AR_ADD, wrapper.argv, NULL);
    if (error == 0)
    {
      reload_current_tree(get_current_tree());
    }
    g_strfreev(wrapper.argv);
  }
  
  g_free(archive_disp);
  g_object_unref(myfc_ls);
} 

void 
remove_cb(GtkWidget *widget, gpointer data)
{
  WrapperData wrapper;
  SelectionData seld;
  GtkTreeView *treeview;
  GtkTreeModel *liststore;
  gint sort_column;
  GtkSortType sort_order;

  if ( (treeview = get_current_tree()) == NULL) return;
  liststore = gtk_tree_view_get_model(treeview);
  seld.sel = gtk_tree_view_get_selection(treeview);
  if ( gtk_tree_selection_count_selected_rows(seld.sel) < 1 ) return;

  wrapper.argv = g_new(gchar *,
                       (4 +
                        gtk_tree_selection_count_selected_rows(seld.sel)));
  wrapper.index = FIRST_FILE_INDEX;
  wrapper.argv[ARCHIVE_INDEX] = g_strdup(get_current_archive());

  /* for removing we need the DFILE column sorted descending so that a
   * directories children are removed before the directory itself.  Tar
   * hiccups if not. So change to that if it's not, do the remove, then
   * change back to what ever it was */
  gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(liststore),
                                       &sort_column, &sort_order);
  if ( ! (sort_column == COL_DFILE && sort_order == GTK_SORT_DESCENDING) ) 
  {
    gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(liststore), 
                                         COL_DFILE, GTK_SORT_DESCENDING);
  }

  gtk_tree_selection_selected_foreach(seld.sel, 
                                      (GtkTreeSelectionForeachFunc)
                                      selected_foreach_func, 
                                      &wrapper);

  gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(liststore),
                                       sort_column, sort_order);

  wrapper_cmd(AR_REMOVE, wrapper.argv, NULL);
  reload_current_tree(treeview);
  g_strfreev(wrapper.argv);
}

void 
select_all_cb(GtkWidget *widget, gpointer data)
{
  GtkTreeView *treeview;
  GtkTreeSelection *sel;

  if ( (treeview = get_current_tree()) == NULL ) return;
  sel = gtk_tree_view_get_selection(treeview);
  gtk_tree_selection_select_all(sel);
}

void 
unselect_all_cb(GtkWidget *widget, gpointer data)
{
  GtkTreeView *treeview;
  GtkTreeSelection *sel;

  if ( (treeview = get_current_tree()) == NULL ) return;
  sel = gtk_tree_view_get_selection(treeview);
  gtk_tree_selection_unselect_all(sel);
}

void 
wrapper_info_cb(GtkWidget *widget, gpointer data)
{
  GtkWidget *dialog, *infobox;
  gchar *wrapinf, *msg;

  dialog = gtk_dialog_new_with_buttons("Wrapper Info", 
                                       NULL,
                                       GTK_DIALOG_DESTROY_WITH_PARENT |
                                       GTK_DIALOG_NO_SEPARATOR,
                                       GTK_STOCK_OK,
                                       GTK_RESPONSE_ACCEPT,
                                       NULL);
  g_signal_connect_swapped(dialog, "response", 
                           G_CALLBACK(gtk_widget_destroy), 
                           dialog);
  gtk_widget_set_size_request(dialog, 500, 300);

  wrapinf = wrapper_info();
  msg = g_strdup_printf("%s\n%s\n\n%s",
                        PACKAGE_STRING, PACKAGE_BUGREPORT, wrapinf);
  g_free(wrapinf);
  infobox = make_info_widget(msg);
  g_free(msg);
  
  gtk_box_pack_start(GTK_BOX( GTK_DIALOG(dialog)->vbox ), infobox, TRUE,TRUE,0);

  gtk_widget_show_all(dialog);
}

void
read_help_cb(GtkWidget *widget, gpointer data)
{
  GtkWidget *dialog, *infobox;
  gchar *helptxt;
  
  dialog = gtk_dialog_new_with_buttons("View Help", 
                                       NULL,
                                       GTK_DIALOG_DESTROY_WITH_PARENT |
                                       GTK_DIALOG_NO_SEPARATOR,
                                       GTK_STOCK_OK,
                                       GTK_RESPONSE_ACCEPT,
                                       NULL);
  g_signal_connect_swapped(dialog, "response", 
                           G_CALLBACK(gtk_widget_destroy), 
                           dialog);
  gtk_widget_set_size_request(dialog, 500, 300);

  g_file_get_contents(HELP_FILE_PATH, &helptxt, NULL, NULL);
  infobox = make_info_widget(helptxt);
  g_free(helptxt);
  gtk_box_pack_start(GTK_BOX( GTK_DIALOG(dialog)->vbox ), 
                     infobox, TRUE,TRUE,0);

  gtk_widget_show_all(dialog);
}

static gboolean
open_cancel_cb(GtkWidget *widget, gpointer data)
{
  gboolean *stopit = (gboolean *) data;

  *stopit = TRUE;
  return FALSE;
}

static gboolean
process_cancel_cb(GtkWidget *widget, gpointer data)
{
  pid_t pid = (pid_t) GPOINTER_TO_INT(data);
  gint err;
  
  printf("Trying to send kill signal to process %d\n", pid);
  err = kill( pid, SIGTERM);
  printf("Returned from kill: %d\n", err);
  return FALSE;
}

/***********************/
/* UIMananger functions*/
/***********************/
void 
add_ui_widget(GtkUIManager *uimanager, 
              GtkWidget *widget,
              GtkContainer *container)
{
  GtkToolbar *toolbar;

  gtk_box_pack_start (GTK_BOX(container), widget, FALSE, FALSE, 0);
  gtk_widget_show(widget);
  if (GTK_IS_TOOLBAR(widget)) 
  {
    toolbar = GTK_TOOLBAR(widget);
    gtk_toolbar_set_show_arrow(toolbar, TRUE);
  }
}

GtkUIManager * 
make_ui_widgets(GtkWidget *window, GtkWidget *box)
{
  GtkUIManager *uimanager;
  GtkActionGroup *action_group;
  GError *error = NULL;
  GtkActionEntry entries[] = {
    { "FileMenuAction", NULL, "_File" },
    { "ActionsMenuAction", NULL, "_Archive" },
    { "HelpMenuAction", NULL, "_Help" },
    { "PopupMenuAction", NULL, "_Popup" },
    { "new", GTK_STOCK_NEW, "_New", "<control>N",
      "(CTRL-N) Create new archive", G_CALLBACK(new_cb)},
    { "open", GTK_STOCK_OPEN, "_Open", "<control>O",
      "(CTRL-O) Open exisiting archive", G_CALLBACK(open_cb)},
    { "close", GTK_STOCK_CLOSE, "_Close", "<control>W",
      "(CTRL-W) Close current archive window", G_CALLBACK(close_cb)},
    { "quit", GTK_STOCK_QUIT, "_Quit", "<control>Q",
      "(CTRL-Q) Quit application, closing all open archives", 
      G_CALLBACK(gtk_main_quit)},
    { "extract", GTK_STOCK_HARDDISK, "_Extract", "<control>E",
      "(CTRL-E) Extract selected files from current archive", 
      G_CALLBACK(extract_cb)},
    { "add", GTK_STOCK_ADD, "_Add", "<control>A",
      "(CTRL-A) Add files to current archive", G_CALLBACK(add_cb)},
    { "remove", GTK_STOCK_REMOVE, "_Remove", "<control>R",
      "(CTRL-R) Remove selected files from current archive", G_CALLBACK(remove_cb)},
    { "openwith", GTK_STOCK_EXECUTE, "O_pen With...", "<control>P",
      "(CTRL-P) Temporarily extract the selected files from current archive then open them with the specified application", G_CALLBACK(openwith_cb)},
    { "SelectionMenuAction", NULL, "_Selection" },
    { "select all", GTK_STOCK_APPLY, "_Select All", "<control>S",
      "(CTRL-S) selected all files in current archive", G_CALLBACK(select_all_cb)},
    { "unselect all", GTK_STOCK_CLEAR, "_Unselect All", "<control>U",
      "(CTRL-U) unselect all files in current archive", G_CALLBACK(unselect_all_cb)},
    { "wrapper info", GTK_STOCK_ABOUT, "Wrapper _Info", "<control>I",
      "(CTRL-I) Show information on found wrappers", G_CALLBACK(wrapper_info_cb)},
    { "read help", GTK_STOCK_HELP, "Read _Help", "<control>H",
      "(CTRL-H) Read help file", G_CALLBACK(read_help_cb)},
  };
  guint n_entries = G_N_ELEMENTS(entries);
  gchar *ui_info =
    "  <menubar>\n"
    "    <menu name=\"_File\" action=\"FileMenuAction\">\n"
    "      <menuitem name=\"open\" action=\"open\" />\n"
    "      <menuitem name=\"new\" action=\"new\" />\n"
    "      <menuitem name=\"close\" action=\"close\" />\n"
    "      <separator name=\"sep1\" />\n"
    "      <menuitem name=\"quit\" action=\"quit\" />\n"
    "    </menu>\n"
    "    <menu name=\"_Selection\" action=\"SelectionMenuAction\">\n"
    "      <menuitem name=\"select all\" action=\"select all\" />\n"
    "      <menuitem name=\"unselect all\" action=\"unselect all\" />\n"
    "    </menu>\n"
    "    <menu name=\"_Actions\" action=\"ActionsMenuAction\" >\n"
    "      <menuitem name=\"extract\" action=\"extract\" />\n"
    "      <menuitem name=\"openwith\" action=\"openwith\" />\n"
    "      <menuitem name=\"remove\" action=\"remove\" />\n"
    "      <menuitem name=\"add\" action=\"add\" />\n"
    "    </menu>\n"
    "    <menu name=\"_Help\" action=\"HelpMenuAction\" >\n"
    "      <menuitem name=\"read help\" action=\"read help\" />\n"
    "      <menuitem name=\"wrapper info\" action=\"wrapper info\" />\n"
    "    </menu>\n"
    "  </menubar>\n"
    "  <toolbar name=\"toolbar\">\n"
    "    <toolitem name=\"open\" action=\"open\" />\n"
    "    <toolitem name=\"new\" action=\"new\" />\n"
    "    <toolitem name=\"close\" action=\"close\" />\n"
    "    <separator name=\"sep1\" /> \n"
    "    <toolitem name=\"select all\" action=\"select all\" />\n"
    "    <toolitem name=\"unselect all\" action=\"unselect all\" />\n"
    "    <separator name=\"sep2\" /> \n"
    "    <toolitem name=\"extract\" action=\"extract\" />\n"
    "    <toolitem name=\"openwith\" action=\"openwith\" />\n"
    "    <toolitem name=\"remove\" action=\"remove\" />\n"
    "    <toolitem name=\"add\" action=\"add\" />\n"
    "    <separator name=\"sep3\" /> \n"
    "    <toolitem name=\"quit\" action=\"quit\" />\n"
    "  </toolbar>\n"
    "  <popup name=\"treeview_popup\" action=\"PopupMenuAction\">\n"
    "    <menuitem name=\"select all\" action=\"select all\" />\n"
    "    <menuitem name=\"unselect all\" action=\"unselect all\" />\n"
    "    <separator name=\"sep4\" /> \n"
    "    <menuitem name=\"extract\" action=\"extract\" />\n"
    "    <menuitem name=\"openwith\" action=\"openwith\" />\n"
    "    <menuitem name=\"remove\" action=\"remove\" />\n"
    "    <menuitem name=\"add\" action=\"add\" />\n"
    "    <separator name=\"sep5\" /> \n"
    "    <menuitem name=\"close\" action=\"close\" />\n"
    "  </popup>\n"
    ;
    
  action_group = gtk_action_group_new("XArchiveActions");
  gtk_action_group_add_actions(action_group, entries, n_entries, NULL);
    
  uimanager = gtk_ui_manager_new();
  gtk_ui_manager_insert_action_group(uimanager, action_group, 0);
  g_signal_connect(uimanager, "add_widget", G_CALLBACK(add_ui_widget), box);
  gtk_window_add_accel_group(GTK_WINDOW(window), 
                             gtk_ui_manager_get_accel_group(uimanager));
  if (!gtk_ui_manager_add_ui_from_string(uimanager, ui_info, -1, &error)) 
  {
    g_message("building menus failed: %s", error->message);
    g_error_free(error);
  }
  return uimanager;
}


/******************************/
/* passed aurgument functions */
/******************************/

gint
ask_create_or_add(gchar *msg)
{
  gint response;
  GtkWidget *md;

  md = gtk_message_dialog_new(GTK_WINDOW(MAIN_WINDOW), 
                              GTK_DIALOG_DESTROY_WITH_PARENT,
                              GTK_MESSAGE_QUESTION,
                              GTK_BUTTONS_CANCEL,
                              msg);
  gtk_dialog_add_buttons(GTK_DIALOG(md),
                         "New", AR_NEW,
                         "Existing", AR_ADD,
                         NULL);
  gtk_dialog_set_alternative_button_order(GTK_DIALOG(md), AR_NEW, AR_ADD,
                                          GTK_RESPONSE_CANCEL, -1);
  response = gtk_dialog_run(GTK_DIALOG(md));
  gtk_widget_destroy(md);
  
  return response;
}

void
process_passed_arguments(ParsedArgs *pargs)
{
  gchar *archive = NULL, *msg, *filepath;
  gint i, response=AR_ADD;
  GtkListStore *filelist;

  switch (pargs->action)
  {
    case AR_OPEN:
      if (pargs->files == NULL) break;
      for (i=0; pargs->files[i] != NULL; i++)
      {
        archive = canonicalize_file_name(pargs->files[i]);
        if(archive != NULL) add_page(archive);
        else
        {
          msg = g_strconcat("Could not open archive:\n\n",
                            pargs->files[i], NULL);
          message(MAIN_WINDOW,
              GTK_MESSAGE_ERROR, msg);
          g_free(msg);
        }
      }
      break;
    
    case AR_ADD:
      msg = g_strdup_printf("Would you like to:\n"
                            "Create a new archive, or\n"
                            "Add to an existing archive?");
      if (strcmp(pargs->archive,"ask") != 0 &&
          (archive = canonicalize_file_name(pargs->archive)) == NULL)
        msg = g_strdup_printf("Archive not found\n%s\n\n%s",
                              pargs->archive, msg);
      else
      {
        g_free(pargs->archive);
        pargs->archive = NULL;
      }
      
      if (archive == NULL &&
          (response = ask_create_or_add(msg)) == AR_ADD)
        archive = askfor_existing_archive();
      
      filelist = make_myfc_ls();
      if (pargs->files != NULL)
        for (i=0; pargs->files[i] != NULL; i++)
        {
          filepath = canonicalize_file_name(pargs->files[i]);
          if (filepath == NULL) continue;
          else myfc_add_foreach_func(filepath, filelist);
          g_free(filepath);
        }

      if (response == AR_ADD && archive != NULL)
      {
        add_page(archive);
        add_cb(NULL, (gpointer) filelist);
      }
      else if (response == AR_NEW)
      {
        g_object_set_data(G_OBJECT(filelist),"name", (gpointer)pargs->archive);
        new_cb(NULL, (gpointer) filelist);
      }
      else 
        gtk_widget_show(EMPTY);

      g_free(archive);
      break;

    case AR_NEW:
      if (strcmp(pargs->archive, "ask") == 0)
      {
        g_free(pargs->archive);
        pargs->archive = NULL;
      }
      filelist = make_myfc_ls();
      if (pargs->files != NULL)
        for (i=0; pargs->files[i] != NULL; i++)
        {
          filepath = canonicalize_file_name(pargs->files[i]);
          if (filepath == NULL) continue;
          else myfc_add_foreach_func(filepath, filelist);
          g_free(filepath);
        }
      g_object_set_data(G_OBJECT(filelist),"name", (gpointer)pargs->archive);
      new_cb(NULL, (gpointer) filelist);
      break;
      
    default:
      gtk_widget_show(EMPTY);
      break;
  }
}

/***********************/
/* Main setup function */
/***********************/

int 
make_widgets(ParsedArgs *pargs)
{
  GdkGeometry size_hints;
  GtkWidget *mainbox;
  static GdkPixbuf *xarchive_pixbuf;

  MAIN_WINDOW = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  xarchive_pixbuf = gdk_pixbuf_new_from_xpm_data(xarchive_xpm);
  gtk_window_set_default_icon(xarchive_pixbuf);
  g_signal_connect(G_OBJECT(MAIN_WINDOW), "delete_event",
                   G_CALLBACK(gtk_main_quit), NULL);
  g_signal_connect(G_OBJECT(MAIN_WINDOW), "destroy",
                   G_CALLBACK(gtk_main_quit), NULL);

  gtk_container_set_border_width(GTK_CONTAINER(MAIN_WINDOW), 0);
  gtk_window_set_title (GTK_WINDOW(MAIN_WINDOW), PACKAGE_STRING);
  size_hints.min_width=300;
  size_hints.min_height=250;
  size_hints.base_width=0;
  size_hints.base_height=0;
  gtk_window_set_geometry_hints(GTK_WINDOW(MAIN_WINDOW), MAIN_WINDOW, 
                                &size_hints,
                                 GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE); 
  gtk_window_set_default_size(GTK_WINDOW(MAIN_WINDOW), 640, 400);
  if (pargs->geom != NULL)
    gtk_window_parse_geometry(GTK_WINDOW(MAIN_WINDOW), pargs->geom);
  
  mainbox = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(MAIN_WINDOW), mainbox);

  UIMANAGER = make_ui_widgets(MAIN_WINDOW, mainbox);

  make_empty_page(mainbox);
  make_notebook_widgets(mainbox);

  process_passed_arguments(pargs);

  gtk_widget_show(mainbox);
  gtk_widget_show(MAIN_WINDOW);
  gtk_main(); 
  return 0;
}

Generated by  Doxygen 1.6.0   Back to index