#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#include "../include/string.h"

#include "guiutils.h"
#include "cdialog.h"
#include "fb.h"
#include "progressdialog.h"

#include "cfg.h"
#include "edv_types.h"
#include "edv_list_cb.h"
#include "edv_date.h"
#include "edv_mime_type.h"
#include "edv_mime_types_list.h"
#include "edv_history.h"
#include "edv_history_list.h"
#include "history_win.h"
#include "endeavour2.h"
#include "edv_cb.h"
#include "edv_utils.h"
#include "edv_utils_gtk.h"
#include "edv_cfg_list.h"
#include "config.h"

#include "images/icon_search_20x20.xpm"
#include "images/icon_executable_20x20.xpm"
#include "images/icon_new_20x20.xpm"
#include "images/icon_copy_file_20x20.xpm"
#include "images/icon_move_file_20x20.xpm"
#include "images/icon_link2_20x20.xpm"
#include "images/icon_chmod_20x20.xpm"
#include "images/icon_owned_20x20.xpm"
#include "images/icon_time_stamp_20x20.xpm"
#include "images/icon_download_file_20x20.xpm"
#include "images/icon_cancel_20x20.xpm"
#include "images/icon_recover_20x20.xpm"
#include "images/icon_purge_20x20.xpm"
#include "images/icon_archive_add_20x20.xpm"
#include "images/icon_archive_extract_20x20.xpm"
#include "images/icon_aid_20x20.xpm"

#include "images/icon_object_misc_20x20.xpm"
#include "images/icon_object_misc_32x32.xpm"

#include "images/icon_error_32x32.xpm"

#include "images/icon_reload_20x20.xpm"
#include "images/icon_clear_20x20.xpm"
#include "images/icon_save_as_20x20.xpm"
#include "images/icon_save_32x32.xpm"
#include "images/icon_close_20x20.xpm"

#include "images/icon_trace_48x48.xpm"


/* Callbacks */
static void EDVHistoryListItemDestroyCB(gpointer data);
static gint EDVHistoryListProgressCB(
	gpointer data, gulong pos, gulong max
);

static gint EDVHistoryWinDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
);
static gint EDVHistoryWinKeyEventCB(
	GtkWidget *widget, GdkEventKey *key, gpointer data
);
static gint EDVHistoryWinButtonPressEventCB(
	GtkWidget *widget, GdkEventButton *button, gpointer data
);
static void EDVHistoryWinSelectRowCB(
	GtkCList *clist, gint row, gint column, GdkEvent *event,
	gpointer data
);
static void EDVHistoryWinUnselectRowCB(
	GtkCList *clist, gint row, gint column, GdkEvent *event,
	gpointer data
);
static void EDVHistoryWinFindCB(
	GtkWidget *widget, gpointer data
);
static void EDVHistoryWinRefreshCB(
	GtkWidget *widget, gpointer data
);
static void EDVHistoryWinSaveAsCB(
	GtkWidget *widget, gpointer data
);
static void EDVHistoryWinClearCB(
	GtkWidget *widget, gpointer data
);
static void EDVHistoryWinCloseCB(
	GtkWidget *widget, gpointer data
);

void EDVHistoryWinWriteProtectChangedCB(
	edv_history_win_struct *lw, gboolean state
);
void EDVHistoryWinHistoryAddedCB(
	edv_history_win_struct *lw,
	gint h_num, const edv_history_struct *h_ptr
);
void EDVHistoryWinHistoryRemovedCB(
	edv_history_win_struct *lw,
	gint h_num
);
void EDVHistoryWinReconfiguredNotifyCB(
	edv_history_win_struct *lw
);


/* Operations */
void EDVHistoryWinClear(edv_history_win_struct *lw);
static gint EDVHistoryWinSave(
	edv_history_win_struct *lw, const gchar *filename,
	const gboolean append
);
void EDVHistoryWinSaveAs(edv_history_win_struct *lw);

void EDVHistoryWinUpdateDisplay(
	edv_history_win_struct *lw,
	const edv_history_struct *h_ptr
);
static void EDVHistoryWinSetRow(
	edv_history_win_struct *lw,
	gint row, const edv_history_struct *h_ptr
);
void EDVHistoryWinUpdateList(edv_history_win_struct *lw);

void EDVHistoryWinSyncConfiguration(edv_history_win_struct *lw);

void EDVHistoryWinListStylesRegenerate(edv_history_win_struct *lw);

edv_history_win_struct *EDVHistoryWinNew(edv_core_struct *core);
void EDVHistoryWinUpdateMenus(edv_history_win_struct *lw);
void EDVHistoryWinSetBusy(
	edv_history_win_struct *lw, gboolean is_busy
);
gboolean EDVHistoryWinIsMapped(edv_history_win_struct *lw);
void EDVHistoryWinMap(edv_history_win_struct *lw);
void EDVHistoryWinUnmap(edv_history_win_struct *lw);
void EDVHistoryWinDelete(edv_history_win_struct *lw);


#define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
#define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
#define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
#define STRDUP(s)       (((s) != NULL) ? g_strdup(s) : NULL)

#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define STRLEN(s)       (((s) != NULL) ? strlen(s) : 0)
#define STRISEMPTY(s)   (((s) != NULL) ? (*(s) == '\0') : TRUE)


#define LISTWIN_WIDTH		640
#define LISTWIN_HEIGHT		520

#define LISTWIN_TITLE		"History"


/*
 *	History list window GtkCList item "destroy" signal callback.
 */
static void EDVHistoryListItemDestroyCB(gpointer data)
{
	EDVHistoryDelete(EDV_HISTORY(data));
}


/*
 *	History list window save progress callback.
 */
static gint EDVHistoryListProgressCB(
	gpointer data, gulong pos, gulong max
)
{
	edv_history_win_struct *lw = EDV_HISTORY_WIN(data);
	if(lw == NULL)
	    return(-1);

	if(ProgressDialogIsQuery())
	{
	    if(ProgressDialogStopCount() > 0)
		return(-1);

	    if(max > 0)
		ProgressDialogUpdate(
		    NULL, NULL, NULL, NULL,
		    CLIP((gfloat)pos / (gfloat)max, 0.0f, 1.0f),
		    EDV_DEF_PROGRESS_BAR_TICKS, TRUE
		);
	}

	return(0);
}


/*
 *	History list window GtkWindow "delete_event" signal callback.
 */
static gint EDVHistoryWinDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
)
{
	edv_history_win_struct *lw = EDV_HISTORY_WIN(data);
	if(lw == NULL)
	    return(TRUE);

	EDVHistoryWinCloseCB(NULL, lw);

	return(TRUE);
}

/*
 *	History list window "key_press_event" or "key_release_event"
 *	signal callback.
 */
static gint EDVHistoryWinKeyEventCB(
	GtkWidget *widget, GdkEventKey *key, gpointer data
)
{
	gint status = FALSE;
	gint etype;
	guint keyval, state;
	gboolean press;
	edv_core_struct *core;
	edv_history_win_struct *lw = EDV_HISTORY_WIN(data);
	if(lw == NULL)
	    return(status);

	core = lw->core;
	if(core == NULL)
	    return(status);

	etype = key->type;
	press = (etype == GDK_KEY_PRESS) ? TRUE : FALSE;
	keyval = key->keyval;
	state = key->state;

/* Macro to emit a signal stop for a key press or release depending
 * on the current event's type
 */
#define DO_STOP_KEY_SIGNAL_EMIT	{		\
 gtk_signal_emit_stop_by_name(			\
  GTK_OBJECT(widget),				\
  press ?					\
   "key_press_event" : "key_release_event"	\
 );						\
}

/* Macro to clamp the GtkAdjustment adj and emit a "value_changed"
 * signal
 */
#define DO_ADJ_CLAMP_EMIT	{		\
 if(adj->value > (adj->upper - adj->page_size)) \
  adj->value = adj->upper - adj->page_size;	\
						\
 if(adj->value < adj->lower)			\
  adj->value = adj->lower;			\
						\
 gtk_signal_emit_by_name(			\
  GTK_OBJECT(adj), "value_changed"		\
 );						\
}

/* Macro to clamp the GtkCList clist's focus_row */
#define DO_CLIST_FOCUS_ROW_CLAMP	{	\
 if(clist->focus_row >= clist->rows)		\
  clist->focus_row = clist->rows - 1;		\
 if(clist->focus_row < 0)			\
  clist->focus_row = 0;				\
}

	if(lw->history_clist == widget)
	{
	    GtkCList *clist = GTK_CLIST(widget);
	    gint row = EDVCListGetSelectedLast(clist, NULL);

	    /* Handle by key value */
	    switch(keyval)
	    {
#if 0
	      case GDK_Return:
	      case GDK_KP_Enter:
	      case GDK_ISO_Enter:
	      case GDK_3270_Enter:
		if(press)
		{
		    EDVHistoryWinEditCB(NULL, lw);
		}
		DO_STOP_KEY_SIGNAL_EMIT
		status = TRUE;
		break;
#endif

#if 0
	      case GDK_Delete:
		if(press)
		{
		    EDVHistoryWinRemoveCB(NULL, lw);
		}
		DO_STOP_KEY_SIGNAL_EMIT
		status = TRUE;
		break;
#endif
	      case GDK_space:
	      case GDK_KP_Space:
		row = clist->focus_row;
		if((row >= 0) && (row < clist->rows) && press)
		{
		    gboolean already_selected = (g_list_find(
			clist->selection, (gpointer)row
		    ) != NULL) ? TRUE : FALSE;
		    gtk_clist_freeze(clist);
		    if(already_selected)
			gtk_clist_unselect_row(clist, row, 0);
		    else
			gtk_clist_select_row(clist, row, 0);
		    gtk_clist_thaw(clist);
		}
		DO_STOP_KEY_SIGNAL_EMIT
		status = TRUE;
		break;
	    }
	}

	return(status);
#undef DO_CLIST_FOCUS_ROW_CLAMP
#undef DO_ADJ_CLAMP_EMIT
#undef DO_STOP_KEY_SIGNAL_EMIT
}

/*
 *	History list window "button_press_event" or
 *	"button_release_event" signal callback.
 */
static gint EDVHistoryWinButtonPressEventCB(
	GtkWidget *widget, GdkEventButton *button, gpointer data
)
{
	gint status = FALSE;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core;
	edv_history_win_struct *lw = EDV_HISTORY_WIN(data);
	if(lw == NULL)
	    return(status);

	core = lw->core;
	if(core == NULL)
	    return(status);

	cfg_list = core->cfg_list;

	if(lw->history_clist == widget)
	{
	    gint row, column;
	    GtkWidget *w;
	    GtkCList *clist = GTK_CLIST(widget);

	    if(clist->clist_window != ((GdkEventAny *)button)->window)
		return(status);

	    /* Find row and column based on given coordinates */
	    if(!gtk_clist_get_selection_info(
		clist, button->x, button->y, &row, &column
	    ))
	    {
		row = -1;
		column = 0;
	    }

	    /* Handle by event type */
	    switch((gint)button->type)
	    {
	      case GDK_BUTTON_PRESS:
		/* Handle by button number */
		switch(button->button)
		{
		  case 3:	/* Map right-click menu */
		    /* Select row before mapping menu? */
		    if(EDV_GET_B(EDV_CFG_PARM_RIGHT_CLICK_MENU_SELECTS) &&
		       (row >= 0) && (row < clist->rows)
		    )
		    {
			gtk_clist_freeze(clist);
			gtk_clist_select_row(clist, row, column);
			gtk_clist_thaw(clist);
		    }

		    /* Map right-click menu */
		    w = lw->menu;
		    if(w != NULL)
			gtk_menu_popup(
			    GTK_MENU(w), NULL, NULL,
			    NULL, NULL,
			    button->button, button->time
			);

		    status = TRUE;
		    break;
		}
		break;
	    }
	}

	return(status);
}

/*
 *	History list window "select_row" signal callback.
 */
static void EDVHistoryWinSelectRowCB(
	GtkCList *clist, gint row, gint column, GdkEvent *event,
	gpointer data
)
{
	edv_core_struct *core;
	edv_history_win_struct *lw = EDV_HISTORY_WIN(data);
	if(lw == NULL)
	    return;

	core = lw->core;
	if(core == NULL)
	    return;

	/* Check which clist this event is for */
	if(GTK_WIDGET(clist) == lw->history_clist)
	{
	    /* Check if selected row is fully visible, if not then
	     * adjust scroll position to try and make it visible
	     */
	    if(gtk_clist_row_is_visible(clist, row) !=
		GTK_VISIBILITY_FULL
	    )
		gtk_clist_moveto(
		    clist,
		    row, -1,	/* Row, column */
		    0.5f, 0.0f	/* Row, column */
		);

	    /* Update displayed history */
	    EDVHistoryWinUpdateDisplay(
		lw,
		EDV_HISTORY(
		    gtk_clist_get_row_data(clist, row)
		)
	    );

	    EDVHistoryWinUpdateMenus(lw);
	}
}

/*
 *	History list window "unselect_row" signal callback.
 */
static void EDVHistoryWinUnselectRowCB(
	GtkCList *clist, gint row, gint column, GdkEvent *event,
	gpointer data
)
{
	edv_core_struct *core;
	edv_history_win_struct *lw = EDV_HISTORY_WIN(data);
	if(lw == NULL)
	    return;

	core = lw->core;
	if(core == NULL)
	    return;

	/* Check which clist this event is for */
	if(GTK_WIDGET(clist) == lw->history_clist)
	{
	    EDVHistoryWinUpdateDisplay(lw, NULL);
	    EDVHistoryWinUpdateMenus(lw);
	}
}

/*
 *	History find entry "activate" signal callback.
 */
