/* copyright    Maher Awamy <muhri@muhri.net>           *
 *              Charlie Schmidt <ishamael@themes.org>   *
 *                                                      *
 *  released under the GPL                              */

#include "skipstone.h"

#define AUTO_SCROLL_EDGE 20
#define AUTO_SCROLL_INTERVAL 50
#define AUTO_SCROLL_TITLE_HEIGHT 20 /* FIXME!! I don't know how to get title height of clist(ctree) widget */

#define MINI_FOLDER "mini_folder.png"
#define MINI_LINK   "mini_link.png"


static gint bookmark_activate(GtkWidget *widget, GdkEventButton *event, SkipStone *skipstone);
static void click_on_bookmark_from_toolbar(GtkWidget *button,  GdkEventButton *event, SkipStone *skipstone);
static void close_bookmark_window(BookmarkWindow *bwin);
static void generate_bookmark_ctree(GNode *node,BookmarkCTreeData *ctree_data);
static void make_bookmark_menu(GNode *node,BookmarkFuncData *funcdata);
static void make_bookmark_toolbar(GNode *node,BookmarkFuncData *funcdata);
static void edit_bookmarks(GtkWidget *menuitem,gpointer user_data);
static void on_bookmark_ctree_select_row(GtkWidget *ctree,GtkCTreeNode *node,gint col,BookmarkWindow *bwin);
static void on_bookmark_ctree_unselect_row(GtkWidget *ctree,GtkCTreeNode *node,gint col,BookmarkWindow *bwin);
static void on_bookmark_ctree_move(GtkWidget *ctree,GtkCTreeNode *node,GtkCTreeNode *parent,GtkCTreeNode *sibling,BookmarkWindow *bwin);
static gboolean scrolling_is_desirable(BookmarkWindow *bwin,gint x,gint y);
static gboolean timeout_auto_scroll(gpointer data);
static void cancel_auto_scroll(BookmarkWindow *bwin);
static void on_bookmark_ctree_drag_motion(GtkWidget *ctree,GdkDragContext *context,gint x,gint y,gint time,BookmarkWindow *bwin);
static void on_bookmark_ctree_drag_end(GtkWidget *ctree,GdkDragContext *context,BookmarkWindow *bwin);
static void on_bookmark_add_button_clicked(GtkWidget *button,BookmarkWindow *bwin);
static void on_bookmark_update_button_clicked(GtkWidget *button,BookmarkWindow *bwin);
static void on_bookmark_remove_button_clicked(GtkWidget *button,BookmarkWindow *bwin);
static void remove_tree_node(GtkWidget *ctree,GtkCTreeNode *node,gpointer user_data);
static void on_bookmark_cancel_button_clicked(GtkWidget *button,BookmarkWindow *bwin);
static void on_bookmark_ok_button_clicked(GtkWidget *button,BookmarkWindow *bwin);
static void on_bookmark_add_folder_button_clicked(GtkWidget *button,BookmarkWindow *bwin);
static void on_bookmark_delete_event(GtkWidget *widget,GdkEvent *event,BookmarkWindow *bwin);
static void open_bookmark_menu(GtkWidget *widget,GdkEventButton *event,GtkWidget *menu);
static void open_all_folder_cb(GtkWidget *menu_item, GtkWidget *menu);
static void real_add_bookmark(gchar *title, gchar *url, SkipStone *skipstone);
static gboolean read_bookmarks_from_ctree(GtkCTree *ctree,gint depth,GNode *gnode,GtkCTreeNode *cnode,gpointer user_data);
static GtkWidget *xpm_label_box(GtkWidget *parent, gchar *xpm_filename,gchar *label_text);

static GSList *bmark_toolbar_widgets;
static gint scroll_timer_id = -1;
static gint drag_motion_x;
static gint drag_motion_y;
static GtkWidget *bmark_window;

extern GNode *bookmarks;
extern GSList *window_count;
extern ConfigData config;

static gint bookmark_activate(GtkWidget *widget, GdkEventButton *event, 
                              SkipStone *skipstone) {
	BookmarkData *bmark;
        SkipStone *my_skipstone=NULL;
     	D_ENTER;

	bmark = g_object_get_data(G_OBJECT(widget),"bmark");
     
	if (skipstone->is_notebook == 2 || skipstone->is_notebook ==1) 
	     	my_skipstone = get_current_browser_from_notebook();
        else
                my_skipstone = skipstone;

       switch ( event->button ) {
	      case 1:
	      case 3:
	     	    if (my_skipstone) 
	               _skipstone_load_url(my_skipstone,bmark->url);				
	            D_RETURN_(TRUE);
	      case 2:
	     	  if (bmark && bmark->url) 
	       		make_window(bmark->url);	    
	          D_RETURN_(TRUE);
	      default:
	          break;
       }
     	D_RETURN_(FALSE);
}

void add_bookmark(GtkWidget *menuitem,SkipStone *skipstone) {
	G_CONST_RETURN gchar *url;
	D_ENTER;
	if (skipstone->is_notebook) {
		skipstone = get_current_browser_from_notebook();
	     	if (!skipstone)
	       		D_RETURN;
	}

	url = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(skipstone->combo)->entry));
	if (g_strcasecmp(url,"") == 0)	D_RETURN;	
	real_add_bookmark(skipstone->title,(gchar *)url,skipstone);
     	D_RETURN;
}

