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

#ifdef __SOLARIS__
# include "../include/os.h"
#endif

#include "../include/strexp.h"
#include "../include/fio.h"

#include "guiutils.h"
#include "piechart.h"
#include "fb.h"

#include "cfg.h"
#include "edvtypes.h"
#include "edvarchfio.h"
#include "archiveinfo.h"
#include "endeavour.h"
#include "edvutils.h"
#include "edvutilsgtk.h"
#include "edvcfglist.h"
#include "config.h"

#include "images/icon_browse_20x20.xpm"
#include "images/icon_paste_20x20.xpm"
#include "images/icon_ok_20x20.xpm"


static gint EDVArchiveInfoDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
);
static void EDVArchiveInfoAnyChangedCB(GtkWidget *widget, gpointer data);

static void EDVArchiveInfoPasteCommentCB(
	GtkWidget *widget, gpointer data
);
static void EDVArchiveInfoInsertCommentFileCB(
	GtkWidget *widget, gpointer data
);
static void EDVArchiveInfoSetCommentCB(
	GtkWidget *widget, gpointer data
);

static void EDVArchiveInfoOKCB(GtkWidget *widget, gpointer data);

static void EDVArchiveInfoInsertCommentFile(
	edv_archive_info_struct *d, const gchar *path
);

edv_archive_info_struct *EDVArchiveInfoNew(
	gpointer core_ptr, const gchar *arch_obj,
	GtkWidget *ref_toplevel
);
void EDVArchiveInfoResetHasChanges(
	edv_archive_info_struct *d, gboolean has_changes
);
void EDVArchiveInfoUpdateMenus(edv_archive_info_struct *d);
void EDVArchiveInfoSetBusy(edv_archive_info_struct *d, gboolean is_busy);
gboolean EDVArchiveInfoIsMapped(edv_archive_info_struct *d);
void EDVArchiveInfoMap(edv_archive_info_struct *d);
void EDVArchiveInfoUnmap(edv_archive_info_struct *d);
void EDVArchiveInfoDelete(edv_archive_info_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)


/*
 *	Archive Info toplevel GtkWindow "delete_event" signal callback.
 */
static gint EDVArchiveInfoDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
)
{
	EDVArchiveInfoOKCB(widget, data);
	return(TRUE);
}


/*
 *	Archive Info changed signal callback.
 */
static void EDVArchiveInfoAnyChangedCB(GtkWidget *widget, gpointer data)
{
	edv_archive_info_struct *d = EDV_ARCHIVE_INFO(data);
	if(d == NULL)
	    return;

	if(d->freeze_count > 0)
	    return;

	if(!d->has_changes)
	    EDVArchiveInfoResetHasChanges(d, TRUE);
}

/*
 *	Paste comment callback.
 */
static void EDVArchiveInfoPasteCommentCB(
	GtkWidget *widget, gpointer data
)
{
	gchar *s;
	GtkText *text;
	edv_archive_info_struct *d = EDV_ARCHIVE_INFO(data);
	if(d == NULL)
	    return;

	text = (GtkText *)d->comment_text;
	if(text == NULL)
	    return;

	EDVArchiveInfoSetBusy(d, TRUE);

	/* Paste */
	s = GUIDDEGetString(
	    GTK_WIDGET(text),		/* Widget */
	    GDK_SELECTION_PRIMARY,	/* Selection */
	    GDK_CURRENT_TIME		/* Time */
	);
	if(s != NULL)
	{
#if 0
/* The GtkEditable widget already has a handler to receive the paste
 * so we only need to make a request and not actually paste
 */
	    gtk_text_freeze(text);
	    gtk_text_insert(
		text, NULL, NULL, NULL,
		s, -1
	    );
	    gtk_text_thaw(text);
#endif
	    g_free(s);
	}

	EDVArchiveInfoResetHasChanges(d, TRUE);

	EDVArchiveInfoSetBusy(d, FALSE);
}

/*
 *	Insert comment file callback.
 */
static void EDVArchiveInfoInsertCommentFileCB(
	GtkWidget *widget, gpointer data
)
{
	gboolean status;
	gchar *parent_path;
	GtkWidget *toplevel;
	fb_type_struct **ftype = NULL, *ftype_rtn = NULL;
	gint total_ftypes = 0;
	gchar **path_rtn = NULL;
	gint total_path_rtns = 0;
	edv_archive_info_struct *d = EDV_ARCHIVE_INFO(data);
	if((d == NULL) || FileBrowserIsQuery())
	    return;

	EDVArchiveInfoSetBusy(d, TRUE);

	toplevel = d->toplevel;

	/* Get startup path from archive path */
	parent_path = (d->arch_obj != NULL) ?
	    g_dirname(d->arch_obj) : NULL;

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

	/* Query user for file to insert */
	FileBrowserSetTransientFor(toplevel);
	status = FileBrowserGetResponse(
	    "Insert File",
	    "Insert", "Cancel",
	    parent_path,	/* Startup path */
	    ftype, total_ftypes,
	    &path_rtn, &total_path_rtns,
	    &ftype_rtn
	);
	FileBrowserSetTransientFor(NULL);

	/* Got user response? */
	if(status && (total_path_rtns > 0))
	    EDVArchiveInfoInsertCommentFile(d, path_rtn[0]);

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

	/* Delete startup path */
	g_free(parent_path);

	EDVArchiveInfoSetBusy(d, FALSE);
}

