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

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

#include "guiutils.h"
#include "cdialog.h"
#include "fb.h"
#include "fprompt.h"
#include "editclist.h"

#include "edvtypes.h"
#include "edvmimetypes.h"
#include "mimetypeswin.h"
#include "endeavour.h"
#include "edvcb.h"
#include "edvutils.h"
#include "edvutilsgtk.h"
#include "config.h"

#include "images/icon_ok_20x20.xpm"
#include "images/icon_select_20x20.xpm"
#include "images/icon_cancel_20x20.xpm"
#include "images/icon_close_20x20.xpm"
#include "images/icon_mimetypes_48x48.xpm"


static void EDVMimeTypesEditIconUpdateDisplay(
	edv_mimetype_icon_picker_struct *ei,
	edv_mimetype_icon_state state
);
static void EDVMimeTypesEditIconChangeCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesEditIconPrevCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesEditIconNextCB(
	GtkWidget *widget, gpointer data
);

static gint EDVMimeTypesEditWinDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
);
static void EDVMimeTypesEditWinAnyChangedCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesEditWinECListRowAddedCB(
	editclist_struct *eclist, gint row,
	gpointer data
);
static void EDVMimeTypesEditWinECListCellChangedCB(
	editclist_struct *eclist, gint row, gint column,
	gpointer data
);
static void EDVMimeTypesEditWinECListRowRemovedCB(
	editclist_struct *eclist, gint row,
	gpointer data
);
static void EDVMimeTypesEditWinClassChangedCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesEditWinHandlerChangedCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesEditWinOKCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesEditWinApplyCB(
	GtkWidget *widget, gpointer data
);
static void EDVMimeTypesEditWinCancelCB(
	GtkWidget *widget, gpointer data
);

static gint EDVMimeTypesEditWinGetClass(
	edv_mimetype_editwin_struct *ew
);
static gint EDVMimeTypesEditWinGetHandler(
	edv_mimetype_editwin_struct *ew
);

static gint EDVMimeTypesEditWinCheckMIMEType(
	edv_core_struct *core_ptr,
	edv_mimetype_struct **list, gint total,
	gint mt_num,
	gboolean verbose, GtkWidget *toplevel
);

void EDVMimeTypesEditWinFetchValues(
	edv_mimetype_editwin_struct *ew, gint mt_num
);

void EDVMimeTypesEditWinMimeTypeRemovedCB(
	edv_mimetype_editwin_struct *ew, gint mt_num
);

static edv_mimetype_icon_picker_struct *EDVMimeTypesEditIconNew(
	gpointer editwin, GtkWidget *parent, const gchar *title,
	gint icon_width, gint icon_height,
	gint btn_width, gint btn_height
);
static void EDVMimeTypesEditIconDelete(edv_mimetype_icon_picker_struct *ei);

edv_mimetype_editwin_struct *EDVMimeTypesEditWinNew(
	gpointer core_ptr, gpointer listwin
);
void EDVMimeTypesEditWinResetHasChanges(
	edv_mimetype_editwin_struct *ew, gboolean has_changes
);
void EDVMimeTypesEditWinUpdateMenus(edv_mimetype_editwin_struct *ew);
gboolean EDVMimeTypesEditWinIsMapped(edv_mimetype_editwin_struct *ew);
void EDVMimeTypesEditWinMap(edv_mimetype_editwin_struct *ew);
void EDVMimeTypesEditWinUnmap(edv_mimetype_editwin_struct *ew);
void EDVMimeTypesEditWinDelete(edv_mimetype_editwin_struct *ew);


#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 EDITWIN_WIDTH		500
#define EDITWIN_HEIGHT		-1

#define EDITWIN_TITLE		"MIME Type"


/*
 *	Updates the icon displayed on the button of the given edit window
 *	icon structure with the corresponding pixmap and mask pair of
 *	the given state.
 */
static void EDVMimeTypesEditIconUpdateDisplay(
	edv_mimetype_icon_picker_struct *ei,
	edv_mimetype_icon_state state
)
{
	const gchar *label_str = "";
	GdkPixmap *pixmap;
	GdkBitmap *mask;
	GtkWidget *w, *parent;


	if(ei == NULL)
	    return;

	if((state < 0) || (state >= EDV_MIMETYPE_TOTAL_ICON_STATES))
	    return;

	/* Get references to pixmap and mask pair specified by the
	 * given state
	 */
	pixmap = ei->pixmap[state];
	mask = ei->mask[state];

	/* Get button widget as the parent to create GtkPixmap in */
	parent = ei->button;
	if(parent == NULL)
	    return;

	/* Referenced pixmap valid? */
	if(pixmap != NULL)
	{
	    /* Referenced pixmap is valid, now check if the GtkPixmap
	     * that is to be used to display the pixmap has been
	     * created yet (if not then create a new one)
	     */
	    w = ei->gtk_pixmap;
	    if(w == NULL)
	    {
		ei->gtk_pixmap = w = gtk_pixmap_new(pixmap, mask);
		gtk_container_add(GTK_CONTAINER(parent), w);
		gtk_widget_show(w);
	    }
	    else
	    {
		/* GtkPixmap exists, so just update it */
		gtk_pixmap_set(GTK_PIXMAP(w), pixmap, mask);
		gtk_widget_show(w);
	    }
	}
	else
	{
	    /* No referenced pixmap, so unmap the the GtkPixmap */
	    w = ei->gtk_pixmap;
	    if(w != NULL)
	    {
		gtk_widget_hide(w);
	    }
	}


	/* Update state label, get the currect label string to display
	 * for the state label based on the given state
	 */
	switch(state)
	{
	  case EDV_MIMETYPE_ICON_STATE_HIDDEN:
	    label_str = "Hidden";
	    break;
	  case EDV_MIMETYPE_ICON_STATE_EXTENDED:
	    label_str =
#if defined(PROG_LANGUAGE_SPANISH)
"Prolongado"
#elif defined(PROG_LANGUAGE_FRENCH)
"Etendu"
#elif defined(PROG_LANGUAGE_GERMAN)
"Ausgedehnt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Esteso"
#elif defined(PROG_LANGUAGE_DUTCH)
"Verlengde"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Estendido"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Forlenget"
#else
"Extended"
#endif
	    ;
	    break;
	  case EDV_MIMETYPE_ICON_STATE_SELECTED:
	    label_str =
#if defined(PROG_LANGUAGE_SPANISH)
"Escogido"
#elif defined(PROG_LANGUAGE_FRENCH)
"Choisi"
#elif defined(PROG_LANGUAGE_GERMAN)
"Ausgewählt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Scelto"
#elif defined(PROG_LANGUAGE_DUTCH)
"Geselecteerde"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Selecionado"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Valgt Ut"
#else
"Selected"
#endif
	    ;
	    break;
	  case EDV_MIMETYPE_ICON_STATE_STANDARD:
	    label_str =
#if defined(PROG_LANGUAGE_SPANISH)
"El Estándar"
#elif defined(PROG_LANGUAGE_FRENCH)
"Norme"
#elif defined(PROG_LANGUAGE_GERMAN)
"Standard"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Norma"
#elif defined(PROG_LANGUAGE_DUTCH)
"Standaard"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Padrão"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Standard"
#else
"Standard"
#endif
	    ;
	    break;
	}
	w = ei->state_label;
	if(w != NULL)
	    gtk_label_set_text(GTK_LABEL(w), label_str);


#if 0
	/* Update button sensitivities */
	w = ei->left_btn;
	if(w != NULL)
	    GTK_WIDGET_SET_SENSITIVE(
		w,
		(state > 0) ? TRUE : FALSE
	    )
	w = ei->right_btn;
	if(w != NULL)
	    GTK_WIDGET_SET_SENSITIVE(
		w,
		(state < (EDV_MIMETYPE_TOTAL_ICON_STATES - 1)) ? TRUE : FALSE
	    )
#endif
}

/*
 *	Edit window icon change callback.
 */