void add_bookmark_with_info(gchar *title, gchar *url, SkipStone *skipstone)
{
     	D_ENTER;
     	g_return_if_fail(skipstone != NULL);
     	real_add_bookmark(title,url,skipstone);
     	D_RETURN;
}

static void real_add_bookmark(gchar *title, gchar *url, SkipStone *skipstone)
{
	BookmarkData *data;
        GNode *root;
        GNode *menu_bookmarks;
	GSList *l;
     	
     	D_ENTER;
	
     	root = g_node_first_sibling(bookmarks);
        menu_bookmarks = g_node_nth_child(root,0);

	data = g_new0(BookmarkData,1);

	data->url = g_strdup(url);
	data->label = g_strdup(title);
	data->type = 1;

	g_node_append_data(menu_bookmarks,data);

       
	if (config.notebook) {
		generate_bookmark_ui(skipstone);
	}
     
     	/* any other stand alone ones exist? */
     	for (l = window_count; l; l = l->next) {
			SkipStone *skipstone = l->data;
	     		if (!skipstone->is_notebook)
				generate_bookmark_ui(skipstone);
	}


	write_bookmarks();
	D_RETURN;
}

static void edit_bookmarks(GtkWidget *menuitem,gpointer user_data) {
	BookmarkWindow *bwin;
	GtkWidget *window;
	GtkWidget *vbox1;
	GtkWidget *scrolled_window;
	GtkWidget *ctree;
	GtkCTreeNode *menu_node;
	GtkCTreeNode *toolbar_node;
	GtkWidget *hbox1;
	GtkWidget *text_label;
	GtkWidget *text_entry;
	GtkWidget *url_label;
	GtkWidget *url_entry;
	GtkWidget *hbox2;
	GtkWidget *hbox3;
	GtkWidget *add_button;
	GtkWidget *update_button;
	GtkWidget *remove_button;
	GtkWidget *hbox4;
	GtkWidget *add_folder_button;
	GtkWidget *folder_entry;
	GtkWidget *cancel_button;
	GtkWidget *ok_button;
	GNode *root;
	GNode *menu_bookmarks;
	GNode *toolbar_bookmarks;
	BookmarkCTreeData ctree_data;
	BookmarkData *menu_node_data;
	BookmarkData *toolbar_node_data;

	gchar *titles[] = {_("Text"),_("Url")};
	gchar *menur[] = {_("Menu"),""};
	gchar *toolbarr[] = {_("Toolbar"),""};

     	D_ENTER;
        if (bmark_window) {
	     gdk_window_raise(bmark_window->window);
	     return;
	}
	bwin = g_new0(BookmarkWindow,1);
	menu_node_data = g_new0(BookmarkData,1);
	menu_node_data->label = g_strdup(_("Menu"));
	menu_node_data->url = NULL;
	menu_node_data->type = 0;
	toolbar_node_data = g_new0(BookmarkData,1);
	toolbar_node_data->label = g_strdup(_("Toolbar"));
	toolbar_node_data->url = NULL;
	toolbar_node_data->type = 0;

	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        skipstone_window_set_icon(window);
	g_object_set_data(G_OBJECT(window),"window",window);
	gtk_window_set_title(GTK_WINDOW(window),_("Edit Bookmarks"));
	gtk_widget_set_usize(window,500,400);

	vbox1 = gtk_vbox_new(FALSE,0);
	gtk_widget_show(vbox1);
	gtk_container_add(GTK_CONTAINER(window),vbox1);

	scrolled_window = gtk_scrolled_window_new(NULL,NULL);
	gtk_widget_show(scrolled_window);
	gtk_box_pack_start(GTK_BOX(vbox1),scrolled_window,TRUE,TRUE,0);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);

	ctree = gtk_ctree_new_with_titles(2,0,titles);
	gtk_container_add(GTK_CONTAINER(scrolled_window),ctree);
	gtk_clist_set_column_width(GTK_CLIST(ctree),0,149);
	gtk_clist_set_column_width(GTK_CLIST(ctree),1,80);
	gtk_clist_column_titles_show(GTK_CLIST(ctree));
	gtk_clist_set_reorderable(GTK_CLIST(ctree),TRUE);

	menu_node = gtk_ctree_insert_node(GTK_CTREE(ctree),NULL,NULL,menur,0,NULL,NULL,NULL,NULL,FALSE,TRUE);
	gtk_ctree_node_set_row_data(GTK_CTREE(ctree),menu_node,menu_node_data);
	gtk_ctree_node_set_selectable(GTK_CTREE(ctree),menu_node,FALSE);
	toolbar_node = gtk_ctree_insert_node(GTK_CTREE(ctree),NULL,NULL,toolbarr,0,NULL,NULL,NULL,NULL,FALSE,TRUE);
	gtk_ctree_node_set_row_data(GTK_CTREE(ctree),toolbar_node,toolbar_node_data);
	gtk_ctree_node_set_selectable(GTK_CTREE(ctree),toolbar_node,FALSE);

	root = g_node_first_sibling(bookmarks);

	menu_bookmarks = g_node_nth_child(root,0);
	toolbar_bookmarks = g_node_nth_child(root,1);

	ctree_data.ctree = ctree;

	if (menu_bookmarks != NULL) {
		ctree_data.parent = menu_node;
		g_node_children_foreach(menu_bookmarks,G_TRAVERSE_ALL,(GNodeForeachFunc)generate_bookmark_ctree,&ctree_data);
	}
	if (toolbar_bookmarks != NULL) {
		ctree_data.parent = toolbar_node;
		g_node_children_foreach(toolbar_bookmarks,G_TRAVERSE_ALL,(GNodeForeachFunc)generate_bookmark_ctree,&ctree_data);
	}

	gtk_widget_show(ctree);

	g_signal_connect(G_OBJECT(ctree),"tree_select_row",G_CALLBACK(on_bookmark_ctree_select_row),bwin);
	g_signal_connect(G_OBJECT(ctree),"tree_unselect_row",G_CALLBACK(on_bookmark_ctree_unselect_row),bwin);
	g_signal_connect(G_OBJECT(ctree),"tree_move",G_CALLBACK(on_bookmark_ctree_move),bwin);
	g_signal_connect(G_OBJECT(ctree),"drag_motion",G_CALLBACK(on_bookmark_ctree_drag_motion),bwin);
	g_signal_connect(G_OBJECT(ctree),"drag_end",G_CALLBACK(on_bookmark_ctree_drag_end),bwin);

	hbox1 = gtk_hbox_new(FALSE,0);
	gtk_widget_show(hbox1);
	gtk_box_pack_start(GTK_BOX(vbox1),hbox1,FALSE,FALSE,0);
	gtk_container_set_border_width(GTK_CONTAINER(hbox1),2);

	text_label = gtk_label_new(_("Text:"));
	gtk_widget_show(text_label);
	gtk_box_pack_start(GTK_BOX(hbox1),text_label,TRUE,FALSE,0);

	text_entry = gtk_entry_new();
	gtk_widget_show(text_entry);
	gtk_box_pack_start(GTK_BOX(hbox1),text_entry,TRUE,TRUE,0);

	url_label = gtk_label_new(_("Url:"));
	gtk_widget_show(url_label);
	gtk_box_pack_start(GTK_BOX(hbox1),url_label,TRUE,FALSE,0);

	url_entry = gtk_entry_new();
	gtk_widget_show(url_entry);
	gtk_box_pack_start(GTK_BOX(hbox1),url_entry,TRUE,TRUE,0);

	hbox2 = gtk_hbox_new(FALSE,0);
	gtk_widget_show(hbox2);
	gtk_box_pack_start(GTK_BOX(vbox1),hbox2,FALSE,FALSE,0);
	gtk_container_set_border_width(GTK_CONTAINER(hbox2),2);

	add_button = gtk_button_new_from_stock(GTK_STOCK_ADD);
	gtk_widget_show(add_button);
	gtk_box_pack_start(GTK_BOX(hbox2),add_button,TRUE,TRUE,5);
	g_signal_connect(G_OBJECT(add_button),"clicked",G_CALLBACK(on_bookmark_add_button_clicked),bwin);

	update_button = gtk_button_new_with_label(_("Update"));
	gtk_widget_show(update_button);
	gtk_box_pack_start(GTK_BOX(hbox2),update_button,TRUE,TRUE,5);
	g_signal_connect(G_OBJECT(update_button),"clicked",G_CALLBACK(on_bookmark_update_button_clicked),bwin);

	remove_button = gtk_button_new_from_stock(GTK_STOCK_REMOVE);
	gtk_widget_show(remove_button);
	gtk_box_pack_start(GTK_BOX(hbox2),remove_button,TRUE,TRUE,5);
	g_signal_connect(G_OBJECT(remove_button),"clicked",G_CALLBACK(on_bookmark_remove_button_clicked),bwin);

	hbox3 = gtk_hbox_new(FALSE,0);
	gtk_widget_show(hbox3);
	gtk_box_pack_start(GTK_BOX(vbox1),hbox3,FALSE,FALSE,0);

	add_folder_button = gtk_button_new_with_label(_("Add Folder"));
	gtk_widget_show(add_folder_button);
	gtk_box_pack_start(GTK_BOX(hbox3),add_folder_button,TRUE,TRUE,5);
	g_signal_connect(G_OBJECT(add_folder_button),"clicked",G_CALLBACK(on_bookmark_add_folder_button_clicked),bwin);

	folder_entry = gtk_entry_new();
	gtk_widget_show(folder_entry);
	gtk_box_pack_start(GTK_BOX(hbox3),folder_entry,TRUE,TRUE,5);

	hbox4 = gtk_hbox_new(FALSE,0);
	gtk_widget_show(hbox4);
	gtk_box_pack_start(GTK_BOX(vbox1),hbox4,FALSE,FALSE,0);
	gtk_container_set_border_width(GTK_CONTAINER(hbox4),2);

	cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
	gtk_widget_show(cancel_button);
	gtk_box_pack_end(GTK_BOX(hbox4),cancel_button,TRUE,TRUE,5);
	g_signal_connect(G_OBJECT(cancel_button),"clicked",G_CALLBACK(on_bookmark_cancel_button_clicked),bwin);

	ok_button = gtk_button_new_from_stock(GTK_STOCK_OK);
	gtk_widget_show(ok_button);
	gtk_box_pack_end(GTK_BOX(hbox4),ok_button,TRUE,TRUE,5);
	g_signal_connect(G_OBJECT(ok_button),"clicked",G_CALLBACK(on_bookmark_ok_button_clicked),bwin);

	gtk_widget_show(window);
	g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(on_bookmark_delete_event),bwin);
	setup_escape_key_handler(window);
     
	bwin->window = window;
        bmark_window = window;
	bwin->scrolled_window = scrolled_window;
	bwin->ctree = ctree;
	bwin->menu_node = menu_node;
	bwin->toolbar_node = toolbar_node;
	bwin->text_entry = text_entry;
	bwin->url_entry = url_entry;
	bwin->folder_entry = folder_entry;

	D_RETURN;
}

