#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

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

#include "edv_types.h"
#include "edv_id.h"
#include "edv_obj.h"
#include "obj_op_dlg.h"
#include "endeavour2.h"
#include "edv_obj_op.h"
#include "edv_cb.h"
#include "edv_op.h"
#include "edv_utils.h"
#include "edv_utils_gtk.h"
#include "config.h"

#include "images/icon_cancel_20x20.xpm"
#include "images/icon_browse_20x20.xpm"
#include "images/icon_move_file_20x20.xpm"
#include "images/icon_copy_file_20x20.xpm"
#include "images/icon_link2_20x20.xpm"
#include "images/icon_move_file_32x32.xpm"
#include "images/icon_copy_file_32x32.xpm"
#include "images/icon_link2_32x32.xpm"
#include "images/icon_chmod_20x20.xpm"
#include "images/icon_chmod_32x32.xpm"
#include "images/icon_owned_20x20.xpm"
#include "images/icon_owned_32x32.xpm"
#include "images/icon_time_stamp_20x20.xpm"
#include "images/icon_time_stamp_32x32.xpm"


static gint EDVObjOpDlgDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
);
static void EDVObjOpDlgProcessCB(GtkWidget *widget, gpointer data);
static void EDVObjOpDlgCancelCB(GtkWidget *widget, gpointer data);
static void EDVObjOpDlgBrowseCB(GtkWidget *widget, gpointer data);

static void EDVObjOpDlgOwnerMapPUListCB(
	GtkWidget *widget, gpointer data
);
static void EDVObjOpDlgGroupMapPUListCB(
	GtkWidget *widget, gpointer data
);

static void EDVObjOpDlgATimeCurrentTimeCB(
	GtkWidget *widget, gpointer data
);
static void EDVObjOpDlgMTimeCurrentTimeCB(
	GtkWidget *widget, gpointer data
);

static void EDVObjOpDlgProcess(edv_obj_op_dlg_struct *d);

static void EDVObjOpDlgCreatePermissionWidgets(
	GtkWidget *parent,		/* GtkVBox */
	GtkStyle *style,
	GtkWidget **ur_w,
	GtkWidget **uw_w,
	GtkWidget **ux_w,
	GtkWidget **gr_w,
	GtkWidget **gw_w,
	GtkWidget **gx_w,
	GtkWidget **or_w,
	GtkWidget **ow_w,
	GtkWidget **ox_w,
	GtkWidget **suid_w,
	GtkWidget **sgid_w,
	GtkWidget **sticky_w
);
static void EDVObjOpDlgCreateTimeStampWidgets(
	GtkWidget *parent,
	const gchar *pfx_label,
	GtkWidget **year_w,
	pulistbox_struct **month_pulistbox,
	GtkWidget **day_w, 
	GtkWidget **hours_w,
	GtkWidget **minutes_w,
	GtkWidget **seconds_w,
	GtkWidget **current_w
);
edv_obj_op_dlg_struct *EDVObjOpDlgNew(edv_core_struct *core);
void EDVObjOpDlgReset(edv_obj_op_dlg_struct *d);
void EDVObjOpDlgSetBusy(edv_obj_op_dlg_struct *d, const gboolean is_busy);
gboolean EDVObjOpDlgIsMapped(edv_obj_op_dlg_struct *d);
void EDVObjOpDlgMapValues(
	edv_obj_op_dlg_struct *d,
	const edv_obj_op_dlg_op op,	/* One of EDV_OBJ_OP_DLG_OP_* */
	edv_object_struct **src_obj,	/* Source list, will be coppied */
	const gint src_obj_total,
	const gchar *src_dir,
	GtkWidget *toplevel
);
void EDVObjOpDlgUnmap(edv_obj_op_dlg_struct *d);
void EDVObjOpDlgDelete(edv_obj_op_dlg_struct *d);


#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 FOPDLG_USE_PERMISSION_CHECK_BUTTON	FALSE


/*
 *	"delete_event" signal callback.
 */
static gint EDVObjOpDlgDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
)
{
	edv_obj_op_dlg_struct *d = EDV_OBJ_OP_DLG(data);
	if(d == NULL)
	    return(FALSE);

	EDVObjOpDlgCancelCB(NULL, d);

	return(TRUE);
}

/*
 *	Process signal callback.
 */
static void EDVObjOpDlgProcessCB(GtkWidget *widget, gpointer data)
{
	edv_obj_op_dlg_struct *d = EDV_OBJ_OP_DLG(data);
	if(d == NULL)
	    return;

	EDVObjOpDlgProcess(d);
}

/*
 *	Cancel signal callback.
 */
static void EDVObjOpDlgCancelCB(GtkWidget *widget, gpointer data)
{
	edv_obj_op_dlg_struct *d = EDV_OBJ_OP_DLG(data);
	if(d == NULL)
	    return;

	/* Unmap the Object Operations Dialog */
	EDVObjOpDlgUnmap(d);         

	/* Delete the source objects list and the source directory
	 * on the object operations dialog
	 */
	EDVObjOpDlgReset(d);
}


/*
 *	Browse callback.
 */
static void EDVObjOpDlgBrowseCB(GtkWidget *widget, gpointer data)
{
	gboolean status;
	GtkWidget *toplevel;
	fb_type_struct **ftype = NULL, *ftype_rtn = NULL;
	gint total_ftypes = 0;
	gchar **path_rtn = NULL;
	gint total_path_rtns = 0;
	GtkEntry *entry = (GtkEntry *)data;
	if((entry == NULL) || FileBrowserIsQuery())
	    return;

	toplevel = gtk_widget_get_toplevel(GTK_WIDGET(entry));

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

	/* Query user for target object */
	FileBrowserSetTransientFor(toplevel);
	status = FileBrowserGetResponse(
	    "Select Target Object",
	    "Select", "Cancel",
	    gtk_entry_get_text(entry),          /* Startup 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;
	    if(!STRISEMPTY(new_path))
	    {
		gtk_entry_set_text(entry, new_path);
		gtk_entry_set_position(entry, -1);
	    }
	}

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

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


/*
 *      Maps the popup list for the owner entry.
 */
static void EDVObjOpDlgOwnerMapPUListCB(GtkWidget *widget, gpointer data)
{
	gint nitems, nitems_visible;
	const gchar *value;
	GtkEntry *entry;
	pulist_struct *pulist;
	edv_core_struct *core;
	edv_obj_op_dlg_struct *d = EDV_OBJ_OP_DLG(data);
	if(d == NULL)
	    return;

	entry = (GtkEntry *)d->target_owner_entry;
	core = d->core;
	if((entry == NULL) || (core == NULL))
	    return;

	pulist = core->users_pulist;
	if(PUListIsQuery(pulist))
	    return;

	nitems = PUListGetTotalItems(pulist);
	nitems_visible = MIN(15, nitems);

	/* Block input and get value */
	value = PUListMapQuery(
	    pulist,			/* Popup List */
	    gtk_entry_get_text(entry),	/* Initial Value */
	    nitems_visible,
	    PULIST_RELATIVE_BELOW,	/* Popup Relativity */
	    GTK_WIDGET(entry),		/* Relative Widget */
	    widget			/* Map Trigger Widget */
	);
	/* Got value? */
	if(value != NULL)
	    gtk_entry_set_text(entry, value);
}

/*
 *      Maps the popup list for the group entry.
 */
static void EDVObjOpDlgGroupMapPUListCB(GtkWidget *widget, gpointer data)
{
	gint nitems, nitems_visible;
	const gchar *value;
	GtkEntry *entry;
	pulist_struct *pulist;
	edv_core_struct *core;
	edv_obj_op_dlg_struct *d = EDV_OBJ_OP_DLG(data);
	if(d == NULL)
	    return;

	entry = (GtkEntry *)d->target_group_entry;
	core = d->core;
	if((entry == NULL) || (core == NULL))
	    return;

	pulist = core->groups_pulist;
	if(PUListIsQuery(pulist))
	    return;

        nitems = PUListGetTotalItems(pulist);
        nitems_visible = MIN(15, nitems);

	/* Block input and get value */
	value = PUListMapQuery(
	    pulist,			/* Popup List */
	    gtk_entry_get_text(entry),	/* Initial Value */
	    nitems_visible,
	    PULIST_RELATIVE_BELOW,	/* Popup Relativity */
	    GTK_WIDGET(entry),		/* Relative Widget */
	    widget			/* Map Trigger Widget */
	);
	/* Got value? */
	if(value != NULL)
	    gtk_entry_set_text(entry, value);
}


/*
 *	Use the current time for access time callback.
 */
static void EDVObjOpDlgATimeCurrentTimeCB(
	GtkWidget *widget, gpointer data
)
{
	time_t t;
	const struct tm *tm_ptr;
	GtkWidget *w, *toplevel;
	edv_core_struct *core;
	edv_obj_op_dlg_struct *d = EDV_OBJ_OP_DLG(data);
	if(d == NULL)
	    return;

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

	/* Get the current time */
	t = time(NULL);
	tm_ptr = localtime(&t);
	if(tm_ptr == NULL)
	{
	    const gint error_code = (gint)errno;
	    gchar *error_msg = STRDUP(g_strerror(error_code));
	    EDVPlaySoundError(core);
	    EDVMessageError(
		"Get Time Error",
		error_msg,
		NULL,
		toplevel
	    );
	    g_free(error_msg);
	    return;
	}

	/* Set the access time stamp widgets */
	w = d->target_atime_year_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)(1900 + tm_ptr->tm_year)
	    );
	PUListBoxSelect(
	    d->target_atime_month_pulistbox,
	    tm_ptr->tm_mon
	);
	w = d->target_atime_day_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)tm_ptr->tm_mday
	    );
	w = d->target_atime_hours_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)tm_ptr->tm_hour
	    );
	w = d->target_atime_minutes_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)tm_ptr->tm_min
	    );
	w = d->target_atime_seconds_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)tm_ptr->tm_sec
	    );
}

/*
 *	Use the current time for the modify time callback.
 */
