/* 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
 * 
 *
 */


static int RDC_root_length;
static char IS_BROWSER_VISIBLE;
static GtkCTreeNode *FTP_TREE_root_node = NULL;


static void browser_show (void);
static void browser_hide (void);
static void FTP_TREE_make_bold (GtkCTree * ctree, GtkCTreeNode * node, char IS_ROOT);
static GtkCTreeNode *FTP_TREE_init (GtkCTree * ctree);
static GtkWidget *FTP_TREE_create (void);
static gint FTP_TREE_event_handler (GtkWidget * widget, GdkEvent * event, gpointer data);
static void FTP_TREE_path_selected (char *this_path);
static void FTP_TREE_path_selected_from_browser_button (GtkWidget * widget, GtkWidget * ctree);
static void FTP_TREE_tree_collapse (GtkCTree * ctree, GtkCTreeNode * node, /*GdkEventButton *event, */ gpointer data);
static void FTP_TREE_tree_expand (GtkCTree * ctree, GtkCTreeNode * node, /*GdkEventButton *event, */ gpointer data);
static void FTP_TREE_select_row (GtkCTree * ctree, GtkCTreeNode * node, gint col, /*GdkEventButton *event, */ GtkWidget * label);




static void
browser_show (void)
{
  if (browser_window != NULL)
    return;
  CURSOR_busy ();
  browser_window = FTP_TREE_create ();
  gtk_widget_hide (clist_window);
  gtk_widget_hide (prompt_entry);
  gtk_widget_hide (frame_info);
  gtk_widget_hide (button_browser_open);
  gtk_widget_show (button_browser_close);
  gtk_box_pack_start (GTK_BOX (browser_box), browser_window, TRUE, TRUE, 0);
  IS_BROWSER_VISIBLE = TRUE;
  CURSOR_default ();
}


static void
browser_hide (void)
{
  gtk_widget_destroy (browser_window);
  browser_window = NULL;
  gtk_widget_hide (button_browser_close);
  gtk_widget_show (clist_window);
  gtk_widget_show (prompt_entry);
  gtk_widget_show (frame_info);
  gtk_widget_show (button_browser_open);
  IS_BROWSER_VISIBLE = FALSE;
}






static char
FTP_TREE_browse_directory (GtkCTree * ctree, GtkCTreeNode * parent, char *this_pathname)
{
  DIR *this_dir = NULL;
  struct dirent *dirlist;
  struct stat stat_buf;
  char path_buf[1024];
  char *pathname = strdup (this_pathname);
  gchar *col[3] =
  {"", "", ""};
  char is_part_of_cwd_dir = FALSE;
  GtkCTreeNode *node = NULL;
  GdkPixmap *dclosepix = NULL, *dopenpix = NULL, *arrowpix;
  GdkBitmap *dclosemsk = NULL, *dopenmsk = NULL, *arrowmsk;

  char *current_remote_path = strdup (this_session.cwd_dir);

  if (DOS_FILESYSTEM)
    RDC_DOS2UNIX (current_remote_path);

  arrowpix = arrow_down_pixmap (&arrowmsk);

  stat (this_pathname, &stat_buf);
  if ((stat_buf.st_mode & S_IFMT) != S_IFDIR)	/* check that this_pathname is a valid dir */
    return 0;


  if ((this_dir = opendir (pathname)))
    {
      while ((dirlist = readdir (this_dir)))
	{
	  sprintf (path_buf, "%s/%s", pathname, dirlist->d_name);	/* Build absolute filename */
	  stat (path_buf, &stat_buf);

	  if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)
	    {
	      char SHOW_IT = TRUE;

	      if (ftplist_hide_hidden)
		{
		  if (dirlist->d_name[0] == '.')
		    switch (dirlist->d_name[1])
		      {
		      case 0:
			SHOW_IT = FALSE;
			break;
		      case '.':
			SHOW_IT = (dirlist->d_name[2] != 0);
			break;
		      }
		}
	      else
		SHOW_IT = (dirlist->d_name[0] != '.');


	      if (SHOW_IT)
		{
		  col[1] = dirlist->d_name;

		  if (strlen (pathname) > 1)
		    sprintf (path_buf, "%s/%s", pathname, col[1]);
		  else
		    sprintf (path_buf, "%s%s", pathname, col[1]);

		  col[2] = path_buf + RDC_root_length;

		  lstat (path_buf, &stat_buf);


		  if (RDC_is_tree_unbrowsed (col[2]))
		    {
		      dclosepix = folder_pixmap (&dclosemsk);
		      dopenpix = folder_open_pixmap (&dopenmsk);
		      node = gtk_ctree_insert_node (ctree, parent, node, col, 3, dclosepix, dclosemsk, dopenpix, dopenmsk, FALSE, FALSE);
		      gtk_ctree_node_set_pixmap (ctree, node, 0, arrowpix, arrowmsk);
		    }
		  else
		    {
		      dclosepix = folder_l_pixmap (&dclosemsk);
		      dopenpix = folder_open_l_pixmap (&dopenmsk);
		      node = gtk_ctree_insert_node (ctree, parent, node, col, 3, dclosepix, dclosemsk, dopenpix, dopenmsk, FALSE, FALSE);
		    }

		  if (parent == FTP_TREE_root_node)
		    FTP_TREE_make_bold (ctree, node, FALSE);

		  if (!strcmp (col[2], current_remote_path) || !strcmp (col[2] + 1, current_remote_path))
		    {
		      RDC_mark_tree_open (col[2]);
		      gtk_ctree_select (ctree, node);
		      gtk_ctree_node_moveto (ctree, node, -1, 0.5, 0);
		      is_part_of_cwd_dir = TRUE;
		    }

		  if (FTP_TREE_browse_directory (ctree, node, path_buf))
		    {
		      RDC_mark_tree_open (col[2]);
		      is_part_of_cwd_dir = TRUE;
		    }

		  if (RDC_is_tree_open (col[2]))
		    gtk_ctree_expand (ctree, node);

		}

	    }

	}
    }

  gtk_ctree_sort_node (ctree, parent);

  if (this_dir)
    closedir (this_dir);
  free (current_remote_path);
  free (pathname);

  if (dclosepix != NULL)
    {
      gdk_pixmap_unref (dclosepix);
      gdk_pixmap_unref (dclosemsk);
    }

  if (dopenpix != NULL)
    {
      gdk_pixmap_unref (dopenpix);
      gdk_pixmap_unref (dopenmsk);
    }

  return is_part_of_cwd_dir;
}