static void generate_bookmark_ctree(GNode *node,BookmarkCTreeData *ctree_data) {
	BookmarkData *data;
	gchar *ctree_entry[2];
	GtkCTreeNode *ctree_node;

     	D_ENTER;
     
     	data =  node->data;
     
     	if (node == NULL)  D_RETURN;
	
	

	ctree_entry[0] = data->label;
	ctree_entry[1] = data->url;

	ctree_node = gtk_ctree_insert_node(GTK_CTREE(ctree_data->ctree),ctree_data->parent,NULL,ctree_entry,0,NULL,NULL,NULL,NULL,FALSE,TRUE);
	gtk_ctree_node_set_row_data(GTK_CTREE(ctree_data->ctree),ctree_node,data);

	if (data->type == 0) {
		BookmarkCTreeData new_ctree_data;
		new_ctree_data.ctree = ctree_data->ctree;
		new_ctree_data.parent = ctree_node;
		g_node_children_foreach(node,G_TRAVERSE_ALL,(GNodeForeachFunc)generate_bookmark_ctree,&new_ctree_data);
	}

	D_RETURN;
}

static void on_bookmark_ctree_select_row(GtkWidget *ctree,GtkCTreeNode *node,gint col,BookmarkWindow *bwin) {
	BookmarkData *bmark;
     	D_ENTER;
     	bmark = gtk_ctree_node_get_row_data(GTK_CTREE(bwin->ctree),node);

     	if (bmark == NULL) D_RETURN;
	
     	switch (bmark->type) {
		case 0:
			gtk_entry_set_text(GTK_ENTRY(bwin->folder_entry),bmark->label);
			break;
		case 1:
		        gtk_entry_set_text(GTK_ENTRY(bwin->text_entry),bmark->label);
		        gtk_entry_set_text(GTK_ENTRY(bwin->url_entry),bmark->url);
			break;
		case 2:
		        gtk_entry_set_text(GTK_ENTRY(bwin->text_entry),"");
		        gtk_entry_set_text(GTK_ENTRY(bwin->url_entry),"");
			break;
		default:
			break;
	}
	D_RETURN;
}

