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

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

#include "edvtypes.h"
#include "edvdevices.h"
#include "deviceswin.h"
#include "endeavour.h"
#include "edvcb.h"
#include "edvutils.h"
#include "edvutilsgtk.h"
#include "edvcfglist.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_device_misc_48x48.xpm"


static void EDVIconPickerUpdateDisplay(
	edv_device_icon_picker_struct *ei, gint state
);
static void EDVIconPickerChangeIconCB(
	GtkWidget *widget, gpointer data
);
static void EDVIconPickerPreviousStateCB(
	GtkWidget *widget, gpointer data
);
static void EDVIconPickerNextStateCB(
	GtkWidget *widget, gpointer data
);

static void EDVDevicesEditWinBrowseProgramCB(
	GtkWidget *widget, gpointer data
);
static gint EDVDevicesEditWinDeleteEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
);
static void EDVDevicesEditWinAnyChangedCB(
	GtkWidget *widget, gpointer data
);
static void EDVDevicesEditWinOKCB(
	GtkWidget *widget, gpointer data
);
static void EDVDevicesEditWinApplyCB(
	GtkWidget *widget, gpointer data
);
static void EDVDevicesEditWinCancelCB(
	GtkWidget *widget, gpointer data
);

void EDVDevicesEditWinFetchValues(
	edv_device_editwin_struct *ew, gint dev_num
);
void EDVDevicesEditWinDeviceRemovedCB(
	edv_device_editwin_struct *ew, gint dev_num
);

static edv_device_icon_picker_struct *EDVDevicesEditIconNew(
	gpointer editwin, GtkWidget *parent, const gchar *title,
	gint icon_width, gint icon_height,
	gint btn_width, gint btn_height
);
static void EDVDevicesEditIconDelete(edv_device_icon_picker_struct *ei);