static void EDVMimeTypesEditIconChangeCB(
	GtkWidget *widget, gpointer data
)
{
	gint status;
	const gchar *old_path;
	gchar *old_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_mimetype_icon_state state;
	edv_core_struct *core_ptr;
	edv_mimetype_editwin_struct *ew;
	edv_mimetype_icon_picker_struct *ei =
	    EDV_MIMETYPE_ICON_PICKER(data);
	if((ei == NULL) || FileBrowserIsQuery())
	    return;

	/* Get icon state */
	state = (edv_mimetype_icon_state)GTK_ADJUSTMENT_GET_VALUE(ei->adj);
	if((state < 0) || (state >= EDV_MIMETYPE_TOTAL_ICON_STATES))
	    return;

	ew = EDV_MIMETYPE_EDITWIN(ei->editwin);
	core_ptr = EDV_CORE(ew->core_ptr);
	if((ew == NULL) || (core_ptr == NULL))
	    return;

	toplevel = ew->toplevel;

	/* Get current path to the icon file */
	old_path = ei->path[state];
	if(old_path != NULL)
	    old_parent_path = g_dirname(old_path);
	else
	    old_parent_path = NULL;

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

	/* Current old_path must be considered invalid at this point */
	old_path = NULL;


	/* Query user for new icon file */
	FileBrowserSetTransientFor(toplevel);
	status = FileBrowserGetResponse(
#if defined(PROG_LANGUAGE_SPANISH)
"Icono Selecto",
"Selecto",
"Cancele",
#elif defined(PROG_LANGUAGE_FRENCH)
"Icône Privilégiée",
"Privilégié",
"Annuler",
#elif defined(PROG_LANGUAGE_GERMAN)
"Erlesenes Abbild",
"Erlesen",
"Heben",
#elif defined(PROG_LANGUAGE_ITALIAN)
"Scegliere L'Icona",
"Scegliere",
"Annullare",
#elif defined(PROG_LANGUAGE_DUTCH)
"Uitgezochte Beeld",
"Uitgezocht",
"Annuleer",
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Selecione Icone",
"Selecione",
"Cancelamento",
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Utvalgt Ikon",
"Utvalgt",
"Kanseller",
#else
"Select Icon",
"Select",
"Cancel",
#endif
	    old_parent_path,
	    ftype, total_ftypes,
	    &path_rtn, &total_path_rtns,
	    &ftype_rtn
	);
	FileBrowserSetTransientFor(NULL);

	/* Got user response? */
	if(status)
	{
	    const gchar *new_path = (total_path_rtns > 0) ?
		path_rtn[0] : NULL;
	    if(!STRISEMPTY(new_path))
	    {
		/* Load new pixmap and mask */
		GdkBitmap *mask;
		GdkPixmap *pixmap = GDK_PIXMAP_NEW_FROM_XPM_FILE(
		    &mask, new_path
		);
		if(pixmap != NULL)
		{
		    /* New pixmap and mask loaded successfully */

		    /* Unref old and set new pixmap and mask */
		    GDK_PIXMAP_UNREF(ei->pixmap[state])
		    GDK_BITMAP_UNREF(ei->mask[state])
		    EDVResizePixmap(
			pixmap, mask,
			ei->icon_width, ei->icon_height,
			&ei->pixmap[state], &ei->mask[state]
		    );
		    GDK_PIXMAP_UNREF(pixmap)
		    GDK_BITMAP_UNREF(mask)

		    /* Set new icon file path */
		    g_free(ei->path[state]);
		    ei->path[state] = STRDUP(new_path);

		    /* Update the displayed icon */
		    EDVMimeTypesEditIconUpdateDisplay(ei, state);

		    /* Mark has changes */
		    EDVMimeTypesEditWinResetHasChanges(ew, TRUE);
		}
		else
		{
		    /* Failed to load icon */
 		    gchar *buf;

		    /* Update the displayed icon */
		    EDVMimeTypesEditIconUpdateDisplay(ei, state);

		    /* Notify user about failed load */
		    buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Incapaz de cargar el archivo de icono:\n\
\n\
    %s\n\
\n\
Verifique por favor que el sendero especificado es correcto y que el\n\
archivo es un archivo válido de la imagen de XPM.\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Incapable de charger le fichier d'icône:\n\
\n\
    %s\n\
\n\
S'il vous plaît vérifier que le sentier spécifié est exact et que le\n\
fichier est un fichier d'image de XPM valide.\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Unfähig, abbild akte zu beladen:\n\
\n\
    %s\n\
\n\
Beglaubigen sie bitte, daß der angegebene pfad richtig ist, und, daß\n\
die akte eine gültige XPM bildnis akte ist.\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Incapace per caricare il file di icona:\n\
\n\
    %s\n\
\n\
Per favore di verificare che il sentiero specificato è corretto e\n\
che il file è un file di immagine di XPM valido.\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Onbekwaam beeld dossier te laden:\n\
\n\
    %s\n\
\n\
Bevestiig alstublieft dat het gespecificeerd pad correcte is en dat\n\
het dossier een geldig XPM beeld dossier is.\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Incapaz de carregar arquivo de ícone:\n\
\n\
    %s\n\
\n\
Por favor verifique-se que o caminho especificado é correto e que o\n\
arquivo é um arquivo válido de imagem de XPM.\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Maktesløs laste ikonarkiv:\n\
\n\
    %s\n\
\n\
Vær så snill og bekreft at den spesifiserte stien er riktig og at\n\
arkivet er et gyldig XPM avbildearkiv\n"
#else
"Unable to load icon file:\n\
\n\
    %s\n\
\n\
Please verify that the specified path is correct and that the file\n\
is a valid XPM image file.\n"
#endif
			, new_path
		    );
		    EDVPlaySoundWarning(core_ptr);
		    EDVMessageWarning(
#if defined(PROG_LANGUAGE_SPANISH)
"Cargue Icono Fallado"
#elif defined(PROG_LANGUAGE_FRENCH)
"Charger L'Icône Echouée"
#elif defined(PROG_LANGUAGE_GERMAN)
"Beladen Sie Abbild, Versagt Wird, Das"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Caricare L'Icona Fallita"
#elif defined(PROG_LANGUAGE_DUTCH)
"Laad Beeld Verzuimde"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Carregue ícone Fracassado"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Last Sviktet Ikon"
#else
"Load Icon Failed"
#endif
			, buf, NULL,
			toplevel
		    );
		    g_free(buf);
		}
	    }
	}


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

	g_free(old_parent_path);
}

/*
 *      Prev icon edit window icon callback.
 */
static void EDVMimeTypesEditIconPrevCB(
	GtkWidget *widget, gpointer data
)
{
	GtkAdjustment *adj;
	edv_mimetype_editwin_struct *ew;
	edv_mimetype_icon_picker_struct *ei =
	    EDV_MIMETYPE_ICON_PICKER(data);
	if(ei == NULL)
	    return;

	ew = EDV_MIMETYPE_EDITWIN(ei->editwin);
	if(ew == NULL)
	    return;

	adj = ei->adj;
	if(adj == NULL)
	    return;

	/* Increment adjustment position */
	if(adj->value > adj->lower)
	    adj->value -= adj->step_increment;
	if(adj->value < adj->lower)
	    adj->value = adj->lower;

	EDVMimeTypesEditIconUpdateDisplay(
	    ei, (edv_mimetype_icon_state)adj->value
	);
}

/*
 *	Next icon edit window icon callback.
 */
static void EDVMimeTypesEditIconNextCB(
	GtkWidget *widget, gpointer data
)
{
	GtkAdjustment *adj;
	edv_mimetype_editwin_struct *ew;
	edv_mimetype_icon_picker_struct *ei =
	    EDV_MIMETYPE_ICON_PICKER(data);
	if(ei == NULL)
	    return;

	ew = EDV_MIMETYPE_EDITWIN(ei->editwin);
	if(ew == NULL)
	    return;

	adj = ei->adj;
	if(adj == NULL)
	    return;

	/* Increment adjustment position */
	if(adj->value < adj->upper)
	    adj->value += adj->step_increment;
	if(adj->value > adj->upper)
	    adj->value = adj->upper;

	EDVMimeTypesEditIconUpdateDisplay(
	    ei, (edv_mimetype_icon_state)adj->value
	);
}


/*
 *	GtkWindow "delete_event" signal callback.
 */
static gint EDVMimeTypesEditWinDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
)
{
	edv_mimetype_editwin_struct *ew = EDV_MIMETYPE_EDITWIN(data);
	if(ew == NULL)
	    return(TRUE);

	EDVMimeTypesEditWinCancelCB(NULL, ew);

	return(TRUE);
}

/*
 *	Any GtkWidget changed signal callback.
 */
static void EDVMimeTypesEditWinAnyChangedCB(
	GtkWidget *widget, gpointer data
)
{
	edv_mimetype_editwin_struct *ew = EDV_MIMETYPE_EDITWIN(data);
	if(ew == NULL)
	    return;

	if(ew->freeze_count > 0)
	    return;

	ew->freeze_count++;

	if(!ew->has_changes)
	    EDVMimeTypesEditWinResetHasChanges(ew, TRUE);

	ew->freeze_count--;
}

/*
 *	Edit CList row added signal callback.
 */
static void EDVMimeTypesEditWinECListRowAddedCB(
	editclist_struct *eclist, gint row,
	gpointer data
)
{
	EDVMimeTypesEditWinAnyChangedCB(
	    EDITCLIST_CLIST(eclist), data
	);
}

/*
 *	Edit CList cell changed signal callback.
 */
static void EDVMimeTypesEditWinECListCellChangedCB(
	editclist_struct *eclist, gint row, gint column,
	gpointer data
)
{
	EDVMimeTypesEditWinAnyChangedCB(
	    EDITCLIST_CLIST(eclist), data
	);
}

/*
 *	Edit CList row removed signal callback.
 */
static void EDVMimeTypesEditWinECListRowRemovedCB(
	editclist_struct *eclist, gint row,
	gpointer data
)
{
	EDVMimeTypesEditWinAnyChangedCB(
	    EDITCLIST_CLIST(eclist), data
	);
}

/*
 *	MIME Types edit window class_combo "changed" callback.
 *
 *	This will update the value_label and value_entry widgets.
 */
static void EDVMimeTypesEditWinClassChangedCB(
	GtkWidget *widget, gpointer data
)
{
	gint mt_class;
	GtkWidget *w;
	gboolean sensitive = TRUE;
	const gchar *value_label_str = "";
	edv_mimetype_editwin_struct *ew = EDV_MIMETYPE_EDITWIN(data);
	if(ew == NULL)
	    return;

	/* Get new class value from class_combo */
	mt_class = EDVMimeTypesEditWinGetClass(ew);

	/* Update widgets depending on class */
	switch(mt_class)
	{
	  case EDV_MIMETYPE_CLASS_SYSTEM:
	    sensitive = FALSE;
	    value_label_str =
#if defined(PROG_LANGUAGE_SPANISH)
"El Valor"
#elif defined(PROG_LANGUAGE_FRENCH)
"Valeur"
#elif defined(PROG_LANGUAGE_GERMAN)
"Wert"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Valore"
#elif defined(PROG_LANGUAGE_DUTCH)
"Waarde"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Valor"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Verdi"
#else
"Value"
#endif
		":";
	    break;

	  case EDV_MIMETYPE_CLASS_FORMAT:
	    sensitive = TRUE;
	    value_label_str =
#if defined(PROG_LANGUAGE_SPANISH)
"Las Extensiones"
#elif defined(PROG_LANGUAGE_FRENCH)
"Extensions"
#elif defined(PROG_LANGUAGE_GERMAN)
"Verlängerungen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Le Estensioni"
#elif defined(PROG_LANGUAGE_DUTCH)
"Uitbreidingen"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"As Extensões"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Utvidelser"
#else
"Extensions"
#endif
		":";
	    break;

	  case EDV_MIMETYPE_CLASS_PROGRAM:
	    sensitive = TRUE;
	    value_label_str =
#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)
"A Localidade"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Plassering"
#else
"Location"
#endif
		":";
	    break;

	  case EDV_MIMETYPE_CLASS_UNIQUE:
	    sensitive = TRUE;
	    value_label_str =
#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)
"A Localidade"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Plassering"
#else
"Location"
#endif
		":";
	    break;
	}

	w = ew->value_label;
	if(w != NULL)
	    gtk_label_set_text(GTK_LABEL(w), value_label_str);

	GTK_WIDGET_SET_SENSITIVE(ew->value_entry, sensitive)
}

/*
 *	MIME Types edit window handler_combo "changed" callback.
 *
 *	This will update the sensitivity or mapping of some widgets
 *	such as the command editable clist.
 */