struct BookmarkNode {
   BookmarkWindow *bwin;
   GtkCTreeNode *node;
   GtkCTreeNode *parent;
   GtkCTreeNode *sibling;
};

static gint idle_move_node (gpointer data) {
	struct BookmarkNode *bnode = data;

	if (bnode) {
		BookmarkWindow *bwin = bnode->bwin;
		if (bwin)
			gtk_ctree_move(GTK_CTREE(bwin->ctree),bnode->node,bnode->parent,bnode->sibling);
	}

	g_free (bnode);

	D_RETURN_( FALSE );
}

static void move_node_to_specified_pos (BookmarkWindow *bwin,GtkCTreeNode *node,GtkCTreeNode *parent,GtkCTreeNode *sibling) {
	struct BookmarkNode *bnode;
	D_ENTER;
	g_return_if_fail (bwin && node && parent);

	bnode = g_new0(struct BookmarkNode,1);
	bnode->bwin = bwin;
	bnode->node = node;
	bnode->parent = parent;
	bnode->sibling = sibling;
	gtk_idle_add(idle_move_node,bnode);

	D_RETURN;
}

static void on_bookmark_ctree_unselect_row(GtkWidget *ctree,GtkCTreeNode *node,gint col,BookmarkWindow *bwin) {
     	D_ENTER;
        gtk_entry_set_text(GTK_ENTRY(bwin->text_entry),"");
        gtk_entry_set_text(GTK_ENTRY(bwin->url_entry),"");
        gtk_entry_set_text(GTK_ENTRY(bwin->folder_entry),"");
	D_RETURN;
}

static void on_bookmark_ctree_move(GtkWidget *ctree,GtkCTreeNode *node,GtkCTreeNode *parent,GtkCTreeNode *sibling,BookmarkWindow *bwin) {
	BookmarkData *parent_data;
	BookmarkData *data;
	D_ENTER;
	if (!parent) {
		move_node_to_specified_pos (bwin, node, GTK_CTREE_ROW(node)->parent, GTK_CTREE_ROW(node)->sibling);
		D_RETURN;
	}

	parent_data = gtk_ctree_node_get_row_data(GTK_CTREE(bwin->ctree),parent);
	data = gtk_ctree_node_get_row_data(GTK_CTREE(bwin->ctree),node);

	if (parent_data->type != 0) {
		move_node_to_specified_pos (bwin, node, GTK_CTREE_ROW(parent)->parent, GTK_CTREE_ROW(parent)->sibling);
	}

	D_RETURN;
}