edv_device_editwin_struct *EDVDevicesEditWinNew(
	gpointer core_ptr, gpointer listwin
);
void EDVDevicesEditWinResetHasChanges(
	edv_device_editwin_struct *ew, gboolean has_changes
);
void EDVDevicesEditWinUpdateMenus(edv_device_editwin_struct *ew);
gboolean EDVDevicesEditWinIsMapped(edv_device_editwin_struct *ew);
void EDVDevicesEditWinMap(edv_device_editwin_struct *ew);
void EDVDevicesEditWinUnmap(edv_device_editwin_struct *ew);
void EDVDevicesEditWinDelete(edv_device_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

#if defined(PROG_LANGUAGE_SPANISH)
# define EDITWIN_TITLE		"El Dispositivo"
#elif defined(PROG_LANGUAGE_FRENCH)
# define EDITWIN_TITLE		"Appareil"
#elif defined(PROG_LANGUAGE_GERMAN)
# define EDITWIN_TITLE		"Vorrichtung"
#elif defined(PROG_LANGUAGE_ITALIAN)
# define EDITWIN_TITLE		"Il Congegno"
#elif defined(PROG_LANGUAGE_DUTCH)
# define EDITWIN_TITLE		"Apparaat"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
# define EDITWIN_TITLE		"O Artifício"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
# define EDITWIN_TITLE		"Innretning"
#else
# define EDITWIN_TITLE		"Device"
#endif


/*
 *	Updates the icon displayed in the Icon Picker based on the
 *	given state.
 */
static void EDVIconPickerUpdateDisplay(
	edv_device_icon_picker_struct *ei, gint state
)
{
	const gchar *label_str = "";
	GdkPixmap *pixmap;
	GdkBitmap *mask;
	GtkWidget *w, *parent;


	if(ei == NULL)
	    return;

	if((state < 0) || (state >= EDV_DEVICE_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_DEVICE_ICON_STATE_UNMOUNTED:
	    label_str =
#if defined(PROG_LANGUAGE_SPANISH)
"No Montado"
#elif defined(PROG_LANGUAGE_FRENCH)
"Pas Monté"
#elif defined(PROG_LANGUAGE_GERMAN)
"Nicht Aufgestellt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Non Montato"
#elif defined(PROG_LANGUAGE_DUTCH)
"Niet Bestijgenene"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Não Montado"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Ikke Montert"
#else
"Unmounted"
#endif
	    ;
	    break;
	  case EDV_DEVICE_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_DEVICE_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
	    ;
	}
	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)
	{
	    gboolean sensitive = (state > 0) ? TRUE : FALSE;
	    GTK_WIDGET_SET_SENSITIVE(w, sensitive)
	}
	w = ei->right_btn;
	if(w != NULL)
	{
	    gboolean sensitive =
		(state < (EDV_DEVICE_TOTAL_ICON_STATES - 1)) ? TRUE : FALSE;
	    GTK_WIDGET_SET_SENSITIVE(w, sensitive)
	}
#endif
}

/*
 *	Devices Edit Window change icon callback.
 */
static void EDVIconPickerChangeIconCB(
	GtkWidget *widget, gpointer data
)
{
	gint state, 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_core_struct *core_ptr;
	edv_device_editwin_struct *ew;
	edv_device_icon_picker_struct *ei =
	    EDV_DEVICE_ICON_PICKER(data);
	if((ei == NULL) || FileBrowserIsQuery())
	    return;

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

	ew = EDV_DEVICE_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 for this state */
	old_path = ei->path[state];
	if(!STRISEMPTY(old_path))
	    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 */
		    EDVIconPickerUpdateDisplay(ei, state);

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

		    /* Update the displayed icon */
		    EDVIconPickerUpdateDisplay(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);
}

/*
 *	Icon Picker previous state callback.
 */
static void EDVIconPickerPreviousStateCB(
	GtkWidget *widget, gpointer data
)
{
	GtkAdjustment *adj;
	edv_device_icon_picker_struct *ei =
	    EDV_DEVICE_ICON_PICKER(data);
	if(ei == 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;

	EDVIconPickerUpdateDisplay(ei, (gint)adj->value);
}

/*
 *	Icon Picker next state callback.
 */
static void EDVIconPickerNextStateCB(
	GtkWidget *widget, gpointer data
)
{
	GtkAdjustment *adj;
	edv_device_icon_picker_struct *ei =
	    EDV_DEVICE_ICON_PICKER(data);
	if(ei == 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;

	EDVIconPickerUpdateDisplay(ei, (gint)adj->value);
}


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

	toplevel = gtk_widget_get_toplevel(GTK_WIDGET(entry));

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

	/* Query user for program */
	FileBrowserSetTransientFor(toplevel);
	status = FileBrowserGetResponse(
	    "Select Program",
	    "Select", "Cancel",
	    gtk_entry_get_text(entry),          /* Startup path */
	    ftype, total_ftypes,
	    &path_rtn, &total_path_rtns,
	    &ftype_rtn
	);
	FileBrowserSetTransientFor(NULL);

	/* Got user response? */
	if(status)
	{
	    const gchar *prog = (total_path_rtns > 0) ?
		path_rtn[0] : NULL;
	    if(!STRISEMPTY(prog))
	    {
		gtk_entry_set_text(entry, prog);
		gtk_entry_set_position(entry, -1);
	    }
	}

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


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

	EDVDevicesEditWinCancelCB(NULL, ew);

	return(TRUE);
}

/*
 *	GtkWidget any changed signal callback.
 */
static void EDVDevicesEditWinAnyChangedCB(
	GtkWidget *widget, gpointer data
)
{
	edv_device_editwin_struct *ew = EDV_DEVICE_EDITWIN(data);
	if(ew == NULL)
	    return;

	if(ew->freeze_count > 0)
	    return;

	ew->freeze_count++;

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

	ew->freeze_count--;
}

/*
 *	Devices Edit Window ok callback.
 */
static void EDVDevicesEditWinOKCB(
	GtkWidget *widget, gpointer data
)
{
	edv_device_editwin_struct *ew = EDV_DEVICE_EDITWIN(data);
	if(ew == NULL)
	    return;

	EDVDevicesEditWinApplyCB(NULL, ew);
	EDVDevicesEditWinUnmap(ew);
}

/*
 *      Devices Edit Window apply callback.
 */
static void EDVDevicesEditWinApplyCB(
	GtkWidget *widget, gpointer data
)
{
	GtkWidget *w;
	GtkEntry *entry;
	GtkCombo *combo;
	edv_core_struct *core_ptr;
	gint dev_num;
	edv_device_struct *dev_ptr;
	edv_device_listwin_struct *lw;
	edv_device_icon_picker_struct *ei;
	edv_device_editwin_struct *ew = EDV_DEVICE_EDITWIN(data);
	if(ew == NULL)
	    return;

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

	/* Get device index and pointer to structure on the core's
	 * list
	 */
	dev_num = ew->dev_num;
	dev_ptr = ((dev_num >= 0) && (dev_num < core_ptr->total_devices)) ?
	    core_ptr->device[dev_num] : NULL;
	if(dev_ptr == NULL)
	    return;


	/* Begin applying values */

	/* Descriptive name */
	entry = (GtkEntry *)ew->name_entry;
	if(entry != NULL)
	{
	    g_free(dev_ptr->name);
	    dev_ptr->name = STRDUP(gtk_entry_get_text(entry));
	}

	/* Device path */
	entry = (GtkEntry *)ew->device_path_entry;
	if(entry != NULL)
	{
	    g_free(dev_ptr->device_path);
	    dev_ptr->device_path = STRDUP(gtk_entry_get_text(entry));
	}

	/* Mount path */
	entry = (GtkEntry *)ew->mount_path_entry;
	if(entry != NULL)
	{
	    g_free(dev_ptr->mount_path);
	    dev_ptr->mount_path = STRDUP(gtk_entry_get_text(entry));
	}

	/* File system type */
	combo = (GtkCombo *)ew->fs_type_combo;
	if(combo != NULL)
	{
	    entry = GTK_ENTRY(combo->entry);
	    dev_ptr->fs_type = EDVDeviceGetFSFromString(
		gtk_entry_get_text(entry)
	    );
	}

	/* Mount command */
	entry = (GtkEntry *)ew->command_mount_entry;
	if(entry != NULL)
	{
	    g_free(dev_ptr->command_mount);
	    dev_ptr->command_mount = STRDUP(gtk_entry_get_text(entry));
	}
	/* Unmount command */
	entry = (GtkEntry *)ew->command_unmount_entry;
	if(entry != NULL)
	{
	    g_free(dev_ptr->command_unmount);
	    dev_ptr->command_unmount = STRDUP(gtk_entry_get_text(entry));
	}
	/* Eject command */
	entry = (GtkEntry *)ew->command_eject_entry;
	if(entry != NULL)
	{
	    g_free(dev_ptr->command_eject);
	    dev_ptr->command_eject = STRDUP(gtk_entry_get_text(entry));
	}

	/* Check command */
	entry = (GtkEntry *)ew->command_check_entry;
	if(entry != NULL)
	{
	    g_free(dev_ptr->command_check);
	    dev_ptr->command_check = STRDUP(gtk_entry_get_text(entry));
	}
	/* Tools command */
	entry = (GtkEntry *)ew->command_tools_entry;
	if(entry != NULL)
	{
	    g_free(dev_ptr->command_tools);
	    dev_ptr->command_tools = STRDUP(gtk_entry_get_text(entry));
	}
	/* Format command */
	entry = (GtkEntry *)ew->command_format_entry;
	if(entry != NULL)
	{
	    g_free(dev_ptr->command_format);
	    dev_ptr->command_format = STRDUP(gtk_entry_get_text(entry));
	}

	/* No unmount */
	w = ew->no_unmount_check;
	if((w != NULL) ? GTK_IS_TOGGLE_BUTTON(w) : FALSE)
	{
	    dev_ptr->no_unmount = GTK_TOGGLE_BUTTON(w)->active;
	}
	/* Read only */
	w = ew->read_only_check;
	if((w != NULL) ? GTK_IS_TOGGLE_BUTTON(w) : FALSE)
	{
	    dev_ptr->read_only = GTK_TOGGLE_BUTTON(w)->active;
	}
	/* Unlisted */
	w = ew->unlisted_check;
	if((w != NULL) ? GTK_IS_TOGGLE_BUTTON(w) : FALSE)
	{
	    dev_ptr->unlisted = GTK_TOGGLE_BUTTON(w)->active;
	}

	/* Begin applying icons file paths */

	/* Small icon */
	ei = ew->icon_small;
	if(ei != NULL)
	{
	    gint i;
	    for(i = 0; i < EDV_DEVICE_TOTAL_ICON_STATES; i++)
	    {
		g_free(dev_ptr->small_icon_file[i]);
		dev_ptr->small_icon_file[i] = STRDUP(ei->path[i]);
	    }
	}

	/* Medium icon */
	ei = ew->icon_medium;
	if(ei != NULL)
	{
	    gint i;
	    for(i = 0; i < EDV_DEVICE_TOTAL_ICON_STATES; i++)
	    {
		g_free(dev_ptr->medium_icon_file[i]);
		dev_ptr->medium_icon_file[i] = STRDUP(ei->path[i]);
	    }
	}

	/* Large icon */
	ei = ew->icon_large;
	if(ei != NULL)
	{
	    gint i;
	    for(i = 0; i < EDV_DEVICE_TOTAL_ICON_STATES; i++)
	    {
		g_free(dev_ptr->large_icon_file[i]);
		dev_ptr->large_icon_file[i] = STRDUP(ei->path[i]);
	    }
	}


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


	/* Re-realize the device */
	EDVDeviceRealize(dev_ptr, TRUE);

	/* Update all device mount states and stats */
	EDVDevicesListUpdateMountStates(
	    core_ptr->device, core_ptr->total_devices
	);
	EDVDevicesListUpdateStats(
	    core_ptr->device, core_ptr->total_devices
	);

	/* Send device modified signal to all of endeavour's resources */
	EDVDeviceModifiedEmit(core_ptr, dev_num, dev_ptr);
}

/*
 *	Devices Edit Window cancel or close callback.
 */
static void EDVDevicesEditWinCancelCB(
	GtkWidget *widget, gpointer data
)
{
	edv_device_editwin_struct *ew = EDV_DEVICE_EDITWIN(data);
	if(ew == NULL)
	    return;

	EDVDevicesEditWinUnmap(ew);
}

/*
 *	Loads the device values to the Devices Edit Window.
 */
void EDVDevicesEditWinFetchValues(
	edv_device_editwin_struct *ew, gint dev_num
)
{
	GtkWidget *w;
	GtkEntry *entry;
	GtkCombo *combo;
	edv_device_struct *dev_ptr;
	edv_core_struct *core_ptr;
	edv_device_icon_picker_struct *ei;


	if(ew == NULL)
	    return;

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

	/* Get pointer to device structure on core's devices list */
	if((dev_num < 0) || (dev_num >= core_ptr->total_devices))
	    return;
	else
	    dev_ptr = core_ptr->device[dev_num];
	if(dev_ptr == NULL)
	    return;


	/* Begin fetching values */

	/* Set device index on core structure from the given dev_num */
	ew->dev_num = dev_num;

	/* Descriptive name */
	entry = (GtkEntry *)ew->name_entry;
	if(entry != NULL)
	{
	    gtk_entry_set_text(
		entry,
		(dev_ptr->name != NULL) ? dev_ptr->name : ""
	    );
	}

	/* Device path */
	entry = (GtkEntry *)ew->device_path_entry;
	if(entry != NULL)
	{
	    gtk_entry_set_text(
		entry,
		(dev_ptr->device_path != NULL) ? dev_ptr->device_path : ""
	    );
	}

	/* Mount path */
	entry = (GtkEntry *)ew->mount_path_entry;
	if(entry != NULL)
	{
	    gtk_entry_set_text(
		entry,
		(dev_ptr->mount_path != NULL) ? dev_ptr->mount_path : ""
	    );
	}


	/* File system type */
	combo = (GtkCombo *)ew->fs_type_combo;
	if(combo != NULL)
	{
	    entry = (GtkEntry *)combo->entry;
	    gtk_entry_set_text(
		entry, EDVDeviceGetFSStringFromNumber(dev_ptr->fs_type)
	    );
	}

	/* Mount command */
	entry = (GtkEntry *)ew->command_mount_entry;
	if(entry != NULL)
	    gtk_entry_set_text(
		entry,
		(dev_ptr->command_mount != NULL) ? dev_ptr->command_mount : ""
	    );
	/* Unmount command */
	entry = (GtkEntry *)ew->command_unmount_entry;
	if(entry != NULL)
	    gtk_entry_set_text(
		entry,
		(dev_ptr->command_unmount != NULL) ? dev_ptr->command_unmount : ""
	    );
	/* Eject command */
	entry = (GtkEntry *)ew->command_eject_entry;
	if(entry != NULL)
	    gtk_entry_set_text(
		entry,
		(dev_ptr->command_eject != NULL) ? dev_ptr->command_eject : ""
	    );

	/* Check command */
	entry = (GtkEntry *)ew->command_check_entry;
	if(entry != NULL)
	    gtk_entry_set_text(
		entry,
		(dev_ptr->command_check != NULL) ? dev_ptr->command_check : ""
	    );
	/* Tools command */
	entry = (GtkEntry *)ew->command_tools_entry;
	if(entry != NULL)
	    gtk_entry_set_text(
		entry,
		(dev_ptr->command_tools != NULL) ? dev_ptr->command_tools : ""
	    );
	/* Format command */
	entry = (GtkEntry *)ew->command_format_entry;
	if(entry != NULL)
	    gtk_entry_set_text(
		entry,
		(dev_ptr->command_format != NULL) ? dev_ptr->command_format : ""
	    );

	/* No unmount */
	w = ew->no_unmount_check;
	if((w != NULL) ? GTK_IS_TOGGLE_BUTTON(w) : FALSE)
	    GTK_TOGGLE_BUTTON(w)->active = dev_ptr->no_unmount;
	/* Read only */
	w = ew->read_only_check;
	if((w != NULL) ? GTK_IS_TOGGLE_BUTTON(w) : FALSE)
	    GTK_TOGGLE_BUTTON(w)->active = dev_ptr->read_only;
	/* Unlisted */
	w = ew->unlisted_check;
	if((w != NULL) ? GTK_IS_TOGGLE_BUTTON(w) : FALSE)
	    GTK_TOGGLE_BUTTON(w)->active = dev_ptr->unlisted;

	/* Begin loading icons */

#define DO_LOAD_ICON	{				\
 gint i;						\
 for(i = 0; i < EDV_DEVICE_TOTAL_ICON_STATES; i++) {	\
  /* Unref pixmap and mask on the 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 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 = dev_ptr->small_pixmap;
	    GdkBitmap **mask = dev_ptr->small_mask;
	    gchar **path = dev_ptr->small_icon_file;

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

	    DO_LOAD_ICON

	    if(ei->adj != NULL)
		EDVIconPickerUpdateDisplay(
		    ei, (gint)ei->adj->value
		);
	}

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

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

	    DO_LOAD_ICON

	    if(ei->adj != NULL)
		EDVIconPickerUpdateDisplay(
		    ei, (gint)ei->adj->value
		);
	}

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

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

	    DO_LOAD_ICON

	    if(ei->adj != NULL)
		EDVIconPickerUpdateDisplay(
		    ei, (gint)ei->adj->value
		);
	}

#undef DO_LOAD_ICON


#if 0
	if(ew->toplevel != NULL)
	    gtk_widget_queue_resize(ew->toplevel);
#endif
}


/*
 *	Device removed signal callback.
 */
void EDVDevicesEditWinDeviceRemovedCB(
	edv_device_editwin_struct *ew, gint dev_num
)
{
	if(ew == NULL)
	    return;

	if(ew->dev_num != dev_num)
	    return;

	ew->dev_num = -1;
	EDVDevicesEditWinUnmap(ew);
}


/*
 *	Creates a new Icon Picker.
 */
static edv_device_icon_picker_struct *EDVDevicesEditIconNew(
	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_device_icon_picker_struct *ei = EDV_DEVICE_ICON_PICKER(
	    g_malloc0(sizeof(edv_device_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_DEVICE_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(EDVIconPickerChangeIconCB), 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(EDVIconPickerPreviousStateCB), 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(EDVIconPickerNextStateCB), 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 EDVDevicesEditIconDelete(edv_device_icon_picker_struct *ei)
{
	gint i;

	if(ei == NULL)
	    return;

	/* Unref all pixmap and mask pairs */
	for(i = 0; i < EDV_DEVICE_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 Devices Edit Window.
 */
edv_device_editwin_struct *EDVDevicesEditWinNew(
	gpointer core_ptr, gpointer listwin
)
{
	const gint border_major = 5;
	gint i;
	gpointer combo_rtn, entry_rtn, browse_rtn;
	GList *glist;
	GdkWindow *window;
	GtkAccelGroup *accelgrp;
	GtkWidget *w, *parent, *parent2, *parent3, *parent4;
	GtkCombo *combo;
	const edv_fs_type_struct *fs_type_ptr;
	const edv_fs_type_struct fs_type_list[] = EDV_FS_TYPE_LIST;
	edv_device_editwin_struct *ew = EDV_DEVICE_EDITWIN(
	    g_malloc0(sizeof(edv_device_editwin_struct))
	);
	if(ew == NULL)
	    return(ew);

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

	ew->listwin = listwin;

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

	ew->dev_num = -1;


	/* Format 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_device_misc_48x48_xpm);
	}
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_event",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinDeleteEventCB), 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;


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

	/* Name entry */
	w = GUIPromptBar(
	    NULL,
#if defined(PROG_LANGUAGE_SPANISH)
"El Nombre"
#elif defined(PROG_LANGUAGE_FRENCH)
"Nom"
#elif defined(PROG_LANGUAGE_GERMAN)
"Name"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Nome"
#elif defined(PROG_LANGUAGE_DUTCH)
"Naam"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Nome"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Navn"
#else
"Name"
#endif
	    ":", NULL, &entry_rtn
	);
	ew->name_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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Entre el nombre de este artefacto (este valor hace sólo sea usado\
 para propósitos de despliegue)"
#elif defined(PROG_LANGUAGE_FRENCH)
"Entrer le nom de cet appareil (cette valeur sera seulement utilisée\
 pour les buts d'exposition)"
#elif defined(PROG_LANGUAGE_GERMAN)
"Tragen sie den namen dieser vorrichtung ein (dieser wert wird nur\
 für ausstellung zwecke benutzt werden)"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Entrare il nome di questo congegno (questo valore sarà soltanto usato\
 per gli scopi di mostra)"
#elif defined(PROG_LANGUAGE_DUTCH)
"Ga de (deze enige waarde zal voor tentoonstelling doelen gebruikt\
 worden) naam van deze apparaat binnen"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Entre o nome deste artifício (este valor só será usado para propósitos\
 de exposição)"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Gå inn i navnet av denne innretningen (denne verdien brukt bare for\
 utstillingsformål)"
#else
"Enter the name of this device (this value will only be used for\
 display purposes)"
#endif
	);


	/* Device path entry */
	w = GUIPromptBar(
	    NULL,
#if defined(PROG_LANGUAGE_SPANISH)
"Sendero Dispositivo"
#elif defined(PROG_LANGUAGE_FRENCH)
"Sentier D'appareil"
#elif defined(PROG_LANGUAGE_GERMAN)
"Gerätepfad"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Sentiero Congegno"
#elif defined(PROG_LANGUAGE_DUTCH)
"Apparaat Pad"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Caminho Artifício"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Innretnings Sti"
#else
"Device Path"
#endif
	    ":", NULL, &entry_rtn
	);
	ew->device_path_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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Entre el sendero al objeto del artefacto"
#elif defined(PROG_LANGUAGE_FRENCH)
"Le objeto d'al de sendero d'el de Entre del artefacto"
#elif defined(PROG_LANGUAGE_GERMAN)
"Tragen sie den pfad zum geräteobjekt ein"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Entrare il sentiero all'oggetto di congegno"
#elif defined(PROG_LANGUAGE_DUTCH)
"Ga het pad aan het apparaat voorwerp binnen"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Entre o caminho ao objeto de artifício"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Gå inn i stien til innretnings objektet"
#else
"Enter the path to the device object"
#endif
	);


	/* Mount path entry */
	w = GUIPromptBar(
	    NULL,
#if defined(PROG_LANGUAGE_SPANISH)
"Monte Sendero"
#elif defined(PROG_LANGUAGE_FRENCH)
"Monter Sentier"
#elif defined(PROG_LANGUAGE_GERMAN)
"Stellen Pfad"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Montare Sentiero"
#elif defined(PROG_LANGUAGE_DUTCH)
"Bestijg Pad"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Monte Caminho"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Monter Sti"
#else
"Mount Path"
#endif
	    ":", NULL, &entry_rtn
	);
	ew->mount_path_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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Entre el sendero al objeto de la guía que este artefacto\
 deberá ser montado en"
#elif defined(PROG_LANGUAGE_FRENCH)
"Entrer le sentier à l'objet d'annuaire que cet appareil va\
 être monté sur"
#elif defined(PROG_LANGUAGE_GERMAN)
"Tragen sie den pfad zum verzeichnis objekt, das diese vorrichtung auf\
 aufgestellt werden soll ein"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Entrare il sentiero all'oggetto di elenco che questo congegno è\
 essere montato su"
#elif defined(PROG_LANGUAGE_DUTCH)
"Ga het pad aan het gids voorwerp binnen dat deze apparaat op bestegen\
 worden zal"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Entre o caminho ao objeto de guia que este artifício é ser montado\
 em"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Gå inn i stien til katalogobjektet som denne innretningen er montert\
 på"
#else
"Enter the path to the directory object that this device is to\
 be mounted on"
#endif
	);


	/* Filesystem Frame */
	w = gtk_frame_new(
#if defined(PROG_LANGUAGE_SPANISH)
"Archivesistema"
#elif defined(PROG_LANGUAGE_FRENCH)
"Systèmeclassement"
#elif defined(PROG_LANGUAGE_GERMAN)
"Dateisystem"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Schedaresistema"
#elif defined(PROG_LANGUAGE_DUTCH)
"Archiveersysteem"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Arquivesistema"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Arkiversystem"
#else
"Filesystem"
#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 filesystem strings glist */
	glist = NULL;
	for(i = 0; fs_type_list[i].fs_type; i++)
	{
	    fs_type_ptr = &fs_type_list[i];
	    if(!STRISEMPTY(fs_type_ptr->name))
		glist = g_list_append(glist, STRDUP(fs_type_ptr->name));
	}
	/* Filesystem type combo */
	w = GUIComboCreate(
#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
	    ":",
	    EDV_FS_TYPE_MSDOS_NAME,
	    glist,		/* Initial glist of items */
	    i,			/* Maximum items */
	    &combo_rtn,
	    ew,
	    NULL,
	    NULL
	);
	ew->fs_type_combo = (GtkWidget *)combo_rtn;
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_widget_show(w);

	w = 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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Escoja el de tipo filesystem de los medios usados con este\
 artefacto"
#elif defined(PROG_LANGUAGE_FRENCH)
"Choisir le type de filesystem du presse utilisé avec cet\
 appareil"
#elif defined(PROG_LANGUAGE_GERMAN)
"Wählen sie den filesystem typ der medien hat benutzt mit dieser\
 vorrichtung aus"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Scegliere il tipo di filesystem della stampa usata con questo\
 congegno"
#elif defined(PROG_LANGUAGE_DUTCH)
"Selecteer het filesystem type van de media gebruikte met deze\
 apparaat"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Selecione o filesystem tipo da imprensa usada com este\
 artifício"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Velg ut filesystem type av mediene som brukt med denne\
 innretningen"
#else
"Select the filesystem type of the media used with this device"
#endif
	);

	/* Delete filesystem type strings glist */
	g_list_foreach(glist, (GFunc)g_free, NULL);
	g_list_free(glist);



	/* Commands Frame */
	w = gtk_frame_new(
#if defined(PROG_LANGUAGE_SPANISH)
"Las órdenes"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ordres"
#elif defined(PROG_LANGUAGE_GERMAN)
"Befehle"
#elif defined(PROG_LANGUAGE_ITALIAN)
"I Comandi"
#elif defined(PROG_LANGUAGE_DUTCH)
"Bevelen"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Os Comandos"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Kommandoer"
#else
"Commands"
#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;

	/* Mount command entry */
	w = GUIPromptBarWithBrowse(
	    NULL,
#if defined(PROG_LANGUAGE_SPANISH)
"El Monte"
#elif defined(PROG_LANGUAGE_FRENCH)
"Mont"
#elif defined(PROG_LANGUAGE_GERMAN)
"Untersatz"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Il Monte"
#elif defined(PROG_LANGUAGE_DUTCH)
"Berg"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Monte"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Fotstykke"
#else
"Mount"
#endif
	    ":", NULL, &entry_rtn, &browse_rtn,
	    NULL, NULL
	);
	ew->command_mount_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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#ifdef PROG_LANGUAGE_ENGLISH
"Enter the command that will be executed to mount\
 this device (or leave it blank if it is not mountable)"
#endif
#ifdef PROG_LANGUAGE_SPANISH
"Entre la orden que será ejecutada al mount este\
 artefacto (o le sale blanco si no es mountable)"
#endif
#ifdef PROG_LANGUAGE_FRENCH
"Entrer l'ordre qui sera exécuté à moun cet\
 appareil (ou le part le vide si ne ce pas est mountable)"
#endif
	);

	w = (GtkWidget *)browse_rtn;
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinBrowseProgramCB), entry_rtn
	);

	/* Unmount command entry */
	w = GUIPromptBarWithBrowse(
	    NULL,
#ifdef PROG_LANGUAGE_ENGLISH
	    "Unmount:",
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "El Unmoute:",
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Unmont:",
#endif
	    NULL, &entry_rtn, &browse_rtn,
	    NULL, NULL
	);
	ew->command_unmount_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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#ifdef PROG_LANGUAGE_ENGLISH
	    "Enter the command that will be executed to unmount\
 this device (or leave it blank if it is not unmountable)"
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Entre la orden que será ejecutada al unmount este\
 artefacto (o le sale blanco si no es unmountable)"
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Entrer l'ordre qui sera exécuté à unmount cet\
 appareil (ou le part le vide si ne ce pas est unmountable)"
#endif
	);

	w = (GtkWidget *)browse_rtn;
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinBrowseProgramCB), entry_rtn
	);

	/* Eject command entry */
	w = GUIPromptBarWithBrowse(
	    NULL,
#ifdef PROG_LANGUAGE_ENGLISH
	    "Eject:",
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Expulse:",
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Ejecter:",
#endif
	    NULL, &entry_rtn, &browse_rtn,
	    NULL, NULL
	);
	ew->command_eject_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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#ifdef PROG_LANGUAGE_ENGLISH
	    "Enter the command that will be executed to eject\
 the media from the device (or leave it blank if the device does not\
 support ejecting)"
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Entre la orden que será ejecutada a eject los\
 medios del artefacto (o le sale blanco si el artefacto hace\
 expulsar de apoyo de not)"
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Entrer l'ordre qui sera exécuté à eject le presse\
 de l'appareil (ou le part le vide si l'appareil fait\
 l'éjecter de soutien de not)"
#endif
	);

	w = (GtkWidget *)browse_rtn;
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinBrowseProgramCB), entry_rtn
	);


	/* Check command entry */
	w = GUIPromptBarWithBrowse(
	    NULL,
#ifdef PROG_LANGUAGE_ENGLISH
	    "Check:",
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Cheque:",
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Chèque:",
#endif
	    NULL, &entry_rtn, &browse_rtn,
	    NULL, NULL
	);
	ew->command_check_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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#ifdef PROG_LANGUAGE_ENGLISH
	    "Enter the command that will be executed to run the\
 file system check program for this device (or leave it blank if\
 you do not have one)"
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Entre la orden que se ejecutará para correr el\
 programa de cheque de sistema de archivo para este artefacto\
 (o le sale blanco si usted no tiene uno)"
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Entrez l'ordre qui sera exécuté courir le\
 programme de chèque de système de fichier pour cet appareil\
 (ou le part le vide si vous ne celui avez pas)"
