/* IglooFTP - Graphical and User Friendly FTP Client.
 * Copyright (c) 1998-1999 Jean-Marc Jacquet. 
 * All rights reserved.
 * 
 * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE
 *
 * IglooFTP Original Packages, information and support,  
 * can be obtained at :
 *                              http://www.littleigloo.org
 * 
 *
 */


#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <utime.h>
#include <locale.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>



#include "protos.h"
#include "dirlist.h"
#include "local_sort.h"
#include "local_select.h"


/* DIRLIST */

/* PUBLIC:
   * active_dir_panel
   * show_or_hide_dir_panel
   * create_dirlist 
   * local_files_select
   * update_dirlist
   * refresh_dirlist : call update_dirlist with current_dir name
   * toggle_local_hidden : toggle show hidden files flag
   * toggle_local_columns_visibility
   * local_popup_menu_enable_disable
   * local_toolbar_enable_disable
   * local_sort_from_menu 
   * local_sort_type_from_menu 
   * STATIC:
   * update_dirlist 
   * dirlist_cdup
   * dirlist_selection_made 
   * dirlist_event_handler
   * dirlist_button_clicked : click on column title button
 */

void
show_or_hide_dir_panel (GtkWidget * widget)
{
  show_hide_widget (dir_panel_box, GTK_CHECK_MENU_ITEM (widget)->active);
  gtk_paned_set_position (GTK_PANED (clist_panel), GTK_CHECK_MENU_ITEM (widget)->active ? clist_pane_pos : 0);
  update_view_local_remote_menu ();
}

void
local_popup_menu_enable_disable (char FLAG)
{
  UPDATE_POPUP_MENU = FLAG;
}

void
local_toolbar_enable_disable (char FLAG)
{
  UPDATE_TOOLBAR = FLAG;
}

void
active_dir_panel (char FLAG)
{
  gtk_widget_set_sensitive (clist, FLAG);
  gtk_widget_set_sensitive (combo, FLAG);
  gtk_widget_set_sensitive (prompt_entry, FLAG);
  gtk_widget_set_sensitive (button_browser_open, FLAG);
  gtk_widget_set_sensitive (button_cdup, FLAG);
  gtk_widget_set_sensitive (browser_window, FLAG);
  if (FLAG)
    {
      update_local_popup_menu (0);
      local_popup_menu_enable ();
      local_toolbar_enable ();
      toolbar_buttons_set_sensitive ();
    }
  else
    {
      local_popup_menu_set_sensitive (FLAG);
      local_popup_menu_disable ();
      local_toolbar_disable ();
    }

}


GtkWidget *
create_dirlist (void)
{
#include "pixmaps/refresh.xpm"
  GtkWidget *vbox;
  GtkWidget *hbox;
  GtkWidget *frame;
  gchar *clist_titles[] =
  {"", "Name", "Size ", "Date ", "Permissions", "Owner", "Group"};


  clist_col_sort = DIR_COL_SORT_BY_NAME;

  dir_panel_box = vbox = gtk_vbox_new (FALSE, 0);
  gtk_widget_show (vbox);


  frame = gtk_vbox_new (FALSE, 0);

  gtk_widget_show (frame);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);



  /* -- browser -- */
  hbox = h_box (frame, FALSE, 2, 0);

  button_browser_open = browser_button (TRUE);
  GTK_BUTTON (button_browser_open)->relief = GTK_RELIEF_NONE;
  gtk_box_pack_start (GTK_BOX (hbox), button_browser_open, FALSE, FALSE, 0);
  gtk_widget_set_usize (button_browser_open, 27, 24);

  button_browser_close = browser_button (FALSE);
  GTK_BUTTON (button_browser_close)->relief = GTK_RELIEF_NONE;
  gtk_box_pack_start (GTK_BOX (hbox), button_browser_close, FALSE, FALSE, 0);
  gtk_widget_hide (button_browser_close);
  gtk_widget_set_usize (button_browser_close, 27, 24);

  combo = gtk_combo_new ();
  gtk_combo_set_use_arrows_always (GTK_COMBO (combo), TRUE);
  gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
  gtk_widget_show (combo);
  combo_items = NULL;


  button_cdup = cdup_button ();
  GTK_BUTTON (button_cdup)->relief = GTK_RELIEF_NONE;
  gtk_box_pack_start (GTK_BOX (hbox), button_cdup, FALSE, FALSE, 0);
  gtk_signal_connect (GTK_OBJECT (button_cdup), "clicked", GTK_SIGNAL_FUNC (dirlist_cdup), NULL);


  hbox = h_box (vbox, TRUE, 0, 0);

  browser_window = DIR_TREE_create (&dirlist_browser, &dirlist_browser_label, FALSE);
  gtk_clist_column_titles_hide (GTK_CLIST (dirlist_browser));
  gtk_box_pack_start (GTK_BOX (hbox), browser_window, TRUE, TRUE, 0);
  gtk_widget_hide (browser_window);


  /* -- files list -- */
  DIR_clist = clist = gtk_clist_new_with_titles (7, clist_titles);
  gtk_clist_set_border (GTK_CLIST (clist), GTK_SHADOW_IN);
  gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);

  gtk_clist_set_row_height (GTK_CLIST (clist), 16);
  gtk_clist_set_column_width (GTK_CLIST (clist), 0, 15);
  gtk_clist_set_column_min_width (GTK_CLIST (clist), 1, 160);
  gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 1, TRUE);
  gtk_clist_set_column_width (GTK_CLIST (clist), 2, 65);
  gtk_clist_set_column_width (GTK_CLIST (clist), 3, 80);
  gtk_clist_set_column_width (GTK_CLIST (clist), 4, 80);
  gtk_clist_set_column_width (GTK_CLIST (clist), 5, 55);
  gtk_clist_set_column_width (GTK_CLIST (clist), 6, 55);
  gtk_clist_set_column_justification (GTK_CLIST (clist), 2, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_justification (GTK_CLIST (clist), 5, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_justification (GTK_CLIST (clist), 6, GTK_JUSTIFY_RIGHT);
  gtk_clist_set_column_widget (GTK_CLIST (clist), 0, new_pixmap (window, refresh_xpm));



  gtk_clist_set_hadjustment (GTK_CLIST (clist), NULL);
  gtk_clist_set_vadjustment (GTK_CLIST (clist), NULL);

  gtk_widget_show (clist);

  clist_window = scroll_win ();
  gtk_container_add (GTK_CONTAINER (clist_window), clist);
  gtk_box_pack_start (GTK_BOX (hbox), clist_window, TRUE, TRUE, 0);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (clist_window), GTK_POLICY_ALWAYS, GTK_POLICY_AUTOMATIC);



  {
    register int f;
    for (f = 1; f < 7; f++)
      sort_arrow[f] = clist_title_with_arrow (clist, f, clist_titles[f]);
  }
  gtk_widget_show (sort_arrow[DIR_COL_SORT_BY_NAME]);

  frame_info = frame = gtk_frame_new (NULL);
  gtk_widget_show (frame);
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);

  label_info = gtk_label_new ("");
  gtk_container_add (GTK_CONTAINER (frame), label_info);
  gtk_widget_show (label_info);
  gtk_label_set_justify (GTK_LABEL (label_info), GTK_JUSTIFY_FILL);


  local_focus_update ();



  prompt_entry = gtk_entry_new ();
  gtk_box_pack_start (GTK_BOX (vbox), prompt_entry, FALSE, TRUE, 0);
  show_hide_widget (prompt_entry, user_rc.view_shell_prompt);




  gtk_signal_connect (GTK_OBJECT (DIR_COMBO_ENTRY), "changed",
		      GTK_SIGNAL_FUNC (dir_combo_new_char_entered), NULL);


  gtk_signal_connect (GTK_OBJECT (DIR_COMBO_ENTRY), "activate",
		      GTK_SIGNAL_FUNC (dir_combo_new_selection), NULL);

  gtk_signal_connect (GTK_OBJECT (GTK_COMBO (combo)->popwin), "button_press_event",
		      GTK_SIGNAL_FUNC (dir_combo_new_selection), NULL);

  gtk_signal_connect (GTK_OBJECT (prompt_entry), "key_press_event",
		      GTK_SIGNAL_FUNC (execute_user_command), NULL);

  gtk_signal_connect (GTK_OBJECT (clist), "select_row",
	  GTK_SIGNAL_FUNC (dirlist_selection_made), GINT_TO_POINTER (TRUE));

  gtk_signal_connect (GTK_OBJECT (clist), "unselect_row",
	 GTK_SIGNAL_FUNC (dirlist_selection_made), GINT_TO_POINTER (FALSE));

  gtk_signal_connect (GTK_OBJECT (dirlist_browser), "event",
		      GTK_SIGNAL_FUNC (browser_event_handler), NULL);

  gtk_signal_connect (GTK_OBJECT (clist), "event",
		      GTK_SIGNAL_FUNC (dirlist_event_handler), NULL);

  gtk_signal_connect (GTK_OBJECT (button_browser_close), "clicked",
		      GTK_SIGNAL_FUNC (browser_hide), NULL);

  gtk_signal_connect (GTK_OBJECT (button_browser_open), "clicked",
		      GTK_SIGNAL_FUNC (browser_show), NULL);

  gtk_signal_connect (GTK_OBJECT (clist), "click_column",
		      GTK_SIGNAL_FUNC (dirlist_button_clicked), NULL);


  if (!strlen (this_session.local_dir))
    getcwd (this_session.local_dir, sizeof (this_session.local_dir));

  startup_message ("Reading Local Directory ...");
  update_dirlist (this_session.local_dir);

  startup_message ("Building Local Directories Browser ...");
  DIR_TREE_init (dirlist_browser, this_session.local_dir, "Root");

  return vbox;
}