static gboolean scrolling_is_desirable(BookmarkWindow *bwin,gint x,gint y) {
	GtkCTree *dirtree;
	GtkAdjustment *vadj;
	D_ENTER;
	dirtree = GTK_CTREE(bwin->ctree);

	vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(bwin->scrolled_window));

	if (y < AUTO_SCROLL_EDGE + AUTO_SCROLL_TITLE_HEIGHT) {
		if (vadj->value > vadj->lower)
			D_RETURN_( TRUE );
	} else {
		if (y > (vadj->page_size - AUTO_SCROLL_EDGE)){
			if (vadj->value < vadj->upper - vadj->page_size)
				D_RETURN_( TRUE );
		}
	}

	D_RETURN_(  FALSE );
}

static gboolean timeout_auto_scroll(gpointer data) {
	BookmarkWindow *bwin = data;
	GtkAdjustment *vadj;
	gfloat vpos;
	D_ENTER;
	vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(bwin->scrolled_window));

	if (drag_motion_y < AUTO_SCROLL_EDGE + AUTO_SCROLL_TITLE_HEIGHT) {
		vpos = vadj->value - vadj->step_increment;
		if (vpos < vadj->lower)
			vpos = vadj->lower;

		gtk_adjustment_set_value(vadj, vpos);
	} else {
		vpos = vadj->value + vadj->step_increment;
		if (vpos > vadj->upper - vadj->page_size)
			vpos = vadj->upper - vadj->page_size;

		gtk_adjustment_set_value(vadj, vpos);
	}

	D_RETURN_( TRUE );
}

static void cancel_auto_scroll(BookmarkWindow *bwin) {
     	D_ENTER;
	g_return_if_fail(bwin);
	if (scroll_timer_id != -1){
		gtk_timeout_remove(scroll_timer_id);
		scroll_timer_id = -1;
	}
     	D_RETURN;
}

static void on_bookmark_ctree_drag_motion(GtkWidget *ctree,GdkDragContext *context,gint x, gint y,gint time,BookmarkWindow *bwin) {
     	D_ENTER;
	g_return_if_fail (bwin);
	cancel_auto_scroll (bwin);
	drag_motion_x = x;
	drag_motion_y = y;
	if (scrolling_is_desirable(bwin,x,y))
		scroll_timer_id = gtk_timeout_add(AUTO_SCROLL_INTERVAL,timeout_auto_scroll,bwin);
     	D_RETURN;
}

static void on_bookmark_ctree_drag_end(GtkWidget *ctree,GdkDragContext *context,BookmarkWindow *bwin) {
	D_ENTER;
     	g_return_if_fail(bwin);
	cancel_auto_scroll(bwin);
     	D_RETURN;
}


static void on_bookmark_add_button_clicked(GtkWidget *button,BookmarkWindow *bwin) {
	BookmarkData *data;
	gchar *ctree_entry[2];
	GtkCTreeNode *node;
	
     	D_ENTER;
     
	data = g_new0(BookmarkData,1);

	data->label = ctree_entry[0] = g_strstrip(g_strdup(gtk_entry_get_text(GTK_ENTRY(bwin->text_entry))));
	data->url = ctree_entry[1] = g_strstrip(g_strdup(gtk_entry_get_text(GTK_ENTRY(bwin->url_entry))));
	data->type = 1;

	

	if (g_strcasecmp(ctree_entry[0],"") == 0 || g_strcasecmp(ctree_entry[1],"") == 0) {
		data->type = 2;
	}

	node = gtk_ctree_insert_node(GTK_CTREE(bwin->ctree),bwin->menu_node,NULL,ctree_entry,0,NULL,NULL,NULL,NULL,TRUE,FALSE);
	gtk_ctree_node_set_row_data(GTK_CTREE(bwin->ctree),node,data);

	D_RETURN;
}

static void on_bookmark_update_button_clicked(GtkWidget *button,BookmarkWindow *bwin) {
	BookmarkData *data;
	BookmarkData *new_data;
	GList *selection;
	GtkCTreeNode *node;
     
     	D_ENTER;

	selection = GTK_CLIST(bwin->ctree)->selection;

	if (g_list_length(selection) == 0) {
		D_RETURN;
	}

	node = g_list_nth_data(selection,0);

	data = gtk_ctree_node_get_row_data(GTK_CTREE(bwin->ctree),node);
	g_free(data->label);
	g_free(data->url);
	g_free(data);

	new_data = g_new0(BookmarkData,1);

	new_data->label = g_strstrip(g_strdup(gtk_entry_get_text(GTK_ENTRY(bwin->text_entry))));
	new_data->url = g_strstrip(g_strdup(gtk_entry_get_text(GTK_ENTRY(bwin->url_entry))));
	new_data->type = 1;

	if (g_strcasecmp(new_data->label,"") == 0 || g_strcasecmp(new_data->url,"") == 0) {
		new_data->type = 2;
	}

	gtk_ctree_node_set_text(GTK_CTREE(bwin->ctree),node,0,new_data->label);
	gtk_ctree_node_set_text(GTK_CTREE(bwin->ctree),node,1,new_data->url);
	gtk_ctree_node_set_row_data(GTK_CTREE(bwin->ctree),node,new_data);

	D_RETURN;
}