static void EDVMimeTypesEditWinHandlerChangedCB(
	GtkWidget *widget, gpointer data
)
{
	gboolean sensitive;
	gint handler;
	GtkWidget *w;
	editclist_struct *eclist;
	edv_mimetype_editwin_struct *ew = EDV_MIMETYPE_EDITWIN(data);
	if(ew == NULL)
	    return;

	if(ew->freeze_count > 0)
	    return;

	ew->freeze_count++;

	/* Get new handler value from handler_combo */
	handler = EDVMimeTypesEditWinGetHandler(ew);

	/* Update widgets depending on class */
	switch(handler)
	{
	  case EDV_MIMETYPE_HANDLER_COMMAND:
	    sensitive = TRUE;
	    break;
	  case EDV_MIMETYPE_HANDLER_EDV_ARCHIVER:
	  case EDV_MIMETYPE_HANDLER_EDV_IMAGE_BROWSER:
	  case EDV_MIMETYPE_HANDLER_EDV_RECYCLE_BIN:
	  default:
	    sensitive = FALSE;
	    break;
	}

	eclist = ew->editclist;
	if(eclist != NULL)
	{
	    w = EDITCLIST_TOPLEVEL(eclist);
	    GTK_WIDGET_SET_SENSITIVE(w, sensitive)
	}

	ew->freeze_count--;
}

/*
 *      MIME Types edit window OK button callback.
 */
static void EDVMimeTypesEditWinOKCB(
	GtkWidget *widget, gpointer data
)
{
	edv_mimetype_editwin_struct *ew = EDV_MIMETYPE_EDITWIN(data);
	if(ew == NULL)
	    return;

	EDVMimeTypesEditWinApplyCB(NULL, ew);
	EDVMimeTypesEditWinUnmap(ew);
}

/*
 *      MIME Types edit window Apply button callback.
 */
static void EDVMimeTypesEditWinApplyCB(
	GtkWidget *widget, gpointer data
)
{
	GtkWidget *toplevel;
	GtkEntry *entry;
	GtkCList *clist;
	editclist_struct *eclist;
	gint mt_num;
	edv_mimetype_struct *mt_ptr;
	edv_mimetype_listwin_struct *lw;
	edv_mimetype_icon_picker_struct *ei;
	edv_core_struct *core_ptr;
	edv_mimetype_editwin_struct *ew = EDV_MIMETYPE_EDITWIN(data);
	if(ew == NULL)
	    return;

	toplevel = ew->toplevel;
	lw = EDV_MIMETYPE_LISTWIN(ew->listwin);
	core_ptr = EDV_CORE(ew->core_ptr);
	if((lw == NULL) || (core_ptr == NULL))
	    return;

	/* Get MIME Type being edited */
	mt_num = ew->mt_num;
	mt_ptr = ((mt_num >= 0) && (mt_num < core_ptr->total_mimetypes)) ?
	    core_ptr->mimetype[mt_num] : NULL;

	/* Does the MIME Type no longer exist? */
	if(mt_ptr == NULL)
	{
	    EDVPlaySoundError(core_ptr);
	    EDVMessageError(
#if defined(PROG_LANGUAGE_SPANISH)
"Aplique Fallado",
"Este MIME Type no más largo existe, estos valores se tirarán.\n",
#elif defined(PROG_LANGUAGE_FRENCH)
"S'appliquer Echoué",
"Ce MIME Type non plus long existe, ces valeurs seront rejetées.\n",
#elif defined(PROG_LANGUAGE_GERMAN)
"Verwenden Sie Versagt".
"Dieser MIME Type werden nicht mehr, diese werte\n\
ausgeschieden werden existiert.\n",
#elif defined(PROG_LANGUAGE_ITALIAN)
"Applicare Fallito".
"Questo MIME Type non più esistere, questi valori saranno scartati.\n",
#elif defined(PROG_LANGUAGE_DUTCH)
"Pas Geverzuimenene Toe".
"Deze MIME Type zullen, deze waarde niet langer weggegooid\n\
worden bestaat.\n",
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Aplique Fracassado".
"Este MIME Type não existe mais, estes valores serão descartados.\n",
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Gjeld Sviktet".
"Denne MIME Type finnes ikke mer, disse verdiene kastet.\n",
#else
"Apply Failed",
"This MIME Type no longer exists, these values will be discarded.\n",
#endif
		NULL,
		toplevel
	    );
	    return;
	}

	/* MIME Type marked as read only? */
	if(mt_ptr->read_only)
	{
	    gchar *buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"MIME Type \"%s\" no se puede redactar, porque era ni\n\
creado internamente ni cargado de una configuración global.\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"MIME Type \"%s\" ne peut pas être édité, parce qu'il\n\
ou a été intérieurement créé ou a été chargé d'une configuration\n\
globale.\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"MIME Type \"%s\" kann nicht redigiert werden, weil es\n\
war, entweder geschaffen inner oder kann von einer globalen\n\
konfiguration beladen werden.\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"MIME Type \"%s\" non può essere redatto, perché era sia\n\
creato internamente o caricato da una configurazione globale.\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"MIME Type \"%s\" kun niet is geredigeerd, omdat het ofwel\n\
gecreëerde inwendig ofwel gelaade van een globale\n\
configuratie was.\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"\"%s\" de MIME Type não pode ser editado, porque ele\n\
qualquer um foi criado internamente nem foi carregado de uma\n\
configuração global.\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"MIME Type \"%s\" redigert ikke, fordi det var hver\n\
skape innvendig eller lastet fra en global konfigurasjon.\n"
#else
"MIME Type \"%s\" cannot be edited, because it\n\
was either created internally or loaded from a global\n\
configuration.\n"
#endif
		, mt_ptr->type
	    );
	    EDVPlaySoundWarning(core_ptr);
	    EDVMessageWarning(
#if defined(PROG_LANGUAGE_SPANISH)
"Aplique Fallado"
#elif defined(PROG_LANGUAGE_FRENCH)
"S'appliquer Echoué"
#elif defined(PROG_LANGUAGE_GERMAN)
"Verwenden Sie Versagt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Applicare Fallito"
#elif defined(PROG_LANGUAGE_DUTCH)
"Pas Geverzuimenene Toe"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Aplique Fracassado"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Gjeld Sviktet"
#else
"Apply Failed"
#endif
		, buf, NULL,
		toplevel
	    );
	    g_free(buf);
	    return;
	}


	/* Begin applying values */

	/* Class */
	mt_ptr->mt_class = EDVMimeTypesEditWinGetClass(ew);

	/* Type */
	entry = (GtkEntry *)ew->type_entry;
	if(entry != NULL)
	{
	    const gchar *s = gtk_entry_get_text(entry);
	    if(s != NULL)
	    {
		g_free(mt_ptr->type);
		mt_ptr->type = STRDUP(s);
	    }
	}

	/* Value */
	entry = (GtkEntry *)ew->value_entry;
	if(entry != NULL)
	{
	    const gchar *s = gtk_entry_get_text(entry);
	    if(s != NULL)
	    {
		g_free(mt_ptr->value);
		mt_ptr->value = STRDUP(s);
	    }
	}

	/* Description */
	entry = (GtkEntry *)ew->description_entry;
	if(entry != NULL)
	{
	    const gchar *s = gtk_entry_get_text(entry);
	    if(s != NULL)
	    {
		g_free(mt_ptr->description);
		mt_ptr->description = STRDUP(s);
	    }
	}

	/* Handler */
	mt_ptr->handler = EDVMimeTypesEditWinGetHandler(ew);

	/* Commands */
	eclist = ew->editclist;
	clist = (GtkCList *)EDITCLIST_CLIST(eclist);
	if(clist != NULL)
	{
	    gint i;
	    gchar *s;


	    /* Delete old command and command names */
	    for(i = 0; i < mt_ptr->total_commands; i++)
	    {
		g_free(mt_ptr->command[i]);
		g_free(mt_ptr->command_name[i]);
	    }

	    /* Adjust total commands on MIME Type structure and
	     * reallocate the command and command_name pointer arrays
	     * to the new size
	     */
	    mt_ptr->total_commands = clist->rows;
	    if(mt_ptr->total_commands > 0)
	    {
		mt_ptr->command = (gchar **)g_realloc(
		    mt_ptr->command,
		    mt_ptr->total_commands * sizeof(gchar *)
		);
		mt_ptr->command_name = (gchar **)g_realloc(
		    mt_ptr->command_name,
		    mt_ptr->total_commands * sizeof(gchar *)
		);
		if((mt_ptr->command == NULL) ||
		   (mt_ptr->command_name == NULL)
		)
		{
		    g_free(mt_ptr->command);
		    mt_ptr->command = NULL;
		    g_free(mt_ptr->command_name);
		    mt_ptr->command_name = NULL;
		    mt_ptr->total_commands = 0;
		}
	    }
	    else
	    {
		mt_ptr->total_commands = 0;
		g_free(mt_ptr->command);
		mt_ptr->command = NULL;
		g_free(mt_ptr->command_name);
		mt_ptr->command_name = NULL;
	    }

	    /* Get command and command name values from clist */
	    if(mt_ptr->total_commands > 0)
	    {
		for(i = 0; i < clist->rows; i++)
		{
		    /* Get text from each cell, we know that the cells
		     * are of type GTK_CELLTYPE_TEXT
		     */
		    EditCListGetCellText(
			eclist, i, 0, &s
		    );
		    mt_ptr->command_name[i] = STRDUP(s);

		    EditCListGetCellText(
			eclist, i, 1, &s
		    );
		    mt_ptr->command[i] = STRDUP(s);
		}
	    }
	}

	/* Begin applying icons file paths */

	/* Small icon */
	ei = ew->icon_small;
	if(ei != NULL)
	{
	    gint i;
	    const gchar *s;

	    for(i = 0; i < EDV_MIMETYPE_TOTAL_ICON_STATES; i++)
	    {
		s = ei->path[i];

		g_free(mt_ptr->small_icon_file[i]);
		mt_ptr->small_icon_file[i] = STRDUP(s);
	    }
	}

	/* Medium icon */
	ei = ew->icon_medium;
	if(ei != NULL)
	{
	    gint i;
	    const gchar *s;

	    for(i = 0; i < EDV_MIMETYPE_TOTAL_ICON_STATES; i++)
	    {
		s = ei->path[i];

		g_free(mt_ptr->medium_icon_file[i]);
		mt_ptr->medium_icon_file[i] = STRDUP(s);
	    }
	}

	/* Large icon */
	ei = ew->icon_large;
	if(ei != NULL)
	{
	    gint i;
	    const gchar *s;

	    for(i = 0; i < EDV_MIMETYPE_TOTAL_ICON_STATES; i++)
	    {
		s = ei->path[i];

		g_free(mt_ptr->large_icon_file[i]);
		mt_ptr->large_icon_file[i] = STRDUP(s);
	    }
	}

	/* Update time stamps */
	mt_ptr->access_time =
	mt_ptr->modify_time =
	mt_ptr->change_time = time(NULL);

	/* Check all of the MIME Type's values to see if they are any
	 * problems
	 */
	EDVMimeTypesEditWinCheckMIMEType(
	    core_ptr,
	    core_ptr->mimetype, core_ptr->total_mimetypes,
	    mt_num,
	    TRUE, ew->toplevel
	);


	/* Reset has changes marker */
	EDVMimeTypesEditWinResetHasChanges(ew, FALSE);


	/* Re-realize the MIME Type */
	EDVMimeTypeRealize(mt_ptr, TRUE);

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