static void EDVObjOpDlgMTimeCurrentTimeCB(
	GtkWidget *widget, gpointer data
)
{
	time_t t;
	const struct tm *tm_ptr;
	GtkWidget *w, *toplevel;
	edv_core_struct *core;
	edv_obj_op_dlg_struct *d = EDV_OBJ_OP_DLG(data);
	if(d == NULL)
	    return;

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

	/* Get the current time */
	t = time(NULL);
	tm_ptr = localtime(&t);
	if(tm_ptr == NULL)
	{
	    const gint error_code = (gint)errno;
	    gchar *error_msg = STRDUP(g_strerror(error_code));
	    EDVPlaySoundError(core);
	    EDVMessageError(
		"Get Time Error",
		error_msg,
		NULL,
		toplevel
	    );
	    g_free(error_msg);
	    return;
	}

	/* Set the modify time stamp widgets */
	w = d->target_mtime_year_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)(1900 + tm_ptr->tm_year)
	    );
	PUListBoxSelect(
	    d->target_mtime_month_pulistbox,
	    tm_ptr->tm_mon
	);
	w = d->target_mtime_day_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)tm_ptr->tm_mday
	    );
	w = d->target_mtime_hours_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)tm_ptr->tm_hour
	    );
	w = d->target_mtime_minutes_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)tm_ptr->tm_min
	    );
	w = d->target_mtime_seconds_spin;
	if(w != NULL)
	    gtk_spin_button_set_value(
		GTK_SPIN_BUTTON(w),
		(gfloat)tm_ptr->tm_sec
	    );
}


/*
 *	Performs the operation based on the current values set
 *	on the Object Operations Dialog.
 *
 *	The values from the Object Operations Dialog's widgets and the
 *	list of objects will be collected and the operation specified
 *	by the Object Operations Dialog will be performed on each
 *	object.
 *
 *	The progress dialog will be mapped as needed as the operation
 *	is performed and any errors that occure during or after
 *	the operation will be displayed.
 *
 *	The Object Operations Dialog will then be unmapped and its
 *	values will be reset.
 */