/*
 *	Set Comment Button callback.
 */
static void EDVArchiveInfoSetCommentCB(GtkWidget *widget, gpointer data)
{
	gchar *s, **strv = NULL;
	gint i, status, strc = 0;
	GtkEditable *editable;
	edv_core_struct *core_ptr;
	edv_archive_info_struct *d = EDV_ARCHIVE_INFO(data);
	if(d == NULL)
	    return;

	core_ptr = EDV_CORE(d->core_ptr);
	editable = (GtkEditable *)d->comment_text;
	if((core_ptr == NULL) || (editable == NULL) || (d->arch_obj == NULL))
	    return;

	EDVArchiveInfoSetBusy(d, TRUE);

	/* Get comment and explode into multiple lines */
	s = gtk_editable_get_chars(editable, 0, -1);
	strv = strchrexp(s, '\n', &strc);
	g_free(s);

	/* Set archive comment */
	status = EDVArchFIOSetComment(
	    core_ptr, d->arch_obj, strv, strc
	);

	/* Delete comment lines */
	for(i = 0; i < strc; i++)
	    g_free(strv[i]);
	g_free(strv);

	/* Reset has changes */
	if(!status)
	    EDVArchiveInfoResetHasChanges(d, FALSE);

	EDVArchiveInfoSetBusy(d, FALSE);

	/* Error setting archive comment? */
	if(status)
	{
	    const gchar *mesg;

	    switch(status)
	    {
	      case -3:
		mesg =
#if defined(PROG_LANGUAGE_SPANISH)
"El error de sistemas."
#elif defined(PROG_LANGUAGE_FRENCH)
"Erreur de systčmes."
#elif defined(PROG_LANGUAGE_GERMAN)
"Systeme fehler."
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'errore di sistemi."
#elif defined(PROG_LANGUAGE_DUTCH)
"Systemen fout."
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O erro de sistemas."
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Systemfeil."
#else
"Systems error."
#endif
		;
		break;
	      case -2:
		mesg =
#if defined(PROG_LANGUAGE_SPANISH)
"Este formato del archivo no sostiene los comentarios."
#elif defined(PROG_LANGUAGE_FRENCH)
"Ce format de l'archive pas soutien commente."
#elif defined(PROG_LANGUAGE_GERMAN)
"Das format dieses archivs unterstützt bemerkungen nicht."
#elif defined(PROG_LANGUAGE_ITALIAN)
"Questo formato dell'archivio non sostiene i commenti."
#elif defined(PROG_LANGUAGE_DUTCH)
"Het formaat van deze archief steunt opmerkingen niet."
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Este formato do arquivo nao apoia comentários."
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Dette arkivs format střtter ikke kommentarer."
#else
"This archive's format does not support comments."
#endif
		;
		break;
	      default:
		mesg =
#if defined(PROG_LANGUAGE_SPANISH)
"El comentario del archivo de poner de error."
#elif defined(PROG_LANGUAGE_FRENCH)
"Le commentaire d'archive de montage d'erreur."
#elif defined(PROG_LANGUAGE_GERMAN)
"Fehler setzen archiv bemerkung."
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il commento di archivio di montaggio di errore."
#elif defined(PROG_LANGUAGE_DUTCH)
"Fout zetten archief opmerking."
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Erro por o comentário de arquivo."
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"En feil forekommet whiles etting arkivkommentaren."
#else
"Error setting archive comment."
#endif
		;
		break;
	    }
	    EDVPlaySoundWarning(core_ptr);
	    EDVMessageWarning(
#if defined(PROG_LANGUAGE_SPANISH)
"El Comentario Fijo Falló"
#elif defined(PROG_LANGUAGE_FRENCH)
"Régler Le Commentaire Echoué"
#elif defined(PROG_LANGUAGE_GERMAN)
"Feste Bemerkung Hat Versagt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Ha Regolato Il Commento Fallito"
#elif defined(PROG_LANGUAGE_DUTCH)
"Vast Opmerking Verzuimde"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Comentário Fixo Fracassou"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Fast Comment Failed"
#else
"Set Comment Failed"
#endif
		, mesg,
		NULL,
		d->toplevel
	    );
	}
}

/*
 *	OK Button callback.
 */
static void EDVArchiveInfoOKCB(GtkWidget *widget, gpointer data)
{
	edv_archive_info_struct *d = EDV_ARCHIVE_INFO(data);
	if(d == NULL)
	    return;

	EDVArchiveInfoUnmap(d);
	EDVArchiveInfoResetHasChanges(d, FALSE);
}


/*
 *	Inserts the contents in the file specified by path into the
 *	comment text.
 */