static void EDVHistoryWinFindCB(
	GtkWidget *widget, gpointer data
)
{
	gint find_iterations = 0;
	gint row, column, sel_row;
	const gchar *expression;
	GtkEntry *entry;
	GtkCList *clist;

	gchar *cell_text;
	guint8 spacing;
	GdkPixmap *pixmap;
	GdkBitmap *mask;

	edv_history_win_struct *lw = EDV_HISTORY_WIN(data);
	if(lw == NULL)
	    return;

	entry = (GtkEntry *)lw->find_entry;
	clist = (GtkCList *)lw->history_clist;
	if((entry == NULL) || (clist == NULL))
	    return;


	/* Get string to match for from entry */
	expression = gtk_entry_get_text(entry);
	if(STRISEMPTY(expression))
	    return;

	/* Get selected row + 1 or 0 if none */
	sel_row = EDVCListGetSelectedLast(clist, NULL);
	if(sel_row < 0)
	    sel_row = 0;
	else
	    sel_row++;

	/* Iterate through rows, checking each Type column to see if
	 * there are any partial patches
	 */
	do
	{
	    /* Iterate from selected row to end */
	    for(row = sel_row; row < clist->rows; row++)
	    {
		/* Iterate through all cells on this row */
		for(column = 0; column < clist->columns; column++)
		{
		    /* Begin fetching current cell's text by its type */
		    cell_text = NULL;
		    switch(gtk_clist_get_cell_type(clist, row, column))
		    {
		      case GTK_CELL_TEXT:
			gtk_clist_get_text(clist, row, column, &cell_text);
			break;
		      case GTK_CELL_PIXTEXT:
			gtk_clist_get_pixtext(
			    clist, row, column, &cell_text,
			    &spacing, &pixmap, &mask
			);
			break;
		      case GTK_CELL_PIXMAP:
		      case GTK_CELL_WIDGET:
		      case GTK_CELL_EMPTY:
			break;
		    }
		    /* Got cell text? */
		    if(!STRISEMPTY(cell_text))
		    {
			/* Find string found inside cell text string? */
			if(strcasestr(cell_text, expression))
			    break;
		    }
		}
		/* If column iteration broke before all columns were
		 * iterated through then that implies a match was made
		 */
		if(column < clist->columns)
		    break;
	    }
	    /* Got match? */
	    if(row < clist->rows)
		break;
	    else
		find_iterations++;

	    /* Reset sel_row to 0 so that find starts at beginning */
	    sel_row = 0;

	} while(find_iterations < 2);

	/* Got match? */
	if(row < clist->rows)
	{
	    /* Select new matched row */
	    gtk_clist_freeze(clist);
	    gtk_clist_unselect_all(clist);
	    gtk_clist_select_row(clist, row, 0);
	    gtk_clist_thaw(clist);
	}
}

/*
 *	History refresh button callback.
 */
static void EDVHistoryWinRefreshCB(
	GtkWidget *widget, gpointer data
)
{
	gint last_row;
	gfloat last_x, last_y;
	GtkAdjustment *hadj, *vadj;
	GtkCList *clist;
	edv_history_win_struct *lw = EDV_HISTORY_WIN(data);
	if(lw == NULL)
	    return;

	clist = (GtkCList *)lw->history_clist;
	if(clist == NULL)
	    return;

	EDVHistoryWinSetBusy(lw, TRUE);

	/* Record last list scroll position */
	hadj = clist->hadjustment;
	last_x = (hadj != NULL) ? hadj->value : 0.0f;
	vadj = clist->vadjustment;
	last_y = (vadj != NULL) ? vadj->value : 0.0f;
	last_row = EDVCListGetSelectedLast(clist, NULL);

	/* Update list */
	EDVHistoryWinUpdateList(lw);

	/* Scroll back to original position */
	EDVScrollCListToPosition(clist, last_x, last_y);
	gtk_clist_select_row(clist, last_row, -1);

	EDVHistoryWinUpdateMenus(lw);

	EDVHistoryWinSetBusy(lw, FALSE);
}

/*
 *	History list window save button callback.
 */
static void EDVHistoryWinSaveAsCB(
	GtkWidget *widget, gpointer data
)
{
	EDVHistoryWinSaveAs(EDV_HISTORY_WIN(data));
}

/*
 *	History list window clear callback.
 */
static void EDVHistoryWinClearCB(
	GtkWidget *widget, gpointer data
)
{
	EDVHistoryWinClear(EDV_HISTORY_WIN(data));
}

/*
 *	History list window close button callback.
 */
static void EDVHistoryWinCloseCB(
	GtkWidget *widget, gpointer data
)
{
	edv_history_win_struct *lw = EDV_HISTORY_WIN(data);
	if(lw == NULL)
	    return;

	EDVHistoryWinSyncConfiguration(lw);
	EDVHistoryWinUnmap(lw);
}


/*
 *	Write protect changed signal callback.
 */
void EDVHistoryWinWriteProtectChangedCB(
	edv_history_win_struct *lw, gboolean state
)
{
	if(!EDVHistoryWinIsMapped(lw))
	    return;

	EDVHistoryWinUpdateMenus(lw);
}

/*
 *	History event added signal callback.
 */
void EDVHistoryWinHistoryAddedCB(
	edv_history_win_struct *lw,
	gint h_num, const edv_history_struct *h_ptr
)
{
	gint i, row;
	gchar **strv;
	GtkAdjustment *adj;
	GtkCList *clist;

	if(!EDVHistoryWinIsMapped(lw))
	    return;

	clist = (GtkCList *)lw->history_clist;
	if(clist == NULL)
	    return;

	if(clist->columns < 1)
	    return;

	gtk_clist_freeze(clist);

	/* Allocate row cell values */
	strv = (gchar **)g_malloc(clist->columns * sizeof(gchar *));
	for(i = 0; i < clist->columns; i++)
	    strv[i] = "";

	/* Append row? */
	if(h_num < 0)
	    row = gtk_clist_append(clist, strv);
	else
	    row = gtk_clist_insert(clist, h_num, strv);
	if(row > -1)
	{
	    gint width;
	    GtkCListColumn *column;

	    EDVHistoryWinSetRow(lw, row, h_ptr);

	    for(i = 0; i < clist->columns; i++)
	    {
		column = &clist->column[i];
		if(!column->visible)
		    continue;

		width = gtk_clist_optimal_column_width(clist, i);
		gtk_clist_set_column_width(clist, i, width);
	    }
	}

	gtk_clist_thaw(clist);

	/* Scroll to end */
	adj = clist->vadjustment;
	if((adj != NULL) && (h_num < 0))
	    gtk_adjustment_set_value(
		adj,
		MAX(
		    adj->upper - adj->page_size,
		    adj->lower
		)
	    );

	EDVHistoryWinUpdateMenus(lw);

	/* Delete row cell values */
	g_free(strv);
}

/*
 *	History event removed signal callback.
 */
void EDVHistoryWinHistoryRemovedCB(
	edv_history_win_struct *lw,
	gint h_num
)
{
	gint row;
	GtkCList *clist;


	if(!EDVHistoryWinIsMapped(lw))
	    return;

	clist = (GtkCList *)lw->history_clist;
	if(clist == NULL)
	    return;

	if(clist->columns < 1)
	    return;

	gtk_clist_freeze(clist);

	/* Remove last row? */
	if(h_num < 0)
	{
	    row = clist->rows - 1;
	    if(row > -1)
		gtk_clist_remove(clist, row);
	}
	/* Row to remove in bounds? */
	else if(h_num < clist->rows)
	{
	    row = h_num;
	    gtk_clist_remove(clist, row);
	}

	gtk_clist_thaw(clist);

	EDVHistoryWinUpdateMenus(lw);
}

/*
 *	Reconfigured notify signal callback.
 */
void EDVHistoryWinReconfiguredNotifyCB(
	edv_history_win_struct *lw
)
{
	GtkRcStyle *standard_rcstyle, *lists_rcstyle;
	GtkWidget *w;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core;


	if(lw == NULL)
	    return;

	core = lw->core;
	if(core == NULL)
	    return;

	cfg_list = core->cfg_list;
	standard_rcstyle = core->standard_rcstyle;
	lists_rcstyle = core->lists_rcstyle;


	/* Update RC styles */
	w = lw->toplevel;
	if((w != NULL) && (standard_rcstyle != NULL))
	    gtk_widget_modify_style_recursive(w, standard_rcstyle);
	w = lw->history_clist;
	if((w != NULL) && (lists_rcstyle != NULL))
	    gtk_widget_modify_style_recursive(w, lists_rcstyle);
	EDVHistoryWinListStylesRegenerate(lw);

	EDVHistoryWinUpdateMenus(lw);
}


/*
 *	Clears the history.
 */
void EDVHistoryWinClear(edv_history_win_struct *lw)
{
	gint response;
	const gchar *s;
	GtkWidget *toplevel;
	cfg_item_struct *cfg_list;
	edv_core_struct *core;

	if(lw == NULL)
	    return;

	toplevel = lw->toplevel;
	core = lw->core;
	if(core == NULL)
	    return;

	cfg_list = core->cfg_list;


	EDVHistoryWinSetBusy(lw, TRUE);

	/* Confirm clear */
	EDVPlaySoundQuestion(core);
	CDialogSetTransientFor(toplevel);
	response = CDialogGetResponse(
#if defined(PROG_LANGUAGE_SPANISH)
"Confirme Claro",
"¿Usted está seguro que usted quiere borrar todos acontecimientos\n\
de la historia?",
#elif defined(PROG_LANGUAGE_FRENCH)
"Confirmer Effacer",
"Etes-vous sûr que vous voulez effacer tous événements de l'historique?",
#elif defined(PROG_LANGUAGE_GERMAN)
"Bestätigen Sie Klar",
"Sind sie sicher sie alles geschichte ereignisse wollen löschen?",
#elif defined(PROG_LANGUAGE_ITALIAN)
"Confermare Chiaro",
"Lei sono sicuro che lei vuole cancellare tutta gli avvenimenti\n\
di storia?",
#elif defined(PROG_LANGUAGE_DUTCH)
"Bevestiig Helder",
"Bent u zeker u alle geschiedenis gebeurtenissen wil schrappen?",
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Confirme Claro",
"Estão seguro quer anular todos acontecimentos de história?",
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Bekreft Klar",
"Er De sikker de stryker all historiebegivenheter?",
#else
"Confirm Clear",
"Are you sure you want to delete all history events?",
#endif
	    NULL,
	    CDIALOG_ICON_QUESTION,
	    CDIALOG_BTNFLAG_YES | CDIALOG_BTNFLAG_NO,
	    CDIALOG_BTNFLAG_YES
	);
	CDialogSetTransientFor(NULL);
	if(response != CDIALOG_RESPONSE_YES)
	{
	    EDVHistoryWinSetBusy(lw, FALSE);
	    return;
	}

	/* Begin clearing */

	/* Delete history events file */
	s = EDV_GET_S(EDV_CFG_PARM_FILE_HISTORY);
	if(!STRISEMPTY(s))
	    unlink((const char *)s);

	EDVPlaySoundCompleted(core);     

	/* Update list */
	EDVHistoryWinUpdateList(lw);
	EDVHistoryWinUpdateDisplay(lw, NULL);
	EDVHistoryWinUpdateMenus(lw);

	EDVHistoryWinSetBusy(lw, FALSE);
}

/*
 *	Saves the current history list to file.
 *
 *	If append is TRUE then the history list will be appended to
 *	the specified file.
 */
static gint EDVHistoryWinSave(
	edv_history_win_struct *lw, const gchar *filename,
	const gboolean append
)
{
	gint row;
	FILE *fp;
	GtkCList *clist;
	const edv_history_struct *h;

	if((lw == NULL) || STRISEMPTY(filename))
	    return(-1);

	clist = (GtkCList *)lw->history_clist;
	if(clist == NULL)
	    return(-1);

	/* Open history file for writing */
	if(append)
	    fp = fopen((const char *)filename, "ab");
	else
	    fp = fopen((const char *)filename, "wb");
	if(fp == NULL)
	    return(-1);

	EDVHistoryListProgressCB(lw, 0, clist->rows);

	/* Iterate through each row, saving the the information of
	 * each cell on each row
	 */
	for(row = 0; row < clist->rows; row++)
	{
	    if(EDVHistoryListProgressCB(lw, row + 1, clist->rows))
		break;

	    h = EDV_HISTORY(
		gtk_clist_get_row_data(clist, row)
	    );

	    EDVHistoryAppendToStream(fp, h);
	}

	/* Close the history file */
	fclose(fp);

	EDVHistoryListProgressCB(lw, clist->rows, clist->rows);

	return(0);
}

/*
 *	Prompts the user to save the history to an alternate file.
 */