static void EDVObjOpDlgProcess(edv_obj_op_dlg_struct *d)
{
	const gboolean show_progress = TRUE;
	gboolean	recursive = FALSE,
			dereference_links = FALSE;
	gint status, nobjs;
	gchar *tar_path;
	edv_obj_op_dlg_op op;
	edv_object_struct **objs_list;
	GtkWidget *w, *toplevel;
	edv_core_struct *core;

	edv_permission_flags permissions = 0x00000000;
	gint owner_id = 0, group_id = 0;
	gulong atime = 0l, mtime = 0l;

	if(d == NULL)
	    return;

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

	/* Check and warn if write protect is enabled */
	if(EDVCheckWriteProtect(core, TRUE, d->toplevel))
	    return;

	/* Get the operation code that indicates the operation that
	 * is to be perfirmed
	 */
	op = d->op;

	/* Get the reference toplevel widget for setting the
	 * transient for of subsequent dialogs
	 */
	toplevel = d->ref_toplevel;

	/* Get the list of objects to operate on */
	nobjs = d->src_obj_total;
	objs_list = d->src_obj;

	/* Get the target value */
	w = d->target_entry;
	if((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE)
	{
	    tar_path = EDVEvaluatePath(
		d->src_dir, gtk_entry_get_text(GTK_ENTRY(w))
	    );
	}
	else
	{
	    tar_path = NULL;
	}

	/* Get the permission values if the operation is Change
	 * Permissions
	 */
	w = d->target_chmod_parent;
	if((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE)
	{
	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_ur_check))
		permissions |= EDV_PERMISSION_UREAD;
	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_uw_check))
		permissions |= EDV_PERMISSION_UWRITE;
	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_ux_check))
		permissions |= EDV_PERMISSION_UEXECUTE;

	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_gr_check))
		permissions |= EDV_PERMISSION_GREAD;
	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_gw_check))
		permissions |= EDV_PERMISSION_GWRITE;
	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_gx_check))
		permissions |= EDV_PERMISSION_GEXECUTE;

	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_or_check))
		permissions |= EDV_PERMISSION_AREAD;
	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_ow_check))
		permissions |= EDV_PERMISSION_AWRITE;
	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_ox_check))
		permissions |= EDV_PERMISSION_AEXECUTE;

	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_suid_check))
		permissions |= EDV_PERMISSION_SETUID;
	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_sgid_check))
		permissions |= EDV_PERMISSION_SETGID;
	    if(GTK_TOGGLE_BUTTON_GET_ACTIVE(d->target_sticky_check))
		permissions |= EDV_PERMISSION_STICKY;
	}

	/* Get the owner & group values if the operation is Change
	 * Ownership
	 */
	w = d->target_chown_parent;
	if((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE)
	{
	    /* Get user id from user entry */
	    w = d->target_owner_entry;
	    if(w != NULL)
		owner_id = EDVUIDNameToUID(
		    core->uid, core->total_uids,
		    gtk_entry_get_text(GTK_ENTRY(w))
		);

	    /* Get group id from group entry */
	    w = d->target_group_entry;
	    if(w != NULL)
		group_id = EDVGIDNameToGID(
		    core->gid, core->total_gids,
		    gtk_entry_get_text(GTK_ENTRY(w))
		);
	}

	/* Get the time values if the operation is Change Time
	 * Stamps
	 */
	w = d->target_time_parent;
	if((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE)
	{
	    /* Access time */
	    struct tm *tm_buf = (struct tm *)g_malloc0(sizeof(struct tm));
	    if(tm_buf != NULL)
	    {
		w = d->target_atime_year_spin;
		if(w != NULL)
		    tm_buf->tm_year = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    ) - 1900;
		tm_buf->tm_mon = (gint)PUListBoxGetSelected(
		    d->target_atime_month_pulistbox
		);
		w = d->target_atime_day_spin;
		if(w != NULL)
		    tm_buf->tm_mday = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    );
		w = d->target_atime_hours_spin;
		if(w != NULL)
		    tm_buf->tm_hour = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    );
		w = d->target_atime_minutes_spin;
		if(w != NULL)
		    tm_buf->tm_min = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    );
		w = d->target_atime_seconds_spin;
		if(w != NULL)
		    tm_buf->tm_sec = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    );

		tm_buf->tm_isdst = -1;		/* Not specified */

		atime = (gulong)mktime(tm_buf);

		g_free(tm_buf);
	    }

	    /* Modify time */
	    tm_buf = (struct tm *)g_malloc0(sizeof(struct tm));
	    if(tm_buf != NULL)
	    {
		w = d->target_mtime_year_spin;
		if(w != NULL)
		    tm_buf->tm_year = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    ) - 1900;
		tm_buf->tm_mon = (gint)PUListBoxGetSelected(
		    d->target_mtime_month_pulistbox
		);
		w = d->target_mtime_day_spin;
		if(w != NULL)
		    tm_buf->tm_mday = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    );
		w = d->target_mtime_hours_spin;
		if(w != NULL)
		    tm_buf->tm_hour = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    );
		w = d->target_mtime_minutes_spin;
		if(w != NULL)
		    tm_buf->tm_min = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    );
		w = d->target_mtime_seconds_spin;
		if(w != NULL)
		    tm_buf->tm_sec = (gint)gtk_spin_button_get_value_as_int(
			GTK_SPIN_BUTTON(w)
		    );

		tm_buf->tm_isdst = -1;		/* Not specified */

		mtime = (gulong)mktime(tm_buf);

		g_free(tm_buf);
	    }
	}

	/* Get the options if they are specified */
	w = d->opt_parent;
	if((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE)
	{
	    w = d->opt_recursive_check;
	    if(GTK_WIDGET_MAPPED(w) && GTK_WIDGET_SENSITIVE(w))
		recursive = GTK_TOGGLE_BUTTON_GET_ACTIVE(
		    d->opt_recursive_check
		);
	    w = d->opt_dereference_links_check;
	    if(GTK_WIDGET_MAPPED(w) && GTK_WIDGET_SENSITIVE(w))
		dereference_links = GTK_TOGGLE_BUTTON_GET_ACTIVE(
		    d->opt_dereference_links_check
		);
	}


	/* Unmap the Object Operations Dialog */
	EDVObjOpDlgUnmap(d);


	status = 0;

	/* Perform the operation
	 *
	 * Copy?
	 */
	if(op == EDV_OBJ_OP_DLG_OP_COPY)
	{
	    struct stat lstat_buf;
	    gboolean yes_to_all = FALSE;
	    gint i;
	    const gchar *src_path;
	    gchar *new_path;
	    const gchar *error_msg;
	    edv_object_struct *obj;

	    /* Iterate through the objects list and copy each object */
	    for(i = 0; i < nobjs; i++)
	    {
		obj = objs_list[i];
		if(obj == NULL)
		    continue;

		src_path = obj->full_path;
		if(STRISEMPTY(src_path))
		    continue;

		/* Copy this object */
		status = EDVObjectOPCopy(
		    core,
		    src_path, tar_path,
		    &new_path,
		    toplevel,
		    show_progress,
		    TRUE,			/* Interactive */
		    &yes_to_all
		);

		/* Check for and report any errors */
		error_msg = EDVObjectOPGetError();
		if(!STRISEMPTY(error_msg))
		{
		    EDVPlaySoundError(core);
		    EDVMessageObjectOPError(
			"Copy Error",
			error_msg,
			src_path,
			toplevel
		    );
		}

		/* Get the source object's statistics */
                if(lstat(src_path, &lstat_buf))
                {
#ifdef ENOENT
		    /* Report the source object being removed */
                    const gint error_code = (gint)errno;
                    if(error_code == ENOENT)
                        EDVObjectRemovedEmit(core, src_path);
#endif
                }

		/* Report a new object being added? */
		if(new_path != NULL)
		{
		    if(!lstat(new_path, &lstat_buf))
			EDVObjectAddedEmit(
			    core,
			    new_path,
			    &lstat_buf
			);

		    /* Delete the new object path */
		    g_free(new_path);
		}

		/* User aborted? */
		if(status == -4)
		    break;
	    }
	}
	/* Move? */
	else if(op == EDV_OBJ_OP_DLG_OP_MOVE)
	{
	    struct stat lstat_buf;
	    gboolean yes_to_all = FALSE;
	    gint i;
	    const gchar *src_path;
	    gchar *new_path;
	    const gchar *error_msg;
	    edv_object_struct *obj;

	    /* Iterate through the objects list and move each object */
	    for(i = 0; i < nobjs; i++)
	    {
		obj = objs_list[i];
		if(obj == NULL)
		    continue;

		src_path = obj->full_path;
		if(STRISEMPTY(src_path))
		    continue;

		/* Move this object */
		status = EDVObjectOPMove(
		    core,
		    src_path, tar_path,
		    &new_path,
		    toplevel,
		    show_progress,
		    TRUE,			/* Interactive */
		    &yes_to_all
		);

		/* Check for and report any errors */
		error_msg = EDVObjectOPGetError();
		if(!STRISEMPTY(error_msg))
		{
		    EDVPlaySoundError(core);
		    EDVMessageObjectOPError(
			"Move Error",
			error_msg,
			src_path,
			toplevel
		    );
		}

		/* Get the source object's statistics */
                if(lstat(src_path, &lstat_buf))
                {
#ifdef ENOENT
		    /* Report the source object being removed */
                    const gint error_code = (gint)errno;
                    if(error_code == ENOENT)
                        EDVObjectRemovedEmit(core, src_path);
#endif
                }

		/* Report a new object being added? */
		if(new_path != NULL)
		{
		    if(!lstat(new_path, &lstat_buf))
			EDVObjectAddedEmit(
			    core,
			    new_path,
			    &lstat_buf
			);

		    /* Delete the new object path */
		    g_free(new_path);
		}

		/* User aborted? */
		if(status == -4)
		    break;
	    }
	}
	/* Link? */
	else if(op == EDV_OBJ_OP_DLG_OP_LINK)
	{
	    struct stat lstat_buf;
	    gboolean yes_to_all = FALSE;
	    gint i;
	    const gchar *src_path;
	    gchar *new_path;
	    const gchar *error_msg;
	    edv_object_struct *obj;

	    /* Iterate through the objects list and link each object */
	    for(i = 0; i < nobjs; i++)
	    {
		obj = objs_list[i];
		if(obj == NULL)
		    continue;

		src_path = obj->full_path;
		if(STRISEMPTY(src_path))
		    continue;

		/* Link this object */
		status = EDVObjectOPLink(
		    core,
		    tar_path,			/* New link */
		    src_path,			/* Destination value */
		    &new_path,
		    toplevel,
		    show_progress,
		    TRUE,			/* Interactive */
		    &yes_to_all
		);

		/* Check for and report any errors */
		error_msg = EDVObjectOPGetError();
		if(!STRISEMPTY(error_msg))
		{
		    EDVPlaySoundError(core);
		    EDVMessageObjectOPError(
			"Link Error",
			error_msg,
			src_path,
			toplevel
		    );
		}

		/* Get the source object's statistics */
                if(lstat(src_path, &lstat_buf))
                {
#ifdef ENOENT
		    /* Report the source object being removed */
                    const gint error_code = (gint)errno;
                    if(error_code == ENOENT)
                        EDVObjectRemovedEmit(core, src_path);
#endif
                }

		/* Report a new object being added? */
		if(new_path != NULL)
		{
		    if(!lstat(new_path, &lstat_buf))
			EDVObjectAddedEmit(
			    core,
			    new_path,
			    &lstat_buf
			);

		    /* Delete the new object path */
		    g_free(new_path);
		}

		/* User aborted? */
		if(status == -4)
		    break;
	    }
	}
	/* Change permissions? */
	else if(op == EDV_OBJ_OP_DLG_OP_CHMOD)
	{
	    gboolean yes_to_all = FALSE;
	    gint i;
	    const gchar *error_msg;
	    GList *paths_list = NULL, *modified_paths_list;
	    edv_object_struct *obj;

	    /* Create the paths list */
	    for(i = 0; i < nobjs; i++)
	    {
		obj = objs_list[i];
		if(obj == NULL)
		    continue;

		paths_list = g_list_append(
		    paths_list,
		    STRDUP(obj->full_path)
		);
	    }

	    /* Change the permissions */
	    status = EDVObjectOPChMod(
		core,
		paths_list, permissions,
		&modified_paths_list,
		toplevel,
		show_progress,
		TRUE,			/* Interactive */
		&yes_to_all,
		recursive,
		!dereference_links	/* Archive */
	    );

	    /* Check for error */
	    error_msg = EDVObjectOPGetError();
	    if(!STRISEMPTY(error_msg))
	    {
		EDVPlaySoundError(core);
		EDVMessageError(
		    "Change Permissions Error",
		    error_msg,
		    NULL,
		    toplevel
		);
	    }

	    /* Report the modified objects */
	    if(modified_paths_list != NULL)
	    {
		struct stat lstat_buf;
		const gchar *modified_path;
		GList *glist;

		for(glist = modified_paths_list;
		    glist != NULL;
		    glist = g_list_next(glist)
		)
		{
		    modified_path = (const gchar *)glist->data;
		    if(modified_path == NULL)
			continue;

		    if(!lstat(modified_path, &lstat_buf))
			EDVObjectModifiedEmit(
			    core,
			    modified_path,
			    modified_path,
			    &lstat_buf
			);
		}

		/* Delete the modified paths list */
		g_list_foreach(modified_paths_list, (GFunc)g_free, NULL);
		g_list_free(modified_paths_list);
	    }

	    /* Delete the paths list */
	    if(paths_list != NULL)
	    {
		g_list_foreach(paths_list, (GFunc)g_free, NULL);
		g_list_free(paths_list);
	    }
	}
	/* Change ownership? */
	else if(op == EDV_OBJ_OP_DLG_OP_CHOWN)
	{
	    gboolean yes_to_all = FALSE;
	    gint i;
	    const gchar *error_msg;
	    GList *paths_list = NULL, *modified_paths_list;
	    edv_object_struct *obj;

	    /* Create the paths list */
	    for(i = 0; i < nobjs; i++)
	    {
		obj = objs_list[i];
		if(obj == NULL)
		    continue;

		paths_list = g_list_append(
		    paths_list,
		    STRDUP(obj->full_path)
		);
	    }

	    /* Change the ownership */
	    status = EDVObjectOPChOwn(
		core,
		paths_list,
		owner_id, group_id,
		&modified_paths_list,
		toplevel,
		show_progress,
		TRUE,			/* Interactive */
		&yes_to_all,
		recursive,
		!dereference_links	/* Archive */
	    );

	    /* Check for error */
	    error_msg = EDVObjectOPGetError();
	    if(!STRISEMPTY(error_msg))
	    {
		EDVPlaySoundError(core);
		EDVMessageError(
		    "Change Ownership Error",
		    error_msg,
		    NULL,
		    toplevel
		);
	    }

	    /* Report the modified objects */
	    if(modified_paths_list != NULL)
	    {
		struct stat lstat_buf;
		const gchar *modified_path;
		GList *glist;

		for(glist = modified_paths_list;
		    glist != NULL;
		    glist = g_list_next(glist)
		)
		{
		    modified_path = (const gchar *)glist->data;
		    if(modified_path == NULL)
			continue;

		    if(!lstat(modified_path, &lstat_buf))
			EDVObjectModifiedEmit(
			    core,
			    modified_path,
			    modified_path,
			    &lstat_buf
			);
		}

		/* Delete the modified paths list */
		g_list_foreach(modified_paths_list, (GFunc)g_free, NULL);
		g_list_free(modified_paths_list);
	    }

	    /* Delete the paths list */
	    if(paths_list != NULL)
	    {
		g_list_foreach(paths_list, (GFunc)g_free, NULL);
		g_list_free(paths_list);
	    }
	}
	/* Change time stamps? */
	else if(op == EDV_OBJ_OP_DLG_OP_CHTIME)
	{
	    gboolean yes_to_all = FALSE;
	    gint i;
	    const gchar *error_msg;
	    GList *paths_list = NULL, *modified_paths_list;
	    edv_object_struct *obj;

	    /* Create the paths list */
	    for(i = 0; i < nobjs; i++)
	    {
		obj = objs_list[i];
		if(obj == NULL)
		    continue;

		paths_list = g_list_append(
		    paths_list,
		    STRDUP(obj->full_path)
		);
	    }

	    /* Change the time stamps */
	    status = EDVObjectOPChTime(
		core,
		paths_list,
		atime, mtime,
		&modified_paths_list,
		toplevel,
		show_progress,
		TRUE,			/* Interactive */
		&yes_to_all,
		recursive,
		!dereference_links	/* Archive */
	    );

	    /* Check for error */
	    error_msg = EDVObjectOPGetError();
	    if(!STRISEMPTY(error_msg))
	    {
		EDVPlaySoundError(core);
		EDVMessageError(
		    "Change Time Stamps Error",
		    error_msg,
		    NULL,
		    toplevel
		);
	    }

	    /* Report the modified objects */
	    if(modified_paths_list != NULL)
	    {
		struct stat lstat_buf;
		const gchar *modified_path;
		GList *glist;

		for(glist = modified_paths_list;
		    glist != NULL;
		    glist = g_list_next(glist)
		)
		{
		    modified_path = (const gchar *)glist->data;
		    if(modified_path == NULL)
			continue;

		    if(!lstat(modified_path, &lstat_buf))
			EDVObjectModifiedEmit(
			    core,
			    modified_path,
			    modified_path,
			    &lstat_buf
			);
		}

		/* Delete the modified paths list */
		g_list_foreach(modified_paths_list, (GFunc)g_free, NULL);
		g_list_free(modified_paths_list);
	    }

	    /* Delete the paths list */
	    if(paths_list != NULL)
	    {
		g_list_foreach(paths_list, (GFunc)g_free, NULL);
		g_list_free(paths_list);
	    }
	}
	else
	{
	    g_printerr(
"EDVObjOpDlgProcess(): Operation %i: Unsupported operation.\n",
		op
	    );
	    status = -2;
	}

	/* Unmap the progress dialog */
	ProgressDialogBreakQuery(TRUE);
	ProgressDialogSetTransientFor(NULL);

	/* Play the completed sound on success */
	if(status == 0)
	    EDVPlaySoundCompleted(core);


	/* Delete the copy of the target path */
	g_free(tar_path);

	/* Delete the source objects list and the source directory
	 * on the object operations dialog
	 */
	EDVObjOpDlgReset(d);
}