static void EDVArchiveInfoInsertCommentFile(
	edv_archive_info_struct *d, const gchar *path
)
{
	FILE *fp;
	GtkText *text;

	if((d == NULL) || STRISEMPTY(path))
	    return;

	text = (GtkText *)d->comment_text;
	if(text == NULL)
	    return;

	/* Open file for reading */
	fp = FOpen(path, "rb");
	if(fp != NULL)
	{
	    gulong size, bytes_read;
	    gchar *buf;
	    struct stat stat_buf;
	    if(fstat(fileno(fp), &stat_buf))
		size = 0;
	    else
		size = stat_buf.st_size;

	    /* Allocate buffer and read contents of file */
	    buf = (gchar *)g_malloc((size + 1) * sizeof(gchar));
	    if(buf != NULL)
		bytes_read = fread(buf, sizeof(gchar), size, fp);
	    else
		bytes_read = 0;

	    /* Read successful? */
	    if((bytes_read > 0) && (bytes_read <= size))
	    {
		gchar *s = buf, *s_end = s + bytes_read;

		buf[bytes_read] = '\0';

		/* Convert any non-printable character into spaces */
		while(s < s_end)
		{
		    /* Not a printable character? */
		    if(!isprint(*s))
		    {
			/* Exclude newlines */
			if(*s != '\n')
			    *s = ' ';
		    }
		    s++;
		}

		/* Insert buffer to comment text */
		gtk_text_freeze(text);
		gtk_text_insert(
		    text, NULL, NULL, NULL,
		    buf, bytes_read
		);
		gtk_text_thaw(text);

		EDVArchiveInfoResetHasChanges(d, TRUE);
	    }

	    /* Delete buffer */
	    g_free(buf);

	    /* Close file */
	    FClose(fp);
	}
}


/*
 *	Creates a new Archive Info Dialog.
 *
 *	If arch_obj is not NULL then the archive object information will
 *	be loaded.
 */
edv_archive_info_struct *EDVArchiveInfoNew(
	gpointer core_ptr, const gchar *arch_obj,
	GtkWidget *ref_toplevel
)
{
	const gint	border_major = 5,
			border_minor = 2;
	gchar *s, *s2, **comment_line = NULL;
	gint	total_objects = 0,
		file_objects = 0,
		directory_objects = 0,
		link_objects = 0,
		other_objects = 0,
		comment_lines = 0;
	gulong	files_size = 0l,
		directories_size = 0l,
		links_size = 0l,
		others_size = 0l,
		uncompressed_size = 0l;
	GdkBitmap *mask;
	GdkPixmap *pixmap;
	GdkWindow *window;
	GtkRcStyle *rcstyle;
	GtkAccelGroup *accelgrp;
	GtkWidget *w, *sb, *parent, *parent2, *parent3, *parent4, *parent5;
	GtkEditable *editable;
	GtkText *text;
	pie_chart_struct *pc;
	edv_object_struct *obj;
	struct stat lstat_buf;
	edv_core_struct *c_ptr = EDV_CORE(core_ptr);
	edv_archive_info_struct *d = EDV_ARCHIVE_INFO(g_malloc0(
	    sizeof(edv_archive_info_struct)
	));


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

	d->busy_cur = gdk_cursor_new(GDK_WATCH);
	d->text_cur = gdk_cursor_new(GDK_XTERM);

	d->arch_obj = STRDUP(arch_obj);
	d->has_changes = FALSE;


	/* Get archive object statistics */
	obj = EDVObjectNew();
	EDVObjectSetPath(obj, d->arch_obj);
	if(!lstat((const char *)arch_obj, &lstat_buf))
	    EDVObjectSetStat(obj, &lstat_buf);
	EDVObjectValidateLink(obj);
	/* Get medium pixmap and mask */
	EDVMatchObjectIcon(
	    c_ptr->device, c_ptr->total_devices,
	    c_ptr->mimetype, c_ptr->total_mimetypes,
	    obj->type,
	    obj->full_path,
	    obj->link_valid,
	    obj->permissions,
	    1,			/* Medium sized icons */
	    &pixmap, &mask,
	    NULL, NULL,
	    NULL, NULL,
	    NULL, NULL
	);
	/* Get number of objects and total size */
	if(d->arch_obj != NULL)
	{
	    gint i, total;
	    gulong this_obj_size;
	    edv_archive_object_struct	*obj_ptr,
					**obj = EDVArchFIOGetListing(
		c_ptr, d->arch_obj, &total,
		NULL, 0,	/* No filter */
		NULL		/* No password */
	    );
	    for(i = 0; i < total; i++)
	    {
		obj_ptr = obj[i];
		if(obj_ptr == NULL)
		    continue;

		total_objects++;
		switch(obj_ptr->type)
		{
		  case EDV_OBJECT_TYPE_UNKNOWN:
		    break;
		  case EDV_OBJECT_TYPE_FILE:
		    file_objects++;
		    this_obj_size = obj_ptr->size + (
			(obj_ptr->full_path != NULL) ?
			STRLEN(obj_ptr->full_path) : STRLEN(obj_ptr->name)
		    );
		    files_size += this_obj_size;
		    uncompressed_size += this_obj_size;
		    break;
		  case EDV_OBJECT_TYPE_DIRECTORY:
		    directory_objects++;
		    this_obj_size = obj_ptr->size + (
			(obj_ptr->full_path != NULL) ?
			STRLEN(obj_ptr->full_path) : STRLEN(obj_ptr->name)
		    );
		    directories_size += this_obj_size;
		    uncompressed_size += this_obj_size;
		    break;
		  case EDV_OBJECT_TYPE_LINK:
		    link_objects++;
		    this_obj_size = obj_ptr->size + (
			(obj_ptr->full_path != NULL) ?
			STRLEN(obj_ptr->full_path) : STRLEN(obj_ptr->name)
		    ) + STRLEN(obj_ptr->linked_to);
		    links_size += this_obj_size;
		    uncompressed_size += this_obj_size;
		    break;
		  default:
		    other_objects++;
		    this_obj_size = obj_ptr->size + (
			(obj_ptr->full_path != NULL) ?
			STRLEN(obj_ptr->full_path) : STRLEN(obj_ptr->name)
		    );
		    others_size += this_obj_size;
		    uncompressed_size += this_obj_size;
		    break;
		}

		EDVArchObjectDelete(obj_ptr);
	    }
	    g_free(obj);

	    /* Get comment */
	    comment_line = EDVArchFIOGetComment(
		c_ptr, d->arch_obj, &comment_lines
	    );
	    for(i = 0; i < comment_lines; i++)
		uncompressed_size += STRLEN(comment_line[i]) + 1;
	}


	d->freeze_count--;


	/* Begin creating widgets */

	/* Create toplevel */
	d->toplevel = w = gtk_window_new(GTK_WINDOW_DIALOG);
	s = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"El Comentario & La Estadística"
#elif defined(PROG_LANGUAGE_FRENCH)
"Commenter & La Statistique"
#elif defined(PROG_LANGUAGE_GERMAN)
"Bemerkung & Statistik"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Commento & La Statistica"
#elif defined(PROG_LANGUAGE_DUTCH)
"Opmerking & Statistieken"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Comentário & Estatística"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kommentar & Statistics"
#else
"Archive Comment & Statistics"
#endif
	    ": %s", obj->name
	);
	gtk_window_set_title(GTK_WINDOW(w), s);
	g_free(s);
        gtk_window_set_wmclass(
            GTK_WINDOW(w), "dialog", PROG_NAME
        );
        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
	    );