static int
local_scandir_select (struct dirent *file_info)
{
  struct stat file_mode;

  if (!dirlist_hide_hidden)
    {
      if (file_info->d_name[0] == '.')
	switch (file_info->d_name[1])
	  {
	  case 0:
	    return 0;
	  case '.':
	    if (file_info->d_name[2] == 0)
	      return 0;
	  }
    }

  stat (file_info->d_name, &file_mode);

  if (!(file_info->d_name[0] == '.' && dirlist_hide_hidden))
    return 1;
  return 0;
}



static void
update_dirlist (char *pathname)
{
  GdkColor lnk_color, dir_color, file_color;
  GdkColormap *colormap;
  GdkPixmap *folderpix, *flinkpix, *dlinkpix, *parentpix;
  GdkBitmap *foldermsk, *flinkmsk, *dlinkmsk, *parentmsk;
  GtkStyle *non_propor_style_folder;
  GtkStyle *non_propor_style_link;
  GtkStyle *non_propor_style_file;
  GtkStyle *cell_style;
  GdkFont *new_font = gdk_font_load (CLIST_PROP_FONT);
  struct dirent **filelist;
  struct stat stat_buf;
  struct stat lstat_buf;
  struct passwd *pwd_buf;
  struct group *grp_buf;
  struct tm *timeptr;
  int files;
  register int f;
  gchar *col[7] =
  {"", "", "", "", "", "", ""};
  char size_buf[15];
  char time_buf[20];
  char mode_buf[20];
  char uid_buf[20];
  char gid_buf[20];
  int row;

  int (*sort_function) __P ((const void *, const void *));

  CURSOR_busy ();
  PROCESS_EVENTS;


  last_dir_row = 1;
  last_file_row = 0;
  search_row = 1;
  MEM0 (directory_search_string);
  total_size = 0;


  non_propor_style_folder = gtk_style_copy (GTK_WIDGET (clist)->style);
  gdk_font_unref (non_propor_style_folder->font);
  non_propor_style_folder->font = new_font;
  non_propor_style_folder->fg[GTK_STATE_NORMAL] = DIR_COLOR;

  non_propor_style_link = gtk_style_copy (GTK_WIDGET (clist)->style);
  gdk_font_unref (non_propor_style_link->font);
  non_propor_style_link->font = new_font;
  non_propor_style_link->fg[GTK_STATE_NORMAL] = LNK_COLOR;

  non_propor_style_file = gtk_style_copy (GTK_WIDGET (clist)->style);
  gdk_font_unref (non_propor_style_file->font);
  non_propor_style_file->font = new_font;
  non_propor_style_file->fg[GTK_STATE_NORMAL] = BLACK;



  folderpix = folder_pixmap (&foldermsk);
  parentpix = parent_pixmap (&parentmsk);
  dlinkpix = dlink_pixmap (&dlinkmsk);
  flinkpix = flink_pixmap (&flinkmsk);

  lnk_color = LNK_COLOR;
  dir_color = DIR_COLOR;
  file_color = BLACK;

  colormap = gtk_widget_get_colormap (window);
  gdk_color_alloc (colormap, &lnk_color);
  gdk_color_alloc (colormap, &dir_color);
  gdk_color_alloc (colormap, &file_color);

  if (strlen (pathname))
    chdir (pathname);
  gtk_clist_freeze (GTK_CLIST (clist));
  gtk_clist_clear (GTK_CLIST (clist));

  gtk_clist_append (GTK_CLIST (clist), col);
  gtk_clist_set_pixmap (GTK_CLIST (clist), 0, 0, parentpix, parentmsk);
  gtk_clist_set_selectable (GTK_CLIST (clist), 0, FALSE);


  switch (local_clist_sort)
    {
    case SORT_BY_NAME:
      sort_function = (local_clist_sort_type == SORT_DOWN) ? local_sort_by_name_down : local_sort_by_name_up;
      break;
    case SORT_BY_SIZE:
      sort_function = (local_clist_sort_type == SORT_DOWN) ? local_sort_by_size_down : local_sort_by_size_up;
      break;
    case SORT_BY_DATE:
      sort_function = (local_clist_sort_type == SORT_DOWN) ? local_sort_by_date_down : local_sort_by_date_up;
      break;
    case SORT_BY_PERM:
      sort_function = (local_clist_sort_type == SORT_DOWN) ? local_sort_by_perm_down : local_sort_by_perm_up;
      break;
    case SORT_BY_UID:
      sort_function = local_sort_by_uid;
      break;
    case SORT_BY_GID:
      sort_function = local_sort_by_gid;
      break;
    default:
      sort_function = alphasort;
      break;
    }


  files = scandir (pathname, &filelist, local_scandir_select, sort_function);
  for (f = 0; f < files; f++)
    {

      stat (filelist[f]->d_name, &stat_buf);
      lstat (filelist[f]->d_name, &lstat_buf);


      col[1] = filelist[f]->d_name;

      sprintf (size_buf, "%ld", lstat_buf.st_size);
      col[2] = size_buf;
      if ((stat_buf.st_mode & S_IFMT) != S_IFDIR)
	total_size += stat_buf.st_size;

      timeptr = localtime (&lstat_buf.st_mtime);
      strftime (time_buf, sizeof (time_buf), LOCAL_DATE_FORMAT, timeptr);
      col[3] = time_buf;

      StrMode (mode_buf, lstat_buf.st_mode);
      col[4] = mode_buf;

      if ((pwd_buf = getpwuid (lstat_buf.st_uid)) == NULL)
	{
	  sprintf (uid_buf, "%d", stat_buf.st_uid);
	  col[5] = uid_buf;
	}
      else
	col[5] = pwd_buf->pw_name;

      if ((grp_buf = getgrgid (lstat_buf.st_gid)) == NULL)
	{
	  sprintf (gid_buf, "%d", stat_buf.st_gid);
	  col[6] = gid_buf;
	}
      else
	col[6] = grp_buf->gr_name;

      if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)	// a dir

	{
	  if (this_session.local_filter_directories)
	    if (!FILTER_is_string_match (filter_search_type, col[1], filter_search_ptr))
	      continue;

	  row = last_dir_row++;
	  gtk_clist_insert (GTK_CLIST (clist), row, col);
	  if ((lstat_buf.st_mode & S_IFMT) != S_IFLNK)
	    {
	      cell_style = non_propor_style_folder;
	      gtk_clist_set_foreground (GTK_CLIST (clist), row, &dir_color);
	      gtk_clist_set_pixmap (GTK_CLIST (clist), row, 0, folderpix, foldermsk);
	    }
	  else
	    {
	      cell_style = non_propor_style_link;
	      gtk_clist_set_foreground (GTK_CLIST (clist), row, &lnk_color);
	      gtk_clist_set_pixmap (GTK_CLIST (clist), row, 0, dlinkpix, dlinkmsk);
	    }

	}
      else
	{
	  if (!FILTER_is_string_match (filter_search_type, col[1], filter_search_ptr))
	    continue;

	  row = last_dir_row + last_file_row++;
	  gtk_clist_insert (GTK_CLIST (clist), row, col);
	  if ((lstat_buf.st_mode & S_IFMT) != S_IFLNK)
	    {
	      cell_style = non_propor_style_file;
	      give_a_nice_icon_to_this_file (col[1], clist, row);
	    }
	  else
	    {
	      cell_style = non_propor_style_link;
	      gtk_clist_set_foreground (GTK_CLIST (clist), row, &lnk_color);
	      gtk_clist_set_pixmap (GTK_CLIST (clist), row, 0, flinkpix, flinkmsk);
	    }


	}

      gtk_clist_set_cell_style (GTK_CLIST (clist), row, 3, cell_style);
      gtk_clist_set_cell_style (GTK_CLIST (clist), row, 4, cell_style);

    }


  sprintf (label_info_text, " %i %s, %i %s, %ld %s listed.",
	   (last_dir_row - 1), last_dir_row > 2 ? "folders" : "folder",
	   last_file_row, last_file_row > 1 ? "files" : "file",
	   total_size, total_size > 1 ? "bytes" : "byte");
  gtk_label_set (GTK_LABEL (label_info), label_info_text);

  last_file_row += last_dir_row;


  update_combo (pathname);
  if (UPDATE_TOOLBAR)
    toolbar_buttons_set_sensitive ();
  if (UPDATE_POPUP_MENU)
    update_local_popup_menu (0);

  gtk_clist_thaw (GTK_CLIST (clist));
  CURSOR_default ();

  gdk_pixmap_unref (folderpix);
  gdk_pixmap_unref (foldermsk);
  gdk_pixmap_unref (flinkpix);
  gdk_pixmap_unref (flinkmsk);
  gdk_pixmap_unref (dlinkpix);
  gdk_pixmap_unref (dlinkmsk);
  gdk_pixmap_unref (parentpix);
  gdk_pixmap_unref (parentmsk);
}