/*
 *      MIME Types edit window Cancel button callback.
 */
static void EDVMimeTypesEditWinCancelCB(
	GtkWidget *widget, gpointer data
)
{
	edv_mimetype_editwin_struct *ew = EDV_MIMETYPE_EDITWIN(data);
	if(ew == NULL)
	    return;

	EDVMimeTypesEditWinUnmap(ew);
}

/*
 *	Returns one of EDV_MIMETYPE_CLASS_* depending on the value
 *	contained on class_combo that corresponds to an index who
 *	is a value of EDV_MIMETYPE_CLASS_*.
 */
static gint EDVMimeTypesEditWinGetClass(
	edv_mimetype_editwin_struct *ew
)
{
	gint mt_class = 0;
	GtkCombo *combo;


	if(ew == NULL)
	    return(mt_class);

	combo = (GtkCombo *)ew->class_combo;
	if(combo != NULL)
	{
	    GList *glist = GUIComboGetList(GTK_WIDGET(combo));
	    const gchar *s = gtk_entry_get_text(
		GTK_ENTRY(combo->entry)
	    );

	    /* Iterate through combo's list of strings, incrementing
	     * mt_class as each iteration corresponds to one index
	     */
	    if(!STRISEMPTY(s))
	    {
		while(glist != NULL)
		{
		    if(glist->data != NULL)
		    {
			if(!g_strcasecmp((const gchar *)glist->data, s))
			    break;
		    }
		    mt_class++;
		    glist = g_list_next(glist);
		}
	    }
	}

	return(mt_class);
}

/*
 *      Returns one of EDV_MIMETYPE_HANDLER_* depending on the value
 *      contained on handler_combo that corresponds to an index who
 *      is a value of EDV_MIMETYPE_HANDLER_*.
 */
static gint EDVMimeTypesEditWinGetHandler(
	edv_mimetype_editwin_struct *ew
)
{
	gint handler = 0;
	const gchar *s, *s2;
	const GList *glist;
	GtkCombo *combo = (GtkCombo *)((ew != NULL) ?
	    ew->handler_combo : NULL
	);
	if(combo == NULL)
	    return(handler);

	glist = GUIComboGetList(GTK_WIDGET(combo));
	s = gtk_entry_get_text(GTK_ENTRY(combo->entry));

	/* Iterate through combo's list of strings, incrementing
	 * handler as each iteration corresponds to one index
	 */
	if(!STRISEMPTY(s))
	{
	    while(glist != NULL)
	    {
		s2 = (const gchar *)glist->data;
		if(s2 != NULL)
		{
		    if(!g_strcasecmp(s2, s))
			break;
		}
		handler++;
		glist = g_list_next(glist);
	    }
	}

	return(handler);
}


/*
 *	Checks all of the specified MIME Type's values to see if they
 *	are any problems
 *
 *	Returns non-zero if there was a problem.
 */