static void on_bookmark_remove_button_clicked(GtkWidget *button,BookmarkWindow *bwin) {
	GList *selection;
	GtkCTreeNode *node;

     	D_ENTER;
     
	selection = GTK_CLIST(bwin->ctree)->selection;

	if (g_list_length(selection) == 0) D_RETURN;
	

	node = g_list_nth_data(selection,0);
	gtk_ctree_post_recursive(GTK_CTREE(bwin->ctree),node,(GtkCTreeFunc)remove_tree_node,NULL);
	gtk_ctree_remove_node(GTK_CTREE(bwin->ctree),node);

	D_RETURN;
}

static void remove_tree_node(GtkWidget *ctree,GtkCTreeNode *node,gpointer user_data) {
	BookmarkData *data;    
     	D_ENTER;     
     	
     	data = gtk_ctree_node_get_row_data(GTK_CTREE(ctree),node);

     	if (data->label != NULL) g_free(data->label);	
	if (data->url != NULL) g_free(data->url);
	
	g_free(data);
	D_RETURN;
}

static void on_bookmark_add_folder_button_clicked(GtkWidget *button,BookmarkWindow *bwin) {
	BookmarkData *data;
	gchar *ctree_entry[2];
	GtkCTreeNode *node;

     	D_ENTER;
     
	data = g_new0(BookmarkData,1);
	data->url = NULL;
	data->label = ctree_entry[0] = g_strstrip(g_strdup(gtk_entry_get_text(GTK_ENTRY(bwin->folder_entry))));
	data->type = 0;

	if (g_strcasecmp(ctree_entry[0],"") == 0) {
		g_free(ctree_entry[0]);
		D_RETURN;
	}

	ctree_entry[1] = "";

	node = gtk_ctree_insert_node(GTK_CTREE(bwin->ctree),bwin->menu_node,NULL,ctree_entry,0,NULL,NULL,NULL,NULL,FALSE,TRUE);
	gtk_ctree_node_set_row_data(GTK_CTREE(bwin->ctree),node,data);

	D_RETURN;
}

static void on_bookmark_cancel_button_clicked(GtkWidget *button,BookmarkWindow *bwin) {
	D_ENTER;
     	close_bookmark_window(bwin);
	D_RETURN;
}

static void on_bookmark_ok_button_clicked(GtkWidget *button,BookmarkWindow *bwin) {
	GNode *menu_node;
	GNode *toolbar_node;
	GSList *l;
	
     	D_ENTER;
     
	bookmarks = NULL;
	bookmarks = g_node_new(NULL);

	menu_node = gtk_ctree_export_to_gnode(GTK_CTREE(bwin->ctree),NULL,NULL,bwin->menu_node,(GtkCTreeGNodeFunc)read_bookmarks_from_ctree,NULL);
	toolbar_node = gtk_ctree_export_to_gnode(GTK_CTREE(bwin->ctree),NULL,NULL,bwin->toolbar_node,(GtkCTreeGNodeFunc)read_bookmarks_from_ctree,NULL);
 
	g_node_append(bookmarks,menu_node);
	g_node_append(bookmarks,toolbar_node);

	write_bookmarks();



	if (config.notebook) {
		SkipStone *skipstone = get_current_browser_from_notebook();
	     	if (!skipstone)
	       		D_RETURN;
		generate_bookmark_ui(skipstone);
	} 
     	
     	for (l = window_count; l ; l = l->next) {
			SkipStone *skipstone = l->data;
	     		if (!skipstone->is_notebook)
				generate_bookmark_ui(skipstone);
	}
	

	close_bookmark_window(bwin);
	D_RETURN;
}

static void on_bookmark_delete_event(GtkWidget *widget,GdkEvent *event,BookmarkWindow *bwin) {
	D_ENTER;
     	close_bookmark_window(bwin);
	D_RETURN;
}

static void close_bookmark_window(BookmarkWindow *bwin) {
     	D_ENTER;
	gtk_widget_destroy(bwin->window);
	g_free(bwin);
        bmark_window=NULL;
	D_RETURN;
}

static gboolean read_bookmarks_from_ctree(GtkCTree *ctree,gint depth,GNode *gnode,GtkCTreeNode *cnode,gpointer user_data) {
	BookmarkData *data;

     	D_ENTER;
     
	if (!cnode || !gnode) D_RETURN_( FALSE );
			
	data = g_new0(BookmarkData,1);
	data = gtk_ctree_node_get_row_data(GTK_CTREE(ctree),cnode);
	gnode->data = data;

	D_RETURN_ ( TRUE );
}