void
refresh_dirlist (void)
{
  char path[MPLEN];
  getcwd (path, sizeof (path));
  update_dirlist (path);
}

static void
dirlist_cdup (GtkWidget * widget, gpointer data)
{
  chdir ("..");
  refresh_dirlist ();
}

void
toggle_local_hidden (void)
{
  dirlist_hide_hidden = !dirlist_hide_hidden;
  refresh_dirlist ();
}

void
toggle_local_columns_visibility (void)
{
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 2, user_rc.view_local_files_size);
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 3, user_rc.view_local_files_date);
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 4, user_rc.view_local_files_perm);
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 5, user_rc.view_local_files_owner);
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 6, user_rc.view_local_files_group);
}


static void
dirlist_selection_made (GtkWidget * this_list, gint row, gint column,
			GdkEventButton * event, gpointer data)
{
  gint selected;

  if ((selected = local_selection_info ()))
    {
      char label_buf[100];
      long selection_size = local_selection_size ();
      sprintf (label_buf, "%i %s, %ld %s selected.",
	       selected, selected > 1 ? "files" : "file",
	       selection_size, selection_size > 1 ? "bytes" : "byte");
      gtk_label_set (GTK_LABEL (label_info), label_buf);
    }
  else
    gtk_label_set (GTK_LABEL (label_info), label_info_text);

  if (UPDATE_TOOLBAR)
    toolbar_buttons_set_sensitive ();
  if (UPDATE_POPUP_MENU)
    update_local_popup_menu (selected);
  if (selected == 1)
    update_local_popup_menu_execute (local_selected_is_executable ());
  queue_popup_menu_set_sensitive ();
}