static gint EDVMimeTypesEditWinCheckMIMEType(
	edv_core_struct *core_ptr,
	edv_mimetype_struct **list, gint total,
	gint mt_num,
	gboolean verbose, GtkWidget *toplevel
)
{
	gint i, status = 0;
	edv_mimetype_class mt_class;
	const gchar *type, *val, *desc;
	edv_mimetype_handler handler;
	const gchar *title =
#if defined(PROG_LANGUAGE_SPANISH)
"MIME Type Advertencia"
#elif defined(PROG_LANGUAGE_FRENCH)
"MIME Type Avertissement"
#elif defined(PROG_LANGUAGE_GERMAN)
"MIME Type Warnen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"MIME Type L'avvertimento"
#elif defined(PROG_LANGUAGE_DUTCH)
"MIME Type Waarschuwen"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"MIME Type Aviso"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"MIME Type Varsling"
#else
"MIME Type Warning"
#endif
	;
	edv_mimetype_struct *mt_ptr;


	if((core_ptr == NULL) || (list == NULL))
	    return(status);

	/* Get pointer to the MIME Type from the MIME Types list */
	mt_ptr = ((mt_num >= 0) && (mt_num < total)) ?
	    list[mt_num] : NULL;
	/* Not in the list? */
	if(mt_ptr == NULL)
	{
	    status = -1;
	    if(verbose)
	    {
		gchar *buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"MIME Type con el índice #%i no está en la lista"
#elif defined(PROG_LANGUAGE_FRENCH)
"MIME Type avec #%i d'index n'est pas dans la liste"
#elif defined(PROG_LANGUAGE_GERMAN)
"MIME Type mit index #%i ist nicht in der liste"
#elif defined(PROG_LANGUAGE_ITALIAN)
"MIME Type con #%i di indice non è nell'elenco"
#elif defined(PROG_LANGUAGE_DUTCH)
"MIME Type met index #%i is niet in de lijst"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"MIME Type com #%i de índice não está na lista"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"MIME Type med indeks #%i er ikke i listen"
#else
"MIME Type with index #%i is not in the list"
#endif
		    , mt_num
		);
		EDVPlaySoundError(core_ptr);
		EDVMessageError(title, buf, NULL, toplevel);
		g_free(buf);
	    }
	    return(status);
	}

	/* Get MIME Type's values */
	mt_class = mt_ptr->mt_class;
	type = mt_ptr->type;
	val = mt_ptr->value;
	desc = mt_ptr->description;
	handler = mt_ptr->handler;

	/* Check the MIME Type's type and value
	 *
	 * Handle by the MIME Type class
	 */
	switch(mt_class)
	{
	  case EDV_MIMETYPE_CLASS_SYSTEM:
	    /* Is the Type defined? */
	    if(STRISEMPTY(type))
	    {
		status = -2;
		if(verbose)
		{
		    gchar *buf = STRDUP(
"The MIME Type's Type is not set, there will be no way to\n\
identify this MIME Type"
		    );
		    EDVPlaySoundWarning(core_ptr);
		    EDVMessageWarning(title, buf, NULL, toplevel);
		    g_free(buf);
		}
	    }
	    /* Value is ignored */
	    break;

	  case EDV_MIMETYPE_CLASS_FORMAT:
	    /* Is the Type defined? */
	    if(STRISEMPTY(type))
	    {
		status = -2;
		if(verbose)
		{
		    gchar *buf = STRDUP(
"The MIME Type's Type is not set, there will be no way to\n\
identify this MIME Type"
		    );
		    EDVPlaySoundWarning(core_ptr);
		    EDVMessageWarning(title, buf, NULL, toplevel);
		    g_free(buf);
		}
	    }
	    /* Is the Value defined? */
	    if(STRISEMPTY(val))
	    {
		status = -2;
		if(verbose)
		{
		    gchar *buf = STRDUP(
"The MIME Type's Value is not set, this MIME Type will not\n\
identify any file formats"
		    );
		    EDVPlaySoundWarning(core_ptr);
		    EDVMessageWarning(title, buf, NULL, toplevel);
		    g_free(buf);
		}
	    }
	    /* Check handler */
	    if(handler == EDV_MIMETYPE_HANDLER_COMMAND)
	    {
		const gchar *cmd_name, *cmd;

		/* Check all defined commands */
		for(i = 0; i < mt_ptr->total_commands; i++)
		{
		    cmd_name = mt_ptr->command_name[i];
		    cmd = mt_ptr->command[i];
		    if(cmd == NULL)
			continue;

		    /* Does the command not start with a path
		     * deliminator, suggesting that it refers to another
		     * MIME Type?
		     */
		    if(*cmd != G_DIR_SEPARATOR)
		    {
			/* This MIME Type refers to another MIME Type,
			 * so check if that MIME Type exists in the list
			 */
			edv_mimetype_struct *m_ref = EDVMimeTypeMatchListByType(
			    list, total, NULL, cmd, TRUE
			);
			if(m_ref == NULL)
			{
			    /* Referenced MIME Type not found */
			    status = -2;
			    if(verbose)
			    {
			        gchar *buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Ordene reffers de \"%s\" a un MIME Type\n\
inexistente llamó \"%s\".\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ordonner reffers à \"%s\" à un MIME Type\n\
inexistant a appelé \"%s\".\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Befehlen Sie \"%s\" reffers zu einem nicht\n\
vorhandenen MIME Type hat gerufen \"%s\".\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Comandare il reffers di \"%s\" a un MIME Type\n\
non-esistente ha chiamato \"%s\".\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Beveel aan een onbestaande MIME Type\n\
\"%s\" reffers riep \"%s\".\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Comande reffers de \"%s\" a um MIME Type\n\
inexistente chamou \"%s\".\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kommander \"%s\" reffers til en\n\
ikke-eksisterende MIME Type kalt \"%s\".\n"
#else
"Command \"%s\" reffers to a non-existent MIME Type\n\
called \"%s\".\n"
#endif
				    , cmd_name, cmd
				);
				EDVPlaySoundWarning(core_ptr);
				EDVMessageWarning(
				    title, buf, NULL,
				    toplevel
			        );
			        g_free(buf);
			    }
		        }
		    }
		}	/* Check all defined commands */ 
	    }
	    break;

	  case EDV_MIMETYPE_CLASS_PROGRAM:
	    /* Is the Type defined? */
	    if(STRISEMPTY(type))
	    {
		status = -2;
		if(verbose)
		{
		    gchar *buf = STRDUP(  
"The MIME Type's Type is not set, there will be no way to\n\
identify this MIME Type"
		    );
		    EDVPlaySoundWarning(core_ptr);
		    EDVMessageWarning(title, buf, NULL, toplevel);
		    g_free(buf);
		}
	    }
	    /* Is the Value defined and refers to an object that is
	     * executable?
	     */
	    if(!STRISEMPTY(val) ? access(val, X_OK) : TRUE)
	    {
		/* Value not defined, object does not exist, or object
		 * is not executable
		 */
		status = -2;
		if(verbose)
		{
		    gchar *buf;
		    if(STRISEMPTY(val))
#if defined(PROG_LANGUAGE_SPANISH)
			buf = STRDUP(
"La ubicación de objeto de aplicación no conjunto"
			);
#elif defined(PROG_LANGUAGE_FRENCH)
			buf = STRDUP(
"L'emplacement d'objet d'application pas série"
			);
#else
			buf = STRDUP(
"Location of application object not set"
			);
#endif
		    else
			buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"El objeto inválido de la aplicación:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"L'objet nul d'application:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Ungültiges anwendung objekt:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'oggetto di domanda di invalido:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Ongeldig toepassing voorwerp:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O objeto de aplicação de inválido:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Ugyldig anvendelses objekt:\n\
\n\
    %s\n"
#else
"Invalid application object:\n\
\n\
    %s\n"
#endif
			    , val
			);
		    EDVPlaySoundWarning(core_ptr);
		    EDVMessageWarning(
			title, buf,
#if defined(PROG_LANGUAGE_SPANISH)
"El objeto de la aplicación no se define, no existe, ni no es puesto\n\
executable. También, se cerciora que usted especifica un sendero\n\
repleto al objeto de la aplicación.\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"L'objet d'application n'est pas défini, ne pas existe, ou n'est pas\n\
réglé executable. Aussi, s'assure que vous spécifiez un sentier plein\n\
à l'objet d'application.\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Das anwendung objekt ist nicht definiert, existiert nicht, oder ist\n\
nicht ausführbar gesetzt. Vergewissern sie auch sich, daß Sie einen\n\
vollen pfad zum anwendung objekt angeben.\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'oggetto di domanda non è definito, non esiste, o non è regolato\n\
eseguibile. , Assicura anche che lei specifica un sentiero pieno\n\
all'oggetto di domanda.\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Het toepassing voorwerp is niet gedefinieerd, niet bestaat of niet\n\
is uitvoerbaar gezet. Vergewis ook zich ervan dat u een vol pad aan\n\
het toepassing voorwerp specificeert.\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O objeto de aplicação não é definido, não existe, nem não é posto\n\
executable. Também, assegure-se que especifica um pleno caminho ao\n\
objeto de aplicação.\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Anvendelsesobjektet ikke-definert, finnes ikke, eller ikke setter\n\
gjennomførbar. Sjekk også at De spesifiserer en full sti til\n\
anvendelses objektet.\n"
#else
"The application object is not defined, does not exist, or is not\n\
set executable. Also, make sure that you specify a full path to\n\
the application object.\n"
#endif
			, toplevel
		    );
		    g_free(buf);
		}
	    }
	    /* Is the handler set to EDV_MIMETYPE_HANDLER_COMMAND and
	     * does it have at least one defined command?
	     */
	    if((handler == EDV_MIMETYPE_HANDLER_COMMAND) ?
		(mt_ptr->total_commands < 1) : FALSE
	    )
	    {
		status = -2;
		if(verbose)
		{
		    gchar *buf;
#if defined(PROG_LANGUAGE_SPANISH)
			buf = STRDUP(
"Ninguna orden se ha definido en esta clase de la\n\
aplicación MIME Type, este MIME Type no será capaz de\n\
ejecutar la aplicación reffers a."
			);
#elif defined(PROG_LANGUAGE_FRENCH)
			buf = STRDUP(
"Aucun ordre a été défini sur ce MIME Type de\n\
classe d'application, ce MIME Type ne pourra pas\n\
exécuter l'application il reffers à."
			);
#else
			buf = STRDUP(
"No command has been defined on this application\n\
class MIME Type, this MIME Type will not be able to\n\
execute the application it reffers to."
			);
#endif
		    EDVPlaySoundWarning(core_ptr);
		    EDVMessageWarning(title, buf, NULL, toplevel);
		    g_free(buf);
		}
	    }
	    break;

	  case EDV_MIMETYPE_CLASS_UNIQUE:
	    /* Is the Type defined? */
	    if(STRISEMPTY(type))
	    {
		status = -2;
		if(verbose)
		{
		    gchar *buf = STRDUP(
"The MIME Type's Type is not set, there will be no way to\n\
identify this MIME Type"
		    );
		    EDVPlaySoundWarning(core_ptr);
		    EDVMessageWarning(title, buf, NULL, toplevel);
		    g_free(buf);
		}
	    }
	    /* Is the Value defined and reffers to a valid object? */
	    if(!STRISEMPTY(val) ? access(val, F_OK) : TRUE)
	    {
		status = -2;
		if(verbose)
		{
		    gchar *buf;
		    if(STRISEMPTY(val))
#if defined(PROG_LANGUAGE_SPANISH)
			buf = STRDUP(
"La ubicación de objeto extraordinario no conjunto"
			);
#elif defined(PROG_LANGUAGE_FRENCH)
			buf = STRDUP(
"L'emplacement d'objet unique pas série"
			);
#else
			buf = STRDUP(
"Location of specific object not set"
			);
#endif
		    else
			buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Incapaz de encontrar objeto:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Incapable de trouver objec:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_GERMAN)
"Unfähig, objec zu finden:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Incapace per trovare l'objec:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_DUTCH)
"Onbekwaam objec te vinden:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Incapaz de achar objec:\n\
\n\
    %s\n"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Maktesløs finne objec:\n\
\n\
    %s\n"
#else
"Unable to find object:\n\
\n\
    %s\n"
#endif
			    , val
			);
		    EDVPlaySoundWarning(core_ptr);
		    EDVMessageWarning(
			title, buf,
#if defined(PROG_LANGUAGE_SPANISH)
"El objeto extraordinario no se define ni no aparece existir. Si\n\
se define y existe, entonces cheque si sus permisos no permiten\n\
ser conseguido acceso a."
#elif defined(PROG_LANGUAGE_FRENCH)
"L'objet unique n'est pas défini ou n'apparaît pas d'exister. S'il\n\
est défini et existe, alors le chèque si ses permissions ne\n\
permettent pas il être accessed."
#elif defined(PROG_LANGUAGE_GERMAN)
"Das spezifische objekt ist nicht definiert oder nicht erscheint zu\n\
existieren. Wenn es dann kontrolle definiert und ist existiert ist,\n\
wenn seine erlaubnis nicht erlaubt, daß es auf zugegriffen wird.\n"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'oggetto specifico non è definito o non appare esistere. Se è\n\
definito ed esiste poi l'assegno se i suoi permessi non lasciano che\n\
esso essere accesso a."
#elif defined(PROG_LANGUAGE_DUTCH)
"Het specifiek voorwerp is niet gedefinieerd of niet verschijnt te\n\
bestaan. Indien het dan controle gedefinieerd en is bestaan is indien\n\
zijne toestemmingen niet toestaan dat het toegang tot te worden\n\
gehad."
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O objeto específico não é definido nem não aparece existir. Se é\n\
definido e existe então cheque se seuas permissões não permitem ser\n\
acedido."
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Det spesifikke ikke-definerte objektet eller kommer ikke fram\n\
dinnes. Om det definerer og finnes da kontroll om dets tillatelse\n\
ikke tillater det kommet til."
#else
"The specific object is not defined or does not appear to exist. If\n\
it is defined and exists then check if its permissions do not\n\
allow it to be accessed."
#endif
			, toplevel
		    );
		    g_free(buf);
		}
	    }
	    break;

	  default:
	    status = -2;
	    if(verbose)
	    {
		gchar *buf = g_strdup_printf(
#if defined(PROG_LANGUAGE_SPANISH)
"Código `%i' no apoyado de clase de MIME Type.\n"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le code `%i' non soutenu de classe de MIME Type.\n"
#else
"Unsupported MIME Type class code `%i'.\n"
#endif
		    , mt_class
		);
		EDVPlaySoundError(core_ptr);
		EDVMessageError(title, buf, NULL, toplevel);
		g_free(buf);
	    }
	    break;
	}

	return(status);
}

/*
 *	Loads the MIME Type values from the structure specified by the index
 *	mt_num on the core structure on the given edit window.
 */