/*	    GUISetWMIcon(window, (guint8 **)archiver_48x48_xpm); */
	}
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_event",
	    GTK_SIGNAL_FUNC(EDVArchiveInfoDeleteEventCB), d
	);
	gtk_container_border_width(GTK_CONTAINER(w), 0);
	gtk_window_add_accel_group(GTK_WINDOW(w), accelgrp);
	if((ref_toplevel != NULL) ?
	    GTK_IS_WINDOW(GTK_OBJECT(ref_toplevel)) : FALSE
	)
	{
	    gtk_window_set_transient_for(
		GTK_WINDOW(w), GTK_WINDOW(ref_toplevel)
	    );
	}
	parent = w;

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


	/* Vbox for information and statistics */
	w = gtk_vbox_new(FALSE, border_major);
	gtk_container_border_width(GTK_CONTAINER(w), border_major);
	gtk_box_pack_start(GTK_BOX(d->main_vbox), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent = w;


	/* Hbox to separate two columns */
	w = gtk_hbox_new(FALSE, 20);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;


	/* Left column vbox */
	w = gtk_vbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;


	/* Hbox for icon and name */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Icon */
	if(pixmap != NULL)
	{
	    d->icon_pm = w = gtk_pixmap_new(pixmap, mask);
	    gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	}
	/* Label */
	rcstyle = gtk_rc_style_new();
	rcstyle->font_name = STRDUP(
"-adobe-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1"
	);
	s = EDVCopyShortenPath(obj->name, 40);
	d->name_label = w = gtk_label_new(s);
	g_free(s);
	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)


	/* Location hbox */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Label */
	rcstyle = gtk_rc_style_new();
	rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	);
	w = gtk_label_new(
#if defined(PROG_LANGUAGE_SPANISH)
"La Ubicación"
#elif defined(PROG_LANGUAGE_FRENCH)
"Emplacement"
#elif defined(PROG_LANGUAGE_GERMAN)
"Ort"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Posizione"
#elif defined(PROG_LANGUAGE_DUTCH)
"Plaats"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Localidade"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Plassering"
#else
"Location"
#endif
	    ":"
	);
	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)
	/* Location Label */
	rcstyle = gtk_rc_style_new();
	rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	);
	s2 = g_dirname(obj->full_path);
	s = EDVCopyShortenPath(s2, 45);
	d->location_label = w = gtk_label_new(s);
	g_free(s);
	g_free(s2);
	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)


	/* Hbox to separate columns for object and size break-down */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* Table for object and size break-down labels */
	w = gtk_table_new(5, 3, FALSE);
	gtk_table_set_row_spacings(GTK_TABLE(w), border_minor);
	gtk_table_set_col_spacings(GTK_TABLE(w), border_major);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

