/* 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 <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <utime.h>
#include <errno.h>


#include "protos.h"
#include "ftplist.h"
#include "ftp_tree.h"
#include "remote_sort.h"
#include "remote_select.h"



/* FTPLIST */

/* PUBLIC:
   * remote_popup_menu_enable_disable
   * remote_toolbar_enable_disable
   * show_or_hide_ftp_prompt 
   * active_ftp_panel
   * clear_ftplist
   * reset_ftp_sort_options
   * create_ftplist
   * update_ftplist
   * refresh_ftplist
   * toggle_remote_hidden
   * toggle_remote_columns_visibility
   * toggle_resolve_links 
   * show_progress_list 
   * STATIC:
   * ftplist_cdup
   * ftplist_selection_made 
   * clist_event_handler
   * clist_button_clicked  
 */

void
show_or_hide_ftp_panel (GtkWidget * widget)
{

  show_hide_widget (ftp_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 : main_window_width);


  update_view_local_remote_menu ();
}

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

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

void
hide_ftp_panel (char FLAG)
{
  show_hide_widget (ftplist_box, FLAG);
}

void
active_ftp_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);

  if (FLAG)
    {
      update_remote_popup_menu (0);
      remote_popup_menu_enable ();
      remote_toolbar_enable ();
      toolbar_buttons_set_sensitive ();
    }
  else
    {
      remote_popup_menu_set_sensitive (FLAG);
      remote_popup_menu_disable ();
      remote_toolbar_disable ();
    }

}


void
clear_ftplist (void)
{
  gtk_clist_clear (GTK_CLIST (clist));

  gtk_label_set (GTK_LABEL (label_info), " ");

  clear_combo ();

  update_remote_popup_menu (FALSE);

  if (browser_window != NULL)
    browser_hide ();

  PANEL_FOCUS = LOCAL_FOCUS;
  local_focus_update ();
  remote_focus_update ();


  active_ftp_panel (FALSE);
}



void
reset_ftp_sort_options (void)
{
  register int f;

  clist_col_sort = FTP_COL_SORT_BY_NAME;
  remote_clist_sort = SORT_BY_NAME;
  remote_clist_sort_type = SORT_DOWN;

  for (f = 1; f < MAX_FTP_COL; f++)
    {
      gtk_widget_hide (sort_arrow[f]);
      clist_title_with_arrow_set_up_dow (sort_arrow[f], FALSE);
    }
  gtk_widget_show (sort_arrow[(int) clist_col_sort]);

}


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

  clist_col_sort = FTP_COL_SORT_BY_NAME;


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

  ftp_panel_box = frame = gtk_vbox_new (FALSE, 0);

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


  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);

  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);

  button_manager = browser_button (MANAGER_BUTTON_CLOSE);
  GTK_BUTTON (button_manager)->relief = GTK_RELIEF_NONE;
  gtk_box_pack_start (GTK_BOX (hbox), button_manager, FALSE, TRUE, 0);

  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 (ftplist_cdup), NULL);


  /* -- browser -- */
  browser_box = hbox = h_box (vbox, FALSE, 0, 0);


  /* -- filelist -- */
  FTP_clist = clist = gtk_clist_new_with_titles (MAX_FTP_COL, 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, 220);
  gtk_clist_set_column_width (GTK_CLIST (clist), 2, 70);
  gtk_clist_set_column_width (GTK_CLIST (clist), 3, 80);
  gtk_clist_set_column_width (GTK_CLIST (clist), 4, 80);
  gtk_clist_set_column_min_width (GTK_CLIST (clist), 5, 55);
  gtk_clist_set_column_min_width (GTK_CLIST (clist), 6, 55);
  gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 1, TRUE);
  gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 5, TRUE);
  gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 6, TRUE);
  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_widget_set_usize (GTK_WIDGET (clist), -1, TOP_PANEL_HEIGHT);

  gtk_widget_show (clist);

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

  clist_window = scroll_win ();
  gtk_container_add (GTK_CONTAINER (clist_window), clist);
  gtk_box_pack_end (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 < MAX_FTP_COL; f++)
      sort_arrow[f] = clist_title_with_arrow (clist, f, clist_titles[f]);
  }
  gtk_widget_show (sort_arrow[DIR_COL_SORT_BY_NAME]);


  GTK_SCROLLED_WINDOW_CLASS (GTK_OBJECT (clist_window)->klass)->scrollbar_spacing = 0;

  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);

  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_ftp_prompt);


  gtk_signal_connect (GTK_OBJECT (FTP_COMBO_ENTRY), "activate",
		      GTK_SIGNAL_FUNC (ftp_combo_new_selection), NULL);

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

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

  gtk_signal_connect (GTK_OBJECT (button_manager), "clicked",
		      GTK_SIGNAL_FUNC (switch_smanager_panel), NULL);

  gtk_signal_connect (GTK_OBJECT (clist), "select_row",
		      GTK_SIGNAL_FUNC (ftplist_selection_made), NULL);

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

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

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

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

  active_ftp_panel (FALSE);
  return vbox;
}



