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

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

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

#include "cfg.h"
#include "edvtypes.h"
#include "edvlistcb.h"
#include "edvdate.h"
#include "edvmimetypes.h"
#include "edvmimetypesfio.h"
#include "mimetypesimportopts.h"
#include "mimetypeswin.h"
#include "endeavour.h"
#include "edvcb.h"
#include "edvutils.h"
#include "edvutilsgtk.h"
#include "edvcfglist.h"
#include "config.h"

#include "images/icon_search_20x20.xpm"
#include "images/icon_add_20x20.xpm"
#include "images/icon_edit_20x20.xpm"
#include "images/icon_remove_20x20.xpm"
#include "images/icon_save_20x20.xpm"
#include "images/icon_save_32x32.xpm"
#include "images/icon_import_20x20.xpm"
#include "images/icon_import_32x32.xpm"
#include "images/icon_export_20x20.xpm"
#include "images/icon_export_32x32.xpm"
#include "images/icon_close_20x20.xpm"

#include "images/icon_mimetypes_48x48.xpm"

#include "images/icon_system_object_20x20.xpm"
#include "images/icon_file_extension_20x20.xpm"
#include "images/icon_executable_20x20.xpm"
#include "images/icon_unique_object_20x20.xpm"


static gint EDVMimeTypesListProgressCB(
	gpointer data, gulong pos, gulong max
);

static gint EDVMimeTypesListWinDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
);
static gint EDVMimeTypesListWinKeyEventCB(
	GtkWidget *widget, GdkEventKey *key, gpointer data
);
static gint EDVMimeTypesListWinButtonPressEventCB(
	GtkWidget *widget, GdkEventButton *button, gpointer data
);
static void EDVMimeTypesListWinSelectRowCB(
	GtkCList *clist, gint row, gint column, GdkEvent *event,
	gpointer data
);
static void EDVMimeTypesListWinUnselectRowCB(
	GtkCList *clist, gint row, gint column, GdkEvent *event,
	gpointer data
);
static void EDVMimeTypesListWinFindCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesListWinAddCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesListWinEditCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesListWinRemoveCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesListWinShiftUpCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesListWinShiftDownCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesListWinSaveCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesListWinImportCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesListWinExportCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesListWinCloseCB(
	GtkWidget *widget, gpointer data
);

void EDVMimeTypesListWinSelect(
	edv_mimetype_listwin_struct *lw, gint i
);
gint EDVMimeTypesListWinSelectByType(
	edv_mimetype_listwin_struct *lw, const gchar *type
);

static void EDVMimeTypesListWinUpdateDisplay(
	edv_mimetype_listwin_struct *lw,
	gint mt_num, edv_mimetype_struct *mt_ptr
);
void EDVMimeTypesListWinSetRow(
	edv_mimetype_listwin_struct *lw,
	gint row, edv_mimetype_struct *mt_ptr
);
void EDVMimeTypesListWinFetchValues(
	edv_mimetype_listwin_struct *lw
);

void EDVMimeTypesListWinReconfiguredNotifyCB(
	edv_mimetype_listwin_struct *lw
);

void EDVMimeTypesListWinMimeTypeAddedCB(
	edv_mimetype_listwin_struct *lw,
	gint mt_num, edv_mimetype_struct *mt_ptr
);
void EDVMimeTypesListWinMimeTypeModifiedCB(
	edv_mimetype_listwin_struct *lw,
	gint mt_num, edv_mimetype_struct *mt_ptr
);
void EDVMimeTypesListWinMimeTypeRemovedCB(
	edv_mimetype_listwin_struct *lw,
	gint mt_num
);

edv_mimetype_listwin_struct *EDVMimeTypesListWinNew(
	gpointer core_ptr
);
void EDVMimeTypesListWinUpdateMenus(
	edv_mimetype_listwin_struct *lw
);
void EDVMimeTypesListWinSetBusy(
	edv_mimetype_listwin_struct *lw, gboolean is_busy
);
gboolean EDVMimeTypesListWinIsMapped(
	edv_mimetype_listwin_struct *lw
);
void EDVMimeTypesListWinMap(
	edv_mimetype_listwin_struct *lw
);
void EDVMimeTypesListWinUnmap(
	edv_mimetype_listwin_struct *lw
);
void EDVMimeTypesListWinDelete(
	edv_mimetype_listwin_struct *lw
);


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

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


#define LISTWIN_WIDTH		500
#define LISTWIN_HEIGHT		480

#define LISTWIN_TITLE		"MIME Types"


#define EDV_MIMETYPES_FORMAT_DESC_MAILCAP		\
 "Mailcap"
#define EDV_MIMETYPES_FORMAT_DESC_MEDIA_TYPES		\
 "Media Types"
#define EDV_MIMETYPES_FORMAT_DESC_ENDEAVOUR		\
 "Endeavour MIME Types"


/*
 *	MIME Types List Window Progress callback.
 *
 *	For save, import, and export progress.
 */
static gint EDVMimeTypesListProgressCB(
	gpointer data, gulong pos, gulong max
)
{
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return(-1);

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

	    if(max > 0)
	    {
		gfloat progress = (gfloat)pos / (gfloat)max;

		ProgressDialogUpdate(
		    NULL, NULL, NULL, NULL,
		    progress, EDV_DEF_PROGRESS_BAR_TICKS, TRUE
		);
	    }
	}

	return(0);
}


/*
 *	MIME Types List Window GtkWindow "delete_event" signal callback.
 */
static gint EDVMimeTypesListWinDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
)
{
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return(TRUE);

	EDVMimeTypesListWinCloseCB(NULL, lw);

	return(TRUE);
}

/*
 *	MIME Types List Window "key_press_event" or "key_release_event"
 *	signal callback.
 */
static gint EDVMimeTypesListWinKeyEventCB(
	GtkWidget *widget, GdkEventKey *key, gpointer data
)
{
	gint status = FALSE;
	gint etype;
	guint keyval, state;
	gboolean press;
	edv_core_struct *core_ptr;
	GtkCList *clist;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if((widget == NULL) || (key == NULL) || (lw == NULL))
	    return(status);

	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return(status);

	/* Get event type */
	etype = key->type;

	/* Get other key event values */
	press = (etype == GDK_KEY_PRESS) ? TRUE : FALSE;
	keyval = key->keyval;
	state = key->state;

/* Stop emit of signal */
#define DO_STOP_KEY_SIGNAL_EMIT	{		\
 gtk_signal_emit_stop_by_name(			\
  GTK_OBJECT(widget),				\
  press ?					\
   "key_press_event" : "key_release_event"	\
 );						\
}

	/* Begin checking to see which widget this event is for */

	/* MIME Types clist */
	if(widget == lw->mimetypes_clist)
	{
	    /* Get last selected row */
	    gint row = EDVCListGetSelectedLast(clist, NULL);

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

	      case GDK_Delete:
		if(press)
		{
		    EDVMimeTypesListWinRemoveCB(NULL, lw);
		}
		DO_STOP_KEY_SIGNAL_EMIT
		status = TRUE;
		break;

	      case GDK_space:
	      case GDK_KP_Space:
		row = clist->focus_row;
		if((row >= 0) && (row < clist->rows) && press)
		{
		    gboolean already_selected = FALSE;

		    /* Check if this row is already selected */
		    GList *glist = clist->selection;
		    while(glist != NULL)
		    {
			if(row == (gint)glist->data)
			{
			    already_selected = TRUE;
			    break;
			}
			glist = g_list_next(glist);
		    }

		    gtk_clist_freeze(clist);
		    if(already_selected)
			gtk_clist_unselect_row(clist, row, 0);
		    else
			gtk_clist_select_row(clist, row, 0);
		    gtk_clist_thaw(clist);
		}
		DO_STOP_KEY_SIGNAL_EMIT
		status = TRUE;
		break;
	    }
	}

	return(status);
#undef DO_STOP_KEY_SIGNAL_EMIT
}

/*
 *	MIME Types List Window "button_press_event" or 
 *	"button_release_event" signal callback.
 */
static gint EDVMimeTypesListWinButtonPressEventCB(
	GtkWidget *widget, GdkEventButton *button, gpointer data
)
{
	gint status = FALSE;
	gint etype;
	GtkCList *clist;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core_ptr;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if((widget == NULL) || (button == NULL) || (lw == NULL))
	    return(status);

	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return(status);

	cfg_list = core_ptr->cfg_list;

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

	/* Get event type */
	etype = button->type;

	/* Begin checking to see which widget this event is for */

	/* MIME Types clist */
	if(widget == lw->mimetypes_clist)
	{
	    gint row, column;
	    GtkWidget *w;


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

	    /* Handle by event type */
	    switch(etype)
	    {
	      case GDK_2BUTTON_PRESS:
		/* Handle by button number */
		switch(button->button)
		{
		  case 1:
		    EDVMimeTypesListWinEditCB(NULL, lw);
		    status = TRUE;
		    break;
		}
		break;

	      case GDK_BUTTON_PRESS:
		/* Handle by button number */
		switch(button->button)
		{
		  case 3:
		    /* Select row before mapping menu? */
		    if(EDV_GET_B(EDV_CFG_PARM_RIGHT_CLICK_MENU_SELECTS) &&
		       (row >= 0) && (row < clist->rows)
		    )
		    {
			/* Select the row that the button was pressed over
			 * if no key modifiers are held then this will also
			 * unselect all previously selected rows
			 */
			gtk_clist_freeze(clist);
			if(!(button->state & GDK_CONTROL_MASK) &&
			   !(button->state & GDK_SHIFT_MASK)
			)
			    gtk_clist_unselect_all(clist);
			clist->focus_row = row;
			gtk_clist_select_row(clist, row, 0);
			gtk_clist_thaw(clist);
		    }

		    /* Get right click menu widget and map it */
		    w = lw->menu;
		    if(w != NULL)
			gtk_menu_popup(
			    GTK_MENU(w), NULL, NULL,
			    NULL, NULL,
			    button->button, button->time
			);
		    status = TRUE;
		    break;
		}
		break;
	    }
	}

	return(status);
}

/*
 *	MIME Types List Window GtkCList "select_row" signal callback.
 */
static void EDVMimeTypesListWinSelectRowCB(
	GtkCList *clist, gint row, gint column, GdkEvent *event,
	gpointer data
)
{
	edv_core_struct *core_ptr;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return;

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

	    /* Update displayed MIME Types structure */
	    if((row >= 0) && (row < core_ptr->total_mimetypes))
		EDVMimeTypesListWinUpdateDisplay(
		    lw, row, core_ptr->mimetype[row]
		);

	    EDVMimeTypesListWinUpdateMenus(lw);
	}
}