#endif
	);

	w = (GtkWidget *)browse_rtn;
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinBrowseProgramCB), entry_rtn
	);

	/* Tools command entry */
	w = GUIPromptBarWithBrowse(
	    NULL,
#ifdef PROG_LANGUAGE_ENGLISH
	    "Tools:",
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Las Herramientas:",
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Outils:",
#endif
	    NULL, &entry_rtn, &browse_rtn,
	    NULL, NULL
	);
	ew->command_tools_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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#ifdef PROG_LANGUAGE_ENGLISH
	    "Enter the command that will be executed to run the\
 tools program for this device (or leave it blank if you do not\
 have one)"
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Entre la orden que se ejecutará para correr el\
 programa de herramientas para este artefacto (o le sale\
 blanco si usted no tiene uno)"
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Entrer l'ordre qui sera exécuté courir le\
 programme d'outils pour cet appareil (ou le part le vide\
 si vous ne celui avez pas)"
#endif
	);

	w = (GtkWidget *)browse_rtn;
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinBrowseProgramCB), entry_rtn
	);

	/* Format command entry */
	w = GUIPromptBarWithBrowse(
	    NULL,
#ifdef PROG_LANGUAGE_ENGLISH
	    "Format:",
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Formato:",
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Format:",
#endif
	    NULL, &entry_rtn, &browse_rtn,
	    NULL, NULL
	);
	ew->command_format_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(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(w,
#ifdef PROG_LANGUAGE_ENGLISH
"Enter the command that will be executed to run the\
 format program for this device (or leave it blank if you do not\
 have one)"
#endif
#ifdef PROG_LANGUAGE_SPANISH
"Entre la orden que se ejecutará para correr the el\
 programa de formato para este artefacto (o le sale\
 blanco si usted hace not tiene uno)"
#endif
#ifdef PROG_LANGUAGE_FRENCH
"Entrer l'ordre qui sera exécuté courir le programme\
 de format pour cet appareil (ou le part le vide si\
 vous ne celui avez pas)"
#endif
	);

	w = (GtkWidget *)browse_rtn;
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinBrowseProgramCB), entry_rtn
	);


	/* Options frame */
	w = gtk_frame_new(
#ifdef PROG_LANGUAGE_ENGLISH
	    "Options"
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Las Opciones"
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Options"
#endif
	);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	w = gtk_hbox_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;

	/* No unmount check */
	ew->no_unmount_check = w = gtk_check_button_new_with_label(
#ifdef PROG_LANGUAGE_ENGLISH
	    "No Unmount"
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Ningún Unmount"
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Aucun Unmount"
#endif
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "toggled",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(
	    w,
"Check this to locally mark the device as \"fixed\", so that it cannot\
 be mounted or unmounted"
	);
	gtk_widget_show(w);

	/* Read only check */
	ew->read_only_check = w = gtk_check_button_new_with_label(
#ifdef PROG_LANGUAGE_ENGLISH
	    "Read Only"
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Lea Sólo"
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Lire Seulement"
#endif
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "toggled",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(
	    w,
"Check this to always mount the device as read only"
	);
	gtk_widget_show(w);

	/* Unlisted check */
	ew->unlisted_check = w = gtk_check_button_new_with_label(
#ifdef PROG_LANGUAGE_ENGLISH
	    "Unlisted"
#endif
#ifdef PROG_LANGUAGE_SPANISH
	    "Unlisted"
#endif
#ifdef PROG_LANGUAGE_FRENCH
	    "Unlisted"
#endif
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "toggled",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinAnyChangedCB), ew
	);
	GUISetWidgetTip(
	    w,
"Check this if you do not want this device to be listed on any\
 of the \"brief\" device listings (such as the devices popup list)"
	);
	gtk_widget_show(w);



	/* 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 = EDVDevicesEditIconNew(
	    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 = EDVDevicesEditIconNew(
	    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 = EDVDevicesEditIconNew(
	    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, TRUE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinOKCB), 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, TRUE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinApplyCB), 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, TRUE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinCancelCB), 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, TRUE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVDevicesEditWinCancelCB), 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);


	EDVDevicesEditWinUpdateMenus(ew);


	return(ew);
}

/*
 *	Resets the Devices Edit Window's has changes marker.
 */
void EDVDevicesEditWinResetHasChanges(
	edv_device_editwin_struct *ew, gboolean has_changes
)
{
	if(ew == NULL)
	    return;

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

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

/*
 *	Updates the Devices Edit Window's widgets to reflect current
 *	values.
 */
void EDVDevicesEditWinUpdateMenus(edv_device_editwin_struct *ew)
{
	gboolean        sensitive,
			has_changes;
	gint dev_num;
	const edv_device_struct *dev_ptr;
	GtkWidget *w;
	edv_core_struct *core_ptr;

	if(ew == NULL)
	    return;

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

	has_changes = ew->has_changes;
	dev_num = ew->dev_num;
	if((dev_num >= 0) && (dev_num < core_ptr->total_devices))
	    dev_ptr = core_ptr->device[dev_num];
	else
	    dev_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);
	}

	/* Update OK, Apply, Save, Cancel Buttons */
	sensitive = has_changes;
	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 Devices Edit Window.
 */
gboolean EDVDevicesEditWinIsMapped(
	edv_device_editwin_struct *ew
)
{
	GtkWidget *w = (ew != NULL) ? ew->toplevel : NULL;
	return((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE);
}

/*
 *	Maps the Devices Edit Window.
 */
void EDVDevicesEditWinMap(
	edv_device_editwin_struct *ew
)
{
	GtkWidget *w = (ew != NULL) ? ew->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_show_raise(w);

	w = ew->name_entry;
	gtk_widget_grab_focus(w);
}

/*
 *	Unmaps the Devices Edit Window.
 */
void EDVDevicesEditWinUnmap(
	edv_device_editwin_struct *ew
)
{
	GtkWidget *w = (ew != NULL) ? ew->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_hide(w);
}

/*
 *	Deletes the Devices List Window.
 */
void EDVDevicesEditWinDelete(
	edv_device_editwin_struct *ew
)
{
	if(ew == NULL)
	    return;

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

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

	GTK_WIDGET_DESTROY(ew->name_entry)
	GTK_WIDGET_DESTROY(ew->device_path_entry)
	GTK_WIDGET_DESTROY(ew->mount_path_entry)
	GTK_WIDGET_DESTROY(ew->fs_type_combo)

	GTK_WIDGET_DESTROY(ew->command_mount_entry)
	GTK_WIDGET_DESTROY(ew->command_unmount_entry)
	GTK_WIDGET_DESTROY(ew->command_eject_entry)
	GTK_WIDGET_DESTROY(ew->command_check_entry)
	GTK_WIDGET_DESTROY(ew->command_tools_entry)
	GTK_WIDGET_DESTROY(ew->command_format_entry)

	GTK_WIDGET_DESTROY(ew->no_unmount_check)
	GTK_WIDGET_DESTROY(ew->read_only_check)
	GTK_WIDGET_DESTROY(ew->unlisted_check)

	GTK_WIDGET_DESTROY(ew->toplevel)

	GTK_ACCEL_GROUP_UNREF(ew->accelgrp)

	g_free(ew->title);

	g_free(ew);
}