static gint
dirlist_event_handler (GtkWidget * this_list, GdkEvent * event, gpointer data)
{
  switch (event->type)
    {
    case GDK_BUTTON_PRESS:
      switch (event->button.button)
	{

	case 1:
	  if (PANEL_FOCUS != LOCAL_FOCUS)
	    {
	      PANEL_FOCUS = LOCAL_FOCUS;
	      remote_unselect_all (NULL, NULL);
	      local_focus_update ();
	      remote_focus_update ();
	    }
	  break;

	case 3:
	  {
	    GdkEventButton *bevent = (GdkEventButton *) event;
	    gtk_menu_popup (GTK_MENU (local_popup_menu), NULL, NULL, NULL, NULL,
			    bevent->button, bevent->time);
	    return TRUE;
	  }
	  break;

	default:
	  break;
	}
      break;

    case GDK_2BUTTON_PRESS:
      switch (event->button.button)
	{
	case 1:
	  {
	    int this_row = GTK_CLIST (this_list)->focus_row;
	    gchar *buf = NULL;

	    if (this_row < 0)
	      return FALSE;

	    if (this_row >= last_dir_row)
	      {
		local_selected_is_executable ()? local_exec () : local_file_view ();
	      }
	    else
	      {
		gtk_clist_get_text (GTK_CLIST (this_list), this_row, 1, &buf);
		if (buf == NULL)
		  return FALSE;
		if (this_row == 0)
		  strcpy (buf, "..");
		chdir (buf);
		refresh_dirlist ();
	      }
	    return TRUE;
	  }
	  break;

	default:
	  break;
	}


    default:
      break;
    }
  return FALSE;
}




static void
sort_button_clicked (gint column)
{

  if (clist_col_sort == column)
    local_clist_sort_type = !local_clist_sort_type;
  else
    {
      gtk_widget_hide (sort_arrow[(int) clist_col_sort]);
      gtk_widget_show (sort_arrow[column]);
      local_clist_sort_type = SORT_DOWN;
    }
  clist_col_sort = column;

  clist_title_with_arrow_set_up_dow (sort_arrow[column], (local_clist_sort_type == SORT_UP));

  switch (column)
    {
    case DIR_COL_SORT_BY_NAME:
      local_clist_sort = SORT_BY_NAME;
      break;
    case DIR_COL_SORT_BY_SIZE:
      local_clist_sort = SORT_BY_SIZE;
      break;
    case DIR_COL_SORT_BY_DATE:
      local_clist_sort = SORT_BY_DATE;
      break;
    case DIR_COL_SORT_BY_PERM:
      local_clist_sort = SORT_BY_PERM;
      break;
    case DIR_COL_SORT_BY_UID:
      local_clist_sort = SORT_BY_UID;
      break;
    case DIR_COL_SORT_BY_GID:
      local_clist_sort = SORT_BY_GID;
      break;
    }

  if (UPDATE_POPUP_MENU_SORT)
    {
      UPDATE_POPUP_MENU_SORT = FALSE;
      update_local_popup_menu_sort ();
      UPDATE_POPUP_MENU_SORT = TRUE;
    }
  if (UPDATE_POPUP_MENU_SORT_TYPE)
    {
      UPDATE_POPUP_MENU_SORT_TYPE = FALSE;
      update_local_popup_menu_sort_type ();
      UPDATE_POPUP_MENU_SORT_TYPE = TRUE;
    }


  refresh_dirlist ();
}


void
local_sort_from_menu (GtkWidget * widget, gint column)
{
  if (!UPDATE_POPUP_MENU_SORT)
    return;
  if (clist_col_sort == column)
    return;
  UPDATE_POPUP_MENU_SORT = FALSE;
  sort_button_clicked (column);
  UPDATE_POPUP_MENU_SORT = TRUE;
}

void
local_sort_type_from_menu (GtkWidget * widget, int data)
{
  if (!UPDATE_POPUP_MENU_SORT_TYPE)
    return;
  if (local_clist_sort_type == (int) data)
    return;

  local_clist_sort_type = (int) data;
  UPDATE_POPUP_MENU_SORT_TYPE = FALSE;
  if (clist != NULL)
    {
      clist_title_with_arrow_set_up_dow (sort_arrow[(int) clist_col_sort], (local_clist_sort_type == SORT_UP));
      refresh_dirlist ();
    }
  UPDATE_POPUP_MENU_SORT_TYPE = TRUE;
}


static void
dirlist_button_clicked (GtkCList * clist, gint column)
{
  switch (column)
    {
    case 0:
      refresh_dirlist ();
      break;
    default:
      sort_button_clicked (column);
    }
}





/* SELECTION  INFO */

/* PUBLIC :
 * local_selection_info : return number of selected files (0 if none)
 * STATIC :
 * local_selection_size : return total size of selected files
 */

gint
local_selection_info (void)
{
  GList *selection;

  if (clist == NULL)
    return 0;
  if ((selection = GTK_CLIST (clist)->selection) == NULL)
    return 0;
  return g_list_length (selection);
}

static long
local_selection_size (void)
{
  GList *selection;
  long selection_size = 0;
  gchar *filesize;
  int index;

  if ((selection = GTK_CLIST (clist)->selection) == NULL)
    return 0;
  while (selection)
    {
      index = GPOINTER_TO_INT (selection->data);
      gtk_clist_get_text (GTK_CLIST (clist), index, 2, &filesize);
      selection_size += atol (filesize);
      selection = selection->next;
    }
  return selection_size;
}


static char
local_selected_is_executable (void)
{
  int this_row = 0;
  GList *selection = GTK_CLIST (clist)->selection;

  if (selection != NULL)
    {
      this_row = (int) selection->data;
    }
  else
    {
      if (GTK_CLIST (clist)->focus_row)
	this_row = GTK_CLIST (clist)->focus_row;
    }

  if (this_row)
    {
      gchar *filename;
      gchar *fileperm;
      gtk_clist_get_text (GTK_CLIST (clist), this_row, 1, &filename);
      gtk_clist_get_text (GTK_CLIST (clist), this_row, 4, &fileperm);
      return (!is_a_dir (filename) && strchr (fileperm, 'x') != NULL);
    }
  return FALSE;
}


char
local_get_fileinfo (char *search_filename, FILEINFO * file_info)