void EDVHistoryWinSaveAs(edv_history_win_struct *lw)
{
	gboolean status;
	fb_type_struct **ftype = NULL, *ftype_rtn = NULL;
	gint total_ftypes = 0;
	gchar **path_rtn = NULL;
	gint total_path_rtns = 0;
	GtkWidget *toplevel;
	edv_core_struct *core;

	if((lw == NULL) || FileBrowserIsQuery())
	    return;

	toplevel = lw->toplevel;
	core = lw->core;
	if(core == NULL)
	    return;

	EDVHistoryWinSetBusy(lw, TRUE);

	/* Create file types list */
	FileBrowserTypeListNew(
	    &ftype, &total_ftypes,
	    ".log", "Log files"
	);

	/* Query user for file to save to */
	FileBrowserSetTransientFor(toplevel);
	status = FileBrowserGetResponse(
#if defined(PROG_LANGUAGE_SPANISH)
"Salve La Historia Como",
"Salve",
"Cancele",
#elif defined(PROG_LANGUAGE_FRENCH)
"Enregister l'historique sous",
"Epargner",
"Annuler",
#elif defined(PROG_LANGUAGE_GERMAN)
"Außer Geschichte Als",
"Sparen",
"Heben",
#elif defined(PROG_LANGUAGE_ITALIAN)
"Risparmiare La Storia Come",
"Risparmiare",
"Annullare",
#elif defined(PROG_LANGUAGE_DUTCH)
"Behalve Geschiedenis Als",
"Red",
"Annuleer",
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Exceto História Como",
"Poupe",
"Cancelamento",
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Untatt Historie Som",
"Untatt",
"Kanseller",
#else
"Save History As",
"Save",
"Cancel",
#endif
	    NULL,               /* Use last path */
	    ftype, total_ftypes,
	    &path_rtn, &total_path_rtns,
	    &ftype_rtn
	);
	FileBrowserSetTransientFor(NULL);

	/* Got user response? */
	if(status)
	{
	    const gchar *new_path = (total_path_rtns > 0) ?
		path_rtn[0] : NULL;
	    const gchar *file_type = (ftype_rtn != NULL) ?
		ftype_rtn->ext : NULL;

	    while(!STRISEMPTY(new_path) && !STRISEMPTY(file_type))
	    {
		gboolean object_exists = FALSE;
		gchar *buf;
		struct stat stat_buf, lstat_buf;

		/* File already exists? */
		if(!stat(new_path, &stat_buf))
		{
		    gboolean need_break = FALSE;
		    gint status2;
		    gchar *buf2 = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Escriba para reemplazar existir el archivo:\n\
\n\
    %s"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ecraser le fichier existant:\n\
\n\
    %s"
#elif defined(PROG_LANGUAGE_GERMAN)
"Überschreiben sie existierend ablegt:\n\
\n\
    %s"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Sovrascrivere il file di esistere:\n\
\n\
    %s"
#elif defined(PROG_LANGUAGE_DUTCH)
"Beschrijf bestaad dossier:\n\
\n\
    %s"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Overwrite existe arquivo:\n\
\n\
    %s"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Overskriv finnes arkiv:\n\
\n\
    %s"
#else
"Overwrite existing file:\n\
\n\
    %s"
#endif
			, new_path
		    );

		    EDVPlaySoundWarning(core);
		    CDialogSetTransientFor(toplevel);
		    status2 = CDialogGetResponse(
#if defined(PROG_LANGUAGE_SPANISH)
"Confirme Escriba Para Reemplazar"
#elif defined(PROG_LANGUAGE_FRENCH)
"Confirmer écraser"
#elif defined(PROG_LANGUAGE_GERMAN)
"Bestätigen Sie Überschreibt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Confermare Sovrascrivere"
#elif defined(PROG_LANGUAGE_DUTCH)
"Bevestiig Beschrijft"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Confirme Overwrite"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Bekreft Overskriver"
#else
"Confirm Overwrite"
#endif
			, buf2,
			NULL,
			CDIALOG_ICON_WARNING,
			CDIALOG_BTNFLAG_YES | CDIALOG_BTNFLAG_NO,
			CDIALOG_BTNFLAG_NO
		    );
		    CDialogSetTransientFor(NULL);

		    g_free(buf2);

		    switch(status2)
		    {
		      case CDIALOG_RESPONSE_YES:
		      case CDIALOG_RESPONSE_YES_TO_ALL:
		      case CDIALOG_RESPONSE_OK:
			break;

		      default:
			need_break = TRUE;
			break;
		    }

		    /* Mark that the object we are saving to currently
		     * exists
		     */
		    object_exists = TRUE;

		    if(need_break)
			break;
		}


		/* Format progress dialog message */
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Salvar la historia para archivar:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Enregister l'historique sous:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Sparende Geschichte abzulegen:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La storia di risparmio di schedare:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Reddende geschiedenis te archiveren:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Que poupando história arquivar:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Sparende historie arkivere:\n\
\n\
    %s\n"
#else
"Saving history to file:\n\
\n\
    %s\n"
#endif
		    , new_path
		);

		/* Map the progress dialog */
		ProgressDialogSetTransientFor(toplevel);
		ProgressDialogMap(
		    "Saving History",
		    buf,
		    (const guint8 **)icon_save_32x32_xpm,
		    "Stop"
		);

		g_free(buf);

		gdk_flush();

		/* Begin saving history using a format based on the
		 * selected extension
		 */
#if 0
		if(!strcmp(file_type, ".txt"))
#else
		if(TRUE)
#endif
		{
		    EDVHistoryWinSave(lw, new_path, TRUE);
		}

		/* Notify Endeavour's resources about the save */
		if(object_exists)
		{
		    if(!lstat(new_path, &lstat_buf))
			EDVObjectModifiedEmit(
			    core, new_path, new_path, &lstat_buf
			);
		}
		else
		{
		    if(!lstat(new_path, &lstat_buf))
			EDVObjectAddedEmit(
			    core, new_path, &lstat_buf
			);
		}

		break;  /* Break since this level is one big while() loop */
	    }
	}       /* Got user response? */

	/* Delete file types list */
	FileBrowserDeleteTypeList(ftype, total_ftypes);

	/* Reset due to possible file related change */
	FileBrowserReset();

	EDVHistoryWinUpdateMenus(lw);

	EDVHistoryWinSetBusy(lw, FALSE);

	/* Unmap progress dialog, it may have been mapped in the above
	 * operation
	 */
	ProgressDialogBreakQuery(TRUE);
	ProgressDialogSetTransientFor(NULL);
}


/*
 *	Updates the displayed history event on the given list window.
 *
 *	This will destroy the display_client widget and create a
 *	new one if h_ptr is not NULL.
 */
void EDVHistoryWinUpdateDisplay(
	edv_history_win_struct *lw,
	const edv_history_struct *h_ptr
)
{
	const gint	border_major = 5,
			border_minor = 2;
	edv_history_type type;
	edv_date_relativity date_relativity;
	const gchar *date_format;
	GtkRcStyle *rcstyle;
	GtkWidget *w, *parent, *parent2, *parent3, *parent4;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core;

	if(lw == NULL)
	    return;

	core = lw->core;
	if(core == NULL)
	    return;

	cfg_list = core->cfg_list;

	date_relativity = (edv_date_relativity)EDV_GET_I(
	    EDV_CFG_PARM_DATE_RELATIVITY
	);
	date_format = EDV_GET_S(EDV_CFG_PARM_DATE_FORMAT);


	/* Get previous display client GtkVBox and destroy it */
	w = lw->display_client;
	if(w != NULL)
	{
	    gtk_widget_destroy(w);
	    lw->display_client = w = NULL;
	}

	/* Get parent */
	parent = lw->display_parent;
	if(parent == NULL)
	    return;

	/* Stop updating at this point if the given history structure
	 * is NULL
	 */
	if(h_ptr == NULL)
	    return;

	type = h_ptr->type;

	/* Create new client vbox */
	lw->display_client = w = gtk_vbox_new(FALSE, border_major);
	gtk_container_border_width(GTK_CONTAINER(w), border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;


	if(TRUE)
	{
	    const gchar *s;
	    GdkBitmap *mask;
	    GdkPixmap *pixmap;

	    /* Hbox for operation heading */
	    w = gtk_hbox_new(FALSE, border_minor);
	    gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent3 = w;

	    /* Get icon and name of operation */
	    switch(type)
	    {
	      case EDV_HISTORY_SYNC_DISKS:
		s = "Sync Disks";
		pixmap = lw->other_operation_pixmap;
		mask = lw->other_operation_mask;
		break;
	      case EDV_HISTORY_SYNC_RECBIN:
		s = "Sync Recycle Bin";
		pixmap = lw->other_operation_pixmap;
		mask = lw->other_operation_mask;
		break;

	      case EDV_HISTORY_DISK_OBJECT_CREATE:
		s = "Create";
		pixmap = lw->object_create_pixmap;
		mask = lw->object_create_mask;
		break;
	      case EDV_HISTORY_DISK_OBJECT_COPY:
		s = "Copy";
		pixmap = lw->object_copy_pixmap;
		mask = lw->object_copy_mask;
		break;
	      case EDV_HISTORY_DISK_OBJECT_MOVE:
		s = "Move";
		pixmap = lw->object_move_pixmap;
		mask = lw->object_move_mask;
		break;
	      case EDV_HISTORY_DISK_OBJECT_LINK:
		s = "Link";
		pixmap = lw->object_link_pixmap;
		mask = lw->object_link_mask;
		break;
	      case EDV_HISTORY_DISK_OBJECT_CHOWN:
		s = "Change Ownership";
		pixmap = lw->object_chown_pixmap;
		mask = lw->object_chown_mask;
		break;
	      case EDV_HISTORY_DISK_OBJECT_CHMOD:
		s = "Change Permissions";
		pixmap = lw->object_chmod_pixmap;
		mask = lw->object_chmod_mask;
		break;
	      case EDV_HISTORY_DISK_OBJECT_CHTIME:
		s = "Change Time Stamps";
		pixmap = lw->object_chtime_pixmap;
		mask = lw->object_chtime_mask;
		break;
	      case EDV_HISTORY_DISK_OBJECT_DOWNLOAD:
		s = "Download";
		pixmap = lw->object_download_pixmap;
		mask = lw->object_download_mask;
		break;
	      case EDV_HISTORY_DISK_OBJECT_DELETE:
		s = "Delete";
		pixmap = lw->object_delete_pixmap;
		mask = lw->object_delete_mask;
		break;

	      case EDV_HISTORY_RECYCLED_OBJECT_RECOVER:
		s = "Recover";
		pixmap = lw->recobj_recover_pixmap;
		mask = lw->recobj_recover_mask;
		break;
	      case EDV_HISTORY_RECYCLED_OBJECT_PURGE:
		s = "Purge";
		pixmap = lw->recobj_purge_pixmap;
		mask = lw->recobj_purge_mask;
		break;
	      case EDV_HISTORY_RECYCLED_OBJECT_PURGE_ALL:
		s = "Purge All";
		pixmap = lw->recobj_purge_pixmap;
		mask = lw->recobj_purge_mask;
		break;

	      case EDV_HISTORY_ARCHIVE_OBJECT_ADD:
		s = "Archive Add";
		pixmap = lw->arcobj_add_pixmap;
		mask = lw->arcobj_add_mask;
		break;
	      case EDV_HISTORY_ARCHIVE_OBJECT_EXTRACT:
		s = "Archive Extract";
		pixmap = lw->arcobj_extract_pixmap;
		mask = lw->arcobj_extract_mask;
		break;
	      case EDV_HISTORY_ARCHIVE_OBJECT_DELETE:
		s = "Archive Delete";
		pixmap = lw->arcobj_delete_pixmap;
		mask = lw->arcobj_delete_mask;
		break;
	      case EDV_HISTORY_ARCHIVE_FIX:
		s = "Archive Fix";
		pixmap = lw->archive_fix_pixmap;
		mask = lw->archive_fix_mask;
		break;

	      default:
		s = "Other Operation";
		pixmap = lw->other_operation_pixmap;
		mask = lw->other_operation_mask;
		break;
	    }

	    /* Create the operation icon */
	    if(pixmap != NULL)
	    {
		w = gtk_pixmap_new(pixmap, mask);
		gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
		gtk_widget_show(w);
	    }

	    /* Create the operation label */
	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-14-*-*-*-*-*-iso8859-1"
	    );
	    w = gtk_label_new(s);
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)

	    /* Error label needed? */
	    if(h_ptr->status != 0)
	    {
		gint state;
		gchar *buf, *s2 = NULL;
		const GdkColor	*c,
				cs_red = EDV_GDKCOLOR_RED,
				cs_orange = EDV_GDKCOLOR_ORANGE;

		/* Get the error string */
		switch(h_ptr->status)
		{
		  case -1:
		    s = "Error";
		    c = &cs_red;
		    break;
		  case -2:
		    s = "Invalid Value";
		    c = &cs_red;
		    break;
		  case -3:
		    s = "System Error";
		    c = &cs_red;
		    break;
		  case -4:
		    s = "User Aborted";
		    c = &cs_orange;
		    break;
		  case -5:
		    s = "User Canceled";
		    c = &cs_orange;
		    break;
		  case -6:
		    s = "Operation In Progress";
		    c = &cs_orange;
		    break;
		  default:
		    s = "Unknown Error";
		    s2 = g_strdup_printf("%i", h_ptr->status);
		    c = &cs_red;
		    break;
		}

		/* Label */
		rcstyle = gtk_rc_style_new();
		rcstyle->font_name = STRDUP(
"-adobe-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1"
		);
		state = GTK_STATE_NORMAL;
		rcstyle->color_flags[state] =
		    GTK_RC_FG | GTK_RC_TEXT;
		memcpy(&rcstyle->fg[state], c, sizeof(GdkColor));
		memcpy(&rcstyle->text[state], c, sizeof(GdkColor));
		state = GTK_STATE_INSENSITIVE;
		rcstyle->color_flags[state] =
		    GTK_RC_FG | GTK_RC_TEXT;
		memcpy(&rcstyle->fg[state], &cs_orange, sizeof(GdkColor));
		memcpy(&rcstyle->text[state], &cs_orange, sizeof(GdkColor));

		buf = g_strdup_printf(
		    "%s%s",
		    s,
		    (s2 != NULL) ? s2 : ""
		);
		w = gtk_label_new(buf);
		gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_CENTER);
		gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, TRUE, 0);
		gtk_widget_modify_style(w, rcstyle);
		gtk_widget_show(w);
		GTK_RC_STYLE_UNREF(rcstyle)

		g_free(buf);
		g_free(s2);
	    }

#if 0
	    /* Event number */
	    if(TRUE)
	    {

	    }