void
update_ftplist (char *pathname)
{
  GdkColor lnk_color, dir_color, file_color, rdc_last_update;
  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 = NULL;
  GdkFont *new_font = gdk_font_load (CLIST_PROP_FONT);
  gchar *col[7] =
  {"", "", "", "", "", "", ""};
  gchar *cdup = "CDUP";
  gchar *folder_mark = "d";
  int row = 0;
  FTPfileinfo this_file;
  FILE *in;
  char directory_listing[1024];
  char IS_CACHED = FALSE;

  CURSOR_busy ();

  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;


  last_dir_row = 0;
  last_file_row = 0;


  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;
  rdc_last_update = GREY;
  colormap = gtk_widget_get_colormap (window);
  gdk_color_alloc (colormap, &lnk_color);
  gdk_color_alloc (colormap, &dir_color);
  gdk_color_alloc (colormap, &file_color);
  gdk_color_alloc (colormap, &rdc_last_update);



  if (strcmp (this_session.cwd_dir, "/"))
    RDC_create_site_dir (this_session.cwd_dir);
  RDC_site_dir_listing (directory_listing, this_session.cwd_dir);


  if ((USE_RDC && !WANT_REFRESH) || WANT_RESORT)
    {
      if (!access (directory_listing, F_OK))	/* existe */
	IS_CACHED = TRUE;
    }


  if (!IS_CACHED)
    {
      CHECK_CONNEXION_VOID;
      IDLE_END;
      FTP_LIST (&this_connexion, directory_listing);
      IDLE_START;
      CHECK_CONNEXION_VOID;
    }
  WANT_REFRESH = FALSE;

  if (MUST_SHOW_FTP_DIRECTORY_MESSAGE)
    {
      move_dir_content_message ();
      if (user_rc.view_host_directory_message)
	popup_window_host_directory_message ();
      MUST_SHOW_FTP_DIRECTORY_MESSAGE = FALSE;
    }

  RDC_mark_tree_browsed (this_session.cwd_dir);


  if (!(in = fopen (directory_listing, "r")))
    {
      CURSOR_default ();
      return;
    }

  default_status_message ();


  gtk_clist_freeze (GTK_CLIST (clist));
  gtk_clist_clear (GTK_CLIST (clist));

  gtk_clist_insert (GTK_CLIST (clist), last_dir_row++, col);
  gtk_clist_set_pixmap (GTK_CLIST (clist), 0, 0, parentpix, parentmsk);
  gtk_clist_set_row_data (GTK_CLIST (clist), 0, cdup);

  if (IS_CACHED)
    {
      struct stat stat_buf;
      char time_buf[128];
      struct tm *timeptr;
      stat (directory_listing, &stat_buf);
      timeptr = localtime (&stat_buf.st_ctime);
      strftime (time_buf, sizeof (time_buf), "[ Last updated on %b %d %Y %H:%M ]", timeptr);
      gtk_clist_set_foreground (GTK_CLIST (clist), 0, &GREY);
      gtk_clist_set_background (GTK_CLIST (clist), 0, &GREYCYAN);
      gtk_clist_set_text (GTK_CLIST (clist), 0, 1, time_buf);
      if (!WANT_RESORT)
	info_message ("(Using cached directory listing)");
    }


  total_size = 0;
  while (fread (&this_file, sizeof (this_file), 1, in))
    {
      col[1] = this_file.name;
      col[2] = this_file.size;
      col[3] = this_file.date;
      col[4] = this_file.attrib;
      col[5] = this_file.uid;
      col[6] = this_file.gid;


      if (!(ftplist_hide_hidden && col[1][0] == '.'))
	switch (this_file.attrib[0])
	  {
	  case 'd':
	    row = last_dir_row++;
	    cell_style = non_propor_style_folder;
	    gtk_clist_insert (GTK_CLIST (clist), row, col);
	    gtk_clist_set_foreground (GTK_CLIST (clist), row, &dir_color);
	    gtk_clist_set_pixmap (GTK_CLIST (clist), row, 0, folderpix, foldermsk);
	    gtk_clist_set_row_data (GTK_CLIST (clist), row, folder_mark);
	    if (!WANT_RESORT)
	      {
		char buf[1024];
		sprintf (buf, "%s/%s", this_session.cwd_dir, this_file.name);
		RDC_create_site_dir (buf);
	      }
	    break;

	  case 'D':
	    row = last_dir_row++;
	    cell_style = non_propor_style_link;
	    col[4][0] = 'l';
	    gtk_clist_insert (GTK_CLIST (clist), row, col);
	    gtk_clist_set_foreground (GTK_CLIST (clist), row, &lnk_color);
	    gtk_clist_set_pixmap (GTK_CLIST (clist), row, 0, dlinkpix, dlinkmsk);
	    gtk_clist_set_row_data (GTK_CLIST (clist), row, folder_mark);
	    if (!WANT_RESORT)
	      {
		char buf[1024];
		sprintf (buf, "%s/%s", this_session.cwd_dir, this_file.name);
		RDC_create_site_dir (buf);
	      }
	    break;

	  case 'l':
	    if (!FILTER_is_string_match (filter_search_type, col[1], filter_search_ptr))
	      continue;
	    row = last_dir_row + last_file_row++;
	    cell_style = non_propor_style_link;
	    gtk_clist_insert (GTK_CLIST (clist), row, col);
	    gtk_clist_set_foreground (GTK_CLIST (clist), row, &lnk_color);
	    gtk_clist_set_pixmap (GTK_CLIST (clist), row, 0, flinkpix, flinkmsk);
	    break;

	  default:
	    if (!FILTER_is_string_match (filter_search_type, col[1], filter_search_ptr))
	      continue;
	    row = last_dir_row + last_file_row++;
	    cell_style = non_propor_style_file;
	    gtk_clist_insert (GTK_CLIST (clist), row, col);
	    give_a_nice_icon_to_this_file (this_file.name, clist, row);
	    total_size += atol (this_file.size);
	  }

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


  switch (remote_clist_sort)
    {
    case SORT_BY_SIZE:
      gtk_clist_set_compare_func (GTK_CLIST (clist), remote_sort_by_size);
      break;
    case SORT_BY_DATE:
      gtk_clist_set_compare_func (GTK_CLIST (clist), remote_sort_by_date);
      break;
    case SORT_BY_PERM:
      gtk_clist_set_compare_func (GTK_CLIST (clist), remote_sort_by_perm);
      break;
    default:
      gtk_clist_set_compare_func (GTK_CLIST (clist), NULL);
    }


  gtk_clist_set_sort_type (GTK_CLIST (clist), (remote_clist_sort_type == SORT_DOWN) ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING);
  gtk_clist_set_sort_column (GTK_CLIST (clist), clist_col_sort);
  gtk_clist_sort (GTK_CLIST (clist));

  {
    int folder_row;
    int folder_new_row = 0;
    while ((folder_row = gtk_clist_find_row_from_data (GTK_CLIST (clist), folder_mark)) != -1)
      {
	gtk_clist_set_row_data (GTK_CLIST (clist), folder_row, NULL);
	gtk_clist_row_move (GTK_CLIST (clist), folder_row, folder_new_row++);
      }
  }

  gtk_clist_row_move (GTK_CLIST (clist), gtk_clist_find_row_from_data (GTK_CLIST (clist), cdup), 0);
  gtk_clist_set_selectable (GTK_CLIST (clist), 0, FALSE);


  fclose (in);

  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 (this_session.cwd_dir);

  if (UPDATE_TOOLBAR)
    toolbar_buttons_set_sensitive ();
  if (UPDATE_POPUP_MENU)
    update_remote_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_ftplist (void)
{
  WANT_REFRESH = TRUE;
  update_ftplist (this_session.cwd_dir);
}


static void
ftplist_cdup (GtkWidget * widget, gpointer data)
{
  IGLOO_cwd ("..");
}


void
toggle_remote_hidden (void)
{
  ftplist_hide_hidden = !ftplist_hide_hidden;
  if (this_connexion.is_connected)
    update_ftplist (this_session.cwd_dir);
}


void
toggle_remote_columns_visibility (void)
{
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 2, user_rc.view_remote_files_size);
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 3, user_rc.view_remote_files_date);
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 4, user_rc.view_remote_files_perm);
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 5, user_rc.view_remote_files_owner);
  gtk_clist_set_column_visibility (GTK_CLIST (clist), 6, user_rc.view_remote_files_group);
}