/*
 *	MIME Types List Window GtkCList "unselect_row" signal callback.
 */
static void EDVMimeTypesListWinUnselectRowCB(
	GtkCList *clist, gint row, gint column, GdkEvent *event,
	gpointer data
)
{
	edv_core_struct *core_ptr;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return;

	/* Check which clist this event is for */
	if(GTK_WIDGET(clist) == lw->mimetypes_clist)
	{
	    EDVMimeTypesListWinUpdateDisplay(lw, -1, NULL);
	    EDVMimeTypesListWinUpdateMenus(lw);
	}
}

/*
 *	Find callback.
 */
static void EDVMimeTypesListWinFindCB(
	GtkWidget *widget, gpointer data
)
{
	gint find_itterations = 0;
	gint row, column, sel_row;
	const gchar *find_str;
	GtkEntry *entry;
	GtkCList *clist;

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

	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	entry = (GtkEntry *)lw->find_entry;
	if(entry == NULL)
	    return;

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


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

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

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

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

	} while(find_itterations < 2);

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

/*
 *      Add callback.
 */
static void EDVMimeTypesListWinAddCB(
	GtkWidget *widget, gpointer data
)
{
	gint row, mt_num;
	edv_mimetype_struct *mt_ptr;
	GtkCList *clist;
	edv_core_struct *core_ptr;
	edv_mimetype_editwin_struct *ew;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return;

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

	EDVMimeTypesListWinSetBusy(lw, TRUE);

	/* Get last selected row */
	row = EDVCListGetSelectedLast(clist, NULL);

	/* Get MIME Type number index as the selected row's index */
	mt_num = row;

	/* Create a new MIME Type at the selected position specified by
	 * mt_num relative to the core structure
	 */
	if((mt_num < 0) || (mt_num >= core_ptr->total_mimetypes))
	{
	    /* Append */
	    gint n;

	    /* Sanitize total */
	    if(core_ptr->total_mimetypes < 0)
		core_ptr->total_mimetypes = 0;

	    /* Allocate more pointers */
	    n = core_ptr->total_mimetypes;
	    core_ptr->total_mimetypes = n + 1;
	    core_ptr->mimetype = (edv_mimetype_struct **)g_realloc(
		core_ptr->mimetype,
		core_ptr->total_mimetypes * sizeof(edv_mimetype_struct *)
	    );
	    if(core_ptr->mimetype == NULL)
	    {
		core_ptr->total_mimetypes = 0;
		EDVMimeTypesListWinSetBusy(lw, FALSE);
		return;
	    }

	    mt_num = n;
	}
	else
	{
	    /* Insert */
	    gint i, n;

	    /* Sanitize total */
	    if(core_ptr->total_mimetypes < 0)
		core_ptr->total_mimetypes = 0;

	    /* Allocate more pointers */
	    n = core_ptr->total_mimetypes;
	    core_ptr->total_mimetypes = n + 1;
	    core_ptr->mimetype = (edv_mimetype_struct **)g_realloc(
		core_ptr->mimetype,
		core_ptr->total_mimetypes * sizeof(edv_mimetype_struct *)
	    );
	    if(core_ptr->mimetype == NULL)
	    {
		core_ptr->total_mimetypes = 0;
		EDVMimeTypesListWinSetBusy(lw, FALSE);
		return;
	    }

	    /* Shift pointers */
	    for(i = n; i > mt_num; i--)
		core_ptr->mimetype[i] = core_ptr->mimetype[i - 1];
	}
	/* Create new MIME Type */
	core_ptr->mimetype[mt_num] = mt_ptr = EDVMimeTypeNew(
	    EDV_MIMETYPE_CLASS_FORMAT,
	    NULL,
	    "misc/untitled",
	    "New MIME Type"
	);


	/* Send MIME Type added signal to all of endeavour's resources */
	EDVMimeTypeAddedEmit(core_ptr, mt_num, mt_ptr);

	/* The new MIME Type should be added to our MIME Types list,
	 * now select the new MIME Type
	 */
	gtk_clist_unselect_all(clist);
	gtk_clist_select_row(clist, mt_num, 0);


	/* Map MIME Types edit window, creating it as needed */
	ew = lw->editwin;
	if(ew == NULL)
	    lw->editwin = ew = EDVMimeTypesEditWinNew(
		core_ptr, lw
	    );
	if(ew != NULL)
	{
	    EDVCenterWindowToWindow(lw->toplevel, ew->toplevel);
	    EDVMimeTypesEditWinMap(ew);
	    EDVMimeTypesEditWinFetchValues(ew, mt_num);
	    EDVMimeTypesEditWinResetHasChanges(ew, FALSE);
	}

	EDVMimeTypesListWinUpdateMenus(lw);

	EDVMimeTypesListWinSetBusy(lw, FALSE);
}

/*
 *      MIME Types List Window Edit callback.
 */
static void EDVMimeTypesListWinEditCB(
	GtkWidget *widget, gpointer data
)
{
	gint row, mt_num;
	edv_mimetype_struct *mt_ptr;
	GtkWidget *toplevel;
	GtkCList *clist;
	edv_core_struct *core_ptr;
	edv_mimetype_editwin_struct *ew;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	toplevel = lw->toplevel;
	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return;

	/* Get last selected row */
	row = EDVCListGetSelectedLast(clist, NULL);

	/* Get MIME Type number index as the selected row's index */
	mt_num = row;

	if((mt_num >= 0) && (mt_num < core_ptr->total_mimetypes))
	    mt_ptr = core_ptr->mimetype[mt_num];
	else
	    mt_ptr = NULL;
	if(mt_ptr == NULL)
	    return;

#if 0
	/* Check if this MIME Type is internally created by this program
	 * or loaded from a global configuration
	 */
/* Skip this check, the MIME Types edit window will make the buttons
 * insensitive if this is read only
 */
	if(mt_ptr->read_only)
	{
	    gchar *buf = g_strdup_printf(
"MIME Type \"%s\" cannot be edited, because it\n\
was either created internally or loaded from a global\n\
configuration.",
		mt_ptr->type
	    );
	    EDVPlaySoundWarning(core_ptr);
	    EDVMessageWarning(
		"Edit Failed",
		buf,
		NULL,
		toplevel
	    );
	    g_free(buf);
	    return;
	}
#endif

	EDVMimeTypesListWinSetBusy(lw, TRUE);

	/* Map MIME Types edit window, creating it as needed */
	ew = lw->editwin;
	if(ew == NULL)
	    lw->editwin = ew = EDVMimeTypesEditWinNew(
		core_ptr, lw
	    );
	if(ew != NULL)
	{
	    EDVCenterWindowToWindow(lw->toplevel, ew->toplevel);
	    EDVMimeTypesEditWinMap(ew);
	    EDVMimeTypesEditWinFetchValues(ew, mt_num);
	    EDVMimeTypesEditWinResetHasChanges(ew, FALSE);
	}

	EDVMimeTypesListWinUpdateMenus(lw);

	EDVMimeTypesListWinSetBusy(lw, FALSE);
}

/*
 *      MIME Types List Window remove callback.
 */