#endif

	    /* Create date label */
	    if(h_ptr->time_start > 0l)
	    {
		s = EDVDateFormatString(
		    h_ptr->time_start,
		    date_format, date_relativity
		);
		rcstyle = gtk_rc_style_new();
		rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
		);
		w = gtk_label_new(s);
		gtk_box_pack_end(GTK_BOX(parent3), w, FALSE, FALSE, 0);
		gtk_widget_modify_style(w, rcstyle);
		gtk_widget_show(w);
		GTK_RC_STYLE_UNREF(rcstyle)
	    }
	}


	/* Create the GtkHBox for the source and target? */
	if(!STRISEMPTY(h_ptr->src_path) ||
	   !STRISEMPTY(h_ptr->tar_path)
	)
	{
	    w = gtk_hbox_new(TRUE, 0);
	    gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent3 = w;
	}

	/* Create the source icon and label? */
	if(!STRISEMPTY(h_ptr->src_path))
	{
	    gchar	*path = STRDUP(h_ptr->src_path),
			*name = EDVShortenPath(
		    (path != NULL) ? g_basename(path) : NULL, 25
			);
	    GdkBitmap *mask = NULL;
	    GdkPixmap *pixmap = NULL;

	    /* Get the icon pixmap & mask */
	    if(path != NULL)
	    {
		if(g_path_is_absolute(path))
		{
		    struct stat lstat_buf;
		    if(lstat(path, &lstat_buf) == 0)
		    {
			edv_object_struct *o = EDVObjectNew();
			EDVObjectSetPath(o, path);
			EDVObjectSetStat(o, &lstat_buf);
			EDVMatchObjectIcon(
			    core->device, core->total_devices,
			    core->mimetype, core->total_mimetypes,
			    o->type,
			    o->full_path,
			    TRUE,		/* Assume link valid */
			    o->permissions,
			    1,			/* Medium icons */
			    &pixmap, &mask,
			    NULL, NULL,
			    NULL, NULL,
			    NULL, NULL
			);
			EDVObjectDelete(o);
		    }
		    else
		    {
			EDVMatchObjectIcon(
			    core->device, core->total_devices,
			    core->mimetype, core->total_mimetypes,
			    EDV_OBJECT_TYPE_FILE,
			    path,
			    TRUE,		/* Assume link valid */
			    0,			/* No permissions */
			    1,			/* Medium icons */
			    &pixmap, &mask,
			    NULL, NULL,
			    NULL, NULL,
			    NULL, NULL
			);
		    }
		}
		else if((type == EDV_HISTORY_SYNC_RECBIN) ||
			(type == EDV_HISTORY_DISK_OBJECT_CREATE) ||
			(type == EDV_HISTORY_DISK_OBJECT_COPY) ||
                        (type == EDV_HISTORY_DISK_OBJECT_MOVE) ||
                        (type == EDV_HISTORY_DISK_OBJECT_LINK) ||
                        (type == EDV_HISTORY_DISK_OBJECT_CHOWN) ||
                        (type == EDV_HISTORY_DISK_OBJECT_CHMOD) ||
                        (type == EDV_HISTORY_DISK_OBJECT_CHTIME) ||
                        (type == EDV_HISTORY_DISK_OBJECT_DELETE) ||
                        (type == EDV_HISTORY_DISK_OBJECT_DOWNLOAD) ||
                        (type == EDV_HISTORY_RECYCLED_OBJECT_RECOVER) ||
                        (type == EDV_HISTORY_RECYCLED_OBJECT_PURGE) ||
                        (type == EDV_HISTORY_RECYCLED_OBJECT_PURGE_ALL) ||
                        (type == EDV_HISTORY_ARCHIVE_OBJECT_ADD) ||
                        (type == EDV_HISTORY_ARCHIVE_OBJECT_EXTRACT) ||
                        (type == EDV_HISTORY_ARCHIVE_OBJECT_DELETE) ||
                        (type == EDV_HISTORY_ARCHIVE_FIX)
		)
		{
		    EDVMatchObjectIcon(
			core->device, core->total_devices,
			core->mimetype, core->total_mimetypes,
			EDV_OBJECT_TYPE_FILE,
			path,
			TRUE,			/* Assume link valid */
			0,			/* No permissions */
			1,			/* Medium icons */
			&pixmap, &mask,
			NULL, NULL,
			NULL, NULL,
			NULL, NULL
		    );
		}
	    }
	    /* If no icon was obtained then use a generic icon for
	     * these operations
	     */
	    if(pixmap == NULL)
	    {
		edv_mime_type_struct *m;
		switch(type)
		{
		  case EDV_HISTORY_SYNC_RECBIN:
		  case EDV_HISTORY_DISK_OBJECT_CREATE:
		  case EDV_HISTORY_DISK_OBJECT_COPY:
		  case EDV_HISTORY_DISK_OBJECT_MOVE:
		  case EDV_HISTORY_DISK_OBJECT_LINK:
		  case EDV_HISTORY_DISK_OBJECT_CHOWN:
		  case EDV_HISTORY_DISK_OBJECT_CHMOD:
		  case EDV_HISTORY_DISK_OBJECT_CHTIME:
		  case EDV_HISTORY_DISK_OBJECT_DELETE:
		  case EDV_HISTORY_DISK_OBJECT_DOWNLOAD:
		  case EDV_HISTORY_RECYCLED_OBJECT_RECOVER:
		  case EDV_HISTORY_RECYCLED_OBJECT_PURGE:
		  case EDV_HISTORY_RECYCLED_OBJECT_PURGE_ALL:
		  case EDV_HISTORY_ARCHIVE_OBJECT_ADD:
		  case EDV_HISTORY_ARCHIVE_OBJECT_EXTRACT:
		  case EDV_HISTORY_ARCHIVE_OBJECT_DELETE:
		  case EDV_HISTORY_ARCHIVE_FIX:
		    m = EDVMimeTypesListMatchType(
			core->mimetype, core->total_mimetypes,
			NULL,
			EDV_MIME_TYPE_TYPE_INODE_FILE,
			FALSE
		    );
		    if(m != NULL)
		    {
			pixmap = m->medium_pixmap[
			    EDV_MIME_TYPE_ICON_STATE_STANDARD
			];
			mask = m->medium_mask[
			    EDV_MIME_TYPE_ICON_STATE_STANDARD
			];
		    }
		    break;
		  default:
		    break;
		}
	    }

	    w = gtk_hbox_new(FALSE, border_major);
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent4 = w;

	    /* Create the icon GtkPixmap */
	    if(pixmap != NULL)
	    {
		w = gtk_pixmap_new(pixmap, mask);
		gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
		gtk_widget_show(w);
	    }

	    /* Create label */
	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1"
	    );
	    w = gtk_label_new(name);
	    gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)

	    g_free(name);
	    g_free(path);
	}
	/* Create the target icon and label? */
	if(!STRISEMPTY(h_ptr->tar_path))
	{
	    gchar	*path = STRDUP(h_ptr->tar_path),
			*name = EDVShortenPath(
		(path != NULL) ? g_basename(path) : NULL, 25
			);
	    GdkBitmap *mask = NULL;
	    GdkPixmap *pixmap = NULL;

	    /* Get the icon pixmap & mask */
	    if(path != NULL)
	    {
		if(g_path_is_absolute(path))
		{
		    struct stat lstat_buf;
		    if(lstat(path, &lstat_buf) == 0)
		    {
			edv_object_struct *o = EDVObjectNew();
			EDVObjectSetPath(o, path);
			EDVObjectSetStat(o, &lstat_buf);
			EDVMatchObjectIcon(
			    core->device, core->total_devices,
			    core->mimetype, core->total_mimetypes,
			    o->type,
			    o->full_path,
			    TRUE,		/* Assume link valid */
			    o->permissions,
			    1,			/* Medium icons */
			    &pixmap, &mask,
			    NULL, NULL,
			    NULL, NULL,
			    NULL, NULL
			);
			EDVObjectDelete(o);
		    }
		    else
		    {
			EDVMatchObjectIcon(
			    core->device, core->total_devices,
			    core->mimetype, core->total_mimetypes,
			    EDV_OBJECT_TYPE_FILE,
			    path,
			    TRUE,		/* Assume link valid */
			    0,			/* No permissions */
			    1,			/* Medium icons */
			    &pixmap, &mask,
			    NULL, NULL,
			    NULL, NULL,
			    NULL, NULL
			);
		    }
		}
		else if((type == EDV_HISTORY_DISK_OBJECT_CREATE) ||
			(type == EDV_HISTORY_DISK_OBJECT_COPY) ||
                        (type == EDV_HISTORY_DISK_OBJECT_MOVE) ||
                        (type == EDV_HISTORY_DISK_OBJECT_LINK) ||
                        (type == EDV_HISTORY_DISK_OBJECT_DOWNLOAD) ||
                        (type == EDV_HISTORY_RECYCLED_OBJECT_RECOVER) ||
                        (type == EDV_HISTORY_RECYCLED_OBJECT_PURGE) ||
                        (type == EDV_HISTORY_RECYCLED_OBJECT_PURGE_ALL) ||
                        (type == EDV_HISTORY_ARCHIVE_OBJECT_ADD) ||
                        (type == EDV_HISTORY_ARCHIVE_OBJECT_EXTRACT) ||
                        (type == EDV_HISTORY_ARCHIVE_OBJECT_DELETE)
		)
		{
		    EDVMatchObjectIcon(
			core->device, core->total_devices,
			core->mimetype, core->total_mimetypes,
			EDV_OBJECT_TYPE_FILE,
			path,
			TRUE,			/* Assume link valid */
			0,			/* No permissions */
			1,			/* Medium icons */
			&pixmap, &mask,
			NULL, NULL,
			NULL, NULL,
			NULL, NULL
		    );
		}
	    }
	    /* If no icon was obtained then use a generic icon for
	     * these operations
	     */
	    if(pixmap == NULL)
	    {
		edv_mime_type_struct *m;
		switch(type)
		{
		  case EDV_HISTORY_DISK_OBJECT_CREATE:
		  case EDV_HISTORY_DISK_OBJECT_COPY:
		  case EDV_HISTORY_DISK_OBJECT_MOVE:
		  case EDV_HISTORY_DISK_OBJECT_LINK:
		  case EDV_HISTORY_DISK_OBJECT_DOWNLOAD:
		  case EDV_HISTORY_RECYCLED_OBJECT_RECOVER:
		  case EDV_HISTORY_RECYCLED_OBJECT_PURGE:
		  case EDV_HISTORY_RECYCLED_OBJECT_PURGE_ALL:
		  case EDV_HISTORY_ARCHIVE_OBJECT_ADD:
		  case EDV_HISTORY_ARCHIVE_OBJECT_EXTRACT:
		  case EDV_HISTORY_ARCHIVE_OBJECT_DELETE:
		    m = EDVMimeTypesListMatchType(
			core->mimetype, core->total_mimetypes,
			NULL,
			EDV_MIME_TYPE_TYPE_INODE_FILE,
			FALSE
		    );
		    if(m != NULL)
		    {
			pixmap = m->medium_pixmap[
			    EDV_MIME_TYPE_ICON_STATE_STANDARD
			];
			mask = m->medium_mask[
			    EDV_MIME_TYPE_ICON_STATE_STANDARD
			];
		    }
		    break;
		  default:
		    break;
		}
	    }

	    /* Create deliminator? */
	    if(!STRISEMPTY(h_ptr->src_path))
	    {
		w = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
		gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
		gtk_widget_show(w);
	    }

	    w = gtk_hbox_new(FALSE, border_major);
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent4 = w;

	    /* Create the icon GtkPixmap */
	    if(pixmap != NULL)
	    {
		w = gtk_pixmap_new(pixmap, mask);
		gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
		gtk_widget_show(w);
	    }

	    /* Create label */
	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1"
	    );
	    w = gtk_label_new(name);
	    gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)

	    g_free(name);
	    g_free(path);
	}


	/* Create the GtkHBox for the source and target locations? */
	if(!STRISEMPTY(h_ptr->src_path) ||
	   !STRISEMPTY(h_ptr->tar_path)
	)
	{
	    w = gtk_hbox_new(TRUE, 0);
	    gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent3 = w;
	}

	/* Create the source location icon & label? */
	if((h_ptr->src_path != NULL) ?
	    g_path_is_absolute(h_ptr->src_path) : FALSE
	)
	{
	    gchar *path = g_dirname(h_ptr->src_path);
	    gchar *text = EDVShortenPath(path, 40);
	    GdkBitmap *mask = NULL;
	    GdkPixmap *pixmap = NULL;
	    struct stat lstat_buf;

	    /* Get the icon pixmap & mask */
	    if(!lstat(path, &lstat_buf))
	    {
		edv_object_struct *o = EDVObjectNew();
		EDVObjectSetPath(o, path);
		EDVObjectSetStat(o, &lstat_buf);
		EDVMatchObjectIcon(
		    core->device, core->total_devices,
		    core->mimetype, core->total_mimetypes,
		    o->type,
		    o->full_path,
		    TRUE,		/* Assume link valid */
		    o->permissions,
		    0,			/* Small icons */
		    &pixmap, &mask,
		    NULL, NULL,
		    NULL, NULL,
		    NULL, NULL
		);
		EDVObjectDelete(o);
	    }
	    else
	    {
		edv_mime_type_struct *m = EDVMimeTypesListMatchType(
		    core->mimetype, core->total_mimetypes,
		    NULL,
		    EDV_MIME_TYPE_TYPE_INODE_DIRECTORY,
		    FALSE
		);
		if(m != NULL)
		{
		    pixmap = m->small_pixmap[
			EDV_MIME_TYPE_ICON_STATE_STANDARD
		    ];
		    mask = m->small_mask[
			EDV_MIME_TYPE_ICON_STATE_STANDARD
		    ];
		}
	    }

	    w = gtk_hbox_new(FALSE, border_major);
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent4 = w;

	    /* Create the icon GtkPixmap */
	    if(pixmap != NULL)
	    {
		w = gtk_pixmap_new(pixmap, mask);
		gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
		gtk_widget_show(w);
	    }

	    /* Create the label */
	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	    );
	    w = gtk_label_new(text);
	    gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)

	    g_free(text);
	    g_free(path);
	}

	/* Create target location icon and label? */
	if((h_ptr->tar_path != NULL) ?
	    g_path_is_absolute(h_ptr->tar_path) : FALSE
	)
	{
	    gchar *path = g_dirname(h_ptr->tar_path);
	    gchar *text = EDVShortenPath(path, 40);
	    GdkBitmap *mask = NULL;
	    GdkPixmap *pixmap = NULL;
	    struct stat lstat_buf;

	    /* Get the icon pixmap & mask */
	    if(!lstat(path, &lstat_buf))
	    {
		edv_object_struct *o = EDVObjectNew();
		EDVObjectSetPath(o, path);
		EDVObjectSetStat(o, &lstat_buf);
		EDVMatchObjectIcon(
		    core->device, core->total_devices,
		    core->mimetype, core->total_mimetypes,
		    o->type,
		    o->full_path,
		    TRUE,		/* Assume link valid */
		    o->permissions,
		    0,			/* Small icons */
		    &pixmap, &mask,
		    NULL, NULL,
		    NULL, NULL,
		    NULL, NULL
		);
		EDVObjectDelete(o);
	    }
	    else
	    {
		edv_mime_type_struct *m = EDVMimeTypesListMatchType(
		    core->mimetype, core->total_mimetypes,
		    NULL,
		    EDV_MIME_TYPE_TYPE_INODE_DIRECTORY,
		    FALSE
		);
		if(m != NULL)
		{
		    pixmap = m->small_pixmap[
			EDV_MIME_TYPE_ICON_STATE_STANDARD
		    ];
		    mask = m->small_mask[
			EDV_MIME_TYPE_ICON_STATE_STANDARD
		    ];
		}
	    }

	    w = gtk_hbox_new(FALSE, border_major);
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent4 = w;

	    /* Create the icon GtkPixmap */
	    if(pixmap != NULL)
	    {
		w = gtk_pixmap_new(pixmap, mask);
		gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
		gtk_widget_show(w);
	    }

	    /* Create label */
	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	    );
	    w = gtk_label_new(text);
	    gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)

	    g_free(text);
	    g_free(path);
	}


	/* Duration */
	if(h_ptr->time_end > 0)
	{
	    gchar *buf;
	    const gchar *s;

	    w = gtk_hbox_new(FALSE, border_major);
	    gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent3 = w;

	    s = EDVDateStringDuration(
		MAX(h_ptr->time_end - h_ptr->time_start, 0)
	    );
	    buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"La Duración"
#elif defined(PROG_LANGUAGE_FRENCH)
"Durée"
#elif defined(PROG_LANGUAGE_GERMAN)
"Zeitdauer"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Durata"
#elif defined(PROG_LANGUAGE_DUTCH)
"Duur"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"A Duração"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Varighet"
#else
"Duration"
#endif
		    ": %s", s
	    );
	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	    );
	    w = gtk_label_new(buf);
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)
	    g_free(buf);
	}


	/* Comments */
	if(!STRISEMPTY(h_ptr->comments))
	{
	    w = gtk_hbox_new(FALSE, border_major);
	    gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent3 = w;

	    /* Vbox for icon */
	    w = gtk_vbox_new(TRUE, 0);
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent4 = w;

	    if(lw->error_medium_pixmap != NULL)
	    {
		w = gtk_pixmap_new(
		    lw->error_medium_pixmap,
		    lw->error_medium_mask
		);
		gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, FALSE, 0);
		gtk_widget_show(w);
	    }

	    /* Vbox for label */
	    w = gtk_vbox_new(TRUE, 0);
	    gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, TRUE, 0);
	    gtk_widget_show(w);
	    parent4 = w;
	    w = gtk_hbox_new(FALSE, 0);
	    gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, FALSE, 0);
	    gtk_widget_show(w);
	    parent4 = w;
	    /* Label */
	    if(h_ptr->status)
	    {
		gint state;
		const GdkColor	cs = EDV_GDKCOLOR_RED,
				cs_insen = EDV_GDKCOLOR_ORANGE;

		rcstyle = gtk_rc_style_new();
		rcstyle->font_name = STRDUP(
"-adobe-helvetica-bold-r-normal-*-12-*-*-*-*-*-iso8859-1"
		);
		state = GTK_STATE_NORMAL;
		rcstyle->color_flags[state] =
		    GTK_RC_FG | GTK_RC_TEXT;
		memcpy(&rcstyle->fg[state], &cs, sizeof(GdkColor));
		memcpy(&rcstyle->text[state], &cs, sizeof(GdkColor));
		state = GTK_STATE_INSENSITIVE;
		rcstyle->color_flags[state] =
		    GTK_RC_FG | GTK_RC_TEXT;
		memcpy(&rcstyle->fg[state], &cs_insen, sizeof(GdkColor));
		memcpy(&rcstyle->text[state], &cs_insen, sizeof(GdkColor));
	    }
	    else
	    {
		rcstyle = gtk_rc_style_new();
		rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
		);
	    }
	    w = gtk_label_new(h_ptr->comments);
	    gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
	    gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)
	}

}