void
toggle_resolve_links (void)
{
  info_message ((this_connexion.resolve_link = !this_connexion.resolve_link) ? "Resolve links Enabled" : "Resolve links Disabled");
}


void
show_progress_list (void)
{
  char msg_buf[100];
  sprintf (msg_buf, "%ld byte(s) received.", this_connexion.xfered_bytes);
  status_message ("Retreiving directory listing ...");
  gtk_label_set (GTK_LABEL (label_info), msg_buf);
  PROCESS_EVENTS_WHILE_XFER;
}



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

  if ((selected = remote_selection_info ()))
    {
      char label_buf[100];
      long selection_size = remote_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_remote_popup_menu (selected);
  queue_popup_menu_set_sensitive ();
}



static gint
clist_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 != REMOTE_FOCUS)
	    {
	      PANEL_FOCUS = REMOTE_FOCUS;
	      local_unselect_all (NULL, NULL);
	      local_focus_update ();
	      remote_focus_update ();
	    }
	  break;

	case 3:
	  {
	    GdkEventButton *bevent = (GdkEventButton *) event;

	    gtk_menu_popup (GTK_MENU (remote_popup_menu), NULL, NULL, NULL, NULL,
			    bevent->button, bevent->time);

	    return TRUE;
	  }
	  break;

	default:
	  return FALSE;
	}
      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;

	    gtk_clist_get_text (GTK_CLIST (this_list), this_row, 1, &buf);
	    if (buf == NULL)
	      return FALSE;

	    if (this_row >= last_dir_row)
	      return FALSE;
	    if (this_row == 0)
	      strcpy (buf, "..");
	    IGLOO_cwd (buf);
	    return TRUE;
	  }
	  break;

	default:
	  return FALSE;
	}


    default:
      break;
    }
  return FALSE;
}