static void EDVMimeTypesListWinRemoveCB(
	GtkWidget *widget, gpointer data
)
{
	gint i, mt_num, total;
	edv_mimetype_struct *mt_ptr, **list;
	GList *glist;
	GtkWidget *toplevel;
	GtkCList *clist;
	edv_core_struct *core_ptr;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	toplevel = lw->toplevel;
	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return;

	/* Iterate through selected MIME Types, check if any are
	 * marked as internal which means they cannot be removed
	 */
	glist = clist->selection;
	while(glist != NULL)
	{
	    mt_num = (gint)glist->data;
	    if((mt_num >= 0) && (mt_num < core_ptr->total_mimetypes))
		mt_ptr = core_ptr->mimetype[mt_num];
	    else
		mt_ptr = NULL;
	    if((mt_ptr != NULL) ? mt_ptr->read_only : FALSE)
	    {
		gchar *buf = g_strdup_printf(
"MIME Type `%s' cannot be removed, because it\n\
was either created internally or loaded from a global\n\
configuration.",
		    mt_ptr->type
		);
		EDVPlaySoundWarning(core_ptr);
		EDVMessageWarning(
		    "Remove Failed",
		    buf,
		    NULL,
		    toplevel
		);
		g_free(buf);
		return;
	    }

	    glist = g_list_next(glist);
	}


	/* Generate a list of MIME Type pointers reffering to the
	 * selected MIME Types to be removed. Only the pointer array is
	 * allocated by this function, each pointer in the array is
	 * shared.
	 */
	list = NULL;
	total = 0;
	glist = clist->selection;
	while(glist != NULL)
	{
	    mt_num = (gint)glist->data;
	    if((mt_num >= 0) && (mt_num < core_ptr->total_mimetypes))
		mt_ptr = core_ptr->mimetype[mt_num];
	    else
		mt_ptr = NULL;

	    if(mt_ptr != NULL)
	    {
		i = total;
		total = i + 1;
		list = (edv_mimetype_struct **)g_realloc(
		    list,
		    total * sizeof(edv_mimetype_struct *)
		);
		if(list == NULL)
		    total = 0;
		else
		    list[i] = mt_ptr;
	    }

	    glist = g_list_next(glist);
	}

	/* Nothing to remove? */
	if(total <= 0)
	{
	    g_free(list);
	    list = NULL;
	    total = 0;
	    return;
	}

	/* Get pointer to first selected MIME Type if and only if
	 * exactly one MIME Type is selected
	 */
	mt_num = -1;
	mt_ptr = (total == 1) ? list[0] : NULL;

	/* Confirm removal of MIME Type */
	if(TRUE)
	{
	    gint status;
	    gchar *buf;

	    if((mt_ptr != NULL) ? (mt_ptr->type != NULL) : FALSE)
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"¿Usted está seguro que usted quiere quitar el MIME Type \"%s\"?\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Etes-vous sûr que vous voulez enlever le MIME Type \"%s\"?\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Sind Sie sicher Sie der MIME Type \"%s\" wollen herausnehmen?\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Lei sono sicuro che lei vuole togliere lo MIME Type \"%s\"?\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Bent u zeker u de MIME Type \"%s\" wil verwijderen?\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Estão seguro quer retirar o MIME Type \"%s\"?\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Er De sikker De fjerner MIME Type \"%s\"?\n"
#else
"Are you sure you want to remove the MIME Type \"%s\"?\n"
#endif
		    , mt_ptr->type
		);
	    else
		buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"¿Usted está seguro que usted quiere quitar %i MIME Types?\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Etes-vous sûr que vous voulez enlever %i MIME Types?\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Sind sie sicher sie %i MIME Types wollen herausnehmen?\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Lei sono sicuro che lei vuole togliere %i MIME Types?\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Bent u zeker u %i MIME Types wil verwijderen?\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Estão seguro quer retirar %i MIME Types?\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Er De sikker De fjerner %i MIME Types?\n"
#else
"Are you sure you want to remove the %i selected MIME Types?\n"
#endif
		    , total
		);
	    EDVPlaySoundQuestion(core_ptr);
	    CDialogSetTransientFor(toplevel);
	    status = CDialogGetResponse(
#if defined(PROG_LANGUAGE_SPANISH)
"Confirme Quite"
#elif defined(PROG_LANGUAGE_FRENCH)
"Confirmer Enlever"
#elif defined(PROG_LANGUAGE_GERMAN)
"Bestätigen Sie Herausnimmt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Confermare Togliere"
#elif defined(PROG_LANGUAGE_DUTCH)
"Bevestiig Verwijdert"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Confirme Retira"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Bekreft Fjerner"
#else
"Confirm Remove"
#endif
		, buf, NULL,
		CDIALOG_ICON_QUESTION,
		CDIALOG_BTNFLAG_YES | CDIALOG_BTNFLAG_NO,
		CDIALOG_BTNFLAG_NO
	    );
	    CDialogSetTransientFor(NULL);

	    g_free(buf);

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

	      default:
		g_free(list);
		list = NULL;
		total = 0;
		return;
		break;
	    }
	}


	EDVMimeTypesListWinSetBusy(lw, TRUE);


	/* Begin removing selected MIME Types */
	for(i = 0; i < total; i++)
	{
	    mt_ptr = list[i];
	    if(mt_ptr == NULL)
		continue;

	    /* Get MIME Type number index from the selected MIME Type
	     * pointer
	     */
	    for(mt_num = 0; mt_num < core_ptr->total_mimetypes; mt_num++)
	    {
		if(core_ptr->mimetype[mt_num] == mt_ptr)
		    break;
	    }
	    /* MIME Type pointer is not in the core structure's list of
	     * MIME Types?
	     */
	    if(mt_num >= core_ptr->total_mimetypes)
		continue;


	    /* Delete MIME Type from the core structure's list of MIME
	     * Types
	     */
	    EDVMimeTypeDelete(core_ptr->mimetype[mt_num]);
	    core_ptr->mimetype[mt_num] = NULL;

	    /* Value of MIME Type number index and pointer should now be
	     * considered invalid, however we will not reset them as they
	     * need to be used to emit the MIME Type removed signal
	     * further below
	     */

	    /* Reduce total */
	    core_ptr->total_mimetypes--;
	    if(core_ptr->total_mimetypes < 0)
		core_ptr->total_mimetypes = 0;

	    /* Shift pointers and reallocate if there are still other
	     * MIME Types?
	     */
	    if(core_ptr->total_mimetypes > 0)
	    {
		gint n;

		for(n = mt_num; n < core_ptr->total_mimetypes; n++)
		    core_ptr->mimetype[n] = core_ptr->mimetype[n + 1];

		core_ptr->mimetype = (edv_mimetype_struct **)g_realloc(
		    core_ptr->mimetype,
		    core_ptr->total_mimetypes * sizeof(edv_mimetype_struct *)
		);
		if(core_ptr->mimetype == NULL)
		{
		    core_ptr->total_mimetypes = 0;
		}
	    }
	    else
	    {
		g_free(core_ptr->mimetype);
		core_ptr->mimetype = NULL;
	    }

	    /* Send MIME Type removed signal to all of endeavour's
	     * resources.
	     */
	    EDVMimeTypeRemovedEmit(core_ptr, mt_num);
	}


	EDVMimeTypesListWinSetBusy(lw, FALSE);


	/* Deallocate pointer array to selected MIME Types but not each
	 * pointer since they are shared and probably invalid after the
	 * removal of each pointer
	 */
	g_free(list);
	list = NULL;
	total = 0;
}

/*
 *      MIME Types List Window Shift Up callback.
 */
static void EDVMimeTypesListWinShiftUpCB(
	GtkWidget *widget, gpointer data
)
{
	gint row;
	GtkCList *clist;
	edv_core_struct *core_ptr;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return;

	EDVMimeTypesListWinSetBusy(lw, TRUE);

	/* Get last selected row */
	row = EDVCListGetSelectedLast(clist, NULL);

	/* Can shift selected row up? */
	if(row > 0)
	{
	    edv_mimetype_struct *tmp_mt_ptr;

	    /* Shift clist rows */
	    gtk_clist_freeze(clist);
	    gtk_clist_swap_rows(clist, row, row - 1);
	    gtk_clist_thaw(clist);

	    /* Shift MIME Type pointers */
	    tmp_mt_ptr = core_ptr->mimetype[row - 1];
	    core_ptr->mimetype[row - 1] = core_ptr->mimetype[row];
	    core_ptr->mimetype[row] = tmp_mt_ptr;

	    /* Emit MIME Type modified signal for both MIME Types
	     * involved in the shift
	     */
	    EDVMimeTypeModifiedEmit(
		core_ptr,
		row - 1,
		core_ptr->mimetype[row - 1]
	    );
	    EDVMimeTypeModifiedEmit(
		core_ptr,
		row,
		core_ptr->mimetype[row]
	    );

	    EDVMimeTypesListWinUpdateMenus(lw);
	}

	EDVMimeTypesListWinSetBusy(lw, FALSE);
}

/*
 *      MIME Types List Window Shift Down callback.
 */
static void EDVMimeTypesListWinShiftDownCB(
	GtkWidget *widget, gpointer data
)
{
	gint row;
	GtkCList *clist;
	edv_core_struct *core_ptr;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return;

	EDVMimeTypesListWinSetBusy(lw, TRUE);

	/* Get last selected row */
	row = EDVCListGetSelectedLast(clist, NULL);

	/* Can shift selected row down? */
	if((row > -1) && (row < (clist->rows - 1)))
	{
	    edv_mimetype_struct *tmp_mt_ptr;

	    /* Shift clist rows */
	    gtk_clist_freeze(clist);
	    gtk_clist_swap_rows(clist, row, row + 1);
	    gtk_clist_thaw(clist);

	    /* Shift MIME Type pointers */
	    tmp_mt_ptr = core_ptr->mimetype[row + 1];
	    core_ptr->mimetype[row + 1] = core_ptr->mimetype[row];
	    core_ptr->mimetype[row] = tmp_mt_ptr;

	    /* Emit MIME Type modified signal for both MIME Types
	     * involved in the shift
	     */
	    EDVMimeTypeModifiedEmit(
		core_ptr,
		row + 1,
		core_ptr->mimetype[row + 1]
	    );
	    EDVMimeTypeModifiedEmit(
		core_ptr,
		row,
		core_ptr->mimetype[row]
	    );

	    EDVMimeTypesListWinUpdateMenus(lw);
	}

	EDVMimeTypesListWinSetBusy(lw, FALSE);
}


/*
 *	MIME Types List Window Save callback.
 */
static void EDVMimeTypesListWinSaveCB(
	GtkWidget *widget, gpointer data
)
{
	const gchar *s;
	GtkWidget *toplevel;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core_ptr;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	toplevel = lw->toplevel;
	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return;

	cfg_list = core_ptr->cfg_list;

	EDVMimeTypesListWinSetBusy(lw, TRUE);


	/* Get MIME Types file path */
	s = EDV_GET_S(EDV_CFG_PARM_FILE_MIME_TYPES);
	if(!STRISEMPTY(s))
	{
	    gboolean object_existed;
	    gchar *buf, *path = STRDUP(s);
	    struct stat stat_buf;

	    /* Map progress dialog */
	    buf = g_strdup_printf(
"Saving MIME Types to file:\n\
\n\
    %s\n",
		path
	    );
	    ProgressDialogSetTransientFor(toplevel);
	    ProgressDialogMap(
		"Saving MIME Types",
		buf,
		(const guint8 **)icon_save_32x32_xpm,
		"Stop"
	    );
	    g_free(buf);

	    /* MIME Types file already exists? */
	    object_existed = (!stat(path, &stat_buf)) ? TRUE : FALSE;

	    /* Save MIME Types */
	    EDVMimeTypeListSaveToFile(
		path,
		core_ptr->mimetype, core_ptr->total_mimetypes,
		FALSE,		/* Do not include read only MIME Types */
		EDVMimeTypesListProgressCB, lw
	    );

	    /* MIME Types file saved? */
	    if(!stat(path, &stat_buf))
	    {
		if(object_existed)
		    EDVObjectModifiedEmit(core_ptr, path, NULL, &stat_buf);
		else
		    EDVObjectAddedEmit(core_ptr, path, &stat_buf);
	    }

	    g_free(path);
	}

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

	EDVMimeTypesListWinUpdateMenus(lw);

	EDVMimeTypesListWinSetBusy(lw, FALSE);
}

/*
 *      MIME Types List Window Import callback.
 */