static void make_bookmark_menu(GNode *node,BookmarkFuncData *funcdata) {
	BookmarkData *data = node->data;
	GtkWidget *menu_item;
	GtkWidget *menu;
	BookmarkFuncData new_funcdata;

	GtkWidget *box1;
	GtkTooltips *tooltip;

     	D_ENTER;
     
	if (node == NULL) D_RETURN;       

	switch (data->type) {
		case 0:
			 menu_item = gtk_menu_item_new();
			 box1 = xpm_label_box( funcdata->widget, MINI_FOLDER, data->label);
             gtk_container_add (GTK_CONTAINER (menu_item), box1);
             gtk_widget_show_all(menu_item);
			gtk_menu_append(GTK_MENU(funcdata->widget),menu_item);
	
			menu = gtk_menu_new();
			gtk_widget_show(menu);
			gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),menu);
			new_funcdata.widget = menu;
			new_funcdata.skipstone = funcdata->skipstone;
			menu_item = gtk_menu_item_new_with_label(_("Open All Bookmarks Here"));
	     		g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(open_all_folder_cb), menu);
	     		gtk_menu_append(GTK_MENU(menu), menu_item);
	     		gtk_widget_show(menu_item);
	     		menu_item = gtk_menu_item_new();
	     		gtk_widget_show(menu_item);
	     		gtk_menu_append(GTK_MENU(menu), menu_item);
			g_node_children_foreach(node,G_TRAVERSE_ALL,(GNodeForeachFunc)make_bookmark_menu,&new_funcdata);
			break;
		case 1:
			 menu_item = gtk_menu_item_new();
			 box1 = xpm_label_box( funcdata->widget, MINI_LINK, data->label);
             gtk_container_add (GTK_CONTAINER (menu_item), box1);
             gtk_widget_show_all(menu_item);
			gtk_menu_append(GTK_MENU(funcdata->widget),menu_item);
			g_object_set_data(G_OBJECT(menu_item),"bmark",data);
			g_signal_connect(G_OBJECT(menu_item),"button_press_event",G_CALLBACK(bookmark_activate), funcdata->skipstone);

			tooltip = gtk_tooltips_new();
			gtk_tooltips_set_tip( tooltip, menu_item, data->url, NULL );
			break;
		case 2:
			menu_item = gtk_menu_item_new();
			gtk_widget_show(menu_item);
			gtk_menu_append(GTK_MENU(funcdata->widget),menu_item);
			break;
		default:
			break;
	}

	D_RETURN;
}

static GtkWidget *xpm_label_box( GtkWidget *parent,
                          gchar     *xpm_filename,
                          gchar     *label_text )
{
    GtkWidget *box1;
    GtkWidget *label;
    GtkWidget *mini_folder;
    gint loaded;
    /* Create box for xpm and label */
    box1 = gtk_hbox_new (FALSE, 0);
/*    gtk_container_set_border_width (GTK_CONTAINER (box1), 2);*/

    mini_folder = create_pixmap(parent,xpm_filename,&loaded);
    /* Create a label for the button */
    label = gtk_label_new (label_text);

    /* Pack the pixmap and label into the box */
    gtk_box_pack_start (GTK_BOX (box1),
                        mini_folder, FALSE, FALSE, 1);

    gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 1);

    return(box1);
}

static void make_bookmark_toolbar(GNode *node,BookmarkFuncData *funcdata) {
	BookmarkData *data = node->data;
	GtkWidget *widget = NULL;
	GtkWidget *menu;
	BookmarkFuncData new_funcdata;
     
	GtkWidget *box1;

     	D_ENTER;

	if (node == NULL) D_RETURN;
	

	switch (data->type) {
		case 0:

			menu = gtk_menu_new();
			gtk_widget_show(menu);
			new_funcdata.widget = menu;
			new_funcdata.skipstone = funcdata->skipstone;

			g_node_children_foreach(node,G_TRAVERSE_ALL,(GNodeForeachFunc)make_bookmark_menu,&new_funcdata);

			widget = gtk_button_new();
			gtk_button_set_relief(GTK_BUTTON(widget),GTK_RELIEF_NONE);
			g_signal_connect(G_OBJECT(widget),"button_press_event",G_CALLBACK(open_bookmark_menu),menu);
                        box1 = xpm_label_box( funcdata->widget, MINI_FOLDER, data->label);
                        gtk_container_add (GTK_CONTAINER (widget), box1);
                        gtk_widget_show_all(widget);
			gtk_toolbar_append_widget(GTK_TOOLBAR(funcdata->widget),widget,data->label,"");
			break;
		case 1:
			widget = gtk_button_new();
			gtk_button_set_relief(GTK_BUTTON(widget),GTK_RELIEF_NONE);	
			g_signal_connect(G_OBJECT(widget), "button_press_event", G_CALLBACK(click_on_bookmark_from_toolbar), funcdata->skipstone);
		     	g_object_set_data(G_OBJECT(widget),"bmark",data);
			box1 = xpm_label_box( funcdata->widget, MINI_LINK, data->label);
                        gtk_container_add (GTK_CONTAINER (widget), box1);
                        gtk_widget_show_all(widget);
			gtk_toolbar_append_widget(GTK_TOOLBAR(funcdata->widget),widget,data->url,"");
			break;
		case 2:
			widget = gtk_label_new("|");
			gtk_widget_show(widget);
			gtk_toolbar_append_widget(GTK_TOOLBAR(funcdata->widget),widget,"","");
			break;
		default:
			break;
	}
	if (funcdata->skipstone->is_notebook) {
		bmark_toolbar_widgets = g_slist_append(bmark_toolbar_widgets,widget);
	} else {
		funcdata->skipstone->bookmark_toolbar_widgets = g_slist_append(funcdata->skipstone->bookmark_toolbar_widgets,widget);
	}


	D_RETURN;
}