/*
 *	Sets the row on the history list window's clist to the values
 *	specified by the given history structure.
 */
static void EDVHistoryWinSetRow(
	edv_history_win_struct *lw,
	gint row, const edv_history_struct *h_ptr
)
{
	GdkPixmap *pixmap;
	GdkBitmap *mask; 
	GtkCList *clist;
	edv_history_type type;
	edv_date_relativity date_relativity;
	const gchar *date_format;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core;
	const gchar *type_name;


	if((lw == NULL) || (h_ptr == NULL))
	    return;

	core = lw->core;
	clist = (GtkCList *)lw->history_clist;
	if((core == NULL) || (clist == NULL))
	    return;

	cfg_list = core->cfg_list;

	date_relativity = (edv_date_relativity)EDV_GET_I(
	    EDV_CFG_PARM_DATE_RELATIVITY
	);
	date_format = EDV_GET_S(EDV_CFG_PARM_DATE_FORMAT);


	/* Get operation type and icon */
	type = h_ptr->type;
	switch(type)
	{
	  case EDV_HISTORY_UNKNOWN:
	    type_name = "Other";
	    pixmap = lw->other_operation_pixmap;
	    mask = lw->other_operation_mask;
	    break;

	  case EDV_HISTORY_SYNC_DISKS:
	    type_name = "Sync Disks";
	    pixmap = lw->other_operation_pixmap;
	    mask = lw->other_operation_mask;
	    break;
	  case EDV_HISTORY_SYNC_RECBIN:
	    type_name = "Sync Recycle Bin";
	    pixmap = lw->other_operation_pixmap;
	    mask = lw->other_operation_mask;
	    break;

	  case EDV_HISTORY_DISK_OBJECT_CREATE:
	    type_name = "Create";
	    pixmap = lw->object_create_pixmap;
	    mask = lw->object_create_mask;
	    break;
	  case EDV_HISTORY_DISK_OBJECT_COPY:
	    type_name = "Copy";
	    pixmap = lw->object_copy_pixmap;
	    mask = lw->object_copy_mask;
	    break;
	  case EDV_HISTORY_DISK_OBJECT_MOVE:
	    type_name = "Move";
	    pixmap = lw->object_move_pixmap;
	    mask = lw->object_move_mask;
	    break;
	  case EDV_HISTORY_DISK_OBJECT_LINK:
	    type_name = "Link";
	    pixmap = lw->object_link_pixmap;
	    mask = lw->object_link_mask;
	    break;
	  case EDV_HISTORY_DISK_OBJECT_CHOWN:
	    type_name = "Change Ownership";
	    pixmap = lw->object_chown_pixmap;
	    mask = lw->object_chown_mask;
	    break;
	  case EDV_HISTORY_DISK_OBJECT_CHMOD:
	    type_name = "Change Permissions";
	    pixmap = lw->object_chmod_pixmap;
	    mask = lw->object_chmod_mask;
	    break;
	  case EDV_HISTORY_DISK_OBJECT_CHTIME:
	    type_name = "Change Time Stamps";
	    pixmap = lw->object_chtime_pixmap;
	    mask = lw->object_chtime_mask;
	    break;
	  case EDV_HISTORY_DISK_OBJECT_DOWNLOAD:
	    type_name = "Download";
	    pixmap = lw->object_download_pixmap;
	    mask = lw->object_download_mask;
	    break;
	  case EDV_HISTORY_DISK_OBJECT_DELETE:
	    type_name = "Delete";
	    pixmap = lw->object_delete_pixmap;
	    mask = lw->object_delete_mask;
	    break;

	  case EDV_HISTORY_RECYCLED_OBJECT_RECOVER:
	    type_name = "Recover";
	    pixmap = lw->recobj_recover_pixmap;
	    mask = lw->recobj_recover_mask;
	    break;
	  case EDV_HISTORY_RECYCLED_OBJECT_PURGE:
	    type_name = "Purge";
	    pixmap = lw->recobj_purge_pixmap;
	    mask = lw->recobj_purge_mask;
	    break;
	  case EDV_HISTORY_RECYCLED_OBJECT_PURGE_ALL:
	    type_name = "Purge All";
	    pixmap = lw->recobj_purge_pixmap;
	    mask = lw->recobj_purge_mask;
	    break;

	  case EDV_HISTORY_ARCHIVE_OBJECT_ADD:
	    type_name = "Archive Add";
	    pixmap = lw->arcobj_add_pixmap;
	    mask = lw->arcobj_add_mask;
	    break;
	  case EDV_HISTORY_ARCHIVE_OBJECT_EXTRACT:
	    type_name = "Archive Extract";
	    pixmap = lw->arcobj_extract_pixmap;
	    mask = lw->arcobj_extract_mask;
	    break;
	  case EDV_HISTORY_ARCHIVE_OBJECT_DELETE:
	    type_name = "Archive Delete";
	    pixmap = lw->arcobj_delete_pixmap;
	    mask = lw->arcobj_delete_mask;
	    break;
	  case EDV_HISTORY_ARCHIVE_FIX:
	    type_name = "Archive Fix";
	    pixmap = lw->archive_fix_pixmap;
	    mask = lw->archive_fix_mask;
	    break;

	  default:
	    type_name = "Other";
	    pixmap = lw->other_operation_pixmap;
	    mask = lw->other_operation_mask;
	    break;
	}


	/* Is the specified row in bounds? */
	if((row >= 0) && (row < clist->rows))
	{
	    /* Set column 0 as the Type */
	    if(clist->columns > 0)
	    {
		if(pixmap != NULL)
		    gtk_clist_set_pixtext(
			clist, row, 0,
			type_name,
			EDV_LIST_PIXMAP_TEXT_SPACING,
			pixmap, mask
		    );
		else
		    gtk_clist_set_text(
			clist, row, 0,
			type_name
		    );
	    }
	    /* Set column 1 as the Source */
	    if((clist->columns > 1) && !STRISEMPTY(h_ptr->src_path))
	    {
		gchar	*s,
			*path = STRDUP(h_ptr->src_path),
			*name = (path != NULL) ? g_basename(path) : NULL;
		mask = NULL;
		pixmap = NULL;
		if((path != NULL) ? g_path_is_absolute(path) : FALSE)
		{
		    struct stat lstat_buf;
		    if(!lstat(path, &lstat_buf))
		    {
			edv_object_struct *o = EDVObjectNew();
			EDVObjectSetPath(o, path);
			EDVObjectSetStat(o, &lstat_buf);
			EDVMatchObjectIcon(
			    core->device, core->total_devices,
			    core->mimetype, core->total_mimetypes,
			    o->type,
			    o->full_path,
			    TRUE,		/* Assume link valid */
			    o->permissions,
			    0,			/* Small icons */
			    &pixmap, &mask,
			    NULL, NULL,
			    NULL, NULL,
			    NULL, NULL
			);
			EDVObjectDelete(o);
		    }
		}
		/* If icon was not obtained then use a generic icon
		 * for certain operation types
		 */
		if(pixmap == NULL)
		{
		    switch(type)
		    {
		      case EDV_HISTORY_SYNC_RECBIN:
		      case EDV_HISTORY_DISK_OBJECT_CREATE:
		      case EDV_HISTORY_DISK_OBJECT_COPY:
		      case EDV_HISTORY_DISK_OBJECT_MOVE:
		      case EDV_HISTORY_DISK_OBJECT_LINK:
		      case EDV_HISTORY_DISK_OBJECT_CHOWN:
		      case EDV_HISTORY_DISK_OBJECT_CHMOD:
		      case EDV_HISTORY_DISK_OBJECT_CHTIME:
		      case EDV_HISTORY_DISK_OBJECT_DOWNLOAD:
		      case EDV_HISTORY_DISK_OBJECT_DELETE:
		      case EDV_HISTORY_RECYCLED_OBJECT_RECOVER:
		      case EDV_HISTORY_RECYCLED_OBJECT_PURGE:
		      case EDV_HISTORY_ARCHIVE_OBJECT_ADD:
		      case EDV_HISTORY_ARCHIVE_OBJECT_EXTRACT:
		      case EDV_HISTORY_ARCHIVE_OBJECT_DELETE:
		      case EDV_HISTORY_ARCHIVE_FIX:
			EDVMatchObjectIcon(
			    NULL, 0,
			    core->mimetype, core->total_mimetypes,
			    EDV_OBJECT_TYPE_FILE,
			    path,
			    TRUE,
			    0x00000000,
			    0,          /* Samll icons */
			    &pixmap, &mask,
			    NULL, NULL,
			    NULL, NULL,
			    NULL, NULL
			);
			break;
		      default:
			break;
		    }
		}

		/* Get cell value */
		if(STRISEMPTY(name))
		    s = STRDUP("");
		else
		    s = EDVShortenPath(name, 32);

		/* Set cell */
		if(pixmap != NULL)
		    gtk_clist_set_pixtext(
			clist, row, 1, s,
			EDV_LIST_PIXMAP_TEXT_SPACING,
			pixmap, mask
		    );
		else
		    gtk_clist_set_text(
		        clist, row, 1, s
		    );
		g_free(s);
		g_free(path);
	    }
	    /* Set column 2 as the Target */
	    if((clist->columns > 2) && !STRISEMPTY(h_ptr->tar_path))
	    {
		gchar	*s,
			*path = STRDUP(h_ptr->tar_path),
			*name = (path != NULL) ? g_basename(path) : NULL;
		mask = NULL;
		pixmap = NULL;
		if((path != NULL) ? g_path_is_absolute(path) : FALSE)
		{
		    struct stat lstat_buf;
		    if(!lstat((char *)path, &lstat_buf))
		    {
			edv_object_struct *o = EDVObjectNew();
			EDVObjectSetPath(o, path);
			EDVObjectSetStat(o, &lstat_buf);
			EDVMatchObjectIcon(
			    core->device, core->total_devices,
			    core->mimetype, core->total_mimetypes,
			    o->type,
			    o->full_path,
			    TRUE,		/* Assume link valid */
			    o->permissions,
			    0,			/* Small icons */
			    &pixmap, &mask,
			    NULL, NULL,
			    NULL, NULL,
			    NULL, NULL
			);
			EDVObjectDelete(o);
		    }
		}
		/* If icon was not obtained then use a generic icon
		 * for certain operation types
		 */
		if(pixmap == NULL)
		{
		    switch(type)
		    {
		      case EDV_HISTORY_DISK_OBJECT_CREATE:
		      case EDV_HISTORY_DISK_OBJECT_COPY:
		      case EDV_HISTORY_DISK_OBJECT_MOVE:
		      case EDV_HISTORY_DISK_OBJECT_LINK:
		      case EDV_HISTORY_DISK_OBJECT_DOWNLOAD:
		      case EDV_HISTORY_DISK_OBJECT_DELETE:
		      case EDV_HISTORY_RECYCLED_OBJECT_RECOVER:
		      case EDV_HISTORY_ARCHIVE_OBJECT_ADD:
		      case EDV_HISTORY_ARCHIVE_OBJECT_EXTRACT:
		      case EDV_HISTORY_ARCHIVE_OBJECT_DELETE:
		      case EDV_HISTORY_ARCHIVE_FIX:
			EDVMatchObjectIcon(
			    NULL, 0,
			    core->mimetype, core->total_mimetypes,
			    EDV_OBJECT_TYPE_FILE,
			    path,
			    TRUE,
			    0x00000000,
			    0,          /* Samll icons */
			    &pixmap, &mask,
			    NULL, NULL,
			    NULL, NULL,
			    NULL, NULL
			);
			break;
		      default:
			break;
		    }
		}

		/* Get cell value */
		if(STRISEMPTY(name))
		    s = STRDUP("");
		else
		    s = EDVShortenPath(name, 32);

		/* Set cell */
		if(pixmap != NULL)
		    gtk_clist_set_pixtext(
			clist, row, 2, s,
			EDV_LIST_PIXMAP_TEXT_SPACING,
			pixmap, mask
		    );
		else
		    gtk_clist_set_text(
			clist, row, 2, s
		    );
		g_free(s);
		g_free(path);
	    }
	    /* Set column 3 as the Status */
	    if(clist->columns > 3)
	    {
		const gchar *s;
		GtkStyle *style;
		switch(h_ptr->status)
		{
		  case 0:
		    s = "Success";
		    style = lw->cell_style[EDV_HISTORY_CELL_STYLE_SUCCESS];
		    break;
		  case -1:
		    s = "Error";
		    style = lw->cell_style[EDV_HISTORY_CELL_STYLE_ERROR];
		    break;
		  case -2:
		    s = "Invalid Value";
		    style = lw->cell_style[EDV_HISTORY_CELL_STYLE_ERROR];
		    break;
		  case -3:
		    s = "System Error";
		    style = lw->cell_style[EDV_HISTORY_CELL_STYLE_ERROR];
		    break;
		  case -4:
		    s = "User Aborted";
		    style = lw->cell_style[EDV_HISTORY_CELL_STYLE_CANCEL];
		    break;
		  case -5:
		    s = "User Canceled";
		    style = lw->cell_style[EDV_HISTORY_CELL_STYLE_CANCEL];
		    break;
		  case -6:
		    s = "Operation In Progress";
		    style = lw->cell_style[EDV_HISTORY_CELL_STYLE_ERROR];
		    break;
		  default:
		    s = "Unknown Error";
		    style = NULL;
		    break;
		}
		gtk_clist_set_text(
		    clist, row, 3, s
		);
		if(style != NULL)
		    gtk_clist_set_cell_style(clist, row, 3, style);
	    }
	    /* Set column 4 as the Start Time */
	    if(clist->columns > 4)
	    {
		const gchar *s = EDVDateFormatString(
		    h_ptr->time_start, date_format, date_relativity
		);
		gtk_clist_set_text(
		    clist, row, 4,
		    (s != NULL) ? s : ""
		);
	    }
	    /* Set column 5 as the End Time */
	    if(clist->columns > 5)
	    {
		const gchar *s = EDVDateFormatString(
		    h_ptr->time_end, date_format, date_relativity
		);
		gtk_clist_set_text(
		    clist, row, 5,
		    (s != NULL) ? s : ""
		);
	    }


	    /* Set row data */
	    gtk_clist_set_row_data_full(
		clist, row,
		EDVHistoryCopy(h_ptr),
		(GtkDestroyNotify)EDVHistoryListItemDestroyCB
	    );
	}
}