{
  gchar *filename;
  gchar *filesize;
  gchar *filedate;
  register int index = 1;

  while (index < last_file_row)
    {
      gtk_clist_get_text (GTK_CLIST (clist), index, 1, &filename);
      if (!strcmp (filename, search_filename))
	{
	  gtk_clist_get_text (GTK_CLIST (clist), index, 2, &filesize);
	  file_info->filesize = strtol (filesize, NULL, 10);
	  gtk_clist_get_text (GTK_CLIST (clist), index, 3, &filedate);
	  strcpy (file_info->filedate, filedate);
	  return TRUE;
	}
      index++;
    }
  return FALSE;
}





/* FOCUS info */

void
local_focus_update (void)
{
  GtkStyle *style = gtk_style_new ();
  style->bg[GTK_STATE_ACTIVE] = (PANEL_FOCUS == LOCAL_FOCUS) ? LICE : SGREY;
  style->bg[GTK_STATE_NORMAL] = (PANEL_FOCUS == LOCAL_FOCUS) ? GREYCYAN : SLGREY;
  style->bg[GTK_STATE_PRELIGHT] = (PANEL_FOCUS == LOCAL_FOCUS) ? GREYCYAN : SLGREY;
  gtk_widget_set_style (GTK_SCROLLED_WINDOW (clist_window)->hscrollbar, style);
}






/* DIRECTORY COMBO */

/* STATIC :
 * update_combo 
 * dir_combo_new_selection
 * dir_combo_new_char_entered
 */

static void
update_combo (char *pathname)
{
  char *ptr;
  GList *list = combo_items;

  while (list)
    {
      ptr = list->data;
      if (!strcmp (ptr, pathname))
	{
	  gtk_entry_set_text (DIR_COMBO_ENTRY, pathname);
	  return;
	}
      list = list->next;
    }

  if (combo_items == NULL)
    combo_items = g_list_append (combo_items, strdup (pathname));
  else
    combo_items = g_list_insert (combo_items, strdup (pathname), 0);
  gtk_combo_set_popdown_strings (GTK_COMBO (combo), combo_items);
}


static void
dir_combo_new_selection (GtkWidget * widget)
{
  gchar *ptr;
  char path[1024];

  gtk_widget_hide (GTK_COMBO (combo)->popwin);
  gtk_grab_remove (GTK_COMBO (combo)->popwin);

  getcwd (path, sizeof (path));
  ptr = gtk_entry_get_text (DIR_COMBO_ENTRY);

  if (ptr[strlen (ptr) - 1] == '/')
    ptr[strlen (ptr) - 1] = 0;

  if (strcmp (ptr, path) && !access (ptr, F_OK))
    {
      strcpy (path, ptr);
      update_dirlist (path);
      if (BROWSER_VISIBLE)
	browser_disable ();
    }
}


static void
dir_combo_new_char_entered (GtkWidget * widget)
{
  gchar *ptr = gtk_entry_get_text (DIR_COMBO_ENTRY);
  GtkStyle *style = gtk_style_new ();

  style->fg[GTK_STATE_NORMAL] = access (ptr, F_OK) ? GREY : BLACK;
  gtk_widget_set_style (GTK_WIDGET (DIR_COMBO_ENTRY), style);
}








/* DIRECTORY BROWSER */

/* STATIC
 * browser_enable : show it and point on current dir
 * browser_disable : hide it
 * browser_hide : hide it and update dirlist
 * browser_show : call browser_enable 
 * browser_path_selected : call brower_hide on double click
 */

static void
browser_enable (void)
{
  char path[1024];
  getcwd (path, sizeof (path));
  gtk_widget_hide (button_browser_open);
  gtk_widget_hide (prompt_entry);
  gtk_widget_hide (frame_info);
  gtk_widget_hide (clist_window);
  gtk_widget_show (button_browser_close);
  gtk_widget_show (browser_window);
  BROWSER_VISIBLE = TRUE;
  DIR_TREE_show_path (dirlist_browser, path);
}

static void
browser_disable (void)
{
  gtk_widget_show (button_browser_open);
  gtk_widget_show (prompt_entry);
  gtk_widget_show (frame_info);
  //gtk_paned_set_position (GTK_PANED (top_panel), top_pane_pos);
  gtk_widget_hide (browser_window);
  gtk_widget_show (clist_window);
  gtk_widget_hide (button_browser_close);
  BROWSER_VISIBLE = FALSE;
}

static void
browser_hide (GtkWidget * widget, gpointer data)
{
  gchar *path_buf;

  gtk_label_get (GTK_LABEL (dirlist_browser_label), &path_buf);
  browser_disable ();
  update_dirlist (path_buf);
}

static void
browser_show (GtkWidget * widget, gpointer data)
{
  browser_enable ();
}


static gint
browser_event_handler (GtkWidget * widget, GdkEvent * event, gpointer data)
{
  switch (event->type)
    {
    case GDK_2BUTTON_PRESS:
      switch (event->button.button)
	{
	case 1:
	  gtk_grab_remove (GTK_WIDGET (dirlist_browser));
	  browser_hide (NULL, NULL);
	  return TRUE;
	  break;

	default:
	  break;
	}
      break;

    default:
      break;
    }
  return FALSE;
}





/* COMMAND PROMPT */

/* PUBLIC:
 * show_or_hide_shell_prompt
 * STATIC:
 * execute_user_command
 */

static void
execute_user_command (GtkWidget * entry, GdkEventKey * event, gpointer data)
{
  char user_command[100];
  int exit_code;
  char buf[256];

  if (event->keyval != GDK_Return)
    return;

  strcpy (user_command, gtk_entry_get_text (GTK_ENTRY (entry)));
  gtk_entry_set_text (GTK_ENTRY (entry), "");

  exit_code = system (user_command);

  if (!exit_code)
    {
      sprintf (buf, "Successful shell command : %s", user_command);
      status_message (buf);
      if (strstr (user_command, "cd ") == user_command)
	chdir (user_command + 3);
      refresh_dirlist ();
    }
  else
    {
      sprintf (buf, "Shell report error executing : %s", user_command);
      status_message (buf);
    }
}


void
show_or_hide_shell_prompt (GtkWidget * widget)
{
  show_hide_widget (prompt_entry, GTK_CHECK_MENU_ITEM (widget)->active);
}










/* LOCAL EXEC  FUNCTIONS */

/* PUBLIC:
 * local_file_view
 * local_file_edit 
 * local_exec
 * STATIC :
 * locale_file_view_or_edit
 */

static void
local_file_view_or_edit (char WANT_EDIT)
{
  GList *selection = GTK_CLIST (clist)->selection;
  int this_row = GTK_CLIST (clist)->focus_row;
  gchar *filename;

  if (selection != NULL)
    this_row = (int) selection->data;
  if (!this_row)
    return;

  gtk_clist_get_text (GTK_CLIST (clist), this_row, 1, &filename);

  if (is_a_dir (filename))
    {
      WANT_EDIT ? local_rename_dialog (NULL, NULL) : chdir (filename);
      refresh_dirlist ();
      return;
    }
  else
    local_execute_view_or_edit_file (g_strdup (filename), WANT_EDIT);
}