static void EDVMimeTypesListWinImportCB(
	GtkWidget *widget, gpointer data
)
{
	gboolean status;
	gint mt_num;
	fb_type_struct **ftype = NULL, *ftype_rtn = NULL;
	gint total_ftypes = 0;
	gchar **path_rtn = NULL;
	gint total_path_rtns = 0;
	GtkWidget *toplevel;
	edv_core_struct *core_ptr;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return;

	/* Get selected MIME Type index number that corresponds to the
	 * last selected row index number on the MIME Types clist
	 */
	mt_num = EDVCListGetSelectedLast(
	    (GtkCList *)lw->mimetypes_clist, NULL
	);

	toplevel = lw->toplevel;

	EDVMimeTypesListWinSetBusy(lw, TRUE);

	/* Create file types list */
	FileBrowserTypeListNew(
	    &ftype, &total_ftypes,
	    "*mailcap",
	    EDV_MIMETYPES_FORMAT_DESC_MAILCAP
	);
	FileBrowserTypeListNew(
	    &ftype, &total_ftypes,
	    "*media.types *mime.types",
	    EDV_MIMETYPES_FORMAT_DESC_MEDIA_TYPES
	);
	FileBrowserTypeListNew(
	    &ftype, &total_ftypes,
	    ".ini",
	    EDV_MIMETYPES_FORMAT_DESC_ENDEAVOUR
	);

	/* Query user for MIME Types file */
	FileBrowserSetTransientFor(toplevel);
	status = FileBrowserGetResponse(
	    "Import MIME Types",
	    "Import", "Cancel",
	    NULL,		/* Use last path */
	    ftype, total_ftypes,
	    &path_rtn, &total_path_rtns,
	    &ftype_rtn
	);
	FileBrowserSetTransientFor(NULL);

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

	    if(!STRISEMPTY(new_path) && !STRISEMPTY(ftype_name))
	    {
#define MAP_PROGRESS	{			\
 gchar *buf = g_strdup_printf(			\
"Importing MIME Types from file:\n\
\n\
    %s\n",					\
  new_path					\
 );						\
 ProgressDialogSetTransientFor(toplevel);	\
 ProgressDialogMap(				\
  "Importing MIME Types", buf,			\
  (const guint8 **)icon_import_32x32_xpm,	\
  "Stop"					\
 );						\
 g_free(buf);					\
}

		/* Begin importing MIME Types based on selected file
		 * type
		 */
		/* Mailcap */
		if(!g_strcasecmp(ftype_name, EDV_MIMETYPES_FORMAT_DESC_MAILCAP))
		{
		    gboolean update, only_newer;
		    if(EDVMimeTypesMailcapImportOptsGetResponse(
			core_ptr, toplevel, new_path,
			&update, &only_newer
		    ))
		    {
			MAP_PROGRESS
			EDVMimeTypeListMailcapImport(
			    new_path,
			    &core_ptr->mimetype, &core_ptr->total_mimetypes,
			    mt_num,		/* Insert index */
			    update, only_newer,
			    EDVMimeTypesListProgressCB, lw,
			    (gpointer)EDVMimeTypeAddedEmit, core_ptr,
			    (gpointer)EDVMimeTypeModifiedEmit, core_ptr
			);
			EDVPlaySoundCompleted(core_ptr);
		    }
		}
		/* Media Types */
		else if(!g_strcasecmp(ftype_name, EDV_MIMETYPES_FORMAT_DESC_MEDIA_TYPES))
		{
		    gboolean update, only_newer;
		    if(EDVMimeTypesMediaTypesImportOptsGetResponse(
			core_ptr, toplevel, new_path,
			&update, &only_newer
		    ))
		    {
			MAP_PROGRESS
 			EDVMimeTypeListMediaTypesImport(
			    new_path,
			    &core_ptr->mimetype, &core_ptr->total_mimetypes,
			    mt_num,		/* Insert index */
			    update, only_newer,
			    EDVMimeTypesListProgressCB, lw,
			    (gpointer)EDVMimeTypeAddedEmit, core_ptr,
			    (gpointer)EDVMimeTypeModifiedEmit, core_ptr
		        );
			EDVPlaySoundCompleted(core_ptr);
		    }
		}
		/* Endeavour */
		else if(!g_strcasecmp(ftype_name, EDV_MIMETYPES_FORMAT_DESC_ENDEAVOUR))
		{
		    if(EDVMimeTypesEndeavourImportOptsGetResponse(
			core_ptr, toplevel, new_path
		    ))
		    {
			MAP_PROGRESS
			EDVMimeTypeListLoadFromFile(
			    new_path,
			    &core_ptr->mimetype, &core_ptr->total_mimetypes,
			    mt_num,		/* Insert index */
			    FALSE, FALSE,
			    EDVMimeTypesListProgressCB, lw,
			    (gpointer)EDVMimeTypeAddedEmit, core_ptr,
			    FALSE
		        );
			EDVPlaySoundCompleted(core_ptr);
		    }
		}
	    }
	}	/* Got user response? */

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

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

	EDVMimeTypesListWinUpdateMenus(lw);

	EDVMimeTypesListWinSetBusy(lw, FALSE);   
}

/*
 *      MIME Types List Window Export callback.
 */
static void EDVMimeTypesListWinExportCB(
	GtkWidget *widget, gpointer data
)
{
	gboolean status;
	edv_mimetype_struct **list, *mt_ptr;
	gint i, mt_num, total;
	fb_type_struct **ftype = NULL, *ftype_rtn = NULL;
	gint total_ftypes = 0;
	gchar **path_rtn = NULL;
	gint total_path_rtns = 0;
	GList *glist;
	GtkWidget *toplevel;
	GtkCList *clist;
	edv_core_struct *core_ptr;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return;

	/* Generate a list of pointers to MIME Types that are selected,
	 * these are the MIME Types that are to be exported
	 */
	glist = clist->selection;
	list = NULL;
	total = 0;
	while(glist != NULL)
	{
	    mt_num = (gint)glist->data;
	    if((mt_num >= 0) && (mt_num < core_ptr->total_mimetypes))
		mt_ptr = core_ptr->mimetype[mt_num];
	    else
		mt_ptr = NULL;
	    if(mt_ptr != NULL)
	    {
		i = total;
		total = i + 1;

		list = (edv_mimetype_struct **)g_realloc(
		    list, total * sizeof(edv_mimetype_struct *)
		);
		if(list == NULL)
		{
		    total = 0;
		    break;
		}

		list[i] = mt_ptr;
	    }

	    glist = g_list_next(glist);
	}
	/* No MIME Types selected? */
	if(total <= 0)
	{
	    g_free(list);
	    list = 0;
	    total = 0;
	    return;
	}


	toplevel = lw->toplevel;

	EDVMimeTypesListWinSetBusy(lw, TRUE);

	/* Create file types list */
	FileBrowserTypeListNew(
	    &ftype, &total_ftypes,
	    "*mailcap",
	    EDV_MIMETYPES_FORMAT_DESC_MAILCAP
	);
	FileBrowserTypeListNew(
	    &ftype, &total_ftypes,
	    "*media.types *mime.types",
	    EDV_MIMETYPES_FORMAT_DESC_MEDIA_TYPES
	);
	FileBrowserTypeListNew(
	    &ftype, &total_ftypes,
	    ".ini",
	    EDV_MIMETYPES_FORMAT_DESC_ENDEAVOUR
	);


	/* Query user for MIME Types file */
	FileBrowserSetTransientFor(toplevel);
	status = FileBrowserGetResponse(
	    "Export MIME Types",
	    "Export", "Cancel",
	    NULL,		/* Use last path */
	    ftype, total_ftypes,
	    &path_rtn, &total_path_rtns,
	    &ftype_rtn
	);
	FileBrowserSetTransientFor(NULL);

	/* Got user response? */
	if(status)
	{
	    const gchar *new_path = (total_path_rtns > 0) ?
		path_rtn[0] : NULL;
	    const gchar *ftype_name = (ftype_rtn != NULL) ?
		ftype_rtn->name : NULL;
	    if(!STRISEMPTY(new_path) && !STRISEMPTY(ftype_name))
	    {
		gboolean object_existed = FALSE;
		gint response = CDIALOG_RESPONSE_YES;
		gchar *buf;
		struct stat stat_buf;

		/* File already exists? */
		if(!stat(new_path, &stat_buf))
		{
		    gchar *buf = g_strdup_printf(
"Overwrite existing file:\n\
\n\
    %s\n",
			new_path
		    );
		    EDVPlaySoundWarning(core_ptr);
		    CDialogSetTransientFor(toplevel);
		    response = CDialogGetResponse(
			"Confirm Overwrite",
			buf,
			NULL,
			CDIALOG_ICON_WARNING,
			CDIALOG_BTNFLAG_YES | CDIALOG_BTNFLAG_NO,
			CDIALOG_BTNFLAG_NO
		    );
		    CDialogSetTransientFor(NULL);
		    g_free(buf);

		    object_existed = TRUE;
		}
		if(response == CDIALOG_RESPONSE_YES)
		{
		    /* Map progress dialog */
		    buf = g_strdup_printf(
"Exporting MIME Types to file:\n\
\n\
    %s\n",
			new_path
		    );
		    ProgressDialogSetTransientFor(toplevel);
		    ProgressDialogMap(
			"Exporting MIME Types",
			buf,
			(const guint8 **)icon_export_32x32_xpm,
			"Stop"
		    );
		    g_free(buf);

		    /* Export the MIME Types based on the selected file
		     * type
		     */
		    /* Mailcap */
		    if(!g_strcasecmp(ftype_name, EDV_MIMETYPES_FORMAT_DESC_MAILCAP))
		    {
			EDVMimeTypeListMailcapExport(
			    new_path,
			    list, total,
			    TRUE,	/* Include read_only MIME Types */
			    EDVMimeTypesListProgressCB, lw
			);
		    }
		    /* Media Types */
		    else if(!g_strcasecmp(ftype_name, EDV_MIMETYPES_FORMAT_DESC_MEDIA_TYPES))
		    {
		        EDVMimeTypeListMediaTypesExport(
			    new_path,
			    list, total,
			    TRUE,	/* Include read_only MIME Types */
			    EDVMimeTypesListProgressCB, lw
			);
		    }
		    /* Endeavour */
		    else if(!g_strcasecmp(ftype_name, EDV_MIMETYPES_FORMAT_DESC_ENDEAVOUR))
		    {
		        EDVMimeTypeListSaveToFile(
			    new_path,
			    list, total,
			    TRUE,	/* Include read_only MIME Types */
			    EDVMimeTypesListProgressCB, lw
			);
		    }
		    EDVPlaySoundCompleted(core_ptr);

		    /* Notify object added or modified */
		    if(!stat(new_path, &stat_buf))
		    {
			if(object_existed)
			    EDVObjectModifiedEmit(
				core_ptr, new_path, new_path, &stat_buf
			    );
			else
			    EDVObjectAddedEmit(
				core_ptr, new_path, &stat_buf
			    );
		    }
		}
	    }
	}       /* Got user response? */

	/* Delete file types list and reset file browser */
	FileBrowserDeleteTypeList(ftype, total_ftypes);
	FileBrowserReset();

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

	EDVMimeTypesListWinUpdateMenus(lw);

	/* Delete list of MIME Types to be exported but not each
	 * pointer in the list since they are shared
	 */
	g_free(list);

	EDVMimeTypesListWinSetBusy(lw, FALSE);
}


/*
 *	MIME Types List Window Close callback.
 */
static void EDVMimeTypesListWinCloseCB(
	GtkWidget *widget, gpointer data
)
{
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(data);
	if(lw == NULL)
	    return;

	EDVMimeTypesListWinUnmap(lw);
}


/*
 *	Selects the MIME Types List Window's MIME Type at index i.
 */
void EDVMimeTypesListWinSelect(
	edv_mimetype_listwin_struct *lw, gint i
)
{
	GtkCList *clist = (GtkCList *)((lw != NULL) ?
	    lw->mimetypes_clist : NULL
	);
	if(clist == NULL)
	    return;

	if((i >= 0) && (i < clist->rows))
	{
	    gtk_clist_unselect_all(clist);
	    gtk_clist_select_row(clist, i, 0);
	}
}

/*
 *	Selects the MIME Types List Window's MIME Type who's type
 *	matches the given type.
 *
 *	Returns the index of the matched MIME Type of -1 on failed
 *	match.
 */