#define CREATE_LABEL(r,n,i,b)	{				\
 GtkAttachOptions	x_attach_opt = 0,			\
			y_attach_opt = 0;			\
 guint	x_pad = 0, y_pad = 0;					\
								\
 /* Alignment for name label */					\
 w = gtk_alignment_new(1.0f, 0.5f, 0.0f, 0.0f);			\
 gtk_widget_set_usize(w, 100, -1);				\
 gtk_table_attach(						\
  GTK_TABLE(parent4), w,					\
  0, 1, (r), (r) + 1,						\
  x_attach_opt, y_attach_opt, x_pad, y_pad			\
 );								\
 gtk_widget_show(w);						\
 parent5 = w;							\
 /* Name label */						\
 w = gtk_label_new((n));					\
 gtk_container_add(GTK_CONTAINER(parent5), w);			\
 gtk_widget_modify_style(w, rcstyle);				\
 gtk_widget_show(w);						\
								\
 /* Alignment for quantity label */				\
 w = gtk_alignment_new(0.0f, 0.5f, 0.0f, 0.0f);			\
 gtk_widget_set_usize(w, 50, -1);				\
 gtk_table_attach(						\
  GTK_TABLE(parent4), w,					\
  1, 2, (r), (r) + 1,						\
  x_attach_opt, y_attach_opt, x_pad, y_pad			\
 );								\
 gtk_widget_show(w);						\
 parent5 = w;							\
 /* Quantity label */						\
 s = g_strdup_printf("%i", (i));				\
 w = gtk_label_new(s);						\
 g_free(s);							\
 gtk_container_add(GTK_CONTAINER(parent5), w);			\
 gtk_widget_modify_style(w, rcstyle);                           \
 gtk_widget_show(w);                                            \
								\
 /* Alignmet for size label */					\
 w = gtk_alignment_new(0.0f, 0.5f, 0.0f, 0.0f);			\
 gtk_widget_set_usize(w, 150, -1);				\
 gtk_table_attach(						\
  GTK_TABLE(parent4), w,					\
  2, 3, (r), (r) + 1,						\
  x_attach_opt, y_attach_opt, x_pad, y_pad			\
 );								\
 gtk_widget_show(w);						\
 parent5 = w;							\
 /* Size label */						\
 s = g_strdup_printf(						\
  "%s byte%s",							\
  EDVGetObjectSizeStr(c_ptr, (b)),				\
  ((b) == 1) ? "" : "s"						\
 );								\
 w = gtk_label_new(s);						\
 g_free(s);							\
 gtk_container_add(GTK_CONTAINER(parent5), w);			\
 gtk_widget_modify_style(w, rcstyle);				\
 gtk_widget_show(w);						\
}

	rcstyle = gtk_rc_style_new();
	rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	);
#if defined(PROG_LANGUAGE_SPANISH)
	CREATE_LABEL(0, "Los Archivos:", file_objects, files_size);
	CREATE_LABEL(1, "Las Guías:", directory_objects, directories_size);
	CREATE_LABEL(2, "Las Conexiones:", link_objects, links_size);
	CREATE_LABEL(3, "Otros Objetos:", other_objects, others_size);
#elif defined(PROG_LANGUAGE_FRENCH)
	CREATE_LABEL(0, "Fichiers:", file_objects, files_size);
	CREATE_LABEL(1, "Annuaires:", directory_objects, directories_size);
	CREATE_LABEL(2, "Liens:", link_objects, links_size);
	CREATE_LABEL(3, "Autres Objets:", other_objects, others_size);
#elif defined(PROG_LANGUAGE_GERMAN)
	CREATE_LABEL(0, "Akten:", file_objects, files_size);
	CREATE_LABEL(1, "Verzeichnisse:", directory_objects, directories_size);
	CREATE_LABEL(2, "Kettenglieder:", link_objects, links_size);
	CREATE_LABEL(3, "Andere Objekte:", other_objects, others_size);
#elif defined(PROG_LANGUAGE_ITALIAN)
	CREATE_LABEL(0, "I File:", file_objects, files_size);
	CREATE_LABEL(1, "Gli Elenchi:", directory_objects, directories_size);
	CREATE_LABEL(2, "Le Maglie:", link_objects, links_size);
	CREATE_LABEL(3, "L'Altro Obbietta:", other_objects, others_size);
#elif defined(PROG_LANGUAGE_DUTCH)
	CREATE_LABEL(0, "Dossiers:", file_objects, files_size);
	CREATE_LABEL(1, "Gidzen:", directory_objects, directories_size);
	CREATE_LABEL(2, "Schakels:", link_objects, links_size);
	CREATE_LABEL(3, "Anderze Voorwerpen:", other_objects, others_size);
#elif defined(PROG_LANGUAGE_PORTUGUESE)
	CREATE_LABEL(0, "Os Arquivos:", file_objects, files_size);
	CREATE_LABEL(1, "Os Guias:", directory_objects, directories_size);
	CREATE_LABEL(2, "Os Elos:", link_objects, links_size);
	CREATE_LABEL(3, "Outro Opőe-se:", other_objects, others_size);