void EDVMimeTypesEditWinFetchValues(
	edv_mimetype_editwin_struct *ew, gint mt_num
)
{
	GtkEntry *entry;
	GtkCombo *combo;
	GtkCList *clist;
	editclist_struct *eclist;
	edv_mimetype_struct *mt_ptr;
	edv_core_struct *core_ptr;
	edv_mimetype_icon_picker_struct *ei;

	if(ew == NULL)
	    return;

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

	/* Get pointer to MIME Type structure on core's MIME Types list */
	if((mt_num < 0) || (mt_num >= core_ptr->total_mimetypes))
	    return;
	else
	    mt_ptr = core_ptr->mimetype[mt_num];
	if(mt_ptr == NULL)
	    return;


	/* Begin fetching values */

	/* Set MIME Type index on core structure from the given mt_num */
	ew->mt_num = mt_num;

	/* Class */
	combo = (GtkCombo *)ew->class_combo;
	if(combo != NULL)
	{
	    gint i = 0;
	    const gchar *class_str = NULL;
	    GList *glist = GUIComboGetList(GTK_WIDGET(combo));

	    entry = GTK_ENTRY(combo->entry);

	    /* Find class string as the index value from the MIME Type
	     * structure's class in the combo's list of strings
	     */
	    while(glist != NULL)
	    {
		if(i == mt_ptr->mt_class)
		{
		    class_str = (const gchar *)glist->data;
		    break;
		}

		i++;
		glist = g_list_next(glist);
	    }

	    /* Check if a class string was matched, in which case we
	     * update the combo's entry widget value with it
	     */
	    if(class_str != NULL)
		gtk_entry_set_text(entry, class_str);
	}

	/* Type */
	entry = (GtkEntry *)ew->type_entry;
	if(entry != NULL)
	{
	    gtk_entry_set_text(
		entry,
		(mt_ptr->type != NULL) ? mt_ptr->type : ""
	    );
	}

	/* Value */
	entry = (GtkEntry *)ew->value_entry;
	if(entry != NULL)
	{
	    gtk_entry_set_text(
		entry,
		(mt_ptr->value != NULL) ? mt_ptr->value : ""
	    );
	}

	/* Description */
	entry = (GtkEntry *)ew->description_entry;
	if(entry != NULL)
	{
	    gtk_entry_set_text(
		entry,
		(mt_ptr->description != NULL) ? mt_ptr->description : ""
	    );
	}


	/* Handler */
	combo = (GtkCombo *)ew->handler_combo;
	if(combo != NULL)
	{
	    gint i = 0;
	    const gchar *handler_str = NULL;
	    GList *glist = GUIComboGetList(GTK_WIDGET(combo));

	    entry = GTK_ENTRY(combo->entry);

	    /* Find handler string as the index value from the MIME Type
	     * structure's handler in the combo's list of strings
	     */
	    while(glist != NULL)
	    {
		if(i == mt_ptr->handler)
		{
		    handler_str = (const gchar *)glist->data;
		    break;
		}

		i++;
		glist = g_list_next(glist);
	    }

	    /* Check if a handler string was matched, in which case we
	     * update the combo's entry widget value with it
	     */
	    if(handler_str != NULL)
		gtk_entry_set_text(entry, handler_str);
	}


	/* Commands */
	eclist = ew->editclist;
	clist = (GtkCList *)EditCListGetCList(eclist);
	if(clist != NULL)
	{
	    gint i, row;

	    gtk_clist_freeze(clist);

	    /* Clear list */
	    EditCListClear(eclist);

	    /* Append new rows */
	    for(i = 0; i < mt_ptr->total_commands; i++)
	    {
		row = EditCListAppendRow(eclist);
		EditCListSetCellText(
		    eclist, row, 0,
		    mt_ptr->command_name[i]
		);
		EditCListSetCellText(
		    eclist, row, 1,
		    mt_ptr->command[i]
		);
	    }

	    gtk_clist_thaw(clist);
	}


	/* Begin loading icons */

#define DO_LOAD_ICON	{				\
 gint i;						\
 for(i = 0; i < EDV_MIMETYPE_TOTAL_ICON_STATES; i++) {	\
  /* Unref existing pixmap and mask on the Edit		\
   * Window's Icon Picker				\
   */							\
  if(ei->pixmap[i] != NULL)				\
   gdk_pixmap_unref(ei->pixmap[i]);			\
  if(ei->mask[i] != NULL)				\
   gdk_bitmap_unref(ei->mask[i]);			\
							\
  /* Increase ref count on new pixmap and mask and set	\
   * if to the Edit Window's Icon Picker		\
   */							\
  if(pixmap[i] != NULL)					\
   gdk_pixmap_ref(pixmap[i]);				\
  if(mask[i] != NULL)					\
   gdk_bitmap_ref(mask[i]);				\
							\
  ei->pixmap[i] = pixmap[i];				\
  ei->mask[i] = mask[i];				\
							\
  /* Set icon path */					\
  g_free(ei->path[i]);					\
  ei->path[i] = STRDUP(path[i]);			\
 }							\
}

	/* Small icons */
	ei = ew->icon_small;
	if(ei != NULL)
	{
	    GdkPixmap **pixmap = mt_ptr->small_pixmap;
	    GdkBitmap **mask = mt_ptr->small_mask;
	    gchar **path = mt_ptr->small_icon_file;

	    if(ei->adj != NULL)
		ei->adj->value = 0.0f;

	    DO_LOAD_ICON

	    if(ei->adj != NULL)
		EDVMimeTypesEditIconUpdateDisplay(
		    ei, (edv_mimetype_icon_state)ei->adj->value
		);
	}

	/* Medium icons */
	ei = ew->icon_medium;
	if(ei != NULL)
	{
	    GdkPixmap **pixmap = mt_ptr->medium_pixmap;
	    GdkBitmap **mask = mt_ptr->medium_mask;
	    gchar **path = mt_ptr->medium_icon_file;

	    if(ei->adj != NULL)
		ei->adj->value = 0.0f;

	    DO_LOAD_ICON

	    if(ei->adj != NULL)
		EDVMimeTypesEditIconUpdateDisplay(
		    ei, (edv_mimetype_icon_state)ei->adj->value
		);
	}

	/* Large icons */
	ei = ew->icon_large;
	if(ei != NULL)
	{
	    GdkPixmap **pixmap = mt_ptr->large_pixmap;
	    GdkBitmap **mask = mt_ptr->large_mask;
	    gchar **path = mt_ptr->large_icon_file;

	    if(ei->adj != NULL)
		ei->adj->value = 0.0f;

	    DO_LOAD_ICON

	    if(ei->adj != NULL)
		EDVMimeTypesEditIconUpdateDisplay(
		    ei, (edv_mimetype_icon_state)ei->adj->value
		);
	}

#undef DO_LOAD_ICON


	EDVMimeTypesEditWinUpdateMenus(ew);
}


/*
 *      Notifies the given MIME Types list window that the given MIME Type
 *      has been removed.
 */
void EDVMimeTypesEditWinMimeTypeRemovedCB(
	edv_mimetype_editwin_struct *ew, gint mt_num
)
{
	if(ew == NULL)
	    return;

	/* If the removed MIME Type is the MIME Type that this edit window
	 * is displaying values for then this edit window needs to be
	 * unmapped
	 */
	if(ew->mt_num == mt_num)
	{
	    ew->mt_num = -1;
	    EDVMimeTypesEditWinUnmap(ew);
	}
}


/*
 *	Creates a new Icon Picker.
 */
static edv_mimetype_icon_picker_struct *EDVMimeTypesEditIconNew(
	gpointer editwin, GtkWidget *parent, const gchar *title,
	gint icon_width, gint icon_height,
	gint btn_width, gint btn_height
)
{
	gint bw = 20, bh = 20;
	GtkAdjustment *adj;
	GtkWidget *w, *parent2, *parent3, *parent4;
	edv_mimetype_icon_picker_struct *ei = EDV_MIMETYPE_ICON_PICKER(
	    g_malloc0(sizeof(edv_mimetype_icon_picker_struct))
	);
	if(ei == NULL)
	    return(ei);

	/* Reset values */
	ei->editwin = editwin;
	ei->icon_width = icon_width;
	ei->icon_height = icon_height;

	/* Create adjustment for keeping track of displayed icon */
	ei->adj = adj = (GtkAdjustment *)gtk_adjustment_new(
	    0.0f,		/* Value */
	    0.0f,		/* Lower */
	    (gfloat)EDV_MIMETYPE_TOTAL_ICON_STATES - 1.0f,	/* Upper */
	    1.0f, 1.0f,		/* Step and page increments */
	    1.0f		/* Page size */
	);

	/* Create toplevel */
	ei->toplevel = w = gtk_vbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* Hbox for title label */
	w = gtk_hbox_new(FALSE, 0);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
	/* Label */
	w = gtk_label_new(title);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);


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

	/* Create button */
	ei->button = w = gtk_button_new();
	gtk_widget_set_usize(w, btn_width, btn_height);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditIconChangeCB), ei
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, FALSE, 0);
	gtk_widget_show(w);
	parent3 = w;
#if 0
	ei->gtk_pixmap = w = gtk_pixmap_new(NULL, NULL);
	gtk_container_add(GTK_CONTAINER(parent3), w);
	gtk_widget_show(w);
#endif


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


	/* Left button */
	ei->left_btn = w = gtk_button_new();
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditIconPrevCB), ei
	);
	gtk_widget_set_usize(w, bw, bh);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Arrow */
	w = gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_OUT);
	gtk_container_add(GTK_CONTAINER(parent4), w);
	gtk_widget_show(w);

	/* Frame for state label */
	w = gtk_frame_new(NULL);
	gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_OUT);
	gtk_widget_set_usize(w, 80, -1);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* State label */
	ei->state_label = w = gtk_label_new("");
	gtk_container_add(GTK_CONTAINER(parent4), w);
	gtk_widget_show(w);

	/* Right button */
	ei->right_btn = w = gtk_button_new();
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditIconNextCB), ei
	);
	gtk_widget_set_usize(w, bw, bh);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;
	/* Arrow */
	w = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
	gtk_container_add(GTK_CONTAINER(parent4), w);
	gtk_widget_show(w);


	return(ei);
}

/*
 *	Deletes the Icon Picker.
 */
static void EDVMimeTypesEditIconDelete(edv_mimetype_icon_picker_struct *ei)
{
	gint i;

	if(ei == NULL)
	    return;

	/* Unref all loaded pixmap and mask pairs */
	for(i = 0; i < EDV_MIMETYPE_TOTAL_ICON_STATES; i++)
	{
	    GDK_PIXMAP_UNREF(ei->pixmap[i])
	    GDK_BITMAP_UNREF(ei->mask[i])
	    g_free(ei->path[i]);
	}

	/* Begin destroying widgets */
	GTK_WIDGET_DESTROY(ei->gtk_pixmap)
	GTK_WIDGET_DESTROY(ei->button)
	GTK_WIDGET_DESTROY(ei->left_btn)
	GTK_WIDGET_DESTROY(ei->right_btn)
	GTK_WIDGET_DESTROY(ei->state_label)
	GTK_WIDGET_DESTROY(ei->toplevel)

	GTK_OBJECT_UNREF(ei->adj)

	g_free(ei);
}


/*
 *	Creates a new MIME Types edit window.
 */