static void
sort_button_clicked (gint column)
{


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


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

  switch (column)
    {
    case FTP_COL_SORT_BY_NAME:
      remote_clist_sort = SORT_BY_NAME;
      break;
    case FTP_COL_SORT_BY_SIZE:
      remote_clist_sort = SORT_BY_SIZE;
      break;
    case FTP_COL_SORT_BY_DATE:
      remote_clist_sort = SORT_BY_DATE;
      break;
    case FTP_COL_SORT_BY_PERM:
      remote_clist_sort = SORT_BY_PERM;
      break;
    case FTP_COL_SORT_BY_UID:
      remote_clist_sort = SORT_BY_UID;
      break;
    case FTP_COL_SORT_BY_GID:
      remote_clist_sort = SORT_BY_GID;
      break;
    }

  if (UPDATE_POPUP_MENU_SORT)
    {
      UPDATE_POPUP_MENU_SORT = FALSE;
      update_remote_popup_menu_sort ();
      UPDATE_POPUP_MENU_SORT = TRUE;
    }
  if (UPDATE_POPUP_MENU_SORT_TYPE)
    {
      UPDATE_POPUP_MENU_SORT_TYPE = FALSE;
      update_remote_popup_menu_sort_type ();
      UPDATE_POPUP_MENU_SORT_TYPE = TRUE;
    }

  WANT_RESORT = TRUE;
  update_ftplist (this_session.cwd_dir);
  WANT_RESORT = FALSE;
}


void
remote_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
remote_sort_type_from_menu (GtkWidget * widget, int data)
{

  if (!UPDATE_POPUP_MENU_SORT_TYPE)
    return;
  if (remote_clist_sort_type == (int) data)
    return;

  remote_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], (remote_clist_sort_type == SORT_UP));
      WANT_RESORT = TRUE;
      if (UPDATE_POPUP_MENU_SORT)
	update_ftplist (this_session.cwd_dir);
      WANT_RESORT = FALSE;
    }
  UPDATE_POPUP_MENU_SORT_TYPE = TRUE;
}



static void
clist_button_clicked (GtkCList * clist, gint column)
{
  if (!this_connexion.is_connected)
    {
      error_message ("NOT connected");
      return;
    }

  switch (column)
    {
    case 0:
      WANT_REFRESH = TRUE;
      update_ftplist (this_session.cwd_dir);
      break;
    default:
      sort_button_clicked (column);
    }
}









/* SELECTION  INFO */

/* PUBLIC :
 * remote_selection_info : return number of selected files (0 if none)
 * remote_get_fileinfo
 * STATIC :
 * remote_selection_size : return total size of selected files
 */


gint
remote_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
remote_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 = (int) selection->data;
      gtk_clist_get_text (GTK_CLIST (clist), index, 2, &filesize);
      selection_size += atol (filesize);
      selection = selection->next;

    }
  return selection_size;
}