/*
 *	Creates the permission widgets.
 */
static void EDVObjOpDlgCreatePermissionWidgets(
	GtkWidget *parent,		/* GtkVBox */
	GtkStyle *style,
	GtkWidget **ur_w,
	GtkWidget **uw_w,
	GtkWidget **ux_w,
	GtkWidget **gr_w,
	GtkWidget **gw_w,
	GtkWidget **gx_w,
	GtkWidget **or_w,
	GtkWidget **ow_w,
	GtkWidget **ox_w,
	GtkWidget **suid_w,
	GtkWidget **sgid_w,
	GtkWidget **sticky_w
)
{
	const gint	border_major = 5,
			border_minor = 2;
	GtkWidget *w, *parent2, *parent3;

	/* Labels hbox */
	w = gtk_hbox_new(TRUE, border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;
	w = gtk_label_new("Owner");
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	gtk_widget_show(w);
	w = gtk_label_new("Group");
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	gtk_widget_show(w);
	w = gtk_label_new("Other");
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	gtk_widget_show(w);

	/* Check buttons hbox */
	w = gtk_hbox_new(TRUE, border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

#define NEW_PERMISSION_TOGGLE_BUTTON(_label_,_tip_,_active_,_parent_)	{ \
 if(FOPDLG_USE_PERMISSION_CHECK_BUTTON) {			\
  /* Create permission button as a GtkCheckButton */		\
  w = gtk_check_button_new_with_label(_label_);			\
 } else {							\
  /* Create permission button as a GtkToggleButton */		\
  GdkFont *font = style->font;					\
  const gint font_height = (font != NULL) ?			\
   (font->ascent + font->descent) : 0;				\
  w = gtk_toggle_button_new_with_label(_label_);		\
  if(font_height > 0)						\
   gtk_widget_set_usize(					\
    w, MIN(font_height + 5, 20), MIN(font_height + 5, 20)	\
   );								\
 }								\
 GTK_TOGGLE_BUTTON(w)->active = (_active_) ? TRUE : FALSE;	\
 gtk_box_pack_start(GTK_BOX(_parent_), w, FALSE, FALSE, 0);	\
 GUISetWidgetTip(w, (_tip_));					\
 gtk_widget_show(w);						\
}

	/* Owner check button set hbox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Read check button */
	NEW_PERMISSION_TOGGLE_BUTTON(
	    "R", "Read",
	    FALSE,
	    parent3
	)
	*ur_w = w;
	/* Write check button */
	NEW_PERMISSION_TOGGLE_BUTTON(
	    "W", "Write",
	    FALSE,
	    parent3
	)
	*uw_w = w;
	/* Execute check button */
	NEW_PERMISSION_TOGGLE_BUTTON(
	    "X", "Execute",
	    FALSE,
	    parent3
	)
	*ux_w = w;

	/* Group check button set hbox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Read check button */
	NEW_PERMISSION_TOGGLE_BUTTON(
	    "R", "Read",
	    FALSE,
	    parent3 
	)
	*gr_w = w;
	/* Write check button */
	NEW_PERMISSION_TOGGLE_BUTTON(
	    "W", "Write",
	    FALSE,
	    parent3
	)
	*gw_w = w;
	/* Execute check button */
	NEW_PERMISSION_TOGGLE_BUTTON(
	    "X", "Execute",
	    FALSE,  
	    parent3
	)
	*gx_w = w;

	/* Other check button set hbox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Read check button */
	NEW_PERMISSION_TOGGLE_BUTTON(
	    "R", "Read",
	    FALSE,
	    parent3
	)
	*or_w = w;
	/* Write check button */
	NEW_PERMISSION_TOGGLE_BUTTON(
	    "W", "Write",
	    FALSE,
	    parent3
	)
	*ow_w = w;
	/* Execute check button */
	NEW_PERMISSION_TOGGLE_BUTTON(
	    "X", "Execute",
	    FALSE,  
	    parent3
	)
	*ox_w = w;

#undef NEW_PERMISSION_TOGGLE_BUTTON

	/* Hbox for setuid, setgid, and sticky permission check buttons */
	w = gtk_hbox_new(TRUE, border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Setuid check button */
	*suid_w = w = gtk_check_button_new_with_label("SetUID");
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	GUISetWidgetTip(w, "Set owner's permission on use");
	gtk_widget_show(w);

	/* Setgid check button */
	*sgid_w = w = gtk_check_button_new_with_label("SetGID");
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	GUISetWidgetTip(w, "Set group's permissions on use");
	gtk_widget_show(w);

	/* Sticky check button */
	*sticky_w = w = gtk_check_button_new_with_label("Sticky");
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, FALSE, 0);
	GUISetWidgetTip(w, "Set user's permissions on use");
	gtk_widget_show(w);

}

/*
 *	Creates the time stamp widgets.
 */
static void EDVObjOpDlgCreateTimeStampWidgets(
	GtkWidget *parent,			/* GtkVBox */
	const gchar *pfx_label,
	GtkWidget **year_w,
	pulistbox_struct **month_pulistbox,
	GtkWidget **day_w,
	GtkWidget **hours_w,
	GtkWidget **minutes_w,
	GtkWidget **seconds_w,
	GtkWidget **current_w	
)
{
	const gint	border_major = 5,
			border_minor = 2;
	gchar *s;
	GtkAdjustment *adj;
	GtkWidget *w, *parent2, *parent3, *parent4;
	pulist_struct *pulist;
	pulistbox_struct *pulistbox;

	/* Year/Month/Day GtkHBox */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Year GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Prefix Label GtkAlignment */
	w = gtk_alignment_new(1.0f, 0.5f, 0.0f, 0.0f);
	gtk_widget_set_usize(w, 80, -1);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);                                      
	parent4 = w;
	/* Prefix GtkLabel */ 
	s = g_strdup_printf("%s Date:", pfx_label);
	w = gtk_label_new(s);
	g_free(s);
	gtk_container_add(GTK_CONTAINER(parent4), w);
	gtk_widget_show(w);
	/* Year GtkSpinButton */
	adj = (GtkAdjustment *)gtk_adjustment_new(
	    0.0f, 0.0f, 1000000.0f,
	    1.0f, 5.0f, 5.0f
	);
	*year_w = w = gtk_spin_button_new(adj, 1.0, 0);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, 60, -1);
	GUISetWidgetTip(w, "Year");
	gtk_widget_show(w);

	/* Month GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Month GtkLabel */
	w = gtk_label_new("/");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	/* Month Popup List Box */
	*month_pulistbox = pulistbox = PUListBoxNew(parent3, 70, -1);
	GUISetWidgetTip(pulistbox->da, "Month");
	PUListBoxMap(pulistbox);
	pulist = PUListBoxGetPUList(pulistbox);
	if(pulist != NULL)
	{
	    gint i = PUListAddItem(pulist, "Jan");
	    i = PUListAddItem(pulist, "Feb");
	    i = PUListAddItem(pulist, "Mar");
	    i = PUListAddItem(pulist, "Apr");
	    i = PUListAddItem(pulist, "May");
	    i = PUListAddItem(pulist, "Jun");
	    i = PUListAddItem(pulist, "Jul");
	    i = PUListAddItem(pulist, "Aug");
	    i = PUListAddItem(pulist, "Sep");
	    i = PUListAddItem(pulist, "Oct");
	    i = PUListAddItem(pulist, "Nov");
	    i = PUListAddItem(pulist, "Dec");
	    PUListBoxSetLinesVisible(pulistbox, i + 1);
	}

	/* Day GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Day GtkLabel */
	w = gtk_label_new("/");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	/* Year GtkSpinButton */
	adj = (GtkAdjustment *)gtk_adjustment_new(
	    1.0f, 1.0f, 32.0f,
	    1.0f, 5.0f, 5.0f
	);
	*day_w = w = gtk_spin_button_new(adj, 1.0, 0);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, 45, -1);
	GUISetWidgetTip(w, "Day");
	gtk_widget_show(w);


	/* Hours/Minutes/Seconds GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Hours GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Hours GtkLabel */
	w = gtk_label_new("Time:");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	/* Hours GtkSpinButton */
	adj = (GtkAdjustment *)gtk_adjustment_new(
	    0.0f, 0.0f, 23.0f,
	    1.0f, 5.0f, 5.0f
	);
	*hours_w = w = gtk_spin_button_new(adj, 1.0, 0);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, 45, -1);
	GUISetWidgetTip(w, "Hours");
	gtk_widget_show(w);

	/* Minutes GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Minutes GtkLabel */
	w = gtk_label_new(":");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	/* Minutes GtkSpinButton */
	adj = (GtkAdjustment *)gtk_adjustment_new(
	    0.0f, 0.0f, 59.0f,
	    1.0f, 5.0f, 5.0f
	);
	*minutes_w = w = gtk_spin_button_new(adj, 1.0, 0);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, 45, -1);
	GUISetWidgetTip(w, "Minutes");
	gtk_widget_show(w);

	/* Seconds GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Seconds GtkLabel */
	w = gtk_label_new(":");
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	/* Seconds GtkSpinButton */
	adj = (GtkAdjustment *)gtk_adjustment_new(
	    0.0f, 0.0f, 59.0f,
	    1.0f, 5.0f, 5.0f
	);
	*seconds_w = w = gtk_spin_button_new(adj, 1.0, 0);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_set_usize(w, 45, -1);
	GUISetWidgetTip(w, "Seconds");
	gtk_widget_show(w);

	/* Current Time Button */
	*current_w = w = GUIButtonPixmap(
	    (guint8 **)icon_time_stamp_20x20_xpm
	);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	GUISetWidgetTip(w, "Use current time");
	gtk_widget_show(w);

}

/*
 *	Creates a new edv_obj_op_dlg_struct.
 */