void
local_file_view (void)
{
  local_file_view_or_edit (FALSE);
}

void
local_file_edit (void)
{
  local_file_view_or_edit (TRUE);
}


void
local_exec (void)
{
  GList *selection = GTK_CLIST (clist)->selection;
  int this_row = GTK_CLIST (clist)->focus_row;
  gchar *filename;
  char current_path[1024];
  char absolute_filename[1024];

  if (selection != NULL)
    this_row = (int) selection->data;
  if (!this_row)
    return;

  gtk_clist_get_text (GTK_CLIST (clist), this_row, 1, &filename);
  getcwd (current_path, sizeof (current_path));
  sprintf (absolute_filename, "%s/%s", current_path, filename);
  execute_program (absolute_filename, NULL);
}










/* LOCAL COMMAND FUNCTIONS */

/* STATIC :
 * local_dir_recurse_chmod 
 * local_chmod
 * local_rename
 * local_move
 * local_dir_recurse_delete_file
 * local_dir_recurse_delete_dir
 * local_delete 
 * local_create_directory
 * local_change_directory
 * PUBLIC : (call STATIC above)
 * local_chmod_dialog 
 * local_rename_dialog
 * local_move_dialog
 * local_delete_dialog 
 * local_create_directory_dialog 
 * local_change_directory_dialog 
 */

/* CHMOD */

static char
local_dir_recurse_chmod (char *filename)
{
  status_message_with_arg ("Chmod", filename);
  if (chmod (filename, chmod_mode) == -1)
    return 0;
  return 1;
}

static void
local_chmod (GtkWidget * widget, GtkWidget * entry)
{
  GtkWidget *alert_window = gtk_widget_get_toplevel (widget);
  GList *selection = GTK_CLIST (clist)->selection;
  gchar *filename;
  int index;
  char buf[5];
  char ERROR_FLAG = FALSE;

  strcpy (buf, gtk_entry_get_text (GTK_ENTRY (entry)));
  gtk_widget_destroy (alert_window);
  CURSOR_MAIN_busy ();
  PROCESS_EVENTS;

  chmod_mode = strtol (buf, NULL, 8);

  while (selection)
    {
      index = (int) selection->data;
      gtk_clist_get_text (GTK_CLIST (clist), index, 1, &filename);

      if (!(is_a_dir (filename)))
	{
	  if (chmod (filename, chmod_mode) == -1)
	    ERROR_FLAG = TRUE;
	}
      else
	{
	  char msg_buf[1024];
	  sprintf (msg_buf, "%s is a directory,\nChmod it recursively?", filename);
	  if (alert_ok_cancel_modal ("Local Chmod", msg_buf, "Ok"))
	    {
	      if (!recurse_dir (filename, (DirRecurseFunc) local_dir_recurse_chmod, (DirRecurseFunc) local_dir_recurse_chmod))
		ERROR_FLAG = TRUE;
	    }

	  if (chmod (filename, chmod_mode) == -1)
	    ERROR_FLAG = TRUE;
	}

      status_message_with_arg ("Chmod", filename);
      selection = selection->next;
    }

  refresh_dirlist ();
  if (ERROR_FLAG)
    alert_ok ("Error", "Some error(s) occured\nwhen trying to chmod file(s).", "Ok");
  default_status_message ();
  CURSOR_MAIN_default ();
}



void
local_chmod_dialog (GtkWidget * widget, gpointer data)
{
  gint selected;

  if (!(selected = local_selection_info ()))
    return;

  if (selected > 1)
    chmod_dialog ("Local Chmod", "0666", GTK_SIGNAL_FUNC (local_chmod));
  else
    {
      GList *selection = GTK_CLIST (clist)->selection;
      gchar *filemode;
      char buf_mode[5];

      gtk_clist_get_text (GTK_CLIST (clist), GPOINTER_TO_INT (selection->data), 4, &filemode);
      StrNumMode (buf_mode, filemode);
      chmod_dialog ("Local Chmod", buf_mode, GTK_SIGNAL_FUNC (local_chmod));
    }
}


/* RENAME */

static void
local_rename (GtkWidget * widget, GtkWidget * entry)
{
  GtkWidget *alert_window = gtk_widget_get_toplevel (entry);
  GList *selection = GTK_CLIST (clist)->selection;
  gchar *oldfilename;
  char buf[1024];

  strcpy (buf, gtk_entry_get_text (GTK_ENTRY (entry)));
  gtk_widget_destroy (alert_window);

  gtk_clist_get_text (GTK_CLIST (clist), (int) selection->data, 1, &oldfilename);

  if (!strlen (buf))
    alert_ok ("Error", "No name specified", "Ok");

  else if (!strcmp (oldfilename, buf))
    alert_ok ("Error", "Old and new filename are the same", "Ok");

  else
    {
      if ((rename (oldfilename, buf) < 0))
	{
	  char msg_buf[1024];
	  sprintf (msg_buf, "Can't rename  : %s", oldfilename);
	  alert_ok ("Error", msg_buf, "Ok");
	}
      else
	refresh_dirlist ();
    }
}


void
local_rename_dialog (GtkWidget * widget, gpointer data)
{
  GList *selection = GTK_CLIST (clist)->selection;
  gchar *filename;

  if (!(local_selection_info ()))
    return;

  gtk_clist_get_text (GTK_CLIST (clist), (int) selection->data, 1, &filename);
  entry_dialog ("Local Rename", "Rename file to :", "Rename", filename, GTK_SIGNAL_FUNC (local_rename));
}


/* MOVE */

static void
local_move (GtkWidget * widget, GtkWidget * entry)
{
  GtkWidget *alert_window = gtk_widget_get_toplevel (entry);
  GList *selection = GTK_CLIST (clist)->selection;
  gchar *filename;
  char path[1024];
  char buf[1024];
  int index;
  char ERROR_FLAG = FALSE;
  char OVERWRITE_ALL = FALSE;

  strcpy (path, gtk_entry_get_text (GTK_ENTRY (entry)));
  gtk_widget_destroy (alert_window);

  if (!strlen (path))
    alert_ok ("Error", "No directory specified", "Ok");

  else if (!is_a_dir (path))
    {
      sprintf (buf, "%s is not a directory.", path);
      alert_ok ("Error", buf, "Ok");
    }

  else
    {
      if (path[strlen (path) - 1] != '/')
	strcat (path, "/");

      CURSOR_MAIN_busy ();

      while (selection)
	{
	  index = (int) selection->data;
	  gtk_clist_get_text (GTK_CLIST (clist), index, 1, &filename);
	  sprintf (buf, "%s%s", path, filename);
	  status_message_with_arg ("Moving", filename);

	  if (!access (buf, F_OK) && !OVERWRITE_ALL)
	    {
	      char msg_buf[1024];
	      sprintf (msg_buf, "%s\n already exists ...", buf);
	      switch (alert_overwrite_modal ("Local Move", msg_buf))
		{
		case DUP_skip:
		  break;
		case DUP_overwrite_all:
		  OVERWRITE_ALL = TRUE;
		case DUP_overwrite:
		  if (rename (filename, buf) < 0)
		    ERROR_FLAG = TRUE;
		  break;
		case DUP_abort:
		default:
		  refresh_dirlist ();
		  default_status_message ();
		  CURSOR_MAIN_default ();
		  return;
		}
	    }
	  else
	    {
	      if (rename (filename, buf) < 0)
		ERROR_FLAG = TRUE;
	    }

	  selection = selection->next;
	}

      refresh_dirlist ();
      default_status_message ();
      if (ERROR_FLAG)
	alert_ok ("Error", "Some error(s) occured\nwhen trying to move file(s).", "Ok");
      CURSOR_MAIN_default ();
    }
}