char
remote_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;
}




/* FTP COMBO */

/* STATIC :
 * update_combo 
 * clear_combo
 * ftp_combo_new_selection 
 */


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 (FTP_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
clear_combo (void)
{
  if (combo_items != NULL)
    combo_items = combo_items->prev;
  gtk_list_clear_items (FTP_COMBO_LIST, 0, -1);
  gtk_entry_set_text (FTP_COMBO_ENTRY, "");
}


static void
ftp_combo_new_selection (GtkWidget * widget)
{
  gchar *ptr;

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

  ptr = gtk_entry_get_text (FTP_COMBO_ENTRY);
  if (strcmp (ptr, this_session.cwd_dir))
    IGLOO_cwd (ptr);
  if (IS_BROWSER_VISIBLE)
    browser_hide ();
}









/* QUOTE PROMPT */

/* PUBLIC:
 * show_or_hide_ftp_prompt
 * STATIC:
 * execute_user_command
 */


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

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

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

  CHECK_CONNEXION_VOID;
  if (!this_connexion.is_connected)
    {
      error_message ("NOT connected to a host.");
      return;
    }

  strcpy (command_buf, user_command);
  strupr (command_buf);

  if (strstr (command_buf, "LIST") || strstr (command_buf, "NLST"))
    {
      IDLE_END;
      refresh_ftplist ();
      return;
    }

  if (strstr (command_buf, "CWD"))
    {
      IGLOO_cwd (strchr (user_command, 32) + 1);
      return;
    }

  if (strstr (command_buf, "CDUP"))
    {
      IGLOO_cwd ("..");
      return;
    }

  if (strstr (command_buf, "QUIT"))
    {
      IGLOO_logoff (TRUE);
      return;
    }
  IDLE_END;
  CURSOR_MAIN_busy ();

  FTP_USER_COMMAND (&this_connexion, user_command);
  CHECK_CONNEXION_VOID;

  CURSOR_MAIN_default ();
  IDLE_START;
}



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











/* FOCUS info */

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






/* REMOTE EXEC  FUNCTIONS */

/* PUBLIC:
 * remote_file_view
 * remote_file_edit 
 * remote_exec
 * STATIC :
 * remote_file_view_or_edit
 * remote_file_viewed
 * remote_file_edited
 */
/*
   static void
   remote_file_viewed (EDITfileinfo * file_info, gint source, GdkInputCondition condition)
   {
   struct stat stat_buf;
   fstat (source, &stat_buf);

   if (stat_buf.st_size)
   {
   unlink (file_info->name);
   gdk_input_remove (REXEC_TAG);
   g_free (file_info);
   fclose (REXEC);
   gtk_widget_set_sensitive (window, TRUE);
   }
   }
 */
static void
remote_file_edited (EDITfileinfo * file_info, gint source, GdkInputCondition condition)
{
  struct stat stat_buf;
  fstat (source, &stat_buf);
  if (stat_buf.st_size)
    {
      CURSOR_MAIN_busy ();
      gdk_input_remove (REXEC_TAG);
      fclose (REXEC);

      stat (file_info->name, &stat_buf);
      if (stat_buf.st_size != file_info->stat_buf.st_size || stat_buf.st_mtime != file_info->stat_buf.st_mtime)
	{
	  char msg_buf[1024];
	  char *dest_filename;
	  sprintf (msg_buf, "%s This file was modified,\ndo you want upload it?", (char *) (dest_filename = strrchr (file_info->name, '/') + 1));
	  if (alert_ok_cancel_modal ("File Modified", msg_buf, "Upload"))
	    {
	      xfer_overwrite = TRUE;
	      IDLE_END;
	      IGLOO_upload_from (file_info->name, dest_filename, "0", NULL, NULL);
	      CHECK_CONNEXION_VOID;
	      IDLE_START;
	      refresh_ftplist ();
	    }
	}
      unlink (file_info->name);
      g_free (file_info);
      gtk_widget_set_sensitive (window, TRUE);
      CURSOR_MAIN_default ();
    }
}