/*
 *	Updates the History List Window's history list.
 */
void EDVHistoryWinUpdateList(edv_history_win_struct *lw)
{
	gint i, max_events, row, columns, width;
	gchar **strv;
	GtkRcStyle *lists_rcstyle;
	GtkAdjustment *adj;
	GtkCList *clist;
	const cfg_item_struct *cfg_list;
	edv_history_struct **list = NULL;
	gint total = 0;
	const edv_history_struct *h_ptr;
	edv_core_struct *core;

	if(lw == NULL)
	    return;

	clist = (GtkCList *)lw->history_clist;
	core = lw->core;
	if((clist == NULL) || (core == NULL))
	    return;

	cfg_list = core->cfg_list;
	lists_rcstyle = core->lists_rcstyle;

	max_events = EDV_GET_I(EDV_CFG_PARM_HISTORY_EVENTS_MAX);

	columns = clist->columns;
	if(columns < 1)
	    return;

	/* Create row cell values */
	strv = (gchar **)g_malloc(columns * sizeof(gchar *));
	for(i = 0; i < columns; i++)
	    strv[i] = "";

	/* Begin fetching row values */

	gtk_clist_freeze(clist);

	/* Delete all existing rows */
	gtk_clist_clear(clist);

	/* Load history items from file */
	EDVHistoryListOpen(
	    EDV_GET_S(EDV_CFG_PARM_FILE_HISTORY),
	    &list, &total,
	    NULL,
	    core
	);

	/* Load history events to the list, skipping earlier events
	 * as needed to avoid exceeding max_events
	 */
	for(i = (max_events > 0) ? MAX(total - max_events, 0) : 0;
	    i < total;
	    i++
	)
	{
	    h_ptr = list[i];
	    if(h_ptr == NULL)
		continue;

	    /* Append a new row */
	    row = gtk_clist_append(clist, strv);
	    if(row > -1)
	    {
		EDVHistoryWinSetRow(lw, row, h_ptr);
	    }
	}

	/* Delete all loaded history events */
	for(i = 0; i < total; i++)
	    EDVHistoryDelete(list[i]);
	g_free(list);

	/* Update columns */
	i = 0;	/* Type */
	if(i < columns)
	{
	    gtk_clist_set_column_visibility(clist, i, TRUE);
	    gtk_clist_set_column_resizeable(clist, i, TRUE);
	    width = gtk_clist_optimal_column_width(clist, i);
	    gtk_clist_set_column_width(clist, i, width);
	    gtk_clist_set_column_justification(
		clist, i, GTK_JUSTIFY_LEFT
	    );
	}
	i = 1;	/* Source */
	if(i < columns)
	{
	    gtk_clist_set_column_visibility(clist, i, TRUE);
	    gtk_clist_set_column_resizeable(clist, i, TRUE);
	    width = gtk_clist_optimal_column_width(clist, i);
	    gtk_clist_set_column_width(clist, i, width);
	    gtk_clist_set_column_justification(
		clist, i, GTK_JUSTIFY_LEFT
	    );
	}
	i = 2;	/* Target */
	if(i < columns)
	{
	    gtk_clist_set_column_visibility(clist, i, TRUE);
	    gtk_clist_set_column_resizeable(clist, i, TRUE);
	    width = gtk_clist_optimal_column_width(clist, i);
	    gtk_clist_set_column_width(clist, i, width);
	    gtk_clist_set_column_justification(
		clist, i, GTK_JUSTIFY_LEFT
	    );
	}
	i = 3;	/* Status */
	if(i < columns)
	{
	    gtk_clist_set_column_visibility(clist, i, TRUE);
	    gtk_clist_set_column_resizeable(clist, i, TRUE);
	    width = gtk_clist_optimal_column_width(clist, i);
	    gtk_clist_set_column_width(clist, i, width);
	    gtk_clist_set_column_justification(
		clist, i, GTK_JUSTIFY_CENTER
	    );
	}
	i = 4;	/* Time Start */
	if(i < columns)
	{
	    gtk_clist_set_column_visibility(clist, i, TRUE);
	    gtk_clist_set_column_resizeable(clist, i, TRUE);
	    width = gtk_clist_optimal_column_width(clist, i);
	    gtk_clist_set_column_width(clist, i, width);
	    gtk_clist_set_column_justification(
		clist, i, GTK_JUSTIFY_LEFT
	    );
	}
	i = 5;	/* Time End */
	if(i < columns)
	{
	    gtk_clist_set_column_visibility(clist, i, TRUE);
	    gtk_clist_set_column_resizeable(clist, i, TRUE);
	    width = gtk_clist_optimal_column_width(clist, i);
	    gtk_clist_set_column_width(clist, i, width);
	    gtk_clist_set_column_justification(
		clist, i, GTK_JUSTIFY_LEFT
	    );
	}

	gtk_clist_thaw(clist);

	/* Scroll to end */
	adj = clist->vadjustment;
	if(adj != NULL)
	    gtk_adjustment_set_value(
		adj,
		MAX(
		    adj->upper - adj->page_size,
		    adj->lower
		)
	    );

	/* Set RC style after column heading mapping */
	if(lists_rcstyle != NULL)
	    gtk_widget_modify_style_recursive(
		GTK_WIDGET(clist), lists_rcstyle
	    );

	/* Delete row cell values */
	g_free(strv);
}


/*
 *      Sets values on the given history list window to the
 *	configuration list.
 */
void EDVHistoryWinSyncConfiguration(edv_history_win_struct *lw)
{
	GtkWidget *w;
	edv_core_struct *core;
	cfg_item_struct *cfg_list;

	if(lw == NULL)
	    return;

	core = lw->core;
	if(core == NULL)
	    return;

	cfg_list = core->cfg_list;

	/* Toplevel geometry */
	w = lw->toplevel;
	if(w != NULL)
	{
#if 0
	    GdkWindow *window = w->window;
	    gint x = 0, y = 0;

	    if(window != NULL)
		gdk_window_get_root_origin(window, &x, &y);

	    EDV_SET_I(EDV_CFG_PARM_HISTORYWIN_X, x);
	    EDV_SET_I(EDV_CFG_PARM_HISTORYWIN_Y, y);
	    EDV_SET_I(EDV_CFG_PARM_HISTORYWIN_WIDTH, w->allocation.width);
	    EDV_SET_I(EDV_CFG_PARM_HISTORYWIN_HEIGHT, w->allocation.height);
#endif
	}
}


/*
 *	Recreates the History List Window's list styles.
 */