edv_obj_op_dlg_struct *EDVObjOpDlgNew(edv_core_struct *core)
{
	const gint	border_major = 5,
			border_minor = 2;
	GdkWindow *window;
	GtkAccelGroup *accelgrp;
	GtkStyle *style;
	GtkWidget	*w, *parent, *parent2, *parent3, *parent4,
			*parent5, *parent6, *parent7;
	edv_obj_op_dlg_struct *d = EDV_OBJ_OP_DLG(
	    g_malloc0(sizeof(edv_obj_op_dlg_struct))
	);
	if((d == NULL) || (core == NULL))
	{
	    g_free(d);
	    return(NULL);
	}

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

	d->ref_toplevel = NULL;
	d->op = EDV_OBJ_OP_DLG_OP_MOVE;
	d->src_obj = NULL;
	d->src_obj_total = 0;
	d->src_dir = NULL;


	/* Begin creating widgets */

	/* Toplevel */
	d->toplevel = w = gtk_window_new(GTK_WINDOW_DIALOG);
	gtk_widget_realize(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
	    );
	}
	gtk_widget_add_events(
	    w,
	    GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
	    GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_event",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgDeleteEventCB), d
	);
	gtk_window_add_accel_group(GTK_WINDOW(w), accelgrp);
	style = gtk_widget_get_style(w);
	parent = w;


	/* Main GtkVBox */
	d->main_vbox = w = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(parent), w);
	gtk_widget_show(w);
	parent = w;


	/* Icon & Label GtkHBox */
	w = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, border_major);
	gtk_widget_show(w);
	parent2 = w;


	/* Icon GtkVBox */
	w = gtk_vbox_new(TRUE, 0);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, border_major);
	gtk_widget_show(w);
	parent3 = w;

	/* Icon GtkFixed */
	d->icon_fixed = w = gtk_fixed_new();
	gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, FALSE, 0);
	gtk_widget_realize(w);
	gtk_widget_show(w);

	/* Icon GtkPixmap will be created later */
	d->icon_pm = NULL;


	/* Label & Operation-Specific Widgets GtkVBox */
	w = gtk_vbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, border_major);
	gtk_widget_show(w);
	parent3 = w;


	/* Label GtkHBox */
	w = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* GtkLabel */
	d->label = w = gtk_label_new("");
	gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);


	/* Operation-Specific GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Label GtkAlignment */
	w = gtk_alignment_new(1.0f, 0.0f, 0.0f, 0.0f);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent5 = w;
	/* Label */
	w = gtk_label_new("To:");
	gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_LEFT);
	gtk_container_add(GTK_CONTAINER(parent5), w);
	gtk_widget_show(w);


	/* Target GtkEntry */
	d->target_entry = w = gtk_entry_new();
	gtk_widget_set_usize(w, 350, -1);
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "activate",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgProcessCB), d
	);
	EDVEntrySetDND(core, w);
	EDVEntrySetCompletePath(core, w);

	/* Target Browse GtkButton */
	d->target_browse_btn = w = GUIButtonPixmap(
	    (guint8 **)icon_browse_20x20_xpm
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgBrowseCB), d->target_entry
	);


	/* Create widgets for the Change Permissions operation */

	/* Parent GtkVBox */
	d->target_chmod_parent = w = gtk_vbox_new(FALSE, border_minor);
	gtk_widget_set_usize(w, 300, -1);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	parent5 = w;

	/* Create the Change Permission widgets */
	EDVObjOpDlgCreatePermissionWidgets(
	    parent5, style,
	    &d->target_ur_check,
	    &d->target_uw_check,
	    &d->target_ux_check,
	    &d->target_gr_check,
	    &d->target_gw_check,
	    &d->target_gx_check,
	    &d->target_or_check,
	    &d->target_ow_check,
	    &d->target_ox_check,
	    &d->target_suid_check,
	    &d->target_sgid_check,
	    &d->target_sticky_check
	);


	/* Create widgets for the Change Ownership operation */

	/* Parent GtkVBox */
	d->target_chown_parent = w = gtk_vbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	parent5 = w;

	/* Owner GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent6 = w;
	/* Owner GtkLabel */
	w = gtk_alignment_new(1.0f, 0.5f, 0.0f, 0.0f);
	gtk_widget_set_usize(w, 60, -1);
	gtk_box_pack_start(GTK_BOX(parent6), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent7 = w;
	w = gtk_label_new("Owner:");
	gtk_container_add(GTK_CONTAINER(parent7), w);
	gtk_widget_show(w);
	/* Owner entry and map button hbox */
	w = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent6), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent7 = w;
	/* Owner GtkEntry */
 	d->target_owner_entry = w = gtk_entry_new();
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
	gtk_widget_set_usize(w, 250, -1);
	gtk_box_pack_start(GTK_BOX(parent7), w, TRUE, TRUE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "activate",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgProcessCB), d
	);
	gtk_widget_show(w);
	/* Owner Popup List Map Button */
	d->target_owner_btn = w = PUListNewMapButtonArrow(
	    GTK_ARROW_DOWN, GTK_SHADOW_OUT,
	    EDVObjOpDlgOwnerMapPUListCB, d
	);
	gtk_box_pack_start(GTK_BOX(parent7), w, FALSE, FALSE, 0);
	gtk_widget_show(w);

	/* Group GtkHBox */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent6 = w;
	/* Group GtkLabel */
	w = gtk_alignment_new(1.0f, 0.5f, 0.0f, 0.0f);
	gtk_widget_set_usize(w, 60, -1);
	gtk_box_pack_start(GTK_BOX(parent6), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent7 = w;
	w = gtk_label_new("Group:");
	gtk_container_add(GTK_CONTAINER(parent7), w);
	gtk_widget_show(w);
	/* Group entry and popup list GtkHBox */
	w = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent6), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent7 = w;
	/* Group GtkEntry */
	d->target_group_entry = w = gtk_entry_new();
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
	gtk_widget_set_usize(w, 250, -1);
	gtk_box_pack_start(GTK_BOX(parent7), w, TRUE, TRUE, 0);
	gtk_signal_connect(                                    
	    GTK_OBJECT(w), "activate",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgProcessCB), d
	);
	gtk_widget_show(w);
	/* Group Popup List Map Button */
	d->target_group_btn = w = PUListNewMapButtonArrow(
	    GTK_ARROW_DOWN, GTK_SHADOW_OUT,
	    EDVObjOpDlgGroupMapPUListCB, d
	);
	gtk_box_pack_start(GTK_BOX(parent7), w, FALSE, FALSE, 0);
	gtk_widget_show(w);


	/* Create widgets for the Change Time Stamps operation */

	/* Parent GtkVBox */
	d->target_time_parent = w = gtk_vbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);    
	parent5 = w;

	/* Access Time GtkHBox */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent6 = w;

	/* Access Time date and time widgets */
	EDVObjOpDlgCreateTimeStampWidgets(
	    parent6,
	    "Access",
	    &d->target_atime_year_spin,
	    &d->target_atime_month_pulistbox,
	    &d->target_atime_day_spin,
	    &d->target_atime_hours_spin,
	    &d->target_atime_minutes_spin,
	    &d->target_atime_seconds_spin,
	    &d->target_atime_current_btn
	);
	gtk_signal_connect(
	    GTK_OBJECT(d->target_atime_current_btn), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgATimeCurrentTimeCB), d
	);

	/* Modify Time GtkHBox */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent6 = w;

	/* Modify Time date and time widgets */
	EDVObjOpDlgCreateTimeStampWidgets(
	    parent6,
	    "Modify",
	    &d->target_mtime_year_spin,
	    &d->target_mtime_month_pulistbox,
	    &d->target_mtime_day_spin,
	    &d->target_mtime_hours_spin,
	    &d->target_mtime_minutes_spin,
	    &d->target_mtime_seconds_spin,
	    &d->target_mtime_current_btn
	);
	gtk_signal_connect(
	    GTK_OBJECT(d->target_mtime_current_btn), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgMTimeCurrentTimeCB), d
	);


	/* Create the Options widgets */

	/* Parent GtkVBox */
	d->opt_parent = w = gtk_vbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	parent4 = w;

	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);    
	gtk_widget_show(w);
	parent5 = w;

	/* Recursive */
	d->opt_recursive_check = w = gtk_check_button_new_with_label(
	    "Recursive"
	);
	gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
	GTK_TOGGLE_BUTTON_SET_ACTIVE(w, FALSE);
	GUISetWidgetTip(
	    w,
	    "Check this to recurse into subdirectories"
	);

	/* Dereference Links */
	d->opt_dereference_links_check = w = gtk_check_button_new_with_label(
	    "Dereference Links"
	);
	gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
	GTK_TOGGLE_BUTTON_SET_ACTIVE(w, FALSE);
	GUISetWidgetTip(
	    w,
"Check this to operate on the links' destination instead\
 of the links themselves"
	);


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


	/* Buttons GtkHBox */
	w = gtk_hbox_new(TRUE, 0);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, border_major);
	gtk_widget_show(w);
	parent2 = w;

	/* Move GtkButton */
	d->move_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_move_file_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Mueva"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le Mouvement"
#elif defined(PROG_LANGUAGE_GERMAN)
"Bewegung"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Movimento"
#elif defined(PROG_LANGUAGE_DUTCH)
"Beweging"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mova"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Trekk"
#else
"Move"
#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_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgProcessCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_m, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_m);

	/* Copy GtkButton */
	d->copy_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_copy_file_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"La Copia"
#elif defined(PROG_LANGUAGE_FRENCH)
"Copie"
#elif defined(PROG_LANGUAGE_GERMAN)
"Kopie"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Copia"
#elif defined(PROG_LANGUAGE_DUTCH)
"Kopie"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"A Cópia"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kopi"
#else
"Copy"
#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_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgProcessCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_o);

	/* Link GtkButton */
	d->link_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_link2_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Enlace"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le Lien"
#elif defined(PROG_LANGUAGE_GERMAN)
"Kettenglied"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Maglia"
#elif defined(PROG_LANGUAGE_DUTCH)
"Schakel"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Elo"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Ledd"
#else
"Link"
#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_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgProcessCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_l, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"         
	);
	GUIButtonLabelUnderline(w, GDK_l);

	/* Change Permissions GtkButton */
	d->chmod_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_chmod_20x20_xpm, "ChMod", 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_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgProcessCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_h, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_h);

	/* Change Ownership GtkButton */
	d->chown_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_owned_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Propio"