static void
FTP_TREE_make_bold (GtkCTree * ctree, GtkCTreeNode * node, char IS_ROOT)
{
  GdkFont *new_font = gdk_font_load (FTP_BROWSER_BOLD_FONT);
  GtkStyle *new_style;

  new_style = gtk_style_copy (GTK_WIDGET (ctree)->style);
  gdk_font_unref (new_style->font);
  new_style->font = new_font;
  if (IS_ROOT)
    new_style->fg[GTK_STATE_NORMAL] = BLUE;
  gtk_ctree_node_set_cell_style (ctree, node, 1, new_style);
}



static GtkCTreeNode *
FTP_TREE_init (GtkCTree * ctree)
{
  GtkCTreeNode *node = NULL;
  GdkPixmap *rootpix;
  GdkBitmap *rootmsk;
  gchar *col[3] =
  {"", "Root Directory", "/"};

  rootpix = computer_pixmap (&rootmsk);
  node = gtk_ctree_insert_node (ctree, NULL, node, col, 3, rootpix, rootmsk, rootpix, rootmsk, FALSE, TRUE);
  FTP_TREE_make_bold (ctree, node, TRUE);
  gdk_pixmap_unref (rootpix);
  gdk_pixmap_unref (rootmsk);
  return node;
}



static GtkWidget *
FTP_TREE_create (void)
{
  GtkWidget *scrolled_win;
  GtkCTree *ctree = NULL;
  gchar *titles[3] =
  {"", "", ""};
  char path_buf[1024];
  char title_buf[1024];

  sprintf (title_buf, " %s [%s]", this_connexion.hostname, USE_FIREWALL ? " Firewall " : this_connexion.connect_address);
  titles[1] = title_buf;

  ctree = GTK_CTREE (gtk_ctree_new_with_titles (3, 1, titles));
  gtk_widget_show (GTK_WIDGET (ctree));
  gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
  gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED);
  gtk_ctree_set_indent (ctree, 13);
  gtk_ctree_show_stub (ctree, FALSE);
  gtk_clist_set_row_height (GTK_CLIST (ctree), 18);
  gtk_clist_set_column_min_width (GTK_CLIST (ctree), 0, 15);
  gtk_clist_set_column_min_width (GTK_CLIST (ctree), 1, 250);
  gtk_clist_set_sort_column (GTK_CLIST (ctree), 1);
  gtk_clist_set_column_visibility (GTK_CLIST (ctree), 2, FALSE);

  gtk_clist_set_hadjustment (GTK_CLIST (ctree), NULL);
  gtk_clist_set_vadjustment (GTK_CLIST (ctree), NULL);
  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_widget_show (scrolled_win);
  gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (ctree));


  gtk_clist_freeze (GTK_CLIST (ctree));

  FTP_TREE_root_node = FTP_TREE_init (ctree);
  RDC_site_root_dir (path_buf);
  RDC_root_length = strlen (path_buf);
  FTP_TREE_browse_directory (ctree, FTP_TREE_root_node, path_buf);

  gtk_clist_thaw (GTK_CLIST (ctree));

  gtk_signal_connect (GTK_OBJECT (ctree), "event",
		      GTK_SIGNAL_FUNC (FTP_TREE_event_handler), NULL);

  gtk_signal_connect (GTK_OBJECT (ctree), "tree_expand",
		      GTK_SIGNAL_FUNC (FTP_TREE_tree_expand), NULL);

  gtk_signal_connect (GTK_OBJECT (ctree), "tree_collapse",
		      GTK_SIGNAL_FUNC (FTP_TREE_tree_collapse), NULL);


  gtk_signal_connect (GTK_OBJECT (ctree), "tree_select_row",
		      GTK_SIGNAL_FUNC (FTP_TREE_select_row), NULL);

  gtk_signal_connect_while_alive (GTK_OBJECT (button_browser_close), "clicked",
				  GTK_SIGNAL_FUNC (FTP_TREE_path_selected_from_browser_button), GTK_WIDGET (ctree),
				  GTK_OBJECT (ctree));

  return scrolled_win;
}