void
local_move_dialog (GtkWidget * widget, gpointer data)
{
  if (!(local_selection_info ()))
    return;
  entry_dialog_with_browser ("Local Move", "Move file(s) to :", "Move", "", GTK_SIGNAL_FUNC (local_move));
}




/* DELETE */

static char
local_dir_recurse_delete_file (char *filename)
{
  status_message_with_arg ("Deleting", filename);
  if (unlink (filename) == -1)
    return 0;
  return 1;
}

static char
local_dir_recurse_delete_dir (char *filename)
{
  status_message_with_arg ("Deleting", filename);
  rmdir (filename);
  return 1;
}

static void
local_delete (GtkWidget * widget, GtkWidget * alert_button)
{
  GtkWidget *alert_window = gtk_widget_get_toplevel (alert_button);
  GList *selection = GTK_CLIST (clist)->selection;
  gchar *filename;
  gchar *permission;
  int index;
  char ERROR_FLAG = FALSE;

  gtk_widget_destroy (alert_window);
  CURSOR_MAIN_busy ();

  while (selection)
    {
      index = (int) selection->data;
      gtk_clist_get_text (GTK_CLIST (clist), index, 1, &filename);
      gtk_clist_get_text (GTK_CLIST (clist), index, 4, &permission);

      status_message_with_arg ("Deleting", filename);
      while (gtk_events_pending ())
	gtk_main_iteration ();

      if (!(*permission == 'd'))
	{
	  if (unlink (filename) == -1)
	    ERROR_FLAG = TRUE;
	}
      else
	{
	  if (rmdir (filename) == -1)
	    {
	      char msg_buf[1024];
	      sprintf (msg_buf, "%s is a directory,\nDELETE it recursively?", filename);
	      if (alert_ok_cancel_modal ("Local Delete", msg_buf, "Ok"))
		{
		  if (!recurse_dir (filename,
			     (DirRecurseFunc) local_dir_recurse_delete_file,
			     (DirRecurseFunc) local_dir_recurse_delete_dir))
		    ERROR_FLAG = TRUE;
		}


	      if (rmdir (filename) == -1)
		ERROR_FLAG = TRUE;

	    }
	}
      selection = selection->next;
    }

  refresh_dirlist ();
  if (ERROR_FLAG)
    alert_ok ("Error", "Some error(s) occured\nwhen trying to delete file(s).", "Ok");
  default_status_message ();
  CURSOR_MAIN_default ();
}


void
local_delete_dialog (GtkWidget * widget, gpointer data)
{
  gint selected;
  char msg_buf[1024];

  if (!(selected = local_selection_info ()))
    return;

  if (selected == 1)
    {
      GList *selection = GTK_CLIST (clist)->selection;
      gchar *filename;
      gtk_clist_get_text (GTK_CLIST (clist), (int) selection->data, 1, &filename);
      sprintf (msg_buf, "Delete %s ?", filename);
    }
  else
    sprintf (msg_buf, "Delete %i file(s), %ld byte(s) ?", selected, local_selection_size ());
  alert_ok_cancel ("Local Delete", msg_buf, "Delete", GTK_SIGNAL_FUNC (local_delete));
}



/* CREATE DIRECTORY */

static void
local_create_directory (GtkWidget * widget, GtkWidget * entry)
{
  GtkWidget *alert_window = gtk_widget_get_toplevel (entry);
  char buf[1024];

  strcpy (buf, gtk_entry_get_text (GTK_ENTRY (entry)));
  gtk_widget_destroy (alert_window);

  if (!strlen (buf))
    alert_ok ("Error", "No directory name specified", "Ok");
  else
    {
      if ((mkdir (buf, 0755) < 0))
	{
	  char msg_buf[1024];
	  sprintf (msg_buf, "Can't create directory : %s", buf);
	  alert_ok ("Error", msg_buf, "Ok");
	}
      else
	refresh_dirlist ();
    }
}


void
local_create_directory_dialog (GtkWidget * widget, gpointer data)
{
  entry_dialog ("Create Local Directory", "Directory name :", "Create", "", GTK_SIGNAL_FUNC (local_create_directory));
}


/* CHANGE DIRECTORY */

static void
local_change_directory (GtkWidget * widget, GtkWidget * entry)
{
  GtkWidget *alert_window = gtk_widget_get_toplevel (entry);
  char buf[1024];

  strcpy (buf, gtk_entry_get_text (GTK_ENTRY (entry)));
  gtk_widget_destroy (alert_window);

  if (!strlen (buf))
    alert_ok ("Error", "No directory name specified", "Ok");
  else
    {
      if ((chdir (buf) < 0))
	{
	  char msg_buf[1024];
	  sprintf (msg_buf, "Can't change to directory :\n %s", buf);
	  alert_ok ("Error", msg_buf, "Ok");
	}
      else
	refresh_dirlist ();
    }
}


void
local_change_directory_dialog (GtkWidget * widget, gpointer data)
{
  entry_dialog_with_browser ("Change Local Directory", "Directory name :", "Change", "", GTK_SIGNAL_FUNC (local_change_directory));
}






/* UPLOAD SELECTION  */

/* PUBLIC :
 * upload_selection
 * STATIC : 
 * upload_selection_recursive
 */