gint EDVMimeTypesListWinSelectByType(
	edv_mimetype_listwin_struct *lw, const gchar *type
)
{
	gint i;
	const edv_mimetype_struct *mt_ptr;
	edv_core_struct *core_ptr;
	if((lw == NULL) || STRISEMPTY(type))
	    return(-1);

	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return(-1);

	/* Iterate through MIME Types */
	for(i = 0; i < core_ptr->total_mimetypes; i++)
	{
	    mt_ptr = core_ptr->mimetype[i];
	    if(mt_ptr == NULL)
		continue;

	    if(STRISEMPTY(mt_ptr->type))
		continue;

	    /* Type strings match? */
	    if(!g_strcasecmp(mt_ptr->type, type))
	    {
		EDVMimeTypesListWinSelect(lw, i);
		return(i);
	    }
	}

	return(-1);
}


/*
 *	Updates the MIME Types List Window's displayed MIME Type.
 *
 *	This will destroy the display_client widget and create a
 *	new one if mt_ptr is not NULL.
 */
static void EDVMimeTypesListWinUpdateDisplay(
	edv_mimetype_listwin_struct *lw,
	gint mt_num, edv_mimetype_struct *mt_ptr
)
{
	const gint	border_major = 5,
			border_minor = 2;
	edv_date_relativity date_relativity;
	const gchar *date_format;
	GtkRcStyle *rcstyle, *standard_rcstyle;
	GtkWidget *w, *parent, *parent2, *parent3, *parent4;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core_ptr;

	if(lw == NULL)
	    return;

	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return;

	cfg_list = core_ptr->cfg_list;
	standard_rcstyle = core_ptr->standard_rcstyle;

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

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

	/* Do not continue updating if the specified MIME Type is NULL */
	if(mt_ptr == NULL)
	    return;

	/* Get configuration */
	date_relativity = (edv_date_relativity)EDV_GET_I(
	    EDV_CFG_PARM_DATE_RELATIVITY
	);
	date_format = EDV_GET_S(EDV_CFG_PARM_DATE_FORMAT);


	/* Realize MIME Type as needed */
	EDVMimeTypeRealize(mt_ptr, FALSE);

	/* Create new client hbox for multiple columns */
	lw->display_client = w = gtk_hbox_new(FALSE, border_major);
	gtk_container_border_width(GTK_CONTAINER(w), border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent = w;

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

	if(TRUE)
	{
	    GdkBitmap *mask = NULL;
	    GdkPixmap *pixmap = NULL;
	    const gchar *class_str = NULL;
	    gboolean has_handler = FALSE;
	    gchar *s, *s2;

	    /* Hbox for class heading label and handler/command */
	    w = gtk_hbox_new(FALSE, border_minor);
	    gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent3 = w;

	    /* Get class heading icon and label */
	    switch(mt_ptr->mt_class)
	    {
	      case EDV_MIMETYPE_CLASS_SYSTEM:
		mask = lw->system_object_mask;
		pixmap = lw->system_object_pixmap;
		class_str =
#if defined(PROG_LANGUAGE_SPANISH)
"El Tipo Del Objeto Del Sistema"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le Type D'Objet De Système"
#else
"System Object Type"
#endif
		;
		break;

	      case EDV_MIMETYPE_CLASS_FORMAT:
		mask = lw->file_format_mask;
		pixmap = lw->file_format_pixmap;
		class_str =
#if defined(PROG_LANGUAGE_SPANISH)
"Archive Formato"
#elif defined(PROG_LANGUAGE_FRENCH)
"Classer Le Format"
#else
"File Format"
#endif
		;
		has_handler = TRUE;
		break;

	      case EDV_MIMETYPE_CLASS_PROGRAM:
		mask = lw->program_mask;
		pixmap = lw->program_pixmap;
		class_str =
#if defined(PROG_LANGUAGE_SPANISH)
"La Aplicación"
#elif defined(PROG_LANGUAGE_FRENCH)
"Application"
#else
"Application"
#endif
		;
		has_handler = TRUE;
		break;

	      case EDV_MIMETYPE_CLASS_UNIQUE:
		mask = lw->unique_object_mask;
		pixmap = lw->unique_object_pixmap;
		class_str =
#if defined(PROG_LANGUAGE_SPANISH)
"El Objeto"
#elif defined(PROG_LANGUAGE_FRENCH)
"Objet"
#else
"Object"
#endif
		;
		has_handler = TRUE;
		break;
	    }
	    /* Class heading icon */
	    if(pixmap != NULL)
	    {
		w = gtk_pixmap_new(pixmap, mask);
		gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
		gtk_widget_show(w);
	    }
	    /* Class heading label */
	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-14-*-*-*-*-*-iso8859-1"
	    );
	    w = gtk_label_new(
		(class_str != NULL) ? class_str :
#if defined(PROG_LANGUAGE_SPANISH)
"*La Clase No Apoyada*"
#elif defined(PROG_LANGUAGE_FRENCH)
"*Classe Non Soutenue*"
#else
"*Unsupported Class*"
#endif
	    );
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)


	    /* Handler/command label, determine by handler */
	    switch(mt_ptr->handler)
	    {
	      case EDV_MIMETYPE_HANDLER_COMMAND:
		if((mt_ptr->total_commands > 0) && has_handler)
		{
		    if(mt_ptr->mt_class == EDV_MIMETYPE_CLASS_PROGRAM)
		    {
			s = s2 = NULL;
		    }
		    else
		    {
			const gchar *name;
		        gint	i,
				total = mt_ptr->total_commands,
				len = 80;

			s = g_strdup_printf(
			    "Command%s: ",
			    (total == 1) ? "" : "s"
			);
			
		        for(i = 0; i < total; i++)
			    len += STRLEN(mt_ptr->command_name[i]) + 1;
			s2 = (gchar *)g_malloc(len * sizeof(gchar));
		        *s2 = '\0';
		        for(i = 0; i < total; i++)
		        {
			    name = mt_ptr->command_name[i];
			    if(name == NULL)
			        continue;

			    strcat(s2, name);
			    if(i < (total - 1))
			        strcat(s2, " ");
			}
		    }
		}
		else
		{
		    s = s2 = NULL;
		}
		break;

	      case EDV_MIMETYPE_HANDLER_EDV_ARCHIVER:
		if(has_handler)
		{
		    s = STRDUP("Handled By: ");
		    s2 = STRDUP("Archiver");
		}
		else
		{
		    s = s2 = NULL;
		}
		break;

	      case EDV_MIMETYPE_HANDLER_EDV_IMAGE_BROWSER:
		if(has_handler)
		{
		    s = STRDUP("Handled By: ");
		    s2 = STRDUP("Image Browser");
		}
		else
		{
		    s = s2 = NULL;
		}
		break;


	      case EDV_MIMETYPE_HANDLER_EDV_RECYCLE_BIN:
		if(has_handler)
		{
		    s = STRDUP("Handled By: ");
		    s2 = STRDUP("Recycle Bin");
		}
		else
		{
		    s = s2 = NULL;
		}
		break;

	      default:
		s = s2 = NULL;
		break;
	    }
	    if(s != NULL)
	    {
		rcstyle = gtk_rc_style_new();
		rcstyle->font_name = STRDUP(
"-adobe-helvetica-bold-r-normal-*-12-*-*-*-*-*-iso8859-1"
		);
		w = gtk_label_new(s2);
		gtk_label_set_justify(GTK_LABEL(w), GTK_JUSTIFY_RIGHT);
		gtk_box_pack_end(GTK_BOX(parent3), w, FALSE, FALSE, 0);
		gtk_widget_modify_style(w, rcstyle);
		gtk_widget_show(w);
		GTK_RC_STYLE_UNREF(rcstyle)

		rcstyle = gtk_rc_style_new();
		rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
		);
		w = gtk_label_new(s);
		gtk_box_pack_end(GTK_BOX(parent3), w, FALSE, FALSE, 0);
		gtk_widget_modify_style(w, rcstyle);
		gtk_widget_show(w);
		GTK_RC_STYLE_UNREF(rcstyle)
	    }
	    g_free(s);
	    g_free(s2);
	}


	/* HBox for icon and type line */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;

	/* Create icon? */
	if(TRUE)
	{
	    GdkPixmap *pixmap;
	    GdkBitmap *mask;
#if 0
	    /* First try to get large sized pixmap, use standard state
	     * always.
	     */
	    pixmap = mt_ptr->large_pixmap[EDV_MIMETYPE_ICON_STATE_STANDARD];
	    mask = mt_ptr->large_mask[EDV_MIMETYPE_ICON_STATE_STANDARD];
	    /* No large? Then try medium */
	    if(pixmap == NULL)
#endif
	    if(TRUE)
	    {
		pixmap = mt_ptr->medium_pixmap[EDV_MIMETYPE_ICON_STATE_STANDARD];
		mask = mt_ptr->medium_mask[EDV_MIMETYPE_ICON_STATE_STANDARD];
	    }
	    /* No medium? Then try small */
	    if(pixmap == NULL)
	    {
		pixmap = mt_ptr->small_pixmap[EDV_MIMETYPE_ICON_STATE_STANDARD];
		mask = mt_ptr->small_mask[EDV_MIMETYPE_ICON_STATE_STANDARD];
	    }

	    /* Got pixmap and mask pair? */
	    if(pixmap != NULL)
	    {
		lw->display_icon = w = gtk_pixmap_new(pixmap, mask);
		gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
		gtk_widget_show(w);
	    }
	}
	/* Type label */
	rcstyle = gtk_rc_style_new();
	rcstyle->font_name = STRDUP(
"-adobe-helvetica-bold-r-normal-*-14-*-*-*-*-*-iso8859-1"
	);
	w = gtk_label_new(
	    (mt_ptr->type != NULL) ? mt_ptr->type : "(null)"
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_modify_style(w, rcstyle);
	gtk_widget_show(w);
	GTK_RC_STYLE_UNREF(rcstyle)

	/* Edit button */
	w = gtk_vbox_new(TRUE, 0);
	gtk_box_pack_end(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	lw->display_edit_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_edit_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Redacte"
#elif defined(PROG_LANGUAGE_FRENCH)
"Editer"
#elif defined(PROG_LANGUAGE_GERMAN)
"Redigieren"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Redigere"
#elif defined(PROG_LANGUAGE_DUTCH)
"Bewerking"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Edite"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Rediger"
#else
"Edit"
#endif
	    "...", NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinEditCB), lw
	);
	if(standard_rcstyle != NULL)
	    gtk_widget_modify_style_recursive(w, standard_rcstyle);
	gtk_widget_show(w);

	/* Value available? */
	if(!STRISEMPTY(mt_ptr->value))
	{
	    const gchar	*value_label = "",
			*value = mt_ptr->value;

	    /* HBox for value line */
	    w = gtk_hbox_new(FALSE, border_major);
	    gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent3 = w;

	    /* Value label */
	    switch(mt_ptr->mt_class)
	    {
	      case EDV_MIMETYPE_CLASS_SYSTEM:
		break;
	      case EDV_MIMETYPE_CLASS_FORMAT:
		value_label = (strchr(value, ' ') != NULL) ?
		    "Extensions: " : "Extension: ";
		break;
	      case EDV_MIMETYPE_CLASS_PROGRAM:
		value_label = "Location: ";
		break;
	      case EDV_MIMETYPE_CLASS_UNIQUE:
		value_label = "Location: ";
		break;
	    }
	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	    );
	    w = gtk_label_new(value_label);
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)

	    /* Value */
	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-courier-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	    );
	    w = gtk_label_new(value);
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    GTK_RC_STYLE_UNREF(rcstyle)
	}

	/* Description available? */
	if(!STRISEMPTY(mt_ptr->description))
	{
	    /* HBox for description line */
	    w = gtk_hbox_new(FALSE, border_major);
	    gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent3 = w;

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

	/* Last modified */
	if(!mt_ptr->read_only)
	{
	    w = gtk_hbox_new(FALSE, border_major);
	    gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	    gtk_widget_show(w);
	    parent3 = w;

	    rcstyle = gtk_rc_style_new();
	    rcstyle->font_name = STRDUP(
"-adobe-helvetica-medium-r-normal-*-12-*-*-*-*-*-iso8859-1"
	    );
	    /* Prefix */
	    w = gtk_label_new(
"Last Modified:"
	    );
	    gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	    gtk_widget_modify_style(w, rcstyle);
	    gtk_widget_show(w);
	    /* Modified Date */
	    if(mt_ptr->modify_time > 0)
	    {
	        w = gtk_label_new(
		    EDVDateFormatString(
		        mt_ptr->modify_time,
		        date_format, date_relativity
		    )
	        );
	        gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	        gtk_widget_modify_style(w, rcstyle);
	        gtk_widget_show(w);
	    }

	    GTK_RC_STYLE_UNREF(rcstyle)
	}


}