#elif defined(PROG_LANGUAGE_NORWEGIAN)
	CREATE_LABEL(0, "Arkiver:", file_objects, files_size);
	CREATE_LABEL(1, "Kataloger:", directory_objects, directories_size);
	CREATE_LABEL(2, "Ledd:", link_objects, links_size);
	CREATE_LABEL(3, "Annen Object:", other_objects, others_size);
#else
	CREATE_LABEL(0, "Files:", file_objects, files_size);
	CREATE_LABEL(1, "Directories:", directory_objects, directories_size);
	CREATE_LABEL(2, "Links:", link_objects, links_size);
	CREATE_LABEL(3, "Misc Objects:", other_objects, others_size);
#endif
	GTK_RC_STYLE_UNREF(rcstyle)

	rcstyle = gtk_rc_style_new();
	rcstyle->font_name = STRDUP(
"-adobe-helvetica-bold-r-normal-*-12-*-*-*-*-*-iso8859-1"
	);
#if defined(PROG_LANGUAGE_SPANISH)
	CREATE_LABEL(4, "El Suma:", total_objects, uncompressed_size);
#elif defined(PROG_LANGUAGE_FRENCH)
	CREATE_LABEL(4, "Total:", total_objects, uncompressed_size);
#elif defined(PROG_LANGUAGE_GERMAN)
	CREATE_LABEL(4, "Summe:", total_objects, uncompressed_size);
#elif defined(PROG_LANGUAGE_ITALIAN)
	CREATE_LABEL(4, "Il Totale:", total_objects, uncompressed_size);
#elif defined(PROG_LANGUAGE_DUTCH)
	CREATE_LABEL(4, "Totaal:", total_objects, uncompressed_size);
#elif defined(PROG_LANGUAGE_PORTUGUESE)
	CREATE_LABEL(4, "O Total:", total_objects, uncompressed_size);
#elif defined(PROG_LANGUAGE_NORWEGIAN)
	CREATE_LABEL(4, "Total:", total_objects, uncompressed_size);
#else
	CREATE_LABEL(4, "Total:", total_objects, uncompressed_size);
#endif
	GTK_RC_STYLE_UNREF(rcstyle)