static char
upload_selection_recursive (void)
{

  GdkColor done_color = GREYCYAN;
  GdkColormap *colormap;
  GList *selection = GTK_CLIST (clist)->selection;
  gchar *filename;
  gchar *filesize;
  gchar *filedate;
  gchar *fileperm;
  int index;
  FILE *tmp;
  char tmp_filename[256];
  char DIR_FOUND_IN_SELECTION = FALSE;
  char *current_remote_dir = strdup (this_session.cwd_dir);
  char current_local_dir[MPLEN];

  getcwd (current_local_dir, sizeof (current_local_dir));

  tmpnam (tmp_filename);
  tmp = fopen (tmp_filename, "w");

  colormap = gtk_widget_get_colormap (window);
  gdk_color_alloc (colormap, &done_color);

  while (selection && (!xfer_abort) && (!want_abort))
    {
      index = (int) selection->data;
      gtk_clist_set_background (GTK_CLIST (clist), index, &done_color);
      gtk_clist_get_text (GTK_CLIST (clist), index, 1, &filename);
      gtk_clist_get_text (GTK_CLIST (clist), index, 2, &filesize);
      gtk_clist_get_text (GTK_CLIST (clist), index, 3, &filedate);
      gtk_clist_get_text (GTK_CLIST (clist), index, 4, &fileperm);

      if (is_a_dir (filename))
	{
	  DIR_FOUND_IN_SELECTION = TRUE;
	  selection = selection->next;
	  fprintf (tmp, "%s,%s,%s\n", fileperm, filename, filedate);
	}
      else
	{
	  if (IGLOO_upload (filename, filesize, filedate, fileperm))
	    {
	      selection = selection->next;
	      gtk_clist_unselect_row (GTK_CLIST (clist), index, 0);
	      gtk_clist_moveto (GTK_CLIST (clist), index, 0, 0.5, 0);
	    }
	  CHECK_CONNEXION;
	}

    }
  fclose (tmp);


  if (DIR_FOUND_IN_SELECTION)
    {
      char this_line[1024];
      char local_path[MPLEN];
      char *path_ptr;
      char *date_ptr;

      tmp = fopen (tmp_filename, "r");
      while (fgets (this_line, sizeof (this_line) - 1, tmp) != NULL)
	{

	  if (this_line[strlen (this_line) - 1] == '\n')
	    this_line[strlen (this_line) - 1] = 0;

	  path_ptr = (char *) (strchr (this_line, ',') + 1);
	  date_ptr = strrchr (this_line, ',');
	  *(date_ptr++) = 0;

	  strcpy (local_path, path_ptr);

	  switch (this_session.uploads_filename)
	    {
	    case XFER_FILENAME_UPPER:
	      strupr (path_ptr);
	      break;
	    case XFER_FILENAME_LOWER:
	      strlwr (path_ptr);
	      break;
	    default:
	      break;
	    }

	  IGLOO_mkd (path_ptr);
	  CHECK_CONNEXION;

	  if (this_session.uploads_date)
	    {
	      struct utimbuf buf;
	      buf.actime = time (NULL);
	      buf.modtime = time (NULL);
	      utime (local_path, &buf);
	    }

	  if ((chdir (local_path) == 0) && IGLOO_cwd (path_ptr))
	    {
	      CHECK_CONNEXION;
	      refresh_dirlist ();
	      gtk_clist_select_all (GTK_CLIST (clist));
	      upload_selection_recursive ();
	    }

	  update_dirlist (current_local_dir);
	  FTP_CWD (&this_connexion, current_remote_dir);
	  CHECK_CONNEXION;

	  if (this_session.uploads_perm)
	    if (fileperm != NULL)
	      {
		char buf_mode[5];
		StrNumMode (buf_mode, this_line);
		IGLOO_chmod (path_ptr, buf_mode);
		CHECK_CONNEXION;
	      }

	  strcpy (this_session.cwd_dir, current_remote_dir);
	}
      fclose (tmp);
    }

  unlink (tmp_filename);
  free (current_remote_dir);
  return TRUE;
}



void
upload_selection (GtkWidget * widget, gpointer data)
{

  if (!(local_selection_info ()))
    return;

  CURSOR_MAIN_busy ();

  active_dir_panel (FALSE);
  active_ftp_panel (FALSE);
  toolbar_xfer_buttons_set_sensitive (FALSE);

  want_abort = FALSE;
  xfer_abort = FALSE;
  xfer_skip = FALSE;
  xfer_overwrite = FALSE;
  IDLE_END;
  CHECK_CONNEXION_VOID;


  upload_selection_recursive ();


  refresh_ftplist ();
  default_status_message ();

  IDLE_START;

  active_dir_panel (TRUE);
  active_ftp_panel (TRUE);
  want_abort = FALSE;

  CURSOR_MAIN_default ();
}







/* QUEUE Functions */

/* PUBLIC:
 * queue_selection_for_upload
 * queue_upload_selection 
 */

void
queue_selection_for_upload (void)
{
  GList *selection = GTK_CLIST (clist)->selection;
  gchar *filename;
  gchar *filesize;
  gchar *filedate;
  int index;

  CURSOR_MAIN_busy ();

  while (selection != NULL)
    {
      index = GPOINTER_TO_INT (selection->data);

      gtk_clist_get_text (GTK_CLIST (clist), index, 1, &filename);
      gtk_clist_get_text (GTK_CLIST (clist), index, 2, &filesize);
      gtk_clist_get_text (GTK_CLIST (clist), index, 3, &filedate);

      QUEUE_add_file (filename, filesize, is_a_dir (filename), QUEUE_UPLOAD);

      selection = selection->next;
      gtk_clist_set_background (GTK_CLIST (clist), index, &GREYCYAN);
      /*
         {
         GtkStyle *cell_style = gtk_clist_get_cell_style (GTK_CLIST (clist), index, 3);
         cell_style->base[GTK_STATE_NORMAL]=GREYCYAN;
         gtk_clist_set_cell_style (GTK_CLIST (clist), index, 3, cell_style);
         gtk_clist_set_cell_style (GTK_CLIST (clist), index, 4, cell_style);
         }
       */
      gtk_clist_unselect_row (GTK_CLIST (clist), index, 0);
    }

  CURSOR_MAIN_default ();
}


char
queue_upload_selection (char *search_filename, char IS_DIR)
{
  gchar *filename;
  gchar *fileperm;
  register int index = 1;

  CURSOR_MAIN_busy ();

  gtk_clist_unselect_all (GTK_CLIST (clist));

  while (index < last_file_row)
    {
      gtk_clist_get_text (GTK_CLIST (clist), index, 1, &filename);
      if (!strcmp (filename, search_filename))
	{
	  gtk_clist_get_text (GTK_CLIST (clist), index, 4, &fileperm);
	  if ((fileperm[0] == 'd') == IS_DIR)
	    {
	      char return_code;
	      gtk_clist_select_row (GTK_CLIST (clist), index, 0);
	      return_code = upload_selection_recursive ();
	      CURSOR_MAIN_default ();
	      return return_code;
	    }
	}
      index++;
    }

  CURSOR_MAIN_default ();
  return FALSE;
}


/* EOF */