/*
 *	Sets the MIME Types List Window's MIME Types clist row to the
 *	values specified by the given MIME Type.
 */
void EDVMimeTypesListWinSetRow(
	edv_mimetype_listwin_struct *lw,
	gint row, edv_mimetype_struct *mt_ptr
)
{
	gint mt_class;
	GtkCList *clist;
	edv_core_struct *core_ptr;

	const gchar *type = NULL, *value = NULL;
	GdkPixmap *pixmap = NULL, *class_pixmap = NULL;
	GdkBitmap *mask = NULL, *class_mask = NULL;


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

	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return;

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

	/* Realize MIME Type structure so we can have use of its
	 * icon pixmap and mask pairs.
	 */
	EDVMimeTypeRealize(mt_ptr, FALSE);

	/* Get MIME Type class */
	mt_class = mt_ptr->mt_class;

	/* Get values based on MIME Type class */
	switch(mt_class)
	{
	  case EDV_MIMETYPE_CLASS_SYSTEM:
	    type = mt_ptr->type;
	    value = "";
	    pixmap = mt_ptr->small_pixmap[
		EDV_MIMETYPE_ICON_STATE_STANDARD
	    ];
	    mask = mt_ptr->small_mask[
		EDV_MIMETYPE_ICON_STATE_STANDARD
	    ];
	    class_pixmap = lw->system_object_pixmap;            
	    class_mask = lw->system_object_mask;
	    break;

	  case EDV_MIMETYPE_CLASS_FORMAT:
	    type = mt_ptr->type;
	    value = mt_ptr->value;
	    pixmap = mt_ptr->small_pixmap[
		EDV_MIMETYPE_ICON_STATE_STANDARD
	    ];
	    mask = mt_ptr->small_mask[
		EDV_MIMETYPE_ICON_STATE_STANDARD
	    ];
	    class_pixmap = lw->file_format_pixmap;
	    class_mask = lw->file_format_mask;
	    break;

	  case EDV_MIMETYPE_CLASS_PROGRAM:
	    type = mt_ptr->type;
	    value = mt_ptr->value;
	    pixmap = mt_ptr->small_pixmap[
		EDV_MIMETYPE_ICON_STATE_STANDARD
	    ];
	    mask = mt_ptr->small_mask[
		EDV_MIMETYPE_ICON_STATE_STANDARD
	    ];
	    class_pixmap = lw->program_pixmap;
	    class_mask = lw->program_mask;
	    break;

	  case EDV_MIMETYPE_CLASS_UNIQUE:
	    type = mt_ptr->type;
	    value = mt_ptr->value;
	    pixmap = mt_ptr->small_pixmap[
		EDV_MIMETYPE_ICON_STATE_STANDARD
	    ];
	    mask = mt_ptr->small_mask[
		EDV_MIMETYPE_ICON_STATE_STANDARD
	    ];
	    class_pixmap = lw->unique_object_pixmap;
	    class_mask = lw->unique_object_mask;
	    break;
	}


	/* Given row index in bounds? */
	if((row >= 0) && (row < clist->rows))
	{
	    /* Set column 0 as MIME Type type */
	    if((type != NULL) && (clist->columns > 0))
	    {
		if(pixmap != NULL)
		    gtk_clist_set_pixtext(
			clist, row, 0,
			type,
			EDV_LIST_PIXMAP_TEXT_SPACING,
			pixmap, mask
		    );
		else
		    gtk_clist_set_text(
			clist, row, 0,
			type
		    );
	    }
	    /* Set column 1 as MIME Type value */
	    if((value != NULL) && (clist->columns > 1))
	    {
		gtk_clist_set_text(
		    clist, row, 1,
		    value
		);
	    }
	    /* Set column 2 as MIME Type class icon */
	    if((class_pixmap != NULL) && (clist->columns > 2))
	    {
		gtk_clist_set_pixmap(
		    clist, row, 2,
		    class_pixmap, class_mask
		);
	    }

	}
}

/*
 *	Regets the MIME Types List Window's list of MIME Types from the
 *	core structure.
 */
void EDVMimeTypesListWinFetchValues(edv_mimetype_listwin_struct *lw)
{
	gint i, row;
	gchar **strv;
	GtkCList *clist;
	edv_core_struct *core_ptr;
	edv_mimetype_struct *mt_ptr;


	if(lw == NULL)
	    return;

	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return;

	if(clist->columns < 1)
	    return;

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


	/* Begin updating MIME Types clist */

	gtk_clist_freeze(clist);

	/* Remove existing rows on clist and clear display */
	gtk_clist_clear(clist);
	EDVMimeTypesListWinUpdateDisplay(lw, -1, NULL);

	/* Iterate through all MIME Types on the core structure */
	for(i = 0; i < core_ptr->total_mimetypes; i++)
	{
	    mt_ptr = core_ptr->mimetype[i];
	    if(mt_ptr == NULL)
		continue;

	    /* Append a new row and set the new row's values */
	    row = gtk_clist_append(clist, strv);
	    if(row < 0)
		break;

	    EDVMimeTypesListWinSetRow(lw, row, mt_ptr);
	}

	gtk_clist_thaw(clist);

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

	EDVMimeTypesListWinUpdateMenus(lw);
}


/*
 *	Reconfigured notify callback.
 */
void EDVMimeTypesListWinReconfiguredNotifyCB(
	edv_mimetype_listwin_struct *lw
)
{
	GtkRcStyle *standard_rcstyle, *lists_rcstyle;
	GtkWidget *w;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core_ptr;

	if(lw == NULL)
	    return;

	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return;

	cfg_list = core_ptr->cfg_list;
	standard_rcstyle = core_ptr->standard_rcstyle;
	lists_rcstyle = core_ptr->lists_rcstyle;

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

	EDVMimeTypesListWinUpdateMenus(lw);
}

/*
 *	MIME Type added callback.
 */
void EDVMimeTypesListWinMimeTypeAddedCB(
	edv_mimetype_listwin_struct *lw,
	gint mt_num, edv_mimetype_struct *mt_ptr
)
{
	gint i, row, new_row;
	gchar **strv;
	GtkCList *clist;
	edv_core_struct *core_ptr;


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

	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return;

	if(clist->columns < 1)
	    return;

	/* Get row to insert at which should correspond to the MIME
	 * Type's index
	 */
	row = mt_num;

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

	/* Append new row? */
	if(row >= clist->rows)
	    new_row = gtk_clist_append(clist, strv);
	else
	    new_row = gtk_clist_insert(clist, row, strv);

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

	/* Failed to add new row? */
	if(new_row < 0)
	    return;

	/* Set new row's values */
	EDVMimeTypesListWinSetRow(lw, new_row, mt_ptr);

	EDVMimeTypesListWinUpdateMenus(lw);
}

/*
 *	MIME Type modified callback.
 */
void EDVMimeTypesListWinMimeTypeModifiedCB(
	edv_mimetype_listwin_struct *lw,
	gint mt_num, edv_mimetype_struct *mt_ptr
)
{
	GtkCList *clist;
	edv_core_struct *core_ptr;


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

	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return;

	if(clist->columns < 1)
	    return;

	/* Check if the MIME Type index number is in bounds */
	if((mt_num >= 0) && (mt_num < core_ptr->total_mimetypes) &&
	   (mt_num < clist->rows)
	)
	{
	    gint sel_row = EDVCListGetSelectedLast(clist, NULL);

	    /* Update this row with the values from the given MIME Type */
	    EDVMimeTypesListWinSetRow(lw, mt_num, mt_ptr);

	    /* This MIME Type currently selected? */
	    if(mt_num == sel_row)
	    {
		/* Update displayed MIME Type */
		EDVMimeTypesListWinUpdateDisplay(lw, mt_num, mt_ptr);
	    }

	    EDVMimeTypesListWinUpdateMenus(lw);
	}
}

/*
 *	MIME Type removed callback.
 */