static void
remote_file_view_or_edit (char WANT_EDIT)
{
  GList *selection = GTK_CLIST (clist)->selection;
  int this_row = GTK_CLIST (clist)->focus_row;
  char this_path[1024];
  char temp_path[1024];
  gchar *filename;
  gchar *filesize;
  gchar *filedate;
  EDITfileinfo *file_info;

  if (selection != NULL)
    this_row = (int) selection->data;
  if (!this_row)
    return;
  if (this_row < last_dir_row)
    {
      WANT_EDIT ? remote_rename_dialog (NULL, NULL) : IGLOO_cwd (filename);
      return;
    }


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

  file_info = g_malloc0 (sizeof (EDITfileinfo));

  getcwd (this_path, sizeof (this_path));
  tmp_cache_path (temp_path);
  sprintf (file_info->name, "%s/%s", temp_path, filename);
  chdir (temp_path);

  xfer_overwrite = TRUE;
  IDLE_END;
  CHECK_CONNEXION_VOID;

  if (IGLOO_download (filename, filesize, filedate, NULL))
    {
      char that_path[1024];
      PROCESS_EVENTS;
      if (WANT_EDIT)
	{
	  stat (file_info->name, &file_info->stat_buf);
	  REXEC_path (that_path);
	  REXEC = fopen (that_path, "w+");
	  REXEC_TAG = gdk_input_add (fileno (REXEC), GDK_INPUT_READ,
				     /*WANT_EDIT ? */ (GdkInputFunction) remote_file_edited /*: (GdkInputFunction) remote_file_viewed */ ,
				     file_info);
	  if (WANT_EDIT)
	    gtk_widget_set_sensitive (window, FALSE);
	  remote_execute_view_or_edit_file (g_strdup (filename), WANT_EDIT);
	}
      else
	local_execute_view_or_edit_file (g_strdup (filename), FALSE);
    }

  chdir (this_path);

  xfer_overwrite = FALSE;
  IDLE_START;
  CHECK_CONNEXION_VOID;
}


void
remote_file_view (void)
{
  remote_file_view_or_edit (FALSE);
}

void
remote_file_edit (void)
{
  remote_file_view_or_edit (TRUE);
}




/* REMOTE COMMAND FUNCTIONS */

/* STATIC :
 * perfom_recursive_command_on_selection 
 * remote_chmod
 * remote_delete 
 * remote_rename
 * remote_move
 * remote_create_directory
 * remote_change_directory
 * PUBLIC : 
 * remote_chmod_dialog 
 * remote_delete_dialog 
 * remote_rename_dialog
 * remote_move_dialog
 * remote_create_directory_dialog 
 * remote_change_directory_dialog 
 */