edv_mimetype_editwin_struct *EDVMimeTypesEditWinNew(
	gpointer core_ptr, gpointer listwin
)
{
	const gint border_major = 5;
	gchar *heading[2];
	gpointer combo_rtn, entry_rtn, label_rtn;
	GList *glist;
	GdkWindow *window;
	GtkAccelGroup *accelgrp;
	GtkWidget *w, *parent, *parent2, *parent3, *parent4;
	GtkCombo *combo;
	GtkCList *clist;
	editclist_struct *eclist;
	edv_mimetype_editwin_struct *ew = EDV_MIMETYPE_EDITWIN(
	    g_malloc0(sizeof(edv_mimetype_editwin_struct))
	);
	if(ew == NULL)
	    return(ew);

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

	ew->listwin = listwin;

	ew->has_changes = FALSE;
	ew->title = NULL;

	ew->mt_num = -1;


	/* Set title */
	ew->title = STRDUP(EDITWIN_TITLE);


	/* Begin creating widgets */

	/* Toplevel */
	ew->toplevel = w = gtk_window_new(GTK_WINDOW_DIALOG);
	gtk_widget_set_usize(w, EDITWIN_WIDTH, EDITWIN_HEIGHT);
	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 **)icon_mimetypes_48x48_xpm);
	}
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_event",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinDeleteEventCB), ew
	);
	gtk_container_border_width(GTK_CONTAINER(w), 0);
	gtk_window_add_accel_group(GTK_WINDOW(w), accelgrp);
	parent = w;


	/* Main vbox */
	ew->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 to split things into two columns */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent2 = w;


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


	/* Class Frame */
	w = gtk_frame_new(
#if defined(PROG_LANGUAGE_SPANISH)
"La Clase"
#elif defined(PROG_LANGUAGE_FRENCH)
"Classe"
#elif defined(PROG_LANGUAGE_GERMAN)
"Klasse"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Classe"
#elif defined(PROG_LANGUAGE_DUTCH)
"Klas"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"A Classe"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Klasse"
#else
"Class"
#endif
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

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

	/* Create class strings glist */
	glist = NULL;
#if defined(PROG_LANGUAGE_SPANISH)
glist = g_list_append(glist, "El Sistema De Tipo Objeto");
glist = g_list_append(glist, "El Formato Del Archivo");
glist = g_list_append(glist, "La Aplicación");
glist = g_list_append(glist, "El Objeto Específico");
#elif defined(PROG_LANGUAGE_FRENCH)
glist = g_list_append(glist, "Le Type D'Objet De Système");
glist = g_list_append(glist, "Format De Fichier");
glist = g_list_append(glist, "Application");
glist = g_list_append(glist, "Objet Spécifique");
#elif defined(PROG_LANGUAGE_GERMAN)
glist = g_list_append(glist, "Systemobjekt Typ");
glist = g_list_append(glist, "Dateiformat");
glist = g_list_append(glist, "Anwendung");
glist = g_list_append(glist, "Spezifisches Objekt");
#elif defined(PROG_LANGUAGE_ITALIAN)
glist = g_list_append(glist, "Il Tipo Di Oggetto Di Sistema");
glist = g_list_append(glist, "Schedare Il Formato");
glist = g_list_append(glist, "La Domanda");
glist = g_list_append(glist, "L'Oggetto Specifico");
#elif defined(PROG_LANGUAGE_DUTCH)
glist = g_list_append(glist, "Systeemvoorwerp Type");
glist = g_list_append(glist, "Archiveer Formaat");
glist = g_list_append(glist, "Toepassing");
glist = g_list_append(glist, "Specifiek Voorwerp");
#elif defined(PROG_LANGUAGE_PORTUGUESE)
glist = g_list_append(glist, "O Tipo De Objeto De Sistema");
glist = g_list_append(glist, "Arquive Formato");
glist = g_list_append(glist, "A Aplicação");
glist = g_list_append(glist, "Objeto Específico");
#elif defined(PROG_LANGUAGE_NORWEGIAN)
glist = g_list_append(glist, "SystemobjektType");
glist = g_list_append(glist, "Arkiver Format");
glist = g_list_append(glist, "Anvendelse");
glist = g_list_append(glist, "Spesifikt Objekt");
#else
glist = g_list_append(glist, "System Object Type");
glist = g_list_append(glist, "File Format");
glist = g_list_append(glist, "Application");
glist = g_list_append(glist, "Specific Object");
#endif
	/* Class combo */
	w = GUIComboCreate(
	    NULL,
	    (const gchar *)((glist != NULL) ? glist->data : NULL),
	    glist,			/* List */
	    g_list_length(glist),	/* Items in list */
	    &combo_rtn,
	    ew,
	    NULL,
	    NULL
	);
	g_list_free(glist);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);

	ew->class_combo = w = (GtkWidget *)combo_rtn;
	combo = GTK_COMBO(w);

	w = combo->entry;
	gtk_entry_set_editable(GTK_ENTRY(w), FALSE);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinAnyChangedCB), ew
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinClassChangedCB), ew
	);


	/* Identification frame */
	w = gtk_frame_new(
#if defined(PROG_LANGUAGE_SPANISH)
"Identificación"
#elif defined(PROG_LANGUAGE_FRENCH)
"Identification"
#elif defined(PROG_LANGUAGE_GERMAN)
"Identifikation"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'Identificazione"
#elif defined(PROG_LANGUAGE_DUTCH)
"Identificatie"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"A Identificação"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Identification"
#else
"Identification"
#endif
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

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

	/* Type entry */
	w = GUIPromptBar(
	    NULL,
#if defined(PROG_LANGUAGE_SPANISH)
"El Tipo"
#elif defined(PROG_LANGUAGE_FRENCH)
"Type"
#elif defined(PROG_LANGUAGE_GERMAN)
"Typ"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Tipo"
#elif defined(PROG_LANGUAGE_DUTCH)
"Type"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Tipo"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Type"
#else
"Type"
#endif
	    ":", NULL, &entry_rtn
	);
	ew->type_entry = (GtkWidget *)entry_rtn;
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);

	w = (GtkWidget *)entry_rtn;
	EDVEntrySetDND(EDV_CORE(core_ptr), w);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinAnyChangedCB), ew
	);


	/* Value entry */
	w = GUIPromptBar(
	    NULL,
#if defined(PROG_LANGUAGE_SPANISH)
"El Valor"
#elif defined(PROG_LANGUAGE_FRENCH)
"Valeur"
#elif defined(PROG_LANGUAGE_GERMAN)
"Wert"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Valore"
#elif defined(PROG_LANGUAGE_DUTCH)
"Waarde"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Valor"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Verdi"
#else
"Value"
#endif
	    ":", &label_rtn, &entry_rtn
	);
	ew->value_label = (GtkWidget *)label_rtn;
	ew->value_entry = (GtkWidget *)entry_rtn;
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);

	w = (GtkWidget *)entry_rtn;
	EDVEntrySetDND(EDV_CORE(core_ptr), w);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinAnyChangedCB), ew
	);


	/* Description entry */
	w = GUIPromptBar(
	    NULL,
#if defined(PROG_LANGUAGE_SPANISH)
"La Descripción"
#elif defined(PROG_LANGUAGE_FRENCH)
"Description"
#elif defined(PROG_LANGUAGE_GERMAN)
"Beschreibung"
#elif defined(PROG_LANGUAGE_ITALIAN)
"La Descrizione"
#elif defined(PROG_LANGUAGE_DUTCH)
"Beschrijving"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"A Descrição"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Beskrivelse"
#else
"Description"
#endif
	    ":", NULL, &entry_rtn
	);
	ew->description_entry = (GtkWidget *)entry_rtn;
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);

	w = (GtkWidget *)entry_rtn;
	EDVEntrySetDND(EDV_CORE(core_ptr), w);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinAnyChangedCB), ew
	);


	/* Handler frame */
	w = gtk_frame_new(
#if defined(PROG_LANGUAGE_SPANISH)
"El Tratante"
#elif defined(PROG_LANGUAGE_FRENCH)
"Agent"
#elif defined(PROG_LANGUAGE_GERMAN)
"Behandler"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'Addestratore"
#elif defined(PROG_LANGUAGE_DUTCH)
"Handler"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Manipulador"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Behandler"
#else
"Handler"
#endif
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

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


	/* Create handlers list */
	glist = NULL;
#if defined(PROG_LANGUAGE_SPANISH)
glist = g_list_append(glist, "La Orden");
glist = g_list_append(glist, "Endeavour El Fabricante Del Archivo");
glist = g_list_append(glist, "Endeavour Imagine A Examinador");
glist = g_list_append(glist, "Endeavour Recicle Cajón");
#elif defined(PROG_LANGUAGE_FRENCH)
glist = g_list_append(glist, "Ordre");
glist = g_list_append(glist, "Endeavour Archiver Fabricant");
glist = g_list_append(glist, "Endeavour Navigateur D'Image");
glist = g_list_append(glist, "Endeavour Recycler L'Huche");
#elif defined(PROG_LANGUAGE_GERMAN)
glist = g_list_append(glist, "Befehl");
glist = g_list_append(glist, "Endeavour Archivieren Sie Hersteller");
glist = g_list_append(glist, "Endeavour Bildnis Browser");
glist = g_list_append(glist, "Endeavour Verwerten Sie Behälter Wieder");
#elif defined(PROG_LANGUAGE_ITALIAN)
glist = g_list_append(glist, "Il Comando");
glist = g_list_append(glist, "Endeavour Fabbricante Di Archivio");
glist = g_list_append(glist, "Endeavour Browser Di Immagine");
glist = g_list_append(glist, "Endeavour Contenitore Raccolta Differenziata");
#elif defined(PROG_LANGUAGE_DUTCH)
glist = g_list_append(glist, "Bevel");
glist = g_list_append(glist, "Endeavour Archief Maker");
glist = g_list_append(glist, "Endeavour Beeld Browser");
glist = g_list_append(glist, "Endeavour Recycl Bak");
#elif defined(PROG_LANGUAGE_PORTUGUESE)
glist = g_list_append(glist, "O Comando");
glist = g_list_append(glist, "Endeavour Criador De Arquivo");
glist = g_list_append(glist, "Endeavour Browser De Imagem");
glist = g_list_append(glist, "Endeavour Recicle Caixa");
#elif defined(PROG_LANGUAGE_NORWEGIAN)
glist = g_list_append(glist, "Kommando");
glist = g_list_append(glist, "Endeavour Arkiv Skaper");
glist = g_list_append(glist, "Endeavour Avbilde Browser");
glist = g_list_append(glist, "Endeavour Resirkulasjons Beholder");
#else
glist = g_list_append(glist, "Command");
glist = g_list_append(glist, "Endeavour Archiver");
glist = g_list_append(glist, "Endeavour Image Browser");
glist = g_list_append(glist, "Endeavour Recycle Bin");
#endif
	/* Handler combo */
	w = GUIComboCreate(
#if defined(PROG_LANGUAGE_SPANISH)
"Maneje Por"
#elif defined(PROG_LANGUAGE_FRENCH)
"Contrôler Par"
#elif defined(PROG_LANGUAGE_GERMAN)
"Behandeln Sie Durch"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Maneggiare Da"
#elif defined(PROG_LANGUAGE_DUTCH)
"Behandeel Door"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Manipule Por"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Håndter Ved"
#else
"Handle By"
#endif
	    ":",
	    (const gchar *)((glist != NULL) ? glist->data : NULL),
	    glist,			/* List */
	    g_list_length(glist),	/* Items in list */
	    &combo_rtn,
	    ew,
	    NULL,
	    NULL
	);
	g_list_free(glist);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);

	ew->handler_combo = w = (GtkWidget *)combo_rtn;
	combo = GTK_COMBO(w);

	w = combo->entry;
	gtk_entry_set_editable(GTK_ENTRY(w), FALSE);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinAnyChangedCB), ew
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "changed",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinHandlerChangedCB), ew
	);


	/* Commands editable clist */