#undef CREATE_LABEL



	/* Right column vbox */
	w = gtk_vbox_new(FALSE, border_major);
	gtk_box_pack_end(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;

	/* Size pie chart */
	if(obj != NULL)
	{
	    gchar *s2;
	    GdkColor *c, uncompressed_size_color, current_size_color;

	    /* Uncompressed Size */
	    GtkAdjustment *adj = (GtkAdjustment *)gtk_adjustment_new(
		0.0f, 0.0f, (gfloat)MAX(uncompressed_size, obj->size),
		0.0f, 0.0f, 0.0f
	    );
	    c = &uncompressed_size_color;
	    GDK_COLOR_SET_COEFF(c, 0.0f, 0.0f, 1.0f);
	    s = g_strdup_printf(
		"%s bytes",
		EDVGetObjectSizeStr(
		    c_ptr, 
		    MAX(uncompressed_size, obj->size)
		)
	    );
	    s2 = g_strdup_printf(
		"%.0f%% Compressed",
		CLIP(100.0f - (((uncompressed_size > 0) ?
		    (gfloat)obj->size / (gfloat)uncompressed_size : 1.0f
		) * 100.0f), 0.0f, 100.0f)
	    );

	    /* Create Pie Chart */
	    d->piechart = pc = PieChartNew(
		adj, c, 110, 70,
#if defined(PROG_LANGUAGE_SPANISH)
		"El Tamańo", s2,
		"Ensanchado:", s
#elif defined(PROG_LANGUAGE_FRENCH)
		"Taille", s2,
		"Augmenté:", s
#elif defined(PROG_LANGUAGE_GERMAN)
		"Größe", s2,
		"Ausgebreitet:", s
#elif defined(PROG_LANGUAGE_ITALIAN)
		"La Misura", s2,
		"Allargato:", s
#elif defined(PROG_LANGUAGE_DUTCH)
		"Maat", s2,
		"Uitgebreide:", s
#elif defined(PROG_LANGUAGE_PORTUGUESE)
		"O Tamanho", s2,
		"Expandido:", s
#elif defined(PROG_LANGUAGE_NORWEGIAN)
		"Střrrelse", s2,
		"Utvidet:", s
#else
		"Size", s2,		/* Header & Footer */
		"Uncompressed:", s
#endif
	    );
	    g_free(s);
	    g_free(s2);
	    gtk_object_unref(GTK_OBJECT(adj));
	    w = pc->toplevel;
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);

	    /* Current Size */
	    adj = (GtkAdjustment *)gtk_adjustment_new(
		0.0f, 0.0f, (gfloat)obj->size,
		0.0f, 0.0f, 0.0f
	    );
	    c = &current_size_color;
	    GDK_COLOR_SET_COEFF(c, 1.0f, 0.0f, 1.0f);
	    s = g_strdup_printf(
		"%s bytes",
		EDVGetObjectSizeStr(c_ptr, obj->size)
	    );
	    PieChartValueAdd(
		pc, adj, c,
#if defined(PROG_LANGUAGE_SPANISH)
"Comprimido"
#elif defined(PROG_LANGUAGE_FRENCH)
"Serré"
#elif defined(PROG_LANGUAGE_GERMAN)
"Zusammengedrückt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Compresso"
#elif defined(PROG_LANGUAGE_DUTCH)
"Samengedrukte"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Comprimido"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Komprimert"
#else
"Compressed"
#endif
		":", s
	    );
	    g_free(s);
	    gtk_object_unref(GTK_OBJECT(adj));
	}


	/* Comments Frame */
	w = gtk_frame_new(
#if defined(PROG_LANGUAGE_SPANISH)
"El Comentario"
#elif defined(PROG_LANGUAGE_FRENCH)
"Commentaire"
#elif defined(PROG_LANGUAGE_GERMAN)
"Bemerkung"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Commento"
#elif defined(PROG_LANGUAGE_DUTCH)
"Opmerking"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Comentário"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kommentar"
#else
"Comment"
#endif
	);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_ETCHED_IN);
	gtk_widget_show(w);
	parent2 = w;

	w = gtk_vbox_new(FALSE, border_major);
	gtk_container_border_width(GTK_CONTAINER(w), border_major);
	gtk_container_add(GTK_CONTAINER(parent2), w);
	gtk_widget_show(w);
	parent2 = w;

	/* Table for comments text box and scroll bars */
	w = gtk_table_new(2, 2, FALSE);
	gtk_table_set_row_spacing(GTK_TABLE(w), 0, border_minor);
	gtk_table_set_col_spacing(GTK_TABLE(w), 0, border_minor);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Comments text box */
	rcstyle = gtk_rc_style_new();
	rcstyle->font_name = STRDUP(
"-adobe-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	);
	d->comment_text = w = gtk_text_new(NULL, NULL);
	editable = GTK_EDITABLE(w);
	text = GTK_TEXT(w);
	gtk_widget_set_usize(w, 520, 150);
	text->default_tab_width = 8;
	gtk_text_set_editable(text, TRUE);
	gtk_text_set_word_wrap(text, TRUE);
	gtk_table_attach(
	    GTK_TABLE(parent3), w,
	    0, 1, 0, 1,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EDVArchiveInfoAnyChangedCB), d
	);
	gtk_widget_realize(w);
	gtk_widget_modify_style(w, rcstyle);
	gdk_window_set_cursor(w->window, d->text_cur);
	gtk_widget_show(w);
	GTK_RC_STYLE_UNREF(rcstyle)
	/* Vertical scroll bar */
	sb = gtk_vscrollbar_new(GTK_TEXT(w)->vadj);
	gtk_table_attach(
	    GTK_TABLE(parent3), sb,
	    1, 2, 0, 1,
	    GTK_FILL,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_widget_show(sb);
	/* Get archive comment */
	text = GTK_TEXT(d->comment_text);
	if(text != NULL)
	{
	    gint strc = comment_lines;
	    gchar **strv = comment_line;
	    if(strv != NULL)
	    {
		gint i;

		gtk_text_freeze(text);

		for(i = 0; i < strc; i++)
		{
		    s = strv[i];
		    if(s == NULL)
			continue;

		    gtk_text_insert(text, NULL, NULL, NULL, s, -1);
		    gtk_text_insert(text, NULL, NULL, NULL, "\n", -1);
		}

		gtk_text_thaw(text);
	    }
	}

	/* Hbox for set comment button */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Set Comment Button */
	d->comment_set_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_ok_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"El Conjunto"
#elif defined(PROG_LANGUAGE_FRENCH)
"Série"
#elif defined(PROG_LANGUAGE_GERMAN)
"Satz"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Serie"
#elif defined(PROG_LANGUAGE_DUTCH)
"Stel"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Jogo"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Sett"
#else
"Set"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVArchiveInfoSetCommentCB), d
	);
	gtk_widget_show(w);


	/* Hbox for comment utils buttons */
	w = gtk_vbox_new(TRUE, 0);
	gtk_box_pack_end(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_end(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Paste Comment Button */
	d->comment_paste_btn = w = GUIButtonPixmap(
	    (guint8 **)icon_paste_20x20_xpm
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVArchiveInfoPasteCommentCB), d
	);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"La Pasta"
#elif defined(PROG_LANGUAGE_FRENCH)
"Pâte"
#elif defined(PROG_LANGUAGE_GERMAN)
"Paste"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Pasta"
#elif defined(PROG_LANGUAGE_DUTCH)
"Plakmiddel"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"A Pasta"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Masse"
#else
"Paste"
#endif
	);
	gtk_widget_show(w);
	/* Insert Comment File Button */
	d->comment_insert_file_btn = w = GUIButtonPixmap(
	    (guint8 **)icon_browse_20x20_xpm
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVArchiveInfoInsertCommentFileCB), d
	);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"El Archivo De La Adición"