static void
perfom_recursive_command_on_selection (char recursive_command, char *optionnal_arg, char IS_TOP_DIR)
{
  GList *selection = GTK_CLIST (clist)->selection;
  gchar *filename;
  gchar *fileperm;
  int index;
  FILE *tmp;
  char tmp_filename[256];
  char path_buf[1024];
  char DIR_FOUND_IN_SELECTION = FALSE;
  char *current_remote_dir = strdup (this_session.cwd_dir);

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


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

      if (fileperm[0] != 'd')
	{
	  switch (recursive_command)
	    {
	    case RECURSIVE_CHMOD:
	      status_message_with_arg ("Chmoding", filename);
	      IGLOO_chmod (filename, optionnal_arg);
	      CHECK_CONNEXION_VOID;
	      break;
	    case RECURSIVE_DELETE:
	      status_message_with_arg ("Deleting", filename);
	      IGLOO_delete (filename);
	      CHECK_CONNEXION_VOID;
	      break;
	    }
	  selection = selection->next;
	}
      else
	{
	  DIR_FOUND_IN_SELECTION = TRUE;
	  selection = selection->next;
	  fprintf (tmp, "%s\n", filename);
	}
    }
  fclose (tmp);


  if (DIR_FOUND_IN_SELECTION)
    {
      tmp = fopen (tmp_filename, "r");
      while (fgets (path_buf, sizeof (path_buf) - 1, tmp) != NULL)
	{
	  char RECURSE_THIS_DIR = !IS_TOP_DIR;

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

	  switch (recursive_command)
	    {
	    case RECURSIVE_CHMOD:
	      {
		char mode_buf[5];
		strcpy (mode_buf, optionnal_arg);
		switch (mode_buf[1])	/* force chmod dir u+x */
		  {
		  case '2':
		    mode_buf[1] = '3';
		    break;
		  case '4':
		    mode_buf[1] = '5';
		    break;
		  case '6':
		    mode_buf[1] = '7';
		    break;
		  }
		IGLOO_chmod (path_buf, mode_buf);
		CHECK_CONNEXION_VOID;

	      }
	      if (!RECURSE_THIS_DIR)
		{
		  char msg_buf[1024];
		  sprintf (msg_buf, "%s is a directory ...\nChmod it recursively?", path_buf);
		  RECURSE_THIS_DIR = (alert_ok_cancel_modal ("Remote Chmod", msg_buf, "Ok") != 0);
		}
	      break;

	    case RECURSIVE_DELETE:
	      if (!RECURSE_THIS_DIR)
		{
		  char msg_buf[1024];
		  sprintf (msg_buf, "%s is a directory ...\nDelete it recursively?", path_buf);
		  RECURSE_THIS_DIR = (alert_ok_cancel_modal ("Remote Delete", msg_buf, "Ok") != 0);
		}
	      break;

	    default:
	      break;
	    }


	  if (RECURSE_THIS_DIR)
	    {
	      char msg_buf[1024];
	      sprintf (msg_buf, "Recursing %s ...\n", path_buf);
	      info_message (msg_buf);

	      WANT_REFRESH = TRUE;
	      if (IGLOO_cwd (path_buf))
		{
		  CHECK_CONNEXION_VOID;
		  gtk_clist_select_all (GTK_CLIST (clist));
		  perfom_recursive_command_on_selection (recursive_command, optionnal_arg, FALSE);
		}

	      FTP_CWD (&this_connexion, current_remote_dir);
	      CHECK_CONNEXION_VOID;
	      strcpy (this_session.cwd_dir, current_remote_dir);

	      if (recursive_command == RECURSIVE_DELETE)
		{
		  status_message_with_arg ("Deleting", path_buf);
		  IGLOO_rmd (path_buf);
		  CHECK_CONNEXION_VOID;
		}
	    }

	}
      fclose (tmp);
    }

  unlink (tmp_filename);
  free (current_remote_dir);
}



 /* CHMOD - RECURSIVE */



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

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

  IDLE_END;
  CURSOR_MAIN_busy ();

  CHECK_CONNEXION_VOID;
  want_abort = FALSE;
  active_ftp_panel (FALSE);

  perfom_recursive_command_on_selection (RECURSIVE_CHMOD, buf, TRUE);

  refresh_ftplist ();
  default_status_message ();
  active_ftp_panel (TRUE);

  CURSOR_MAIN_default ();
  IDLE_START;
}


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

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

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

      gtk_clist_get_text (GTK_CLIST (clist), (int) selection->data, 4, &filemode);
      StrNumMode (buf_mode, filemode);
      chmod_dialog ("Remote Chmod", buf_mode, GTK_SIGNAL_FUNC (remote_chmod));
    }
}




/* DELETE - RECURSIVE */



static void
remote_delete (GtkWidget * widget, GtkWidget * entry)
{
  GtkWidget *alert_window = gtk_widget_get_toplevel (widget);
  gtk_widget_destroy (alert_window);

  IDLE_END;
  CURSOR_MAIN_busy ();

  CHECK_CONNEXION_VOID;
  want_abort = FALSE;
  active_ftp_panel (FALSE);

  perfom_recursive_command_on_selection (RECURSIVE_DELETE, NULL, TRUE);
  refresh_ftplist ();
  default_status_message ();
  active_ftp_panel (TRUE);

  CURSOR_MAIN_default ();
  IDLE_START;
}


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

  if (!(selected = remote_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, remote_selection_size ());
  alert_ok_cancel ("Remote Delete", msg_buf, "Delete", GTK_SIGNAL_FUNC (remote_delete));
}



/* RENAME */



static void
remote_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
    {
      IDLE_END;
      CHECK_CONNEXION_VOID;
      if (!IGLOO_rename (oldfilename, buf))
	{
	  char msg_buf[1024];
	  sprintf (msg_buf, "Can't rename  : %s", oldfilename);
	  alert_ok ("Error", msg_buf, "Ok");
	}
      else
	{
	  refresh_ftplist ();
	}
    }
  CHECK_CONNEXION_VOID;
  IDLE_START;
}


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

  if (!(remote_selection_info ()))
    return;

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



/* MOVE - NOT RECURSIVE but directories move too */

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

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

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

  else
    {
      IDLE_END;
      CURSOR_MAIN_busy ();

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

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

	  if (!IGLOO_rename (filename, buf))
	    ERROR_FLAG = TRUE;
	  CHECK_CONNEXION_VOID;
	  selection = selection->next;
	}
      refresh_ftplist ();
      if (ERROR_FLAG)
	alert_ok ("Error", "Some error(s) occured\nwhen trying to move file(s).", "Ok");

      CURSOR_MAIN_default ();
      IDLE_START;
    }
}