void EDVMimeTypesListWinMimeTypeRemovedCB(
	edv_mimetype_listwin_struct *lw, gint mt_num
)
{
	gint row, sel_row;
	GtkCList *clist;
	edv_core_struct *core_ptr;


	if(lw == NULL)
	    return;

	clist = (GtkCList *)lw->mimetypes_clist;
	core_ptr = EDV_CORE(lw->core_ptr);
	if((clist == NULL) || (core_ptr == NULL))
	    return;

	if(clist->columns < 1)
	    return;

	/* The row to remove should correspond to the MIME Type's
	 * index
	 */
	row = mt_num;

	/* Get currently selected row */
	sel_row = EDVCListGetSelectedLast(clist, NULL);

	/* Row in bounds? */
	if((row >= 0) && (row < clist->rows))
	{
	    /* Remove row */
	    gtk_clist_remove(clist, row);

	    /* This MIME Type currently selected? */
	    if(mt_num == sel_row)
	    {
		/* Update displayed MIME Type */
		EDVMimeTypesListWinUpdateDisplay(lw, mt_num, NULL);
	    }

	    EDVMimeTypesListWinUpdateMenus(lw);
	}

	/* Forward this signal to the MIME Type Edit Window */
	EDVMimeTypesEditWinMimeTypeRemovedCB(lw->editwin, mt_num);
}


/*
 *	Creates a new MIME Types List Window.
 */
edv_mimetype_listwin_struct *EDVMimeTypesListWinNew(
	gpointer core_ptr
)
{
	const gint	border_major = 5,
			border_minor = 2;
	const gchar	*wm_name = NULL,
			*wm_class = NULL;
	gchar *heading[3];
	gpointer mclient_data;
	gpointer entry_rtn;
	GdkWindow *window;
	GtkRcStyle	*standard_rcstyle = NULL,
			*lists_rcstyle = NULL;
	GtkAccelGroup *accelgrp;
	GtkStyle *style;
	GtkWidget *w, *menu;
	GtkWidget *parent, *parent2, *parent3, *parent4;
	GtkEntry *entry;
	GtkCList *clist;
	edv_mimetype_listwin_struct *lw = EDV_MIMETYPE_LISTWIN(
	    g_malloc0(sizeof(edv_mimetype_listwin_struct))
	);
	if(lw == NULL)
	    return(lw);

	/* Get configuration */
	if(core_ptr != NULL)
	{
	    edv_core_struct *c_ptr = EDV_CORE(core_ptr);

	    standard_rcstyle = c_ptr->standard_rcstyle;
	    lists_rcstyle = c_ptr->lists_rcstyle;

	    wm_name = c_ptr->wm_name;
	    wm_class = c_ptr->wm_class;
	}

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


	/* Begin creating widgets */

	/* Toplevel */
	lw->toplevel = w = gtk_window_new(GTK_WINDOW_DIALOG);
	gtk_widget_set_usize(w, LISTWIN_WIDTH, LISTWIN_HEIGHT);
	gtk_window_set_title(GTK_WINDOW(w), LISTWIN_TITLE);
	if(!STRISEMPTY(wm_name) && !STRISEMPTY(wm_class))
	    gtk_window_set_wmclass(GTK_WINDOW(w), wm_name, wm_class);
	else
	    gtk_window_set_wmclass(
		GTK_WINDOW(w), "mimetypeslist", 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 **)icon_mimetypes_48x48_xpm);
	}
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_event",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinDeleteEventCB), lw
	);
	gtk_window_add_accel_group(GTK_WINDOW(w), accelgrp);
	style = gtk_widget_get_style(w);
	parent = w;


	/* Load pixmaps */
#define LOAD_PIXMAP(_d_,_n_,_pixmap_rtn_,_mask_rtn_)	{	\
 EDVLoadPixmap(							\
  EDV_CORE(core_ptr),						\
  (guint8 **)(_d_), (_n_),					\
  (_pixmap_rtn_), (_mask_rtn_)					\
 );								\
}
	LOAD_PIXMAP(
	    icon_system_object_20x20_xpm,
	    "icon_system_object_20x20_xpm",
	    &lw->system_object_pixmap,
	    &lw->system_object_mask
	)
	LOAD_PIXMAP(
	    icon_file_extension_20x20_xpm,
	    "icon_file_extension_20x20_xpm",
	    &lw->file_format_pixmap,
	    &lw->file_format_mask
	) 
	LOAD_PIXMAP(
	    icon_executable_20x20_xpm,
	    "icon_executable_20x20_xpm",
	    &lw->program_pixmap,
	    &lw->program_mask
	)    
	LOAD_PIXMAP(
	    icon_unique_object_20x20_xpm,
	    "icon_unique_object_20x20_xpm",
	    &lw->unique_object_pixmap,
	    &lw->unique_object_mask
	)
#undef LOAD_PIXMAP


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


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

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


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


	/* Scrolled window for MIME Types clist */
	w = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(
	    GTK_SCROLLED_WINDOW(w),
	    GTK_POLICY_AUTOMATIC,
	    GTK_POLICY_AUTOMATIC
	);
	gtk_box_pack_start(GTK_BOX(parent2), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent3 = w;

	/* MIME Types clist */
#if defined(PROG_LANGUAGE_SPANISH)
	heading[0] = "De Tipo MIME";
	heading[1] = "El Valor";
	heading[2] = "";
#elif defined(PROG_LANGUAGE_FRENCH)
	heading[0] = "MIME Le Type";
	heading[1] = "Valeur";
	heading[2] = "";
#elif defined(PROG_LANGUAGE_GERMAN)
	heading[0] = "MIME Typ";
	heading[1] = "Wert";
	heading[2] = "";
#elif defined(PROG_LANGUAGE_ITALIAN)
	heading[0] = "Il Tipo Di MIME";
	heading[1] = "Il Valore";
	heading[2] = "";
#elif defined(PROG_LANGUAGE_DUTCH)
	heading[0] = "MIME Type";
	heading[1] = "Waarde";
	heading[2] = "";
#elif defined(PROG_LANGUAGE_PORTUGUESE)
	heading[0] = "MIME Tipo";
	heading[1] = "O Valor";
	heading[2] = "";
#elif defined(PROG_LANGUAGE_NORWEGIAN)
	heading[0] = "MIME Type";
	heading[1] = "Verdi";
	heading[2] = "";
#else
	heading[0] = "MIME Type";
	heading[1] = "Value";
	heading[2] = "";		/* Class */
#endif
	lw->mimetypes_clist = w = gtk_clist_new_with_titles(3, heading);
	clist = GTK_CLIST(w);
	gtk_widget_add_events(
	    w,
	    GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
	    GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
	    GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
	    GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_press_event",
	    GTK_SIGNAL_FUNC(EDVCListKeyEventCB), core_ptr
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_release_event",
	    GTK_SIGNAL_FUNC(EDVCListKeyEventCB), core_ptr
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_press_event",
	    GTK_SIGNAL_FUNC(EDVCListButtonEventCB), core_ptr
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_release_event",
	    GTK_SIGNAL_FUNC(EDVCListButtonEventCB), core_ptr
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "motion_notify_event",
	    GTK_SIGNAL_FUNC(EDVCListMotionEventCB), core_ptr
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_press_event",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinKeyEventCB), lw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_release_event",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinKeyEventCB), lw
	);
	gtk_signal_connect_after(
	    GTK_OBJECT(w), "button_press_event",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinButtonPressEventCB), lw
	);
	gtk_widget_set_usize(w, -1, LISTWIN_HEIGHT * 0.5f);
	gtk_container_add(GTK_CONTAINER(parent3), w);      
	gtk_widget_realize(w);
	gtk_clist_set_selection_mode(clist, GTK_SELECTION_EXTENDED);
	gtk_clist_set_column_width(clist, 0, 160);
	gtk_clist_set_column_width(clist, 1, 150);
	gtk_clist_set_column_width(clist, 2, 20);
	gtk_clist_column_titles_passive(clist);
	gtk_clist_set_row_height(clist, EDV_LIST_ROW_SPACING);
	gtk_clist_set_shadow_type(clist, GTK_SHADOW_IN);
	gtk_signal_connect(
	    GTK_OBJECT(w), "select_row",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinSelectRowCB), lw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "unselect_row",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinUnselectRowCB), lw
	);
	gtk_widget_show(w);


	/* Vbox for buttons */
	w = gtk_vbox_new(FALSE, 2 * border_major);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;

	/* Vbox for add, edit, and remove set of buttons */
	w = gtk_vbox_new(FALSE, 2 * border_minor);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* Add button */
	lw->add_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_add_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Agregue"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ajouter"
#elif defined(PROG_LANGUAGE_GERMAN)
"Fügen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Aggiungere"
#elif defined(PROG_LANGUAGE_DUTCH)
"Toevoeg"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Adicione"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Tilføy"
#else
"Add"
#endif
	    "...", NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinAddCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_a, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_a);
	gtk_widget_show(w);

	/* Edit button */
	lw->edit_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_edit_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Redacte"
#elif defined(PROG_LANGUAGE_FRENCH)
"Editer"
#elif defined(PROG_LANGUAGE_GERMAN)
"Redigieren"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Redigere"
#elif defined(PROG_LANGUAGE_DUTCH)
"Bewerking"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Edite"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Rediger"
#else
"Edit"
#endif
	    "...", NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinEditCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_e, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_e);
	gtk_widget_show(w);

	/* Remove button */
	lw->remove_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_remove_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Quite"
#elif defined(PROG_LANGUAGE_FRENCH)
"Enlever"
#elif defined(PROG_LANGUAGE_GERMAN)
"Nehmen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Togliere"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verwijdeer"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Retire"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Fjern"
#else
"Remove"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinRemoveCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_r, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_r);
	gtk_widget_show(w);


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

	/* Shift Up Button */
	lw->up_btn = w = GUIButtonArrowLabelH(
	    GTK_ARROW_UP, 20, 20,
#if defined(PROG_LANGUAGE_SPANISH)
"Cambie Arriba"
#elif defined(PROG_LANGUAGE_FRENCH)
"Changer Haut"
#elif defined(PROG_LANGUAGE_GERMAN)
"Spostare Su"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Spostare Su"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verplaats Op"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mude Cima"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forskyv Opp"
#else
"Shift Up"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinShiftUpCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_u, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_u);
	gtk_widget_show(w);
	gtk_box_set_child_packing(
	    GTK_BOX(GUIButtonGetMainBox(w)),
	    GUIButtonGetArrow(w),
	    FALSE, FALSE, 0, GTK_PACK_START
	);

	/* Shift Down Button */
	lw->down_btn = w = GUIButtonArrowLabelH(
	    GTK_ARROW_DOWN, 20, 20,
#if defined(PROG_LANGUAGE_SPANISH)
"Cambie Abajo"
#elif defined(PROG_LANGUAGE_FRENCH)
"Changer Bas"
#elif defined(PROG_LANGUAGE_GERMAN)
"Spostare Giù"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Spostare Giù"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verplaats Beneden"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mude Baixo"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forskyv Ned"
#else
"Shift Down"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinShiftDownCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_d, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_d);
	gtk_widget_show(w);
	gtk_box_set_child_packing(
	    GTK_BOX(GUIButtonGetMainBox(w)),
	    GUIButtonGetArrow(w),
	    FALSE, FALSE, 0, GTK_PACK_START
	);

	/* Vbox for Save, Import, and Export Buttons */
	w = gtk_vbox_new(FALSE, 2 * border_minor);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* Save Button */
	lw->save_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_save_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Salve"