static void click_on_bookmark_from_toolbar(GtkWidget *button, GdkEventButton *event, SkipStone *skipstone)
{
     
     	D_ENTER;

	if (skipstone->is_notebook) {		
	     	skipstone = get_current_browser_from_notebook();
	     	if (!skipstone)
	       		D_RETURN;
	     
	}

     	if (event->button == 2) {
	     	
	     	BookmarkData *bmark = g_object_get_data(G_OBJECT(button),"bmark");
	     	make_window(bmark->url);

	} else if (event->button == 1) {
	
	     	BookmarkData *bmark = g_object_get_data(G_OBJECT(button),"bmark");
	     	_skipstone_load_url(skipstone,bmark->url);

	}
     	D_RETURN;
}


static void open_all_folder_cb(GtkWidget *menuitem, GtkWidget *menu)
{
     	GList *c = NULL, *l = NULL;
     
     	D_ENTER;
     
     	c = gtk_container_children (GTK_CONTAINER(menu));
     	if (c == NULL) D_RETURN;
     	for (l=c;l;l=l->next) {
	     	GtkWidget *m;
	     	BookmarkData *bmark;
	     	if (!l->data || l->data == NULL) continue;
	     	m = l->data;
	     	bmark = g_object_get_data(G_OBJECT(m), "bmark");
	     	if (bmark && bmark->url)
	       		make_window(bmark->url);
	}
     	D_RETURN;
}

static void open_bookmark_menu(GtkWidget *widget,GdkEventButton *event,GtkWidget *menu) {
     	D_ENTER;
     	if (event->button == 1 || event->button == 3) {
		gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,GDK_BUTTON1_MASK,gtk_get_current_event_time());
	} else if (event->button == 2) {
	     	open_all_folder_cb(NULL,menu);
	}		     		     	
	D_RETURN;
}


void generate_bookmark_ui(SkipStone *skipstone) {
	GtkWidget *bookmark_add,*bookmark_edit,*sep;
	GSList *l = NULL;
	GNode *menu_bookmarks;
	GNode *toolbar_bookmarks;
	GNode *root;
	BookmarkFuncData funcdata;

     	D_ENTER;

	if (skipstone->bookmark_menu != NULL) {
		gtk_widget_destroy(skipstone->bookmark_menu);
	}

	if (skipstone->is_notebook && bmark_toolbar_widgets != NULL) {
		for (l = bmark_toolbar_widgets; l; l = l->next) {
		     	GtkWidget *widget = (GtkWidget *)l->data;
		     	if (GTK_IS_WIDGET(widget))
				gtk_widget_destroy(widget);
			
		}
		g_slist_free(bmark_toolbar_widgets);
		bmark_toolbar_widgets = NULL;
	} else {
		if (skipstone->bookmark_toolbar_widgets != NULL) {
		     	for (l = skipstone->bookmark_toolbar_widgets; l; l=l->next) {
			     	GtkWidget *widget = (GtkWidget *)l->data;
				if (GTK_IS_WIDGET(widget))
				     	gtk_widget_destroy(widget);				
			}
			g_slist_free(skipstone->bookmark_toolbar_widgets);
			skipstone->bookmark_toolbar_widgets = NULL;
		}
	}

	root = g_node_first_sibling(bookmarks);

	menu_bookmarks = g_node_nth_child(root,0);
	toolbar_bookmarks = g_node_nth_child(root,1);


	skipstone->bookmark_menu = gtk_menu_new();
	gtk_widget_show(skipstone->bookmark_menu);
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(skipstone->bookmark_menubar_item),skipstone->bookmark_menu);

	bookmark_add = gtk_image_menu_item_new_with_label(_("Add Bookmark"));
        gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(bookmark_add), gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
	gtk_widget_show(bookmark_add);
	g_signal_connect(G_OBJECT(bookmark_add),"activate",G_CALLBACK(add_bookmark),skipstone);
	gtk_menu_append(GTK_MENU(skipstone->bookmark_menu),bookmark_add);

	
     	bookmark_edit = gtk_menu_item_new_with_label(_("Edit Bookmarks"));
	gtk_widget_show(bookmark_edit);
	g_signal_connect(G_OBJECT(bookmark_edit),"activate",G_CALLBACK(edit_bookmarks),NULL);
	gtk_menu_append(GTK_MENU(skipstone->bookmark_menu),bookmark_edit);

	sep = gtk_menu_item_new();
	gtk_widget_show(sep);
	gtk_menu_append(GTK_MENU(skipstone->bookmark_menu), sep);

	funcdata.skipstone = skipstone;

	if (menu_bookmarks != NULL) {
		funcdata.widget = skipstone->bookmark_menu;
		g_node_children_foreach(menu_bookmarks,G_TRAVERSE_ALL,(GNodeForeachFunc)make_bookmark_menu,&funcdata);
	}
	if (toolbar_bookmarks != NULL) {
		funcdata.widget = skipstone->bookmark_toolbar;
		g_node_children_foreach(toolbar_bookmarks,G_TRAVERSE_ALL,(GNodeForeachFunc)make_bookmark_toolbar,&funcdata);
	}

	D_RETURN;
}