void
remote_move_dialog (GtkWidget * widget, gpointer data)
{
  if (!(remote_selection_info ()))
    return;
  entry_dialog ("Remote Move", "Move file(s) to :", "Move", "", GTK_SIGNAL_FUNC (remote_move));
}



/* CREATE DIRECTORY */



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

  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
    {
      IDLE_END;
      CHECK_CONNEXION_VOID;
      if (!IGLOO_mkd (buf))
	{
	  char msg_buf[1024];
	  sprintf (msg_buf, "Can't create directory : %s", buf);
	  alert_ok ("Error", msg_buf, "Ok");
	}
      else
	{
	  refresh_ftplist ();
	}
    }
  CHECK_CONNEXION_VOID;
  IDLE_START;
}


void
remote_create_directory_dialog (GtkWidget * widget, gpointer data)
{
  entry_dialog ("Create Remote Directory", "Directory name :", "Create", "", GTK_SIGNAL_FUNC (remote_create_directory));
}



/* CHANGE DIRECTORY */



static void
remote_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 (!IGLOO_cwd (buf))
    {
      char msg_buf[1024];
      sprintf (msg_buf, "Can't change to directory : %s", buf);
      alert_ok ("Error", msg_buf, "Ok");
    }
}


void
remote_change_directory_dialog (GtkWidget * widget, gpointer data)
{
  entry_dialog ("Change Remote Directory", "Directory name :", "Change", "", GTK_SIGNAL_FUNC (remote_change_directory));
}










/* DOWNLOAD SELECTION  */

/* PUBLIC :
 * download_selection
 * STATIC : 
 * download_selection_recursive
 */


static char
download_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[1024];

  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))
    {
      static GtkStyle *cell_style;
      index = (int) selection->data;

      cell_style = gtk_clist_get_cell_style (GTK_CLIST (clist), index, 3);
      cell_style->base[GTK_STATE_NORMAL] = GREYCYAN;
      cell_style->bg[GTK_STATE_PRELIGHT] = 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_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 (fileperm[0] != 'd')
	{
	  if (IGLOO_download (filename, filesize, filedate, fileperm))
	    {
	      refresh_dirlist ();
	      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;
	}
      else
	{
	  DIR_FOUND_IN_SELECTION = TRUE;
	  selection = selection->next;
	  fprintf (tmp, "%s,%s,%s\n", fileperm, filename, filedate);
	}
    }
  fclose (tmp);


  if (DIR_FOUND_IN_SELECTION)
    {
      char this_line[1024];
      char remote_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 (remote_path, path_ptr);

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

	  if (this_session.downloads_perm)
	    {
	      char buf_mode[5];
	      static long int this_chmod_mode = 755;
	      StrNumMode (buf_mode, this_line);
	      this_chmod_mode = strtol (buf_mode, NULL, 8);
	      mkdir (path_ptr, this_chmod_mode);
	    }
	  else
	    mkdir (path_ptr, 0755);


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


	  chdir (current_local_dir);

	  if (this_session.downloads_date)
	    {
	      const char *format = REMOTE_DATE_FORMAT;
	      struct tm remote_date;
	      struct utimbuf buf;
	      memset (&remote_date, 0, sizeof (struct tm));
	      strptime (date_ptr, format, &remote_date);
	      buf.actime = mktime (&remote_date);
	      buf.modtime = mktime (&remote_date);
	      utime (path_ptr, &buf);
	    }

	  refresh_dirlist ();
	  FTP_CWD (&this_connexion, current_remote_dir);
	  CHECK_CONNEXION;
	  strcpy (this_session.cwd_dir, current_remote_dir);
	}
      fclose (tmp);
      update_ftplist (this_session.cwd_dir);
    }

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



void
download_selection (GtkWidget * widget, gpointer data)
{

  if (!(remote_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;

  download_selection_recursive ();

  default_status_message ();
  IDLE_START;

  active_ftp_panel (TRUE);
  active_dir_panel (TRUE);

  CURSOR_MAIN_default ();
}




/* QUEUE RELATED functions */

/* PUBLIC:
 * queue_selection_for_download 
 */

void
queue_selection_for_download (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_DOWNLOAD);

      selection = selection->next;
      gtk_clist_set_background (GTK_CLIST (clist), index, &GREYCYAN);
      gtk_clist_unselect_row (GTK_CLIST (clist), index, 0);
    }

  CURSOR_MAIN_default ();
}


char
queue_download_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 = download_selection_recursive ();
	      CURSOR_MAIN_default ();
	      return return_code;
	    }
	}
      index++;
    }

  CURSOR_MAIN_default ();
  return FALSE;
}



/* EOF */