static gint
FTP_TREE_event_handler (GtkWidget * widget, GdkEvent * event, gpointer data)
{
  switch (event->type)
    {
    case GDK_2BUTTON_PRESS:
      switch (event->button.button)
	{
	case 1:
	  {
	    gchar *buf;
	    gtk_clist_get_text (GTK_CLIST (widget), GTK_CLIST (widget)->focus_row, 2, &buf);
	    FTP_TREE_path_selected (g_strdup (buf));
	  }
	  return TRUE;
	  break;

	default:
	}
      break;

    default:
    }
  return FALSE;
}



static void
FTP_TREE_path_selected (char *this_path)
{
  char *ptr = this_path;
  browser_hide ();


  /* DOS FILESYSTEM !!!! */
  if (DOS_FILESYSTEM)
    {
      while ((ptr = strrchr (this_path, '/')) != NULL)
	*ptr = '\\';
      if (this_path[0] == '\\')
	ptr = this_path + 1;
    }


  if (strcmp (ptr, this_session.cwd_dir))
    IGLOO_cwd (ptr);

  g_free (this_path);
}


static void
FTP_TREE_path_selected_from_browser_button (GtkWidget * widget, GtkWidget * ctree)
{
  GList *selection;
  gchar *buf;

  if ((selection = GTK_CLIST (ctree)->selection) != NULL)
    {
      gtk_ctree_node_get_text (GTK_CTREE (ctree), selection->data, 2, &buf);
      FTP_TREE_path_selected (g_strdup (buf));
    }
  else
    browser_hide ();
}




static void
FTP_TREE_tree_expand (GtkCTree * ctree, GtkCTreeNode * node, /*GdkEventButton *event, */ gpointer data)
{
  gchar *buf;
  gtk_ctree_node_get_text (GTK_CTREE (ctree), node, 2, &buf);
  RDC_mark_tree_open (buf);
}


static void
FTP_TREE_tree_collapse (GtkCTree * ctree, GtkCTreeNode * node, /*GdkEventButton *event, */ gpointer data)
{
  gchar *buf;
  gtk_ctree_node_get_text (GTK_CTREE (ctree), node, 2, &buf);
  RDC_mark_tree_closed (buf);
}


static void
FTP_TREE_select_row (GtkCTree * ctree, GtkCTreeNode * node, gint col, /*GdkEventButton *event, */ GtkWidget * label)
{
  GdkPixmap *pixmap = NULL;
  GdkBitmap *mask = NULL;
  GdkPixmap *dclosepix = NULL, *dopenpix = NULL;
  GdkBitmap *dclosemsk = NULL, *dopenmsk = NULL;
  gchar *buf;
  gchar *ptr;
  char path_buf[1024];
  char old_cwd[1024];
  char MAY_NOT_BROWSE = FALSE;
  if (col)
    return;

  gtk_ctree_node_get_pixmap (ctree, node, 0, &pixmap, &mask);
  if (pixmap == NULL)
    return;

  CURSOR_MAIN_busy ();

  gtk_ctree_node_get_text (GTK_CTREE (ctree), node, 2, &buf);

  strcpy (old_cwd, this_session.cwd_dir);

  ptr = buf;

  /* DOS FILESYSTEM !!!! */
  if (DOS_FILESYSTEM)
    {
      while ((ptr = strrchr (buf, '/')) != NULL)
	*ptr = '\\';
      if (buf[0] == '\\')
	ptr = buf + 1;
    }


  if (!(MAY_NOT_BROWSE = (!IGLOO_cwd (ptr))))
    MAY_NOT_BROWSE = (!strcmp (old_cwd, this_session.cwd_dir)) || (!strcmp ("/", this_session.cwd_dir));


  RDC_site_dir_dir (path_buf, this_session.cwd_dir);
  gtk_clist_freeze (GTK_CLIST (ctree));

  if (!MAY_NOT_BROWSE)
    FTP_TREE_browse_directory (ctree, node, path_buf);

  gtk_ctree_node_set_text (ctree, node, 0, " ");

  dclosepix = folder_l_pixmap (&dclosemsk);
  dopenpix = folder_open_l_pixmap (&dopenmsk);
  GTK_CTREE_ROW (node)->pixmap_closed = dclosepix;
  GTK_CTREE_ROW (node)->mask_closed = dclosemsk;
  GTK_CTREE_ROW (node)->pixmap_opened = dopenpix;
  GTK_CTREE_ROW (node)->mask_opened = dopenmsk;

  gtk_ctree_expand (ctree, node);

  gtk_clist_thaw (GTK_CLIST (ctree));
  CURSOR_MAIN_default ();
}


/* EOF */