void EDVHistoryWinListStylesRegenerate(edv_history_win_struct *lw)
{
	gint i;
	edv_history_win_cell_style n;
	GdkColormap *colormap;
	GtkStyle *style, *src_style;
	GtkWidget *w;

	if(lw == NULL)
	    return;

	w = lw->history_clist;
	if(w == NULL)
	    return;

	/* Unref existing cell styles */
	for(i = 0; i < EDV_HISTORY_TOTAL_CELL_STYLES; i++)
	{
	    GTK_STYLE_UNREF(lw->cell_style[i]);
	    lw->cell_style[i] = NULL;
	}

	/* Get source style from contents clist as a template */
	colormap = gtk_widget_get_colormap(w);
	src_style = gtk_widget_get_style(w);
	if(src_style == NULL)
	    return;

	/* Begin creating cell styles */

#define REALLOC_COLOR(_ct_,_cs_)	{			\
 GDK_COLORMAP_FREE_COLOR(colormap, (_ct_))			\
 memcpy((_ct_), (_cs_), sizeof(GdkColor));			\
 GDK_COLORMAP_ALLOC_COLOR(colormap, (_ct_))			\
}

	/* Success */
	n = EDV_HISTORY_CELL_STYLE_SUCCESS;
	lw->cell_style[n] = style = gtk_style_copy(src_style);
	if(style != NULL)
	{
	    const GdkColor      cs = EDV_GDKCOLOR_MEDIUM_GREEN,
				cs_sel = EDV_GDKCOLOR_GREEN,
				cs_insen = EDV_GDKCOLOR_DARK_GREEN;

	    GtkStateType state = GTK_STATE_NORMAL;
	    REALLOC_COLOR(&style->fg[state], &cs)

	    state = GTK_STATE_ACTIVE;
	    REALLOC_COLOR(&style->fg[state], &cs)

	    state = GTK_STATE_PRELIGHT;
	    REALLOC_COLOR(&style->fg[state], &cs)

	    state = GTK_STATE_SELECTED;
	    REALLOC_COLOR(&style->fg[state], &cs_sel)

	    state = GTK_STATE_INSENSITIVE;
	    REALLOC_COLOR(&style->fg[state], &cs_insen)
	}

	/* Error */
	n = EDV_HISTORY_CELL_STYLE_ERROR;
	lw->cell_style[n] = style = gtk_style_copy(src_style);
	if(style != NULL)
	{
	    const GdkColor      cs = EDV_GDKCOLOR_RED,
				cs_sel = EDV_GDKCOLOR_RED,
				cs_insen = EDV_GDKCOLOR_DARK_RED;

	    GtkStateType state = GTK_STATE_NORMAL;
	    REALLOC_COLOR(&style->fg[state], &cs)

	    state = GTK_STATE_ACTIVE;
	    REALLOC_COLOR(&style->fg[state], &cs)

	    state = GTK_STATE_PRELIGHT;
	    REALLOC_COLOR(&style->fg[state], &cs)

	    state = GTK_STATE_SELECTED;
	    REALLOC_COLOR(&style->fg[state], &cs_sel)

	    state = GTK_STATE_INSENSITIVE;
	    REALLOC_COLOR(&style->fg[state], &cs_insen)
	}

	/* Cancel */
	n = EDV_HISTORY_CELL_STYLE_CANCEL;
	lw->cell_style[n] = style = gtk_style_copy(src_style);
	if(style != NULL)
	{
	    const GdkColor      cs = EDV_GDKCOLOR_ORANGE,
				cs_sel = EDV_GDKCOLOR_ORANGE,
				cs_insen = EDV_GDKCOLOR_DARK_ORANGE;

	    GtkStateType state = GTK_STATE_NORMAL;
	    REALLOC_COLOR(&style->fg[state], &cs)

	    state = GTK_STATE_ACTIVE;
	    REALLOC_COLOR(&style->fg[state], &cs)

	    state = GTK_STATE_PRELIGHT;
	    REALLOC_COLOR(&style->fg[state], &cs)

	    state = GTK_STATE_SELECTED;
	    REALLOC_COLOR(&style->fg[state], &cs_sel)

	    state = GTK_STATE_INSENSITIVE;
	    REALLOC_COLOR(&style->fg[state], &cs_insen)
	}

#undef REALLOC_COLOR
}


/*
 *	Creates a new History List Window.
 */
edv_history_win_struct *EDVHistoryWinNew(edv_core_struct *core)
{
	const gint border_major = 5;
	gchar *heading[6];
	gpointer mclient_data;
	gpointer entry_rtn;
	GdkWindow *window;
	GtkRcStyle *standard_rcstyle = NULL, *lists_rcstyle = NULL;
	GtkAccelGroup *accelgrp;
	GtkStyle *style;
	GtkWidget *w, *menu;
	GtkWidget *parent, *parent2;
	GtkEntry *entry;
	GtkCList *clist;
	const cfg_item_struct *cfg_list;
	edv_history_win_struct *lw = EDV_HISTORY_WIN(
	    g_malloc0(sizeof(edv_history_win_struct))
	);
	if((lw == NULL) || (core == NULL))
	{
	    g_free(lw);
	    return(NULL);
	}

	cfg_list = core->cfg_list;

	standard_rcstyle = core->standard_rcstyle;
	lists_rcstyle = core->lists_rcstyle;

	lw->accelgrp = accelgrp = gtk_accel_group_new();
	lw->processing = FALSE;
	lw->busy_count = 0;
	lw->freeze_count = 0;
	lw->core = core;


	/* Begin creating widgets */

	/* Toplevel */
	lw->toplevel = w = gtk_window_new(GTK_WINDOW_DIALOG);
	gtk_widget_set_usize(w, LISTWIN_WIDTH, LISTWIN_HEIGHT);
	gtk_window_set_title(GTK_WINDOW(w), LISTWIN_TITLE);
	gtk_window_set_wmclass(
	    GTK_WINDOW(w), "history", PROG_NAME
	);
	gtk_widget_realize(w);
	style = gtk_widget_get_style(w);
	window = w->window;
	if(window != NULL)
	{
	    gdk_window_set_decorations(
		window,
		GDK_DECOR_BORDER | GDK_DECOR_TITLE | GDK_DECOR_MENU |
		GDK_DECOR_MINIMIZE
	    );
	    gdk_window_set_functions(
		window,
		GDK_FUNC_MOVE | GDK_FUNC_MINIMIZE | GDK_FUNC_CLOSE
	    );
	    GUISetWMIcon(window, (guint8 **)icon_trace_48x48_xpm);
	}
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_event",
	    GTK_SIGNAL_FUNC(EDVHistoryWinDeleteEventCB), lw
	);
	gtk_container_border_width(GTK_CONTAINER(w), 0);
	gtk_window_add_accel_group(GTK_WINDOW(w), accelgrp);
	parent = w;


	/* Load pixmaps */
#define LOAD_PIXMAP(_d_,_n_,_pixmap_rtn_,_mask_rtn_)    {       \
 EDVLoadPixmap(                                                 \
  core,                                           \
  (guint8 **)(_d_), (_n_),                                      \
  (_pixmap_rtn_), (_mask_rtn_)                                  \
 );                                                             \
}
	LOAD_PIXMAP(
	    icon_executable_20x20_xpm,
	    "icon_executable_20x20_xpm",
	    &lw->other_operation_pixmap,
	    &lw->other_operation_mask
	);
	LOAD_PIXMAP(
	    icon_new_20x20_xpm,
	    "icon_new_20x20_xpm",
	    &lw->object_create_pixmap,
	    &lw->object_create_mask
	);
	LOAD_PIXMAP(
	    icon_copy_file_20x20_xpm,
	    "icon_copy_file_20x20_xpm",
	    &lw->object_copy_pixmap,
	    &lw->object_copy_mask
	);
	LOAD_PIXMAP(
	    icon_move_file_20x20_xpm,
	    "icon_move_file_20x20_xpm",
	    &lw->object_move_pixmap,
	    &lw->object_move_mask
	);
	LOAD_PIXMAP(
	    icon_link2_20x20_xpm,
	    "icon_link2_20x20_xpm",
	    &lw->object_link_pixmap,
	    &lw->object_link_mask
	);
	LOAD_PIXMAP(
	    icon_owned_20x20_xpm,
	    "icon_owned_20x20_xpm",
	    &lw->object_chown_pixmap,
	    &lw->object_chown_mask
	);
	LOAD_PIXMAP(
	    icon_chmod_20x20_xpm,
	    "icon_chmod_20x20_xpm",
	    &lw->object_chmod_pixmap,
	    &lw->object_chmod_mask
	);
	LOAD_PIXMAP(
	    icon_time_stamp_20x20_xpm,
	    "icon_time_stamp_20x20_xpm",
	    &lw->object_chtime_pixmap,
	    &lw->object_chtime_mask
	);
	LOAD_PIXMAP(
	    icon_download_file_20x20_xpm,
	    "icon_download_file_20x20_xpm",
	    &lw->object_download_pixmap,
	    &lw->object_download_mask
	);
	LOAD_PIXMAP(
	    icon_cancel_20x20_xpm,
	    "icon_cancel_20x20_xpm",
	    &lw->object_delete_pixmap,
	    &lw->object_delete_mask
	);

	LOAD_PIXMAP(
	    icon_recover_20x20_xpm,
	    "icon_recover_20x20_xpm",
	    &lw->recobj_recover_pixmap,
	    &lw->recobj_recover_mask
	);
	LOAD_PIXMAP(
	    icon_purge_20x20_xpm,
	    "icon_purge_20x20_xpm",
	    &lw->recobj_purge_pixmap,
	    &lw->recobj_purge_mask
	);

	LOAD_PIXMAP(
	    icon_archive_add_20x20_xpm,
	    "icon_archive_add_20x20_xpm",
	    &lw->arcobj_add_pixmap,
	    &lw->arcobj_add_mask
	);
	LOAD_PIXMAP(
	    icon_archive_extract_20x20_xpm,
	    "icon_archive_extract_20x20_xpm",
	    &lw->arcobj_extract_pixmap,
	    &lw->arcobj_extract_mask
	);
	LOAD_PIXMAP(
	    icon_cancel_20x20_xpm,
	    "icon_cancel_20x20_xpm",
	    &lw->arcobj_delete_pixmap,
	    &lw->arcobj_delete_mask
	);
	LOAD_PIXMAP(
	    icon_aid_20x20_xpm,
	    "icon_aid_20x20_xpm",
	    &lw->archive_fix_pixmap,
	    &lw->archive_fix_mask
	);

	LOAD_PIXMAP(
	    icon_object_misc_20x20_xpm,
	    "icon_object_misc_20x20_xpm",
	    &lw->object_other_small_pixmap,
	    &lw->object_other_small_mask
	);
	LOAD_PIXMAP(
	    icon_object_misc_32x32_xpm,
	    "icon_object_misc_32x32_xpm",
	    &lw->object_other_medium_pixmap,
	    &lw->object_other_medium_mask
	);
	LOAD_PIXMAP(
	    icon_error_32x32_xpm,
	    "icon_error_32x32_xpm",
	    &lw->error_medium_pixmap,
	    &lw->error_medium_mask
	);
#undef LOAD_PIXMAP


	/* Main vbox */
	lw->main_vbox = w = gtk_vbox_new(FALSE, border_major);
	gtk_container_border_width(GTK_CONTAINER(w), border_major);
	gtk_container_add(GTK_CONTAINER(parent), w);
	gtk_widget_show(w);
	parent = w;


	/* Hbox for find prompt */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	w = GUIPromptBar(
	    (guint8 **)icon_search_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"El Hallazgo"
#elif defined(PROG_LANGUAGE_FRENCH)
"Recherche"
#elif defined(PROG_LANGUAGE_GERMAN)
"Fund"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Trovare"
#elif defined(PROG_LANGUAGE_DUTCH)
"Vondst"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Ache"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Funn"
#else
"Find"
#endif
	    ":", NULL, &entry_rtn
	);
	lw->find_entry = (GtkWidget *)entry_rtn;
	entry = (GtkEntry *)entry_rtn;
	gtk_signal_connect(
	    GTK_OBJECT(entry), "activate",
	    GTK_SIGNAL_FUNC(EDVHistoryWinFindCB), lw
	);
	EDVEntrySetDND(core, w);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, 0);
	gtk_widget_show(w);


	/* Scrolled window for history clist */
	w = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(
	    GTK_SCROLLED_WINDOW(w),
	    GTK_POLICY_AUTOMATIC,
	    GTK_POLICY_AUTOMATIC
	);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Contents clist */
#if defined(PROG_LANGUAGE_SPANISH)
	heading[0] = "El Tipo";
	heading[1] = "La Fuente";
	heading[2] = "El Objetivo";
	heading[3] = "La Posición";
	heading[4] = "El Comienzo Del Tiempo";
	heading[5] = "El Fin Del Tiempo.";
#elif defined(PROG_LANGUAGE_FRENCH)
	heading[0] = "Type";
	heading[1] = "Source";
	heading[2] = "Destination";
	heading[3] = "Etat";
	heading[4] = "Heure Début";
	heading[5] = "Heure Fin";
#elif defined(PROG_LANGUAGE_GERMAN)
	heading[0] = "Typ";
	heading[1] = "Quelle";
	heading[2] = "Ziel";
	heading[3] = "Status";
	heading[4] = "Zeit Anfang";
	heading[5] = "Zeit Ende";
#elif defined(PROG_LANGUAGE_ITALIAN)
	heading[0] = "Il Tipo";
	heading[1] = "La Fonte";
	heading[2] = "Il Bersaglio";
	heading[3] = "Lo Stato";
	heading[4] = "L'Inizio Di Tempo";
	heading[5] = "La Fine Di Tempo";
#elif defined(PROG_LANGUAGE_DUTCH)
	heading[0] = "Type";
	heading[1] = "Bron";
	heading[2] = "Doel";
	heading[3] = "Status";
	heading[4] = "Regeel Start";
	heading[5] = "Regeel Einde";
#elif defined(PROG_LANGUAGE_PORTUGUESE)
	heading[0] = "O Tipo";
	heading[1] = "A Fonte";
	heading[2] = "O Alvo";
	heading[3] = "O Estado";
	heading[4] = "O Tempo Começa";
	heading[5] = "O Fim De Tempo";
#elif defined(PROG_LANGUAGE_NORWEGIAN)
	heading[0] = "Type";
	heading[1] = "Kilde";
	heading[2] = "Mål";
	heading[3] = "Status";
	heading[4] = "TidsStart";
	heading[5] = "TidsSlutt";
#else
	heading[0] = "Type";
	heading[1] = "Source";
	heading[2] = "Target";
	heading[3] = "Status";
	heading[4] = "Time Start";
	heading[5] = "Time End";