#elif defined(PROG_LANGUAGE_FRENCH)
"Fichier D'Insertion"
#elif defined(PROG_LANGUAGE_GERMAN)
"Fügen Sie Akte Ein"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il File Di Inserzione"
#elif defined(PROG_LANGUAGE_DUTCH)
"Voeg Dossier In"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Insira Arquivo"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Tilfřy Arkiv"
#else
"Insert File"
#endif
	);
	gtk_widget_show(w);


	/* Delete archive object statistics (no longer needed) */
	EDVObjectDelete(obj);

	/* Delete comment */
	if(comment_line != NULL)
	{
	    gint i;
	    for(i = 0; i < comment_lines; i++)
		g_free(comment_line[i]);
	    g_free(comment_line);
	    comment_line = NULL;
	    comment_lines = 0;
	}



	/* Separator */
	w = gtk_hseparator_new();
	gtk_box_pack_start(GTK_BOX(d->main_vbox), w, FALSE, FALSE, 0);
	gtk_widget_show(w);

	/* Buttons */
	w = gtk_hbox_new(TRUE, 0);
	gtk_box_pack_start(GTK_BOX(d->main_vbox), w, FALSE, FALSE, border_major);
	gtk_widget_show(w);
	parent2 = w;

	/* OK button */
	d->ok_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_ok_20x20_xpm, "OK", 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, TRUE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVArchiveInfoOKCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_Escape, 0, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
        gtk_accel_group_add(
            accelgrp, GDK_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
            GTK_OBJECT(w), "clicked"
        );
        GUIButtonLabelUnderline(w, GDK_o);
	gtk_widget_show(w);


	d->freeze_count--;


	EDVArchiveInfoUpdateMenus(d);


	return(d);
}

/*
 *	Resets the Archive Info Dialog has_changes marker.
 */
void EDVArchiveInfoResetHasChanges(
	edv_archive_info_struct *d, gboolean has_changes
)
{
	if(d == NULL)
	    return;

	if(d->has_changes == has_changes)
	    return;

	d->has_changes = has_changes;
	EDVArchiveInfoUpdateMenus(d);
}

/*
 *	Updates the Archive Info Dialog's widgets to reflect current
 *	values.
 */
void EDVArchiveInfoUpdateMenus(edv_archive_info_struct *d)
{
	gboolean	sensitive,
			has_changes;

	if(d == NULL)
	    return;

	has_changes = d->has_changes;

	/* Set Comment Button */
	sensitive = has_changes;
	GTK_WIDGET_SET_SENSITIVE(d->comment_set_btn, sensitive);
}

/*
 *	Sets the Archive Info Dialog as busy or ready.
 */
void EDVArchiveInfoSetBusy(edv_archive_info_struct *d, gboolean is_busy)
{
	GdkCursor *cursor;
	GtkWidget *w;
	edv_core_struct *core_ptr;

	if(d == NULL)
	    return;

	core_ptr = EDV_CORE(d->core_ptr);
	if(core_ptr == 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_ptr, 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 Archive Info Dialog is mapped.
 */
gboolean EDVArchiveInfoIsMapped(edv_archive_info_struct *d)
{
	GtkWidget *w = (d != NULL) ? d->toplevel : NULL;
	return((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE);
}

/*
 *	Maps the Archive Info Dialog.
 */
void EDVArchiveInfoMap(edv_archive_info_struct *d)
{
	GtkWidget *w = (d != NULL) ? d->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_show_raise(w);

	/* Grab focus and default on the OK button */
	w = d->ok_btn;
	if(w != NULL)
	{
	    gtk_widget_grab_focus(w);
	    gtk_widget_grab_default(w);
	}
}

/*
 *	Unmap the Archive Info Dialog.
 */
void EDVArchiveInfoUnmap(edv_archive_info_struct *d)
{
	GtkWidget *w = (d != NULL) ? d->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_hide(w);
}

/*
 *	Deletes the Archive Info Dialog.
 */
void EDVArchiveInfoDelete(edv_archive_info_struct *d)
{
	if(d == NULL)
	    return;

	g_free(d->arch_obj);
	d->arch_obj = NULL;

	PieChartDelete(d->piechart);
	d->piechart = NULL;

	GTK_WIDGET_DESTROY(d->icon_pm);
	GTK_WIDGET_DESTROY(d->name_label);
	GTK_WIDGET_DESTROY(d->location_label);
	GTK_WIDGET_DESTROY(d->comment_text);
	GTK_WIDGET_DESTROY(d->comment_set_btn);
	GTK_WIDGET_DESTROY(d->comment_paste_btn);
	GTK_WIDGET_DESTROY(d->comment_insert_file_btn);
	GTK_WIDGET_DESTROY(d->ok_btn);

	GTK_WIDGET_DESTROY(d->main_vbox);

	gtk_window_set_modal(GTK_WINDOW(d->toplevel), FALSE);
	gtk_window_set_transient_for(GTK_WINDOW(d->toplevel), NULL);
	GTK_WIDGET_DESTROY(d->toplevel);

	GTK_ACCEL_GROUP_UNREF(d->accelgrp);

	GDK_CURSOR_DESTROY(d->text_cur);
	GDK_CURSOR_DESTROY(d->busy_cur);

	g_free(d);
}