#if defined(PROG_LANGUAGE_SPANISH)
heading[0] = "El Nombre";
heading[1] = "La Orden";
#elif defined(PROG_LANGUAGE_FRENCH)
heading[0] = "Nom";
heading[1] = "Ordre";
#elif defined(PROG_LANGUAGE_GERMAN)
heading[0] = "Name";
heading[1] = "Befehl";
#elif defined(PROG_LANGUAGE_ITALIAN)
heading[0] = "Il Nome";
heading[1] = "Il Comando";
#elif defined(PROG_LANGUAGE_DUTCH)
heading[0] = "Naam";
heading[1] = "Bevel";
#elif defined(PROG_LANGUAGE_PORTUGUESE)
heading[0] = "O Nome";
heading[1] = "O Comando";
#elif defined(PROG_LANGUAGE_NORWEGIAN)
heading[0] = "Navn";
heading[1] = "Kommando";
#else
heading[0] = "Name";
heading[1] = "Command";
#endif
	ew->editclist = eclist = EditCListNew(
	    parent4, -1, 120,
	    FALSE, FALSE, 0,
	    heading, 2
	);
	clist = (GtkCList *)EDITCLIST_CLIST(eclist);
	gtk_clist_set_column_width(clist, 0, 80);
	gtk_clist_set_column_width(clist, 1, 230);
	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);
	EditCListSetRowAddedCB(
	    eclist,
	    EDVMimeTypesEditWinECListRowAddedCB, ew
	);
	EditCListSetCellChangedCB(
	    eclist,
	    EDVMimeTypesEditWinECListCellChangedCB, ew
	);
	EditCListSetRowRemovedCB(
	    eclist,
	    EDVMimeTypesEditWinECListRowRemovedCB, ew
	);
	EditCListMap(eclist);



	/* Right side 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;

	/* Icons frame */
	w = gtk_frame_new(
#if defined(PROG_LANGUAGE_SPANISH)
"Iconos"
#elif defined(PROG_LANGUAGE_FRENCH)
"Icônes"
#elif defined(PROG_LANGUAGE_GERMAN)
"Abbilder"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Le Icone"
#elif defined(PROG_LANGUAGE_DUTCH)
"Beelden"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Os ícones"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Ikoner"
#else
"Icons"
#endif
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent4 = w;

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


	/* Create icon structures */
	ew->icon_large = EDVMimeTypesEditIconNew(
	    ew, parent4,
#if defined(PROG_LANGUAGE_SPANISH)
"Grande"
#elif defined(PROG_LANGUAGE_FRENCH)
"Grand"
#elif defined(PROG_LANGUAGE_GERMAN)
"Groß"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Grande"
#elif defined(PROG_LANGUAGE_DUTCH)
"Groot"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Grande"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Stor"
#else
"Large"
#endif
	    " 48x48:",
	    48, 48,
	    54, 54
	);
	ew->icon_medium = EDVMimeTypesEditIconNew(
	    ew, parent4,
#if defined(PROG_LANGUAGE_SPANISH)
"El Medio"
#elif defined(PROG_LANGUAGE_FRENCH)
"Milieu"
#elif defined(PROG_LANGUAGE_GERMAN)
"Medium"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Mezzo"
#elif defined(PROG_LANGUAGE_DUTCH)
"Middel"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Médio"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Middel"
#else
"Medium"
#endif
	    " 32x32:",
	    32, 32,
	    38, 38
	);
	ew->icon_small = EDVMimeTypesEditIconNew(
	    ew, parent4,
#if defined(PROG_LANGUAGE_SPANISH)
"Pequeño"
#elif defined(PROG_LANGUAGE_FRENCH)
"Petit"
#elif defined(PROG_LANGUAGE_GERMAN)
"Klein"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Piccolo"
#elif defined(PROG_LANGUAGE_DUTCH)
"Klein"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Pequeno"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Liten"
#else
"Small"
#endif
	    " 20x20:",
	    20, 20,
	    26, 26
	);


	/* 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(TRUE, 0);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* OK button */
	ew->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, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinOKCB), ew
	);
	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);

	/* Apply button */
	ew->apply_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_select_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Aplique"
#elif defined(PROG_LANGUAGE_FRENCH)
"S'Appliquer"
#elif defined(PROG_LANGUAGE_GERMAN)
"Verwenden"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Applicare"
#elif defined(PROG_LANGUAGE_DUTCH)
"Toepas"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Aplique"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Gjeld"
#else
"Apply"
#endif
	    , NULL
	);
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH_DEF, GUI_BUTTON_HLABEL_HEIGHT_DEF
	);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinApplyCB), ew
	);
	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);

	/* Cancel button */
	ew->cancel_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_cancel_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Cancele"
#elif defined(PROG_LANGUAGE_FRENCH)
"Annuler"
#elif defined(PROG_LANGUAGE_GERMAN)
"Heben"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Annullare"
#elif defined(PROG_LANGUAGE_DUTCH)
"Annuleer"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Cancelamento"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kanseller"
#else
"Cancel"
#endif
	    , NULL
	);
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH_DEF, GUI_BUTTON_HLABEL_HEIGHT_DEF
	);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinCancelCB), ew
	);
	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);

	/* Close button */
	ew->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_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVMimeTypesEditWinCancelCB), ew
	);
	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);


	EDVMimeTypesEditWinUpdateMenus(ew);


	return(ew);
}

/*
 *	Resets the MIME Types Edit Window's has changes marker.
 */
void EDVMimeTypesEditWinResetHasChanges(
	edv_mimetype_editwin_struct *ew, gboolean has_changes
)
{
	if(ew == NULL)
	    return;

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

	ew->has_changes = has_changes;
	EDVMimeTypesEditWinUpdateMenus(ew);
}

/*
 *	Updates the MIE Types Edit Window's widgets to reflect current
 *	values.
 */
void EDVMimeTypesEditWinUpdateMenus(edv_mimetype_editwin_struct *ew)
{
	gboolean	sensitive,
			has_changes;
	gint mt_num;
	const edv_mimetype_struct *mt_ptr;
	GtkWidget *w;
	editclist_struct *eclist;
	edv_core_struct *core_ptr;

	if(ew == NULL)
	    return;

	eclist = ew->editclist;
	core_ptr = EDV_CORE(ew->core_ptr);
	if((eclist == NULL) || (core_ptr == NULL))
	    return;

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

#define MAP(w)                  \
{ if((w) != NULL) { gtk_widget_show(w); } }
#define UNMAP(w)                \
{ if((w) != NULL) { gtk_widget_hide(w); } }

	/* Update title */
	w = ew->toplevel;
	if(w != NULL)
	{
	    gchar *title = g_strdup_printf(
		"%s%s",
		STRISEMPTY(ew->title) ? "Untitled" : ew->title,
		(has_changes) ? " (*)" : ""
	    );
	    gtk_window_set_title(GTK_WINDOW(w), title);
	    g_free(title);
	}

	/* Edit CList */
	EditCListUpdateMenus(eclist);

	/* Update OK, Apply, Save, Cancel Buttons */
	sensitive = has_changes;
	if(sensitive && (mt_ptr != NULL))
	    sensitive = !mt_ptr->read_only;
	GTK_WIDGET_SET_SENSITIVE(ew->ok_btn, sensitive)
	GTK_WIDGET_SET_SENSITIVE(ew->apply_btn, sensitive)

	if(has_changes)
	{
	    MAP(ew->cancel_btn);
	    UNMAP(ew->close_btn);
	}
	else
	{
	    UNMAP(ew->cancel_btn);
	    MAP(ew->close_btn);
	}
	sensitive = TRUE;
	GTK_WIDGET_SET_SENSITIVE(ew->cancel_btn, sensitive)
	GTK_WIDGET_SET_SENSITIVE(ew->close_btn, sensitive)

#undef UNMAP
#undef MAP
}

/*
 *	Checks if the MIME Types Edit Window is mapped.
 */
gboolean EDVMimeTypesEditWinIsMapped(
	edv_mimetype_editwin_struct *ew
)
{
	GtkWidget *w = (ew != NULL) ? ew->toplevel : NULL;
	return((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE);
}

/*
 *	Maps the MIME Types Edit Window.
 */
void EDVMimeTypesEditWinMap(
	edv_mimetype_editwin_struct *ew
)
{
	GtkWidget *w = (ew != NULL) ? ew->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_show_raise(w);

	w = ew->class_combo;
	w = GTK_COMBO(w)->entry;
	gtk_widget_grab_focus(w);
}

/*
 *	Unmaps the MIME Types Edit Window.
 */
void EDVMimeTypesEditWinUnmap(
	edv_mimetype_editwin_struct *ew
)
{
	GtkWidget *w = (ew != NULL) ? ew->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_hide(w);
}

/*
 *	Deletes the MIME Types Edit Window.
 */
void EDVMimeTypesEditWinDelete(
	edv_mimetype_editwin_struct *ew
)
{
	if(ew == NULL)
	    return;

	/* Delete edit icons */
	EDVMimeTypesEditIconDelete(ew->icon_small);
	ew->icon_small = NULL;
	EDVMimeTypesEditIconDelete(ew->icon_medium);
	ew->icon_medium = NULL;
	EDVMimeTypesEditIconDelete(ew->icon_large);
	ew->icon_large = NULL;

	/* Delete edit clist */
	EditCListDelete(ew->editclist);
	ew->editclist = NULL;

	/* Begin destroying widgets */
	GTK_WIDGET_DESTROY(ew->ok_btn)
	ew->ok_btn = NULL;
	GTK_WIDGET_DESTROY(ew->apply_btn)
	ew->apply_btn = NULL;
	GTK_WIDGET_DESTROY(ew->cancel_btn)
	ew->cancel_btn = NULL;
	GTK_WIDGET_DESTROY(ew->close_btn)
	ew->close_btn = NULL;

	GTK_WIDGET_DESTROY(ew->class_combo)
	ew->class_combo = NULL;
	GTK_WIDGET_DESTROY(ew->description_entry)
	ew->description_entry = NULL;
	GTK_WIDGET_DESTROY(ew->value_label)
	ew->value_label = NULL;
	GTK_WIDGET_DESTROY(ew->value_entry)
	ew->value_entry = NULL;

	GTK_WIDGET_DESTROY(ew->type_entry)
	ew->type_entry = NULL;
	GTK_WIDGET_DESTROY(ew->handler_combo)
	ew->handler_combo = NULL;

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

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

	g_free(ew->title);
	ew->title = NULL;

	g_free(ew);
}