#elif defined(PROG_LANGUAGE_FRENCH)
"Epargner"
#elif defined(PROG_LANGUAGE_GERMAN)
"Außer"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Risparmiare"
#elif defined(PROG_LANGUAGE_DUTCH)
"Red"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Poupe"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Untatt"
#else
"Save"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinSaveCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_s);
	gtk_widget_show(w);

	/* Import Button */
	lw->import_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_import_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Importación"
#elif defined(PROG_LANGUAGE_FRENCH)
"Importation"
#elif defined(PROG_LANGUAGE_GERMAN)
"Import"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'Importazione"
#elif defined(PROG_LANGUAGE_DUTCH)
"Import"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Importe"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Import"
#else
"Import"
#endif
	    "...", NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinImportCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_i, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_i);
	gtk_widget_show(w);

	/* Export Button */
	lw->export_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_export_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Exportación"
#elif defined(PROG_LANGUAGE_FRENCH)
"Exportation"
#elif defined(PROG_LANGUAGE_GERMAN)
"Export"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'Esportazione"
#elif defined(PROG_LANGUAGE_DUTCH)
"Export"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Exportação"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Eksport"
#else
"Export"
#endif
	    "...", NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesListWinExportCB), lw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_p, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_p);
	gtk_widget_show(w);



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


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

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


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


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

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



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

#define DO_ADD_MENU_ITEM_LABEL	{		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_LABEL, accelgrp,	\
  icon, label, accel_key, accel_mods, NULL,	\
  mclient_data, func_cb				\
 );						\
}
#define DO_ADD_MENU_SEP		{		\
 w = GUIMenuItemCreate(				\
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL,	\
  NULL, NULL, 0, 0, NULL,			\
  NULL, NULL					\
 );						\
}
	    icon = (guint8 **)icon_add_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Agregue"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ajouter"
#elif defined(PROG_LANGUAGE_GERMAN)
"Fügen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Aggiungere"
#elif defined(PROG_LANGUAGE_DUTCH)
"Toevoeg"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Adicione"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Tilføy"
#else
"Add"
#endif
		"...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVMimeTypesListWinAddCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->add_mi = w;

	    icon = (guint8 **)icon_edit_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Redacte"
#elif defined(PROG_LANGUAGE_FRENCH)
"Editer"
#elif defined(PROG_LANGUAGE_GERMAN)
"Redigieren"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Redigere"
#elif defined(PROG_LANGUAGE_DUTCH)
"Bewerking"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Edite"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Rediger"
#else
"Edit"
#endif
		"...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVMimeTypesListWinEditCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->edit_mi = w;

	    icon = (guint8 **)icon_remove_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Quite"
#elif defined(PROG_LANGUAGE_FRENCH)
"Enlever"
#elif defined(PROG_LANGUAGE_GERMAN)
"Nehmen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Togliere"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verwijdeer"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Retire"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Fjern"
#else
"Remove"
#endif
		;
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVMimeTypesListWinRemoveCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->remove_mi = w;

	    DO_ADD_MENU_SEP

	    icon = NULL;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Cambie Arriba"
#elif defined(PROG_LANGUAGE_FRENCH)
"Changer En Haut"
#elif defined(PROG_LANGUAGE_GERMAN)
"Spostare Su"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Spostare Su"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verplaats Op"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mude Para Cima"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forskyv Opp"
#else
"Shift Up"
#endif
		;
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVMimeTypesListWinShiftUpCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->up_mi = w;

	    icon = NULL;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Cambie Hacia Abajo"
#elif defined(PROG_LANGUAGE_FRENCH)
"Changer En Bas"
#elif defined(PROG_LANGUAGE_GERMAN)
"Spostare Giù"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Spostare Giù"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verplaats Beneden"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Mude Para Baixo"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forskyv Ned"
#else
"Shift Down"
#endif
		;
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVMimeTypesListWinShiftDownCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->down_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_save_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Salve"
#elif defined(PROG_LANGUAGE_FRENCH)
"Epargner"
#elif defined(PROG_LANGUAGE_GERMAN)
"Außer"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Risparmiare"
#elif defined(PROG_LANGUAGE_DUTCH)
"Red"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Poupe"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Untatt"
#else
"Save"
#endif
		;
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVMimeTypesListWinSaveCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->save_mi = w;

	    icon = (guint8 **)icon_import_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Importación"
#elif defined(PROG_LANGUAGE_FRENCH)
"Importation"
#elif defined(PROG_LANGUAGE_GERMAN)
"Import"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'Importazione"
#elif defined(PROG_LANGUAGE_DUTCH)
"Import"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Importe"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Import"
#else
"Import"
#endif
		"...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVMimeTypesListWinImportCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->import_mi = w;

	    icon = (guint8 **)icon_export_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Exportación"
#elif defined(PROG_LANGUAGE_FRENCH)
"Exportation"
#elif defined(PROG_LANGUAGE_GERMAN)
"Export"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'Esportazione"
#elif defined(PROG_LANGUAGE_DUTCH)
"Export"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Exportação"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Eksport"
#else
"Export"
#endif
		"...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVMimeTypesListWinExportCB;
	    DO_ADD_MENU_ITEM_LABEL
	    lw->export_mi = w;



#undef DO_ADD_MENU_ITEM_LABEL
#undef DO_ADD_MENU_SEP
	}


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


	EDVMimeTypesListWinUpdateMenus(lw);

	return(lw);
}

/*
 *	Updates the MIME Types List Window's widgets to reflect current
 *	values.
 */
void EDVMimeTypesListWinUpdateMenus(
	edv_mimetype_listwin_struct *lw
)
{
	gboolean sensitive;
	gint sel_row;
	GtkCList *clist;

	if(lw == NULL)
	    return;

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

	sensitive = (sel_row > -1) ? TRUE : FALSE;
	GTK_WIDGET_SET_SENSITIVE(lw->edit_btn, sensitive)
	GTK_WIDGET_SET_SENSITIVE(lw->remove_btn, sensitive)

	GTK_WIDGET_SET_SENSITIVE(lw->edit_mi, sensitive)
	GTK_WIDGET_SET_SENSITIVE(lw->remove_mi, sensitive)

	/* Shift up? */
	sensitive = (sel_row > 0) ? TRUE : FALSE;
	GTK_WIDGET_SET_SENSITIVE(lw->up_btn, sensitive)
	GTK_WIDGET_SET_SENSITIVE(lw->up_mi, sensitive)

	/* Shift down? */
	sensitive = ((sel_row > -1) && (sel_row < (clist->rows - 1))) ?
	    TRUE : FALSE;
	GTK_WIDGET_SET_SENSITIVE(lw->down_btn, sensitive)
	GTK_WIDGET_SET_SENSITIVE(lw->down_mi, sensitive)

	/* Export */
	sensitive = (sel_row > -1) ? TRUE : FALSE;
	GTK_WIDGET_SET_SENSITIVE(lw->export_mi, sensitive)
	GTK_WIDGET_SET_SENSITIVE(lw->export_btn, sensitive)
}

/*
 *	Sets the MIME Types List Window as busy or ready.
 */
void EDVMimeTypesListWinSetBusy(
	edv_mimetype_listwin_struct *lw, gboolean is_busy
)
{
	GdkCursor *cursor;
	GtkWidget *w;
	edv_core_struct *core_ptr;


	if(lw == NULL)
	    return;

	core_ptr = EDV_CORE(lw->core_ptr);
	if(core_ptr == NULL)
	    return;

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

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

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

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

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

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

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

/*
 *	Maps the MIME Types List Window.
 */
void EDVMimeTypesListWinMap(
	edv_mimetype_listwin_struct *lw
)
{
	GtkWidget *w = (lw != NULL) ? lw->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_show_raise(w);

	w = lw->mimetypes_clist;
	gtk_widget_grab_focus(w);
}

/*
 *	Unmaps the MIME Types List Window.
 */
void EDVMimeTypesListWinUnmap(
	edv_mimetype_listwin_struct *lw
)
{
	GtkWidget *w = (lw != NULL) ? lw->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_hide(w);
}

/*
 *	Delete the MIME Types List Window.
 */
void EDVMimeTypesListWinDelete(
	edv_mimetype_listwin_struct *lw
)
{
	if(lw == NULL)
	    return;

	/* Delete MIME Type Edit window */
	EDVMimeTypesEditWinDelete(lw->editwin);
	lw->editwin = NULL;

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

	/* Destroy display widgets */
	GTK_WIDGET_DESTROY(lw->display_icon)
	lw->display_icon = NULL;
	GTK_WIDGET_DESTROY(lw->display_edit_btn)
	lw->display_edit_btn = NULL;
	GTK_WIDGET_DESTROY(lw->display_client)
	lw->display_client = NULL;
	GTK_WIDGET_DESTROY(lw->display_parent)
	lw->display_parent = NULL;

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

	GTK_WIDGET_DESTROY(lw->add_btn)
	lw->add_btn = NULL;
	GTK_WIDGET_DESTROY(lw->edit_btn)
	lw->edit_btn = NULL;
	GTK_WIDGET_DESTROY(lw->remove_btn)
	lw->remove_btn = NULL;
	GTK_WIDGET_DESTROY(lw->up_btn)
	lw->up_btn = NULL;
	GTK_WIDGET_DESTROY(lw->down_btn)
	lw->down_btn = NULL;
	GTK_WIDGET_DESTROY(lw->save_btn)
	lw->save_btn = NULL;
	GTK_WIDGET_DESTROY(lw->import_btn)
	lw->import_btn = NULL;
	GTK_WIDGET_DESTROY(lw->export_btn)
	lw->export_btn = NULL;
	GTK_WIDGET_DESTROY(lw->close_btn)
	lw->close_btn = NULL;

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

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

	GDK_PIXMAP_UNREF(lw->system_object_pixmap)
	GDK_BITMAP_UNREF(lw->system_object_mask)
	GDK_PIXMAP_UNREF(lw->file_format_pixmap)
	GDK_BITMAP_UNREF(lw->file_format_mask)
	GDK_PIXMAP_UNREF(lw->program_pixmap)
	GDK_BITMAP_UNREF(lw->program_mask)
	GDK_PIXMAP_UNREF(lw->unique_object_pixmap)
	GDK_BITMAP_UNREF(lw->unique_object_mask)

	g_free(lw);
}