#elif defined(PROG_LANGUAGE_FRENCH)
"Propre"
#elif defined(PROG_LANGUAGE_GERMAN)
"Eigen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Proprio"
#elif defined(PROG_LANGUAGE_DUTCH)
"Eigen"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Próprio"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Egen"
#else
"ChOwn"
#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_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgProcessCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_h, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_h);

	/* Change Time Stamps GtkButton */
	d->chtime_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_time_stamp_20x20_xpm,
	    "ChTime",
	    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_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgProcessCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_s);

	/* Cancel GtkButton */
	d->cancel_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_cancel_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Cancela"
#elif defined(PROG_LANGUAGE_FRENCH)
"Annuler"
#elif defined(PROG_LANGUAGE_GERMAN)
"Heben"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Annulla"
#elif defined(PROG_LANGUAGE_DUTCH)
"Annuleer"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Cancelamento"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kanseller"
#else
"Cancel"
#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_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVObjOpDlgCancelCB), d
	);
	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);


	return(d);
}


/*
 *	Deletes source disk object structure list and current
 *	source directory on the given dialog.
 */
void EDVObjOpDlgReset(edv_obj_op_dlg_struct *d)
{
	gint i;

	if(d == NULL)
	    return;

	/* Delete the objects list */
	for(i = 0; i < d->src_obj_total; i++)
	    EDVObjectDelete(d->src_obj[i]);
	g_free(d->src_obj);
	d->src_obj = NULL;
	d->src_obj_total = 0;

	/* Delete the source directory */
	g_free(d->src_dir);
	d->src_dir = NULL;
}

/*
 *	Sets the Object Operations Dialog as busy or ready.
 */
void EDVObjOpDlgSetBusy(edv_obj_op_dlg_struct *d, const gboolean is_busy)
{
	GdkCursor *cursor;
	GtkWidget *w;
	edv_core_struct *core;

	if(d == NULL)
	    return;

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

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

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

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

		/* If still busy do not change anything */
		if(d->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 Object Operations Dialog is mapped.
 */
gboolean EDVObjOpDlgIsMapped(edv_obj_op_dlg_struct *d)
{
	GtkWidget *w = (d != NULL) ? d->toplevel : NULL;
	return((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE);
}

/*
 *	Maps the Object Operations Dialog.
 *
 *	The d specifies the Object Operations Dialog.
 *
 *	The op specifies the operation.
 *
 *	The src_obj and src_obj_total specifies the list of objects
 *	to be operated on. This list of objects will be coppied and
 *	stored locally on the Object Operations Dialog.
 *
 *	The src_dir specifies the initial target location.
 *
 *	The toplevel specifies the relative toplevel GtkWindow.
 */
void EDVObjOpDlgMapValues(
	edv_obj_op_dlg_struct *d,
	const edv_obj_op_dlg_op op,
	edv_object_struct **src_obj,
	const gint src_obj_total,
	const gchar *src_dir,
	GtkWidget *toplevel
)
{
	gint i;
	gboolean	need_warn_chmod_link = FALSE,
			need_warn_chtime_link = FALSE,
			map_browse_btn = FALSE;
	const gchar *title = NULL;
	gchar *buf = NULL;
	const gchar *src_obj_full_path, *src_obj_name;
	guint8 **icon_data = NULL;
	const gchar *icon_name = NULL;
	edv_object_struct *obj;
	edv_core_struct *core;
	GtkWidget *w, *parent, *button = NULL, *op_parent = NULL;

	if(d == NULL)
	    return;

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

	/* Delete the source objects list and the source directory
	 * on the object operations dialog
	 */
	EDVObjOpDlgReset(d);

	/* If there is exactly one object in the source object list
	 * then get its full path and name
	 *
	 * Otherwise set the single object full path and name to NULL
	 */
	if(src_obj_total == 1)
	{
	    obj = src_obj[0];
	    src_obj_name = (obj != NULL) ? obj->name : NULL;
	    src_obj_full_path = (obj != NULL) ? obj->full_path : NULL;
	}
	else
	{
	    obj = NULL;
	    src_obj_name = NULL;
	    src_obj_full_path = NULL;
	}


	/* Set operation code */
	d->op = op;

	/* Update the widgets based on the operation */
	switch(op)
	{
	  case EDV_OBJ_OP_DLG_OP_MOVE:
	    title =
#if defined(PROG_LANGUAGE_SPANISH)
"Mueva"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le Mouvement"
#elif defined(PROG_LANGUAGE_GERMAN)
"Bewegung"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Movimento"
#elif defined(PROG_LANGUAGE_DUTCH)
"Beweging"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mova"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Trekk"
#else
"Move"
#endif
	    ;
	    icon_data = (guint8 **)icon_move_file_32x32_xpm;
	    icon_name = "icon_move_file_32x32_xpm";
	    if(src_obj_name != NULL)
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Mueva:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le Mouvement:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Bewegung:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Movimento:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Beweging:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mova:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Trekk:\n\
\n\
    %s\n"
#else
"Move:\n\
\n\
    %s\n"
#endif
		    , src_obj_name
		);
	    else
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Mueva %i objetos\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Déplacer %i objets\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Bewegen sie %i objekte\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Muovere %i oggetti\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Beweeg %i voorwerpen\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mova %i objetos\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Flytt %i objekt\n"
#else
"Move %i objects\n"
#endif
		    , src_obj_total
		);
	    button = d->move_btn;
	    op_parent = d->target_entry;
	    map_browse_btn = TRUE;
	    gtk_widget_hide(d->opt_parent);
	    gtk_widget_hide(d->opt_recursive_check);
	    gtk_widget_hide(d->opt_dereference_links_check);
	    break;

	  case EDV_OBJ_OP_DLG_OP_COPY:
	    title =
#if defined(PROG_LANGUAGE_SPANISH)
"La Copia"
#elif defined(PROG_LANGUAGE_FRENCH)
"Copie"
#elif defined(PROG_LANGUAGE_GERMAN)
"Kopie"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Copia"
#elif defined(PROG_LANGUAGE_DUTCH)
"Kopie"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"A Cópia"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kopi"
#else
"Copy"
#endif
	    ;
	    icon_data = (guint8 **)icon_copy_file_32x32_xpm;
	    icon_name = "icon_copy_file_32x32_xpm";
	    if(src_obj_name != NULL)
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"La Copia:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Copie:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Kopie:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Copia:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Kopie:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"A Cópia:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kopi:\n\
\n\
    %s\n"
#else
"Copy:\n\
\n\
    %s\n"
#endif
		    , src_obj_name
		);
	    else
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Copie %i objetos\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"La copie %i objets\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Kopieren sie %i objekte\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Copiare %i oggetti\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Kopieer %i voorwerpen\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Copie %i objetos\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kopier %i objekt\n"
#else
"Copy %i objects\n"
#endif
		    , src_obj_total
		);
	    button = d->copy_btn;
	    op_parent = d->target_entry;
	    map_browse_btn = TRUE;
	    gtk_widget_hide(d->opt_parent);
	    gtk_widget_hide(d->opt_recursive_check);
	    gtk_widget_hide(d->opt_dereference_links_check);
	    break;

	  case EDV_OBJ_OP_DLG_OP_LINK:
	    title =
#if defined(PROG_LANGUAGE_SPANISH)
"Enlace"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le Lien"
#elif defined(PROG_LANGUAGE_GERMAN)
"Kettenglied"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Maglia"
#elif defined(PROG_LANGUAGE_DUTCH)
"Schakel"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Elo"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Ledd"
#else
"Link"
#endif
	    ;
	    icon_data = (guint8 **)icon_link2_32x32_xpm;
	    icon_name = "icon_link2_32x32_xpm";
	    if(src_obj_name != NULL)
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"El enlace:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le Lien:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Kettenglied:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Maglia:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Schakel:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Elo:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Ledd:\n\
\n\
    %s\n"
#else
"Link:\n\
\n\
    %s\n"
#endif
		    , src_obj_name
		);
	    else
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Trabe %i objetos\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le lien %i objets\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Verknüpfen sie %i objekte\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Concatenare %i oggetti\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verbind %i voorwerpen\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Ligue %i objetos\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forbind %i objekt\n"
#else
"Link %i objects\n"
#endif
		    , src_obj_total
		);
	    button = d->link_btn;
	    op_parent = d->target_entry;
	    map_browse_btn = TRUE;
	    gtk_widget_hide(d->opt_parent);
	    gtk_widget_hide(d->opt_recursive_check);
	    gtk_widget_hide(d->opt_dereference_links_check);
	    break;

	  case EDV_OBJ_OP_DLG_OP_CHMOD:
	    title =
#if defined(PROG_LANGUAGE_SPANISH)
"Cambie Los Permisos"
#elif defined(PROG_LANGUAGE_FRENCH)
"Changer Des Permissions"
#elif defined(PROG_LANGUAGE_GERMAN)
"Ändern Sie Erlaubnis"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Cambiare I Permessi"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verandeer Toestemmingen"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mude Permissões"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forandr Permissions"
#else
"Change Permissions"
#endif
	    ;
	    icon_data = (guint8 **)icon_chmod_32x32_xpm;
	    icon_name = "icon_chmod_32x32_xpm";
	    if(src_obj_name != NULL)
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Cambie los permisos de:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Changer des permissions de:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Ändern sie erlaubnis von:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Cambiare i permessi di:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verandeer toestemmingen van:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mude permissões de:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forandr tillatelse av:\n\
\n\
    %s\n"
#else
"Change permissions of:\n\
\n\
    %s\n"
#endif
		    , src_obj_name
		);
	    else
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Cambie los permisos de %i objetos\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Changer des permissions de %i objets\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Ändern sie erlaubnis von %i objekten\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Cambiare i permessi di %i oggetti\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verandeer toestemmingen van %i voorwerpen\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mude permissões de %i objetos\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forandr tillatelse av %i objekt\n"
#else
"Change permissions of %i objects\n"
#endif
		    , src_obj_total
		);
	    button = d->chmod_btn;
	    op_parent = d->target_chmod_parent;
	    gtk_widget_show(d->opt_parent);
	    gtk_widget_show(d->opt_recursive_check);
	    gtk_widget_show(d->opt_dereference_links_check);
	    break;

	  case EDV_OBJ_OP_DLG_OP_CHOWN:
	    title =