#endif
	lw->history_clist = w = gtk_clist_new_with_titles(6, heading);
	clist = GTK_CLIST(w);
	gtk_widget_add_events(
	    w,
	    GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
	    GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
	    GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
	    GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_press_event",
	    GTK_SIGNAL_FUNC(EDVCListKeyEventCB), core
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_release_event",
	    GTK_SIGNAL_FUNC(EDVCListKeyEventCB), core
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_press_event",
	    GTK_SIGNAL_FUNC(EDVCListButtonEventCB), core
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_release_event",
	    GTK_SIGNAL_FUNC(EDVCListButtonEventCB), core
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "motion_notify_event",
	    GTK_SIGNAL_FUNC(EDVCListMotionEventCB), core
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_press_event",
	    GTK_SIGNAL_FUNC(EDVHistoryWinKeyEventCB), lw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_release_event",
	    GTK_SIGNAL_FUNC(EDVHistoryWinKeyEventCB), lw
	);
	gtk_signal_connect_after(
	    GTK_OBJECT(w), "button_press_event",
	    GTK_SIGNAL_FUNC(EDVHistoryWinButtonPressEventCB), lw
	);
	gtk_widget_set_usize( 
	    w,
	    -1,
	    MAX(LISTWIN_HEIGHT * 0.45f, 100)
	);
	gtk_container_add(GTK_CONTAINER(parent2), w);
	gtk_widget_realize(w);
	gtk_clist_set_selection_mode(clist, GTK_SELECTION_SINGLE);
	gtk_clist_column_titles_passive(clist);
	gtk_clist_set_row_height(clist, EDV_LIST_ROW_SPACING);
	gtk_clist_set_shadow_type(clist, GTK_SHADOW_IN);
	gtk_signal_connect(
	    GTK_OBJECT(w), "select_row",
	    GTK_SIGNAL_FUNC(EDVHistoryWinSelectRowCB), lw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "unselect_row",
	    GTK_SIGNAL_FUNC(EDVHistoryWinUnselectRowCB), lw
	);
	gtk_widget_show(w);


	/* Hbox for buttons */
	w = gtk_hbox_new(TRUE, 0);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Refresh Button */
	lw->refresh_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_reload_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Refresque"
#elif defined(PROG_LANGUAGE_FRENCH)
"Rafraîchir"
#elif defined(PROG_LANGUAGE_GERMAN)
"Erfrischen Sie"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Rinfrescare"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verfris"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Refresque-se"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forfrisk"
#else
"Refresh"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVHistoryWinRefreshCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_F5, 0, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	gtk_accel_group_add(
	    accelgrp, GDK_r, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_r);
	gtk_widget_show(w);

#if 0
	/* Save As Button */
	lw->save_as_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_save_as_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Salve Como"
#elif defined(PROG_LANGUAGE_FRENCH)
"Enregister sous:"
#elif defined(PROG_LANGUAGE_GERMAN)
"Außer Als"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Risparmiare Come"
#elif defined(PROG_LANGUAGE_DUTCH)
"Behalve Als"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Exceto Como"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Untatt Som"
#else
"Save As"
#endif
	    "...", NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVHistoryWinSaveAsCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_s);
	gtk_widget_show(w);
#endif

	/* Clear Button */
	lw->clear_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_clear_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Claro"
#elif defined(PROG_LANGUAGE_FRENCH)
"Effacer"
#elif defined(PROG_LANGUAGE_GERMAN)
"Klar"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Chiaro"
#elif defined(PROG_LANGUAGE_DUTCH)
"Helder"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Claro"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Klar"
#else
"Clear"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVHistoryWinClearCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_l, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_l);
	gtk_widget_show(w);


	/* Horizontal separator */
	w = gtk_hseparator_new();
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);


	/* Parent vbox for displaying selected history */
	lw->display_parent = w = gtk_vbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Client vbox that is parented to the display_parent, leave
	 * this NULL, it will be created when needed
	 */
	lw->display_client = NULL;


	/* Horizontal separator */
	w = gtk_hseparator_new();
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);


	/* Hbox for buttons */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Close button */
	lw->close_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_close_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Cierre"
#elif defined(PROG_LANGUAGE_FRENCH)
"Quitter"
#elif defined(PROG_LANGUAGE_GERMAN)
"Nah"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Vicino"
#elif defined(PROG_LANGUAGE_DUTCH)
"Einde"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Próximo"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Nær"
#else
"Close"
#endif
	    , NULL
	);
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH_DEF, GUI_BUTTON_HLABEL_HEIGHT_DEF
	);
	gtk_box_pack_end(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVHistoryWinCloseCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_Escape, 0, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	gtk_accel_group_add(
	    accelgrp, GDK_c, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_c);
	gtk_widget_show(w);



	/* Right click menu */
	lw->menu = menu = GUIMenuCreate();
	mclient_data = lw;
	if(menu != NULL)
	{
	    guint8 **icon;
	    const gchar *label;
	    guint accel_key, accel_mods;
	    void (*func_cb)(GtkWidget *, gpointer);

#define DO_ADD_MENU_ITEM_LABEL	{		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_LABEL, accelgrp,	\
  icon, label, accel_key, accel_mods, NULL,	\
  mclient_data, func_cb				\
 );						\
}
#define DO_ADD_MENU_SEP		{		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL,	\
  NULL, NULL, 0, 0, NULL,			\
  NULL, NULL					\
 );						\
}
	    icon = (guint8 **)icon_reload_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Refresque"
#elif defined(PROG_LANGUAGE_FRENCH)
"Rafraîchir"
#elif defined(PROG_LANGUAGE_GERMAN)
"Erfrischen Sie"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Rinfrescare"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verfris"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Refresque-se"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forfrisk"
#else
"Refresh"
#endif
	    ;
	    accel_key = GDK_F5;
	    accel_mods = 0;
	    func_cb = EDVHistoryWinRefreshCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->refresh_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_save_as_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Salve Como"
#elif defined(PROG_LANGUAGE_FRENCH)
"Enregister sous"
#elif defined(PROG_LANGUAGE_GERMAN)
"Außer Als"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Risparmiare Come"
#elif defined(PROG_LANGUAGE_DUTCH)
"Behalve Als"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Exceto Como"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Untatt Som"
#else
"Save As"
#endif
		"...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVHistoryWinSaveAsCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->save_as_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_clear_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Claro"
#elif defined(PROG_LANGUAGE_FRENCH)
"Effacer"
#elif defined(PROG_LANGUAGE_GERMAN)
"Klar"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Chiaro"
#elif defined(PROG_LANGUAGE_DUTCH)
"Helder"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Claro"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Klar"
#else
"Clear"
#endif
	    ;
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVHistoryWinClearCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->clear_mi = w;


#undef DO_ADD_MENU_ITEM_LABEL
#undef DO_ADD_MENU_SEP
	}


	/* Set initial RC styles */
	if(standard_rcstyle != NULL)
	    gtk_widget_modify_style_recursive(
		lw->toplevel, standard_rcstyle
	    );
	if(lists_rcstyle != NULL)
	    gtk_widget_modify_style(
		lw->history_clist, lists_rcstyle
	    );
	EDVHistoryWinListStylesRegenerate(lw);


	EDVHistoryWinUpdateMenus(lw);

	return(lw);
}

/*
 *	Updates menus and other widgets on the given history list
 *	window to reflect its current data.
 */
void EDVHistoryWinUpdateMenus(edv_history_win_struct *lw)
{
	gint sel_row;
	GtkCList *clist;

	if(lw == NULL)
	    return;

	/* Get selected row on clist */
	clist = (GtkCList *)lw->history_clist;
	sel_row = EDVCListGetSelectedLast(clist, NULL);

}

/*
 *	Marks the history list window as busy or ready.
 */
void EDVHistoryWinSetBusy(
	edv_history_win_struct *lw, gboolean is_busy
)
{
	GdkCursor *cursor;
	GtkWidget *w;
	edv_core_struct *core;


	if(lw == NULL)
	    return;

	core = lw->core;
	if(core == NULL)
	    return;

	w = lw->toplevel;
	if(w != NULL)
	{
	    if(is_busy)
	    {
		/* Increase busy count */
		lw->busy_count++;

		/* If already busy then don't change anything */
		if(lw->busy_count > 1)
		    return;

		cursor = EDVGetCursor(core, EDV_CURSOR_CODE_BUSY);
	    }
	    else
	    {
		/* Reduce busy count */
		lw->busy_count--;
		if(lw->busy_count < 0)
		    lw->busy_count = 0;

		/* If still busy do not change anything */
		if(lw->busy_count > 0)
		    return;

		cursor = NULL;  /* Use default cursor */
	    }

	    /* Update toplevel window's cursor */
	    if(w->window != NULL)
	    {
		gdk_window_set_cursor(w->window, cursor);
		gdk_flush();
	    }
	}
}


/*
 *	Checks if the History List Window is mapped.
 */
gboolean EDVHistoryWinIsMapped(edv_history_win_struct *lw)
{
	GtkWidget *w = (lw != NULL) ? lw->toplevel : NULL;
	return((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE);
}

/*
 *	Maps the History List Window.
 */
void EDVHistoryWinMap(edv_history_win_struct *lw)
{
	GtkWidget *w = (lw != NULL) ? lw->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_show_raise(w);

	/* Grab focus and default on the Close button */
	w = lw->close_btn;
	if(w != NULL)
	{
	    gtk_widget_grab_focus(w);
	    gtk_widget_grab_default(w);
	}
}

/*
 *	Unmaps the History List Window.
 */
void EDVHistoryWinUnmap(edv_history_win_struct *lw)
{
	GtkWidget *w = (lw != NULL) ? lw->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_hide(w);
}

/*
 *	Deletes the History List Window.
 */
void EDVHistoryWinDelete(edv_history_win_struct *lw)
{
	gint i;

	if(lw == NULL)
	    return;

	/* Destroy right click menu */
	GTK_WIDGET_DESTROY(lw->menu);
	lw->menu = NULL;

	/* Begin destroying widgets */
	GTK_WIDGET_DESTROY(lw->display_client);
	lw->display_client = NULL;
	GTK_WIDGET_DESTROY(lw->display_parent);
	lw->display_parent = NULL;

	GTK_WIDGET_DESTROY(lw->find_entry);
	lw->find_entry = NULL;
	GTK_WIDGET_DESTROY(lw->history_clist);
	lw->history_clist = NULL;

	GTK_WIDGET_DESTROY(lw->refresh_btn);
	lw->refresh_btn = NULL;
	GTK_WIDGET_DESTROY(lw->save_as_btn);
	lw->save_as_btn = NULL;
	GTK_WIDGET_DESTROY(lw->clear_btn);
	lw->clear_btn = NULL;
	GTK_WIDGET_DESTROY(lw->close_btn);
	lw->close_btn = NULL;

	GTK_WIDGET_DESTROY(lw->toplevel);
	lw->toplevel = NULL;

	GTK_ACCEL_GROUP_UNREF(lw->accelgrp);
	lw->accelgrp = NULL;


	/* Delete pixmaps */
	GDK_PIXMAP_UNREF(lw->other_operation_pixmap);
	GDK_BITMAP_UNREF(lw->other_operation_mask);

	GDK_PIXMAP_UNREF(lw->object_create_pixmap);
	GDK_BITMAP_UNREF(lw->object_create_mask);
	GDK_PIXMAP_UNREF(lw->object_copy_pixmap);
	GDK_BITMAP_UNREF(lw->object_copy_mask);
	GDK_PIXMAP_UNREF(lw->object_move_pixmap);
	GDK_BITMAP_UNREF(lw->object_move_mask);
	GDK_PIXMAP_UNREF(lw->object_link_pixmap);
	GDK_BITMAP_UNREF(lw->object_link_mask);
	GDK_PIXMAP_UNREF(lw->object_chown_pixmap);
	GDK_BITMAP_UNREF(lw->object_chown_mask);
	GDK_PIXMAP_UNREF(lw->object_chmod_pixmap);
	GDK_BITMAP_UNREF(lw->object_chmod_mask);
	GDK_PIXMAP_UNREF(lw->object_chtime_pixmap);
	GDK_BITMAP_UNREF(lw->object_chtime_mask);
	GDK_PIXMAP_UNREF(lw->object_download_pixmap);
	GDK_BITMAP_UNREF(lw->object_download_mask);
	GDK_PIXMAP_UNREF(lw->object_delete_pixmap);
	GDK_BITMAP_UNREF(lw->object_delete_mask);

	GDK_PIXMAP_UNREF(lw->recobj_recover_pixmap);
	GDK_BITMAP_UNREF(lw->recobj_recover_mask);
	GDK_PIXMAP_UNREF(lw->recobj_purge_pixmap);
	GDK_BITMAP_UNREF(lw->recobj_purge_mask);

	GDK_PIXMAP_UNREF(lw->arcobj_add_pixmap);
	GDK_BITMAP_UNREF(lw->arcobj_add_mask);
	GDK_PIXMAP_UNREF(lw->arcobj_extract_pixmap);
	GDK_BITMAP_UNREF(lw->arcobj_extract_mask);
	GDK_PIXMAP_UNREF(lw->arcobj_delete_pixmap);
	GDK_BITMAP_UNREF(lw->arcobj_delete_mask);
	GDK_PIXMAP_UNREF(lw->archive_fix_pixmap);
	GDK_BITMAP_UNREF(lw->archive_fix_mask);

	GDK_PIXMAP_UNREF(lw->object_other_small_pixmap);
	GDK_BITMAP_UNREF(lw->object_other_small_mask);
	GDK_PIXMAP_UNREF(lw->object_other_medium_pixmap);
	GDK_BITMAP_UNREF(lw->object_other_medium_mask);

	GDK_PIXMAP_UNREF(lw->error_small_pixmap);
	GDK_BITMAP_UNREF(lw->error_small_mask);
	GDK_PIXMAP_UNREF(lw->error_medium_pixmap);
	GDK_BITMAP_UNREF(lw->error_medium_mask);


	/* Unref all cell styles */
	for(i = 0; i < EDV_HISTORY_TOTAL_CELL_STYLES; i++)
	    GTK_STYLE_UNREF(lw->cell_style[i]);


	g_free(lw);
}