#if defined(PROG_LANGUAGE_SPANISH)
"Propio"
#elif defined(PROG_LANGUAGE_FRENCH)
"Propre"
#elif defined(PROG_LANGUAGE_GERMAN)
"Eigen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Proprio"
#elif defined(PROG_LANGUAGE_DUTCH)
"Eigen"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Próprio"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Egen"
#else
"Change Ownership"
#endif
	    ;
	    icon_data = (guint8 **)icon_owned_32x32_xpm;
	    icon_name = "icon_owned_32x32_xpm";
	    if(src_obj_name != NULL)
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Cambie la propiedad de:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Changer la possession de:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Ändern sie eigentumsrecht von:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Cambiare la proprietà di:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verandeer eigendomsrecht van:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mude posse de:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forandr eiendomsrett av:\n\
\n\
    %s\n"
#else
"Change ownership of:\n\
\n\
    %s\n"
#endif
		    , src_obj_name
		);
	    else
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Cambie la propiedad de %i objetos\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Changer la possession de %i objetos\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Ändern sie eigentumsrecht von %i objetos\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Cambiare la proprietà di %i objetos\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verandeer eigendomsrecht van %i objetos\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mude posse de %i objetos\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forandr eiendomsrett av %i objetos\n"
#else
"Change ownership of %i objects\n"
#endif
		    , src_obj_total
		);
	    button = d->chown_btn;
	    op_parent = d->target_chown_parent;
	    gtk_widget_show(d->opt_parent);
	    gtk_widget_show(d->opt_recursive_check);
	    gtk_widget_show(d->opt_dereference_links_check);
	    break;

	  case EDV_OBJ_OP_DLG_OP_CHTIME:
	    title = "Change Time Stamps";
	    icon_data = (guint8 **)icon_time_stamp_32x32_xpm;
	    icon_name = "icon_time_stamp_32x32_xpm";
	    if(src_obj_name != NULL)
		buf = g_strdup_printf(
"Change time stamps of:\n\
\n\
    %s\n\
\n",
		    src_obj_name
		);
	    else
		buf = g_strdup_printf(
"Change time stamps of %i objects\n"
		    , src_obj_total
		);
	    button = d->chtime_btn;
	    op_parent = d->target_time_parent;
	    gtk_widget_show(d->opt_parent);
	    gtk_widget_show(d->opt_recursive_check);
	    gtk_widget_show(d->opt_dereference_links_check);
	    break;
	}

	/* Update the icon */
	parent = d->icon_fixed;
	if((icon_data != NULL) && (parent != NULL))
	{
	    GdkBitmap *mask;
	    GdkPixmap *pixmap;

	    /* Create new pixmap from icon_data */
	    EDVLoadPixmap(
		core,
		icon_data, icon_name,
		&pixmap, &mask
	    );
	    if(pixmap != NULL)
	    {
		gint width, height;

		/* Get size of new pixmap and mask pair */
		gdk_window_get_size(pixmap, &width, &height);

		/* Get icon GtkPixmap, create it as needed */
		w = d->icon_pm;
		if(w == NULL)
		{
		    d->icon_pm = w = gtk_pixmap_new(pixmap, mask);
		    gtk_fixed_put(GTK_FIXED(parent), w, 0, 0);
		    gtk_widget_show(w);
		}
		else
		{
		    gtk_pixmap_set(GTK_PIXMAP(w), pixmap, mask);
		}

		/* Adjust size of fixed widget to fit pixmap */
		gtk_widget_set_usize(parent, width, height);
		gtk_widget_queue_resize(parent);
		gtk_widget_shape_combine_mask(parent, mask, 0, 0);

		GDK_PIXMAP_UNREF(pixmap);
		GDK_BITMAP_UNREF(mask);
	    }

	    /* Update toplevel GdkWindow's WM icon */
	    w = d->toplevel;
	    if(w != NULL)
		GUISetWMIcon(w->window, (guint8 **)icon_data);
	}

	/* Update label */
	if(buf != NULL)
	{
	    w = d->label;
	    if(w != NULL)
		gtk_label_set_text(GTK_LABEL(w), buf);

	    g_free(buf);
	    buf = NULL;
	}


	/* Set the source directory */
	g_free(d->src_dir);
	d->src_dir = STRDUP(src_dir);

	/* Set the target GtkEntry's value if it is the operation
	 * widget?
	 */
	w = d->target_entry;
	if((w != NULL) && (w == op_parent))
	{
	    gtk_entry_set_text(
		GTK_ENTRY(w),
		(src_dir != NULL) ? src_dir : ""
	    );
	    if(GTK_WIDGET_CAN_FOCUS(w))
		gtk_widget_grab_focus(w);
	    if(GTK_WIDGET_CAN_DEFAULT(w))
		gtk_widget_grab_default(w);
	}


	/* Copy the specified objects list to the object operations
	 * dialog's objects list
	 */
	d->src_obj_total = src_obj_total;
	if(d->src_obj_total > 0)
	{
	    d->src_obj = (edv_object_struct **)g_malloc(
		d->src_obj_total * sizeof(edv_object_struct *)
	    );
	    if(d->src_obj != NULL)
	    {
		for(i = 0; i < d->src_obj_total; i++)
		    d->src_obj[i] = EDVObjectCopy(src_obj[i]);
	    }
	    else
	    {
		d->src_obj_total = 0;
	    }
	}
	else
	{
	    d->src_obj_total = 0;
	}


	/* Is the operation to change permissions? */
	w = d->target_chmod_parent;
	if((w != NULL) && (w == op_parent))
	{
	    /* Set the initial values for the change permission
	     * widgets
	     */
	    edv_permission_flags permissions = 0x00000000;
	    edv_object_struct *ref_obj;

	    /* Iterate through the objects list and collect the
	     * permission values that are common to all of them
	     */
	    for(i = 0; i < d->src_obj_total; i++)
	    {
		ref_obj = d->src_obj[i];
		if(ref_obj == NULL)
		    continue;

		/* Do a quick check to see if the object to change
		 * permissions of is a symbolic link
		 *
		 * If this is a symbolic link then a warning needs to
		 * be issued about changing a symbolic link's
		 * permissions that will actually change its
		 * destination permissions
		 */
		if(ref_obj->type == EDV_OBJECT_TYPE_LINK)
		    need_warn_chmod_link = TRUE;

		/* Gather the permissions from this object */
		permissions |= ref_obj->permissions;
	    }

	    /* Set the initial values for the change permission
	     * widgets based on the collected permission values
	     */

	    /* User RWX */
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_ur_check,
		(permissions & EDV_PERMISSION_UREAD) ? TRUE : FALSE
	    )
	    if(GTK_WIDGET_CAN_FOCUS(d->target_ur_check))
		gtk_widget_grab_focus(d->target_ur_check);
	    if(GTK_WIDGET_CAN_DEFAULT(d->target_ur_check))
		gtk_widget_grab_default(d->target_ur_check);
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_uw_check,
		(permissions & EDV_PERMISSION_UWRITE) ? TRUE : FALSE
	    )
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_ux_check,
		(permissions & EDV_PERMISSION_UEXECUTE) ? TRUE : FALSE
	    )

	    /* Group RWX */
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_gr_check,
		(permissions & EDV_PERMISSION_GREAD) ? TRUE : FALSE
	    )
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_gw_check,
		(permissions & EDV_PERMISSION_GWRITE) ? TRUE : FALSE
	    )
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_gx_check,
		(permissions & EDV_PERMISSION_GEXECUTE) ? TRUE : FALSE
	    )

	    /* Other RWX */
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_or_check,
		(permissions & EDV_PERMISSION_AREAD) ? TRUE : FALSE
	    )
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_ow_check,
		(permissions & EDV_PERMISSION_AWRITE) ? TRUE : FALSE
	    )
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_ox_check,
		(permissions & EDV_PERMISSION_AEXECUTE) ? TRUE : FALSE
	    )

	    /* Setuid, setgid, and sticky */
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_suid_check,
		(permissions & EDV_PERMISSION_SETUID) ? TRUE : FALSE
	    )
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_sgid_check,
		(permissions & EDV_PERMISSION_SETGID) ? TRUE : FALSE
	    )
	    GTK_TOGGLE_BUTTON_SET_ACTIVE(
		d->target_sticky_check,
		(permissions & EDV_PERMISSION_STICKY) ? TRUE : FALSE
	    )
	}

	/* Is the operation to change ownership? */
	w = d->target_chown_parent;
	if((w != NULL) && (w == op_parent))
	{
	    /* Set the initial values for the owner and group widgets */
	    edv_object_struct *ref_obj = obj;

	    /* Owner */
	    w = d->target_owner_entry;
	    if(w != NULL)
	    {
		gtk_entry_set_text(
		    GTK_ENTRY(w),
		    EDVUIDGetNameFromUID(
			core->uid, core->total_uids,
			(ref_obj != NULL) ?
			    ref_obj->owner_id : core->effective_user_id,
			NULL
		    )
		);
		if(GTK_WIDGET_CAN_FOCUS(w))
		    gtk_widget_grab_focus(w);
		if(GTK_WIDGET_CAN_DEFAULT(w))
		    gtk_widget_grab_default(w);
	    }

	    /* Group */
	    w = d->target_group_entry;
	    if(w != NULL)
	    {
		gtk_entry_set_text(
		    GTK_ENTRY(w),
		    EDVGIDGetNameFromGID(
			core->gid, core->total_gids,
			(ref_obj != NULL) ?
			    ref_obj->group_id : core->effective_group_id,
			NULL
		    )
		);
	    }
	}

	/* Is the operation to change time stamps? */
	w = d->target_time_parent;
	if((w != NULL) && (w == op_parent))
	{
	    /* Set the initial time stamp widget values to the time
	     * stamps of the specified object
	     */
	    gint i;
	    edv_object_struct *ref_obj = obj;

	    /* If there was more than one object specified then use the
	     * last specified object as the reference object
	     */
	    if(ref_obj == NULL)
	    {
		const gint last_obj_num = src_obj_total - 1;
		if(last_obj_num > -1)
		    ref_obj = src_obj[last_obj_num];
	    }

	    /* Got a reference object? */
	    if(ref_obj != NULL)
	    {
		/* Set the time stamp widget values to the time stamps
		 * of the reference object
		 */

		/* Access time */
		time_t t = (time_t)ref_obj->access_time;
		const struct tm *tm_ptr = localtime(&t);
		if(tm_ptr != NULL)
		{
		    w = d->target_atime_year_spin;
		    if(w != NULL)
		    {
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)(1900 + tm_ptr->tm_year)
			);
			if(GTK_WIDGET_CAN_FOCUS(w))
			    gtk_widget_grab_focus(w);
			if(GTK_WIDGET_CAN_DEFAULT(w))
			    gtk_widget_grab_default(w);
		    }
		    PUListBoxSelect(
			d->target_atime_month_pulistbox,
			tm_ptr->tm_mon
		    );
		    w = d->target_atime_day_spin;
		    if(w != NULL)
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)tm_ptr->tm_mday
			);
		    w = d->target_atime_hours_spin;
		    if(w != NULL)
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)tm_ptr->tm_hour
			);
		    w = d->target_atime_minutes_spin;
		    if(w != NULL)
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)tm_ptr->tm_min
			);
		    w = d->target_atime_seconds_spin;
		    if(w != NULL)
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)tm_ptr->tm_sec
			);
		}

		/* Modify time */
		t = (time_t)ref_obj->modify_time;
		tm_ptr = localtime(&t);
		if(tm_ptr != NULL)
		{
		    w = d->target_mtime_year_spin;
		    if(w != NULL)
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)(1900 + tm_ptr->tm_year)
			);
		    PUListBoxSelect(
			d->target_mtime_month_pulistbox,
			tm_ptr->tm_mon
		    );
		    w = d->target_mtime_day_spin;
		    if(w != NULL)
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)tm_ptr->tm_mday
			);
		    w = d->target_mtime_hours_spin;
		    if(w != NULL)
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)tm_ptr->tm_hour
			);
		    w = d->target_mtime_minutes_spin;
		    if(w != NULL)
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)tm_ptr->tm_min
			);
		    w = d->target_mtime_seconds_spin;
		    if(w != NULL)
			gtk_spin_button_set_value(
			    GTK_SPIN_BUTTON(w),
			    (gfloat)tm_ptr->tm_sec
			);
		}
	    }

	    /* Check if we need to warn about links */
	    for(i = 0; i < d->src_obj_total; i++)
	    {
		ref_obj = d->src_obj[i];
		if(ref_obj == NULL)
		    continue;

		if(ref_obj->type == EDV_OBJECT_TYPE_LINK)
		    need_warn_chtime_link = TRUE;
	    }
	}



	/* Unmap all the buttons */
	w = d->move_btn;
	if(w != NULL)
	    gtk_widget_hide(w);
	w = d->copy_btn;
	if(w != NULL)
	    gtk_widget_hide(w);
	w = d->link_btn;
	if(w != NULL)
	    gtk_widget_hide(w);
	w = d->chmod_btn;
	if(w != NULL)
	    gtk_widget_hide(w);
	w = d->chown_btn;
	if(w != NULL)
	    gtk_widget_hide(w);
	w = d->chtime_btn;
	if(w != NULL)
	    gtk_widget_hide(w);

	/* Check if button to be mapped is valid and map it */
	if(button != NULL)
	    gtk_widget_show(button);


	/* Unmap all the target widgets */
	w = d->target_entry;
	if(w != NULL)
	    gtk_widget_hide(w);
	w = d->target_chmod_parent;
	if(w != NULL)
	    gtk_widget_hide(w);
	w = d->target_chown_parent;
	if(w != NULL)
	    gtk_widget_hide(w);
	w = d->target_time_parent;
	if(w != NULL)
	    gtk_widget_hide(w);

	/* Check if the target widget to be mapped is valid and map it */
	if(op_parent != NULL)
	    gtk_widget_show(op_parent);

	/* Map or unmap the browse button */
	w = d->target_browse_btn;
	if(w != NULL)
	{
	    if(map_browse_btn)
		gtk_widget_show(w);
	    else
		gtk_widget_hide(w);
	}

	/* Need to print warning about changing permissions on link
	 * objects?
	 */
	if(need_warn_chmod_link)
	{
	    EDVPlaySoundWarning(core);
	    EDVMessageWarning(
"Changing Permissions Warning",
"Changing the permissions on a link will effectively\n\
change the permissions of its destination object.",
"One or more of the selected object(s) are of type\n\
link. Links do not have permissions, instead, their\n\
permissions are determined by the permissions of the\n\
destination object. So changing the permissions on a\n\
link will effectively change the permissions of its\n\
destination object.",
		toplevel
	    );
	}
	if(need_warn_chtime_link)
	{
	    EDVPlaySoundWarning(core);
	    EDVMessageWarning(
"Changing Time Stamps Warning",
"Changing the time stamps on a link will effectively\n\
change the time stamps of its destination object.",
"One or more of the selected object(s) are of type\n\
link. Links do not have time stamps, instead, their\n\
time stamps are determined by the time stamps of the\n\
destination object. So changing the time stamps on a\n\
link will effectively change the time stamps of its\n\
destination object.",
		toplevel
	    );
	}


	w = d->toplevel;
	if(w != NULL)
	{
	    /* Update title? */
	    if(title != NULL)
		gtk_window_set_title(GTK_WINDOW(w), title);

	    /* If given toplevel is not NULL then set transient for */
	    if((toplevel != NULL) ? GTK_IS_WINDOW(toplevel) : FALSE)
	    {
		gtk_window_set_transient_for(
		    GTK_WINDOW(w), GTK_WINDOW(toplevel)
		);
		d->ref_toplevel = toplevel;
	    }

	    /* Map the object operations dialog */
	    gtk_widget_show_raise(w);
	}
}

/*
 *	Unmaps the Object Operations Dialog.
 */
void EDVObjOpDlgUnmap(edv_obj_op_dlg_struct *d)
{
	GtkWidget *w = (d != NULL) ? d->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_hide(w);

	/* Unset transient for */
	gtk_window_set_transient_for(GTK_WINDOW(w), NULL);
	d->ref_toplevel = NULL;
}

/*
 *	Deletes the Object Operations Dialog.
 */
void EDVObjOpDlgDelete(edv_obj_op_dlg_struct *d)
{
	if(d == NULL)
	    return;

	/* Delete the object list and the source directory */
	EDVObjOpDlgReset(d);

	d->ref_toplevel = NULL;		/* Shared */

	/* Begin destroying widgets */
	GTK_WIDGET_DESTROY(d->icon_pm);
	GTK_WIDGET_DESTROY(d->icon_fixed);

	GTK_WIDGET_DESTROY(d->target_entry);
	GTK_WIDGET_DESTROY(d->target_browse_btn);

	GTK_WIDGET_DESTROY(d->target_ur_check);
	GTK_WIDGET_DESTROY(d->target_uw_check);
	GTK_WIDGET_DESTROY(d->target_ux_check);
	GTK_WIDGET_DESTROY(d->target_gr_check);
	GTK_WIDGET_DESTROY(d->target_gw_check);
	GTK_WIDGET_DESTROY(d->target_gx_check);
	GTK_WIDGET_DESTROY(d->target_or_check);
	GTK_WIDGET_DESTROY(d->target_ow_check);
	GTK_WIDGET_DESTROY(d->target_ox_check);
	GTK_WIDGET_DESTROY(d->target_suid_check);
	GTK_WIDGET_DESTROY(d->target_sgid_check);
	GTK_WIDGET_DESTROY(d->target_sticky_check);
	GTK_WIDGET_DESTROY(d->target_chmod_parent);

	GTK_WIDGET_DESTROY(d->target_owner_entry);
	GTK_WIDGET_DESTROY(d->target_owner_btn);
	GTK_WIDGET_DESTROY(d->target_group_entry);
	GTK_WIDGET_DESTROY(d->target_group_btn);
	GTK_WIDGET_DESTROY(d->target_chown_parent);

	GTK_WIDGET_DESTROY(d->target_atime_year_spin);
	PUListBoxDelete(d->target_atime_month_pulistbox);
	GTK_WIDGET_DESTROY(d->target_atime_day_spin);
	GTK_WIDGET_DESTROY(d->target_atime_hours_spin);
	GTK_WIDGET_DESTROY(d->target_atime_minutes_spin);
	GTK_WIDGET_DESTROY(d->target_atime_seconds_spin);
	GTK_WIDGET_DESTROY(d->target_atime_current_btn);
	GTK_WIDGET_DESTROY(d->target_mtime_year_spin);
	PUListBoxDelete(d->target_mtime_month_pulistbox);
	GTK_WIDGET_DESTROY(d->target_mtime_day_spin);
	GTK_WIDGET_DESTROY(d->target_mtime_hours_spin);
	GTK_WIDGET_DESTROY(d->target_mtime_minutes_spin);
	GTK_WIDGET_DESTROY(d->target_mtime_seconds_spin);
	GTK_WIDGET_DESTROY(d->target_mtime_current_btn);
	GTK_WIDGET_DESTROY(d->target_time_parent);

	GTK_WIDGET_DESTROY(d->opt_recursive_check);
	GTK_WIDGET_DESTROY(d->opt_dereference_links_check);
	GTK_WIDGET_DESTROY(d->opt_parent);

	GTK_WIDGET_DESTROY(d->move_btn)
	GTK_WIDGET_DESTROY(d->copy_btn)
	GTK_WIDGET_DESTROY(d->link_btn)
	GTK_WIDGET_DESTROY(d->chmod_btn)
	GTK_WIDGET_DESTROY(d->chown_btn)
	GTK_WIDGET_DESTROY(d->chtime_btn)
	GTK_WIDGET_DESTROY(d->cancel_btn)

	GTK_WIDGET_DESTROY(d->toplevel)

	GTK_ACCEL_GROUP_UNREF(d->accelgrp)

	g_free(d);
}
