#include <stdlib.h>
#include <string.h>

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

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

#include "guiutils.h"
#include "pulist.h"

#include "cfg.h"
#include "edv_types.h"
#include "edv_list_cb.h"
#include "edv_date.h"
#include "edv_obj.h"
#include "edv_recycled_obj.h"
#include "edv_recbin_stat.h"
#include "edv_status_bar.h"
#include "find_win.h"
#include "find_win_cb.h"
#include "endeavour2.h"
#include "edv_utils.h"
#include "edv_utils_gtk.h"
#include "edv_cfg_list.h"
#include "config.h"

#include "images/icon_search_20x20.xpm"
#include "images/icon_open_20x20.xpm"
#include "images/icon_stop_20x20.xpm"
#include "images/icon_clear_20x20.xpm"
#include "images/icon_close_20x20.xpm"
#include "images/icon_goto_20x20.xpm"

#include "images/icon_search_48x48.xpm"


const gchar *EDVFindWinCurrentSearch(edv_find_win_struct *fw);
void EDVFindWinSetSearch(
	edv_find_win_struct *fw, const gchar *s,
	const gboolean record_history
);

const gchar *EDVFindWinCurrentLocation(edv_find_win_struct *fw);
void EDVFindWinSetLocation(
	edv_find_win_struct *fw, const gchar *path,
	const gboolean record_history
);

edv_findwin_operation EDVFindWinCurrentOperation(edv_find_win_struct *fw); 
void EDVFindWinSetReferenceWindow(
	edv_find_win_struct *fw,
	const gint browser_num,
	const gint imbr_num,
	const gint recbin_num,
	const gint archiver_num
);

void EDVFindWinListResetColumns(
	edv_find_win_struct *fw, const edv_findwin_operation operation
);
void EDVFindWinListAppend(
	edv_find_win_struct *fw,
	const gchar *path, const struct stat *lstat_buf,
	const gchar *excerpt, const gint line_index
);
void EDVFindWinListClear(edv_find_win_struct *fw);

void EDVFindWinSyncConfiguration(edv_find_win_struct *fw);

edv_find_win_struct *EDVFindWinNew(edv_core_struct *core);
void EDVFindWinUpdateMenus(edv_find_win_struct *fw);
void EDVFindWinSetBusy(edv_find_win_struct *fw, const gboolean is_busy);
gboolean EDVFindWinIsMapped(edv_find_win_struct *fw);
void EDVFindWinMap(edv_find_win_struct *fw);
void EDVFindWinUnmap(edv_find_win_struct *fw);
void EDVFindWinDelete(edv_find_win_struct *fw);


#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)


/*
 *	Returns the Find Window's search string.
 */
const gchar *EDVFindWinCurrentSearch(edv_find_win_struct *fw)
{
	GtkCombo *combo = (GtkCombo *)((fw != NULL) ?
	    fw->search_combo : NULL
	);
	return((combo != NULL) ?
	    gtk_entry_get_text(GTK_ENTRY(combo->entry)) : NULL
	);
}

/*
 *	Sets the Find Window's search string.
 *
 *	If record_history is TRUE then the new search string will be
 *	recorded on the search history.
 */
void EDVFindWinSetSearch(
	edv_find_win_struct *fw, const gchar *s,
	const gboolean record_history
)
{
	gchar *new_s;
	GtkCombo *combo = (GtkCombo *)((fw != NULL) ?
	    fw->search_combo : NULL
	);
	if((combo == NULL) || STRISEMPTY(s))
	    return;

	/* Make a copy of the given path */
	new_s = STRDUP(s);

#if 0
/* This does not work out if we need to record history */
	/* Check for no change in value */
	s = gtk_entry_get_text(GTK_ENTRY(combo->entry));
	if((s != NULL) ? !strcmp(s, new_s) : FALSE)
	{
	    g_free(new_s);
	    return;
	}
#endif

	/* Record history? */
	if(record_history)
	    GUIComboAddItem(GTK_WIDGET(combo), new_s);

	/* Set new value */
	gtk_entry_set_text(GTK_ENTRY(combo->entry), new_s);

	g_free(new_s);
}

/*
 *	Returns the Find Window's current location.
 */
const gchar *EDVFindWinCurrentLocation(edv_find_win_struct *fw)
{
	GtkCombo *combo = (GtkCombo *)((fw != NULL) ?
	    fw->location_combo : NULL
	);
	return((combo != NULL) ?
	    gtk_entry_get_text(GTK_ENTRY(combo->entry)) : NULL
	);
}

/*
 *	Sets Find Window's location.
 *
 *	If record_history is TRUE then the new location will be
 *	recorded in the locations history.
 */
void EDVFindWinSetLocation(
	edv_find_win_struct *fw, const gchar *path,
	const gboolean record_history
)
{
	gchar *new_path;
	GtkCombo *combo = (GtkCombo *)((fw != NULL) ?
	    fw->location_combo : NULL
	);
	if((combo == NULL) || STRISEMPTY(path))
	    return;

	/* Make a copy of the path */
	new_path = STRDUP(path);

	/* Simplify path */
	SimplifyPath(new_path);

#if 0
/* This does not work out if we need to record history */
	/* Check for no change in value */
	path = gtk_entry_get_text(GTK_ENTRY(combo->entry));
	if((path != NULL) ? !strcmp(path, new_path) : FALSE)
	{
	    g_free(new_path);
	    return;
	}
#endif

	/* Record history? */
	if(record_history)
	    GUIComboAddItem(GTK_WIDGET(combo), new_path);

	/* Set new value */
	gtk_entry_set_text(GTK_ENTRY(combo->entry), new_path);

	g_free(new_path);
}

/*
 *	Returns the Find Window's current operation.
 */
edv_findwin_operation EDVFindWinCurrentOperation(edv_find_win_struct *fw)
{
	pulist_struct *pulist;

	if(fw == NULL)
	    return(EDV_FIND_WIN_FIND_OBJECT_NAME);

        pulist = PUListBoxGetPUList(fw->find_op_pulistbox);
        if(pulist == NULL)
            return(EDV_FIND_WIN_FIND_OBJECT_NAME);

        return((edv_findwin_operation)PUListGetItemData(
            pulist,
            PUListGetSelectedLast(pulist)
        ));
}

/*
 *	Sets the Find Window's reference window and role based on one of
 *	the specified window indices (only one may be non-negative).
 */
void EDVFindWinSetReferenceWindow(
	edv_find_win_struct *fw,
	const gint browser_num,
	const gint imbr_num,
	const gint recbin_num,
	const gint archiver_num
)
{
	if(fw == NULL)
	    return;

	fw->browser_num = browser_num;
	fw->imbr_num = imbr_num;
	fw->recbin_num = recbin_num;
	fw->archiver_num = archiver_num;

	/* Set the role depending on which reference window was specified */
	if(browser_num > -1)
	    fw->role = EDV_FIND_WIN_ROLE_DISK_OBJECT;
	else if(imbr_num > -1)
	    fw->role = EDV_FIND_WIN_ROLE_DISK_OBJECT;
	else if(recbin_num > -1)
	    fw->role = EDV_FIND_WIN_ROLE_RECYCLED_OBJECT;
	else if(archiver_num > -1)
	    fw->role = EDV_FIND_WIN_ROLE_ARCHIVE_OBJECT;
	else
	    fw->role = EDV_FIND_WIN_ROLE_DISK_OBJECT;
}


/*
 *	Resets the Find Window's Results List column attributes based
 *	on the specified operation.
 */
void EDVFindWinListResetColumns(
	edv_find_win_struct *fw, const edv_findwin_operation operation
)
{
	gint i, columns;
	gchar **title;
	gint *justify;
	GtkRcStyle *lists_rcstyle;
	edv_core_struct *core;
	GtkCList *clist = (GtkCList *)((fw != NULL) ?
	    fw->results_clist : NULL
	);
	if(clist == NULL)
	    return;

	columns = clist->columns;
	core = fw->core;
	if((columns <= 0) || (core == NULL))
	    return;

	lists_rcstyle = core->lists_rcstyle;

	/* Allocate column property values */
	title = (gchar **)g_malloc0(columns * sizeof(gchar *));
	justify = (gint *)g_malloc0(columns * sizeof(gint));


	/* Begin resetting columns */

	gtk_clist_freeze(clist);

	/* Update clist column settings */
	gtk_clist_column_titles_show(clist);
	gtk_clist_column_titles_passive(clist); 

	/* Iterate through columns */
	for(i = 0; i < columns; i++)
	{
	    /* Set column attributes by the find operation code */
	    switch(operation)
	    {
	      case EDV_FIND_WIN_FIND_OBJECT_NAME:
		switch(i)
		{
		  case 0:
		    title[i] = "Name";
		    justify[i] = GTK_JUSTIFY_LEFT;
		    break;
		  case 1:
		    title[i] = "Last Modified";
		    justify[i] = GTK_JUSTIFY_LEFT;
		    break;
		  case 2:
		    title[i] = "Location";
		    justify[i] = GTK_JUSTIFY_LEFT;
		    break;
		  default:
		    title[i] = NULL;
		    justify[i] = GTK_JUSTIFY_LEFT;
		    break;
		}
		break;
	      case EDV_FIND_WIN_FIND_OBJECT_CONTENT:
		switch(i)
		{
		  case 0:
		    title[i] = "Name";	/* And location */
		    justify[i] = GTK_JUSTIFY_LEFT;
		    break;
		  case 1:
		    title[i] = "Line";
		    justify[i] = GTK_JUSTIFY_RIGHT;
		    break;
		  case 2:
		    title[i] = "Excerpt";
		    justify[i] = GTK_JUSTIFY_LEFT;
		    break;
		  case 3:
		    title[i] = "Last Modified";
		    justify[i] = GTK_JUSTIFY_LEFT;
		    break;
		  case 4:
		    title[i] = "Location";
		    justify[i] = GTK_JUSTIFY_LEFT;
		    break;
		  default:
		    title[i] = NULL;
		    justify[i] = GTK_JUSTIFY_LEFT;
		    break;
		}
		break;
	    }

	    /* Is this column's properties defined? */
	    if(title[i] != NULL)
	    {
		/* Show column and set column properties */
		gtk_clist_set_column_visibility(
		    clist, i, TRUE
		);
		gtk_clist_set_column_auto_resize(
		    clist, i, TRUE
		);
		gtk_clist_set_column_title(
		    clist, i, title[i]
		);
		gtk_clist_set_column_justification(
		    clist, i, justify[i]
		);
	    }
	    else
	    {
		/* Hide column */
		gtk_clist_set_column_visibility(
		    clist, i, FALSE
		);
	    }
	}

	gtk_clist_thaw(clist);

	/* Set RC style */
	if(lists_rcstyle != NULL)
	    gtk_widget_modify_style_recursive(
		GTK_WIDGET(clist), lists_rcstyle
	    );

	g_free(title);
	g_free(justify);
}

/*
 *	Appends an item to the Find Window's Results List specified by
 *	the given values.
 */
void EDVFindWinListAppend(
	edv_find_win_struct *fw,
	const gchar *path, const struct stat *lstat_buf,
	const gchar *excerpt, const gint line_index
)
{
	edv_findwin_operation operation;
	gint columns;
	edv_date_relativity relativity;
	const gchar *format;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core;
	GtkCList *clist = (GtkCList *)((fw != NULL) ?
	    fw->results_clist : NULL
	);
	if((clist == NULL) || STRISEMPTY(path))
	    return;

	columns = clist->columns;
	core = fw->core;
	if((columns <= 0) || (core == NULL))
	    return;

	/* Get current operation */
	operation = EDVFindWinCurrentOperation(fw);

	/* Get configuration */
	cfg_list = core->cfg_list;
	relativity = (edv_date_relativity)EDV_GET_I(EDV_CFG_PARM_DATE_RELATIVITY);
	format = EDV_GET_S(EDV_CFG_PARM_DATE_FORMAT);

	/* Begin appending item */
	if(TRUE)
	{
	    gint i, row;

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

	    gtk_clist_freeze(clist);

	    /* Append new row */
	    row = gtk_clist_append(clist, strv);
	    if(row > -1)
	    {
		guint index;
		edv_object_struct *obj = NULL;
		edv_recycled_object_struct *recobj;

		/* Create object data depending on the role */
		switch(fw->role)
		{
		  case EDV_FIND_WIN_ROLE_DISK_OBJECT:
		    obj = EDVObjectNew();
		    EDVObjectSetPath(obj, path);
		    EDVObjectSetStat(obj, lstat_buf);
		    EDVObjectUpdateLinkFlags(obj);
		    break;

		  case EDV_FIND_WIN_ROLE_RECYCLED_OBJECT:
		    obj = EDVObjectNew();
		    /* Get recycled object stats */
		    index = (guint)ATOI(path);
		    recobj = EDVRecBinObjectStat(
			EDV_GET_S(EDV_CFG_PARM_FILE_RECYCLE_BIN_INDEX),
			index
		    );
		    /* Set recycled object stats to object */
		    g_free(obj->name);
		    obj->name = STRDUP(path);
		    g_free(obj->full_path);
		    obj->full_path = STRDUP(
			PrefixPaths(recobj->original_path, recobj->name)
		    );
		    obj->type = recobj->type;
		    obj->permissions = recobj->permissions;
		    obj->access_time = recobj->access_time;
		    obj->modify_time = recobj->modify_time;
		    obj->change_time = recobj->change_time;
		    obj->owner_id = recobj->owner_id;
		    obj->group_id = recobj->group_id;
		    obj->size = recobj->size;
		    /* Delete recycled object stats */
		    EDVRecycledObjectDelete(recobj);
		    break;

		  case EDV_FIND_WIN_ROLE_ARCHIVE_OBJECT:
		    obj = EDVObjectNew();
		    g_free(obj->name);
		    obj->name = STRDUP(g_basename(path));
		    g_free(obj->full_path);
		    obj->full_path = STRDUP(path);
		    break;
		}
		/* Object created? */
		if(obj != NULL)
		{
		    GdkPixmap *pixmap, *pixmap_hid;
		    GdkBitmap *mask, *mask_hid;

		    /* Get pointer to object's name, always derive it
		     * from the full path since the obj->name may
		     * contain some other value depending on the role
		     */
		    const gchar *name = (obj->full_path != NULL) ?
			g_basename(obj->full_path) : NULL;

		    /* Get pixmap and mask for the given object */
		    EDVMatchObjectIcon(
			core->device, core->total_devices,
			core->mimetype, core->total_mimetypes,
			obj->type,
			obj->full_path,
			EDV_OBJECT_IS_LINK_VALID(obj),
			obj->permissions,
			0,			/* Small icons */
			&pixmap, &mask,
			NULL, NULL,
			NULL, NULL,
			&pixmap_hid, &mask_hid
		    );
		    /* Hidden? */
		    if(EDVIsObjectNameHidden(name))
		    {
			pixmap = pixmap_hid;
			mask = mask_hid;
		    }

		    /* Begin setting cell values */

		    /* Set name (always first column regardless of the
		     * find operation)
		     */
		    i = 0;
		    if(i < columns)
		    {
			if(pixmap != NULL)
			    gtk_clist_set_pixtext(
				clist, row, i,
				(name != NULL) ? name : "(null)",
				EDV_LIST_PIXMAP_TEXT_SPACING,
				pixmap, mask
			    );
			else
			    gtk_clist_set_text(
				clist, row, i,
				(name != NULL) ? name : "(null)"
			    );
		    }
		    /* Set subsequent cells by the find operation */
		    switch(operation)
		    {
		      case EDV_FIND_WIN_FIND_OBJECT_NAME:
			/* Last modified */
			i = 1;
			if(i < columns)
			{
			    const gulong last_modified = obj->modify_time;
			    const gchar *s = (last_modified > 0l) ?
				EDVDateFormatString(
				    last_modified, format, relativity
				) : NULL;
			    gtk_clist_set_text(
				clist, row, i,
				(s != NULL) ? s : ""
			    );
			}
			/* Location */
			i = 2;
			if(i < columns)
			{
			    gchar *location = (obj->full_path != NULL) ?
				g_dirname(obj->full_path) : NULL;
			    if(!STRISEMPTY(location))
			    {
				struct stat lstat_buf;
				edv_object_struct *loc_obj = EDVObjectNew();
				EDVObjectSetPath(loc_obj, location);
				if(lstat(location, &lstat_buf))
				{
				    loc_obj->type = EDV_OBJECT_TYPE_DIRECTORY;
				}
				else
				{
				    EDVObjectSetStat(loc_obj, &lstat_buf);
				}
				EDVMatchObjectIcon(
				    core->device, core->total_devices,
				    core->mimetype, core->total_mimetypes,
				    loc_obj->type, loc_obj->full_path,
				    EDV_OBJECT_IS_LINK_VALID(loc_obj),
				    loc_obj->permissions,
				    0,		/* Small icons */
				    &pixmap, &mask,
				    NULL, NULL,
				    NULL, NULL,
				    &pixmap_hid, &mask_hid
				);
				/* Hidden? */
			        if(EDVIsObjectNameHidden(loc_obj->name))
				{
				    pixmap = pixmap_hid;
				    mask = mask_hid;
				}
				if(pixmap != NULL)
				    gtk_clist_set_pixtext(
					clist, row, i,
					location,
					EDV_LIST_PIXMAP_TEXT_SPACING,
					pixmap, mask
				    );
				else
				    gtk_clist_set_text(
					clist, row, i,
					location
				    );
				EDVObjectDelete(loc_obj);
			    }
			    g_free(location);
			}
			break;

		      case EDV_FIND_WIN_FIND_OBJECT_CONTENT:
			/* Line */
			i = 1;
			if(i < columns)
			{
			    gchar *s;
			    if(line_index > -1)
				s = g_strdup_printf(
				    "%i", line_index + 1
				);
			    else
				s = STRDUP("");
			    gtk_clist_set_text(
				clist, row, i, s
			    );
			    g_free(s);
			}
			/* Excerpt */
			i = 2;
			if(i < columns)
			{
			    gtk_clist_set_text(
				clist, row, i,
				(excerpt != NULL) ? excerpt : ""
			    );
			}
			/* Last modified */
			i = 3;
			if(i < columns)
			{
			    const gulong last_modified = obj->modify_time;
			    const gchar *s = (last_modified > 0l) ?
				EDVDateFormatString(
				    last_modified, format, relativity
				) : NULL;
			    gtk_clist_set_text(
				clist, row, i,
				(s != NULL) ? s : ""
			    );
			}
			/* Location */
			i = 4;
			if(i < columns)
			{
			    gchar *location = (obj->full_path != NULL) ?
				g_dirname(obj->full_path) : NULL;
			    if(!STRISEMPTY(location))
			    {
				struct stat lstat_buf;
				edv_object_struct *loc_obj = EDVObjectNew();
				EDVObjectSetPath(loc_obj, location);
				if(lstat(location, &lstat_buf))
				{
				    loc_obj->type = EDV_OBJECT_TYPE_DIRECTORY;
				}
				else
				{
				    EDVObjectSetStat(loc_obj, &lstat_buf);
				}
				EDVMatchObjectIcon(
				    core->device, core->total_devices,
				    core->mimetype, core->total_mimetypes,
				    loc_obj->type, loc_obj->full_path,
				    EDV_OBJECT_IS_LINK_VALID(loc_obj),
				    loc_obj->permissions,
				    0,          /* Small icons */
				    &pixmap, &mask,
				    NULL, NULL,
				    NULL, NULL,
				    &pixmap_hid, &mask_hid
				);
				/* Hidden? */
				if(EDVIsObjectNameHidden(loc_obj->name))
				{
				    pixmap = pixmap_hid;
				    mask = mask_hid;
				}
				if(pixmap != NULL)
				    gtk_clist_set_pixtext(
					clist, row, i,
					location,
					EDV_LIST_PIXMAP_TEXT_SPACING,
					pixmap, mask
				    );
				else
				    gtk_clist_set_text(
					clist, row, i,
					location
				    );
				EDVObjectDelete(loc_obj);
			    }
			    g_free(location);
			}
			break;
		    }

		    /* Set row data as the object */
		    gtk_clist_set_row_data_full(
			clist, row,
			obj, EDVFindWinListItemDestroyCB
		    );
		    obj = NULL;
		}
	    }

	    gtk_clist_thaw(clist);

	    /* Delete the row's cell values */
	    g_free(strv);
	}

}

/*
 *	Clears the results clist.
 */
void EDVFindWinListClear(edv_find_win_struct *fw)
{
	GtkCList *clist = (GtkCList *)((fw != NULL) ?
	    fw->results_clist : NULL
	);
	if(clist == NULL)
	    return;

	gtk_clist_freeze(clist);
	gtk_clist_clear(clist);
	gtk_clist_thaw(clist);
}



/*
 *	Sets values on the given find window to the configuration list on
 *	the core structure of the given find window.
 */
void EDVFindWinSyncConfiguration(edv_find_win_struct *fw)
{
	GtkWidget *w;
	cfg_item_struct *cfg_list;
	edv_core_struct *core;


	if(fw == NULL)
	    return;

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

	cfg_list = core->cfg_list;

	/* Get size of toplevel */
	w = fw->toplevel;
	if(w != NULL)
	{
	    GdkWindow *window = w->window;
	    gint x = 0, y = 0;

	    if(window != NULL)
		gdk_window_get_root_origin(window, &x, &y);

	    EDV_SET_I(EDV_CFG_PARM_FINDWIN_X, x);
	    EDV_SET_I(EDV_CFG_PARM_FINDWIN_Y, y);
	    EDV_SET_I(EDV_CFG_PARM_FINDWIN_WIDTH, w->allocation.width);
	    EDV_SET_I(EDV_CFG_PARM_FINDWIN_HEIGHT, w->allocation.height);
	}

	/* Find operation */
	EDV_SET_I(
	    EDV_CFG_PARM_FINDWIN_FIND_OP,
	    EDVFindWinCurrentOperation(fw)
	);

	/* Search string */
	w = fw->search_combo;
	if(w != NULL)
	{
	    GtkCombo *combo = GTK_COMBO(w);
	    GtkEntry *entry = GTK_ENTRY(combo->entry);
	    EDV_SET_S(
		EDV_CFG_PARM_FINDWIN_SEARCH_STRING,
		gtk_entry_get_text(entry)
	    );
	}


	/* Case sensitive */
	w = fw->case_sensitive_check;
	if(w != NULL)
	{
	    EDV_SET_B(
		EDV_CFG_PARM_FINDWIN_CASE_SENSITIVE,
		GTK_TOGGLE_BUTTON_GET_ACTIVE(w)
	    );
	}

	/* Recursive */
	w = fw->recursive_check;
	if(w != NULL)
	{
	    EDV_SET_B(
		EDV_CFG_PARM_FINDWIN_RECURSIVE,
		GTK_TOGGLE_BUTTON_GET_ACTIVE(w)
	    );
	}
}



/*
 *	Creates a new Find Window.
 */
edv_find_win_struct *EDVFindWinNew(edv_core_struct *core)
{
	const gint	border_major = 5,
			border_minor = 2;
	gint	i,
		toplevel_x = 0,
		toplevel_y = 0,
		toplevel_width = EDV_DEF_FINDWIN_WIDTH,
		toplevel_height = EDV_DEF_FINDWIN_HEIGHT;
	gboolean status_bar_map_state = TRUE;
	edv_findwin_operation find_op;
	const gchar *search_string;
	gboolean case_sensitive, recursive;
	edv_status_bar_struct *status_bar;
	GList *glist;
	GtkRcStyle *standard_rcstyle, *lists_rcstyle;
	GtkWidget *w, *parent, *parent2, *parent3, *parent4, *parent5;
	gpointer combo_rtn;
	GtkCombo *combo;
	GtkCList *clist;
	GdkWindow *window;
	GtkAccelGroup *accelgrp;
        pulist_struct *pulist;
        pulistbox_struct *pulistbox;
	const cfg_item_struct *cfg_list;
	edv_find_win_struct *fw = EDV_FIND_WIN(
	    g_malloc0(sizeof(edv_find_win_struct))
	);
	if((fw == NULL) || (core == NULL))
	{
	    g_free(fw);
	    return(NULL);
	}

	cfg_list = core->cfg_list;

	standard_rcstyle = core->standard_rcstyle;
	lists_rcstyle = core->lists_rcstyle;

	toplevel_x = EDV_GET_I(EDV_CFG_PARM_FINDWIN_X);
	toplevel_y = EDV_GET_I(EDV_CFG_PARM_FINDWIN_Y);
	toplevel_width = EDV_GET_I(EDV_CFG_PARM_FINDWIN_WIDTH);
	toplevel_height = EDV_GET_I(EDV_CFG_PARM_FINDWIN_HEIGHT);
	find_op = (edv_findwin_operation)EDV_GET_I(
	    EDV_CFG_PARM_FINDWIN_FIND_OP
	);
	search_string = EDV_GET_S(EDV_CFG_PARM_FINDWIN_SEARCH_STRING);
	case_sensitive = EDV_GET_B(EDV_CFG_PARM_FINDWIN_CASE_SENSITIVE);
	recursive = EDV_GET_B(EDV_CFG_PARM_FINDWIN_RECURSIVE);

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

	fw->stop_count = 0;

	fw->status_bar_map_state = status_bar_map_state;

	fw->browser_num = -1;
	fw->imbr_num = -1;
	fw->recbin_num = -1;
	fw->archiver_num = -1;

	fw->role = EDV_FIND_WIN_ROLE_DISK_OBJECT;
	fw->find_op = EDV_FIND_WIN_FIND_OBJECT_NAME;
	fw->last_write_protect_state = -1;


	/* Begin creating widgets */

	/* Toplevel */
	fw->toplevel = w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_widget_set_uposition(w, toplevel_x, toplevel_y);
	gtk_widget_set_usize(w, toplevel_width, toplevel_height);
	gtk_window_set_wmclass(
	    GTK_WINDOW(w), "find", PROG_NAME
	);
	gtk_window_set_policy(
	    GTK_WINDOW(w),
	    TRUE, TRUE, TRUE
	);
	gtk_window_set_title(GTK_WINDOW(w), "Find Objects");
	gtk_widget_realize(w);
	window = w->window;
	if(window != NULL)
	{
	    GdkGeometry geo;
	    geo.min_width = 100;
	    geo.min_height = 70;
	    geo.base_width = 0;
	    geo.base_height = 0;
	    geo.width_inc = 1;
	    geo.height_inc = 1;
	    gdk_window_set_geometry_hints(
		window, &geo,
		GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE |
		GDK_HINT_RESIZE_INC
	    );
	    GUISetWMIcon(window, (guint8 **)icon_search_48x48_xpm);
	}
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_event",
	    GTK_SIGNAL_FUNC(EDVFindWinDeleteEventCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "destroy",
	    GTK_SIGNAL_FUNC(EDVFindWinDestroyCB), fw
	);
	gtk_container_set_border_width(GTK_CONTAINER(w), 0);
	gtk_window_add_accel_group(GTK_WINDOW(w), accelgrp);
	parent = w;


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


	/* Upper section hbox to separate two columns */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_container_set_border_width(GTK_CONTAINER(w), border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, 0);
	gtk_widget_show(w);
	parent2 = w;


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

	/* Begin creating search criteria widgets */
	w = gtk_vbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* GtkHBox for find operation and search string */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* GtkHBox for the find operation */
        w = gtk_hbox_new(FALSE, border_minor);
        gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
        gtk_widget_show(w);
        parent5 = w;

        w = gtk_label_new(
#if defined(PROG_LANGUAGE_SPANISH)
"Buscar"
#elif defined(PROG_LANGUAGE_FRENCH)
"Découverte"
#elif defined(PROG_LANGUAGE_GERMAN)
"Fund"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Trovare"
#elif defined(PROG_LANGUAGE_DUTCH)
"Vondst"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Ache"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Funn"
#else
"Find"
#endif
	    ":"
	);
        gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
        gtk_widget_show(w);

        fw->find_op_pulistbox = pulistbox = PUListBoxNew(
            parent5,
            150, -1
        );
        pulist = PUListBoxGetPUList(pulistbox);
        PUListBoxMap(pulistbox);
#if defined(PROG_LANGUAGE_SPANISH)
	i = PUListAddItem(pulist, "Por Nombre de archivo");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_NAME);
	i = PUListAddItem(pulist, "Por Contenido");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_CONTENT);
#elif defined(PROG_LANGUAGE_FRENCH)
	i = PUListAddItem(pulist, "Nom D'Objet");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_NAME);
	i = PUListAddItem(pulist, "Contenu D'Objet");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_CONTENT);
#elif defined(PROG_LANGUAGE_GERMAN)
	i = PUListAddItem(pulist, "Wenden Sie Gegen Namen Ein");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_NAME);
	i = PUListAddItem(pulist, "Wenden Sie Gegen Inhalt Ein");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_CONTENT);
#elif defined(PROG_LANGUAGE_ITALIAN)
	i = PUListAddItem(pulist, "Il Nome Di Oggetto");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_NAME);
	i = PUListAddItem(pulist, "Il Contenuto Di Oggetto");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_CONTENT);
#elif defined(PROG_LANGUAGE_DUTCH)
	i = PUListAddItem(pulist, "Heb Bezwaar Naam");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_NAME);
	i = PUListAddItem(pulist, "Heb Bezwaar Inhoud");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_CONTENT);
#elif defined(PROG_LANGUAGE_PORTUGUESE)
	i = PUListAddItem(pulist, "O Nome De Objeto");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_NAME);
	i = PUListAddItem(pulist, "O Conteúdo De Objeto");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_CONTENT);
#elif defined(PROG_LANGUAGE_NORWEGIAN)
	i = PUListAddItem(pulist, "Protester Navn");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_NAME);
	i = PUListAddItem(pulist, "Protester Innhold");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_CONTENT);
#else
	i = PUListAddItem(pulist, "Object Name");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_NAME);
	i = PUListAddItem(pulist, "Object Content");
        PUListSetItemData(pulist, i, (gpointer)EDV_FIND_WIN_FIND_OBJECT_CONTENT);
#endif
        PUListBoxSetLinesVisible(pulistbox, i + 1);


	/* Search string combo */
	glist = NULL;
	w = GUIComboCreate(
#if defined(PROG_LANGUAGE_SPANISH)
"Palabra"
#elif defined(PROG_LANGUAGE_FRENCH)
"Egaler"
#elif defined(PROG_LANGUAGE_GERMAN)
"Anpassend"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Uguagliare"
#elif defined(PROG_LANGUAGE_DUTCH)
"Passend"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Combinar"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Passende"
#else
"Matching"
#endif
	    ":",
	    "",			/* No initial value */
	    glist,		/* List */
	    20,			/* Max items */
	    &combo_rtn,
	    fw,
	    EDVFindWinComboActivateCB,
	    NULL
	);
	fw->search_combo = (GtkWidget *)combo_rtn;
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
	gtk_widget_show(w);

	w = fw->search_combo;
	combo = GTK_COMBO(w);
	gtk_combo_set_case_sensitive(combo, TRUE);

	w = combo->entry;
	EDVEntrySetDND(core, w);
	if(search_string != NULL)
	    gtk_entry_set_text(GTK_ENTRY(w), search_string);

	/* Hbox for location combo */
	w = gtk_hbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* Location combo */
	glist = NULL;
	w = GUIComboCreate(
#if defined(PROG_LANGUAGE_SPANISH)
"Empezar En"
#elif defined(PROG_LANGUAGE_FRENCH)
"Commencer A"
#elif defined(PROG_LANGUAGE_GERMAN)
"Anfangen An"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Cominciare A"
#elif defined(PROG_LANGUAGE_DUTCH)
"Beginnen Aan"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Começar Em"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Start På"
#else
"Starting At"
#endif
	    ":",
	    "",
	    glist,
	    25,		/* Maximum items */
	    &combo_rtn,
	    fw,
	    EDVFindWinComboActivateCB,
	    NULL
	);
	fw->location_combo = (GtkWidget *)combo_rtn;
	gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
	gtk_widget_show(w);

	w = fw->location_combo;
	combo = GTK_COMBO(w);
	gtk_combo_set_case_sensitive(combo, TRUE);

	w = combo->entry;
	EDVEntrySetDND(core, w);
	EDVEntrySetCompletePath(core, w);


	/* Hbox for options */
	w = gtk_hbox_new(FALSE, border_major);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* Case sensitive check */
	fw->case_sensitive_check = w = gtk_check_button_new_with_label(
#if defined(PROG_LANGUAGE_SPANISH)
"Sensible May/min."
#elif defined(PROG_LANGUAGE_FRENCH)
"Reconnaître Sensible"
#elif defined(PROG_LANGUAGE_GERMAN)
"Fall Empfindlich"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Imballare Sensibile"
#elif defined(PROG_LANGUAGE_DUTCH)
"Sluit Gevoelig In"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"O Caso Sensível"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Tilfelle Sensitiv"
#else
"Case Sensitive"
#endif
	);
	GTK_TOGGLE_BUTTON_SET_ACTIVE(w, case_sensitive);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "enter_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "leave_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Verifique esto para discriminar Mayusculas y minusculas"
#elif defined(PROG_LANGUAGE_FRENCH)
"Vérifier ceci pour égaler des ficelles reconnaissent sensiblement"
#elif defined(PROG_LANGUAGE_GERMAN)
"Prüfen sie dies, schnüren fall empfindlich anzupassen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Controllare questo per uguagliare le cordicelle imballano\
 sensibilmente"
#elif defined(PROG_LANGUAGE_DUTCH)
"Controleer dit om bij koorden geval gevoelig te passen"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Verifique isto combinar caso de barbantes sensivelmente"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Sjekk dette passe snortilfelle sensitivt"
#else
"Check this to match strings case sensitively"
#endif
	);
	gtk_widget_show(w);

	/* Recursive check */
	fw->recursive_check = w = gtk_check_button_new_with_label(
#if defined(PROG_LANGUAGE_SPANISH)
"Recursivo"
#elif defined(PROG_LANGUAGE_FRENCH)
"Recursive"
#elif defined(PROG_LANGUAGE_GERMAN)
"Rekursiv"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Ricorsivo"
#elif defined(PROG_LANGUAGE_DUTCH)
"Recursief"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Recursive"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Rekursiv"
#else
"Recursive"
#endif
	);
	GTK_TOGGLE_BUTTON_SET_ACTIVE(w, recursive);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "enter_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "leave_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Verifique esto buscar recursivamente en sub guías"
#elif defined(PROG_LANGUAGE_FRENCH)
"Vérifier ceci pour chercher recursively dans sous les annuaires"
#elif defined(PROG_LANGUAGE_GERMAN)
"Prüfen sie dies, rekursiv in u-boot verzeichnisse zu suchen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Controllare questo per ricercare ricorsivamente in sotto gli elenchi"
#elif defined(PROG_LANGUAGE_DUTCH)
"Controleer dit om recursief in sub gidzen te zoeken"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Verifique isto procurar recursively em guias de submarino"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Sjekk dette gjennomsøke rekursivt inn i sub kataloger"
#else
"Check this to search recursively into sub directories"
#endif
	);
	gtk_widget_show(w);


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


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

	/* Results clist */
	fw->results_clist = w = gtk_clist_new(
	    DEV_FINDWIN_RESULTS_LIST_COLUMNS_MAX
	);
	clist = GTK_CLIST(w);
	gtk_widget_add_events(
	    w,
	    GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
	    GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
	    GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
	    GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_press_event",
	    GTK_SIGNAL_FUNC(EDVCListKeyEventCB), core
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "key_release_event",
	    GTK_SIGNAL_FUNC(EDVCListKeyEventCB), core
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_press_event",
	    GTK_SIGNAL_FUNC(EDVCListButtonEventCB), core
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "button_release_event",
	    GTK_SIGNAL_FUNC(EDVCListButtonEventCB), core
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "motion_notify_event",
	    GTK_SIGNAL_FUNC(EDVCListMotionEventCB), core
	);
	gtk_signal_connect_after(
	    GTK_OBJECT(w), "button_press_event",
	    GTK_SIGNAL_FUNC(EDVFindWinButtonCB), fw
	);
	gtk_container_add(GTK_CONTAINER(parent4), w);
	gtk_widget_realize(w);
	gtk_clist_set_selection_mode(clist, GTK_SELECTION_EXTENDED);
	gtk_clist_column_titles_hide(clist);
	gtk_clist_set_row_height(clist, EDV_LIST_ROW_SPACING);
	gtk_clist_set_shadow_type(clist, GTK_SHADOW_IN);
	gtk_signal_connect(
	    GTK_OBJECT(w), "click_column",
	    GTK_SIGNAL_FUNC(EDVFindWinClickColumnCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "select_row",
	    GTK_SIGNAL_FUNC(EDVFindWinSelectRowCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "unselect_row",
	    GTK_SIGNAL_FUNC(EDVFindWinUnselectRowCB), fw
	);
	gtk_widget_show(w);


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

#define DO_ADD_MENU_ITEM_LABEL  {                       \
 w = GUIMenuItemCreate(                                 \
  menu, GUI_MENU_ITEM_TYPE_LABEL, accelgrp,             \
  icon, label, accel_key, accel_mods, NULL,		\
  mclient_data, func_cb                                 \
 );                                                     \
}
#define DO_ADD_MENU_SEP         {                       \
 w = GUIMenuItemCreate(                                 \
  menu, GUI_MENU_ITEM_TYPE_SEPARATOR, NULL,             \
  NULL, NULL, 0, 0, NULL,                               \
  NULL, NULL                                            \
 );                                                     \
}
	    icon = (guint8 **)icon_open_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Abrir"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ouvrir"
#elif defined(PROG_LANGUAGE_GERMAN)
"Offen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Aperto"
#elif defined(PROG_LANGUAGE_DUTCH)
"Open"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Aberto"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Åpen"
#else
"Open"
#endif
	    ;
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVFindWinOpenCB;
	    DO_ADD_MENU_ITEM_LABEL
	    fw->results_clist_open_mi = w;

	    icon = NULL;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Abrir Con"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ouvrir Avec"
#elif defined(PROG_LANGUAGE_GERMAN)
"Offen Mit"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Aperto Con"
#elif defined(PROG_LANGUAGE_DUTCH)
"Open Met"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Aberto Com"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Åpn Med"
#else
"Open With"
#endif
	    "...";
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVFindWinOpenWithCB;
	    DO_ADD_MENU_ITEM_LABEL
	    fw->results_clist_open_with_mi = w;

	    DO_ADD_MENU_SEP

	    icon = (guint8 **)icon_goto_20x20_xpm;
	    label =
#if defined(PROG_LANGUAGE_SPANISH)
"Vaya A"
#elif defined(PROG_LANGUAGE_FRENCH)
"Aller A"
#elif defined(PROG_LANGUAGE_GERMAN)
"Gehen Zu"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Andare A"
#elif defined(PROG_LANGUAGE_DUTCH)
"Ga Te"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Vá A"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Dra Til"
#else
"GoTo"
#endif
	    ;
	    accel_key = 0;
	    accel_mods = 0;
	    func_cb = EDVFindWinGotoCB;
	    DO_ADD_MENU_ITEM_LABEL
	    fw->results_clist_goto_mi = w;

#undef DO_ADD_MENU_SEP
#undef DO_ADD_MENU_ITEM_LABEL
	}

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

	/* Open button */
	fw->open_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_open_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Abrir"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ouvrir"
#elif defined(PROG_LANGUAGE_GERMAN)
"Offen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Aperto"
#elif defined(PROG_LANGUAGE_DUTCH)
"Open"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Aberto"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Åpen"
#else
"Open"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVFindWinOpenCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "enter_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "leave_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_o, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_o);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Abrir archivo escogido"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ouvrir l'objet choisi"
#elif defined(PROG_LANGUAGE_GERMAN)
"Offen ausgewählten objekt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Aperto scelto oggetto"
#elif defined(PROG_LANGUAGE_DUTCH)
"Open geselecteerd voorwerp"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Objeto selecionado aberto"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Åpn valgt ut objekt"
#else
"Open selected object"
#endif
	);
	gtk_widget_show(w);

	/* Open With button */
	fw->open_with_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_open_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Abrir Con"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ouvrir Avec"
#elif defined(PROG_LANGUAGE_GERMAN)
"Offen Mit"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Aperto Con"
#elif defined(PROG_LANGUAGE_DUTCH)
"Open Met"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Aberto Com"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Åpn Med"
#else
"Open With"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVFindWinOpenWithCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "enter_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "leave_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_w, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_w);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Abrir archivo escogido utilizando un método específico"
#elif defined(PROG_LANGUAGE_FRENCH)
"Ouvrir l'objet choisi utilisant une méthode spécifique"
#elif defined(PROG_LANGUAGE_GERMAN)
"Offen ausgewählten objekt, eine spezifische methode zu benutzen"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Aperto scelto oggetto usando uno specifico metodo"
#elif defined(PROG_LANGUAGE_DUTCH)
"Open geselecteerd voorwerp een specifieke methode te gebruiken"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Objeto selecionado aberto usando um método específico"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Åpn valgt ut objekt bruke en spesifikk metode"
#else
"Open selected object using a specific method"
#endif
	);
	gtk_widget_show(w);

	/* Goto button */
	fw->goto_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_goto_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Vaya A"
#elif defined(PROG_LANGUAGE_FRENCH)
"Aller A"
#elif defined(PROG_LANGUAGE_GERMAN)
"Gehen Zu"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Andare A"
#elif defined(PROG_LANGUAGE_DUTCH)
"Ga Te"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Vá A"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Dra Til"
#else
"GoTo"
#endif
	    , NULL
	);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH, GUI_BUTTON_HLABEL_HEIGHT
	);
	gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVFindWinGotoCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "enter_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "leave_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_g, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_g);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Vaya a escogido se opone"
#elif defined(PROG_LANGUAGE_FRENCH)
"Aller à l'objet choisi"
#elif defined(PROG_LANGUAGE_GERMAN)
"Gehen sie zu ausgewähltem objekt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Andare all'oggetto scelto"
#elif defined(PROG_LANGUAGE_DUTCH)
"Ga te geselecteerd voorwerp"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Vá a objeto selecionado"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Dra til valgt ut objekt"
#else
"Go to selected object"
#endif
	);
	gtk_widget_show(w);


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

	/* Buttons set vbox */
	w = gtk_vbox_new(FALSE, border_minor);
	gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* Search button */
	fw->search_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_search_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Búsqueda"
#elif defined(PROG_LANGUAGE_FRENCH)
"Recherche"
#elif defined(PROG_LANGUAGE_GERMAN)
"Suche"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Ricerca"
#elif defined(PROG_LANGUAGE_DUTCH)
"Zoektocht"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Busca"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Leting"
#else
"Search"
#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(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVFindWinSearchCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "enter_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "leave_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_s);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Empiece la búsqueda"
#elif defined(PROG_LANGUAGE_FRENCH)
"Commencer la recherche"
#elif defined(PROG_LANGUAGE_GERMAN)
"Fangen sie die suche an"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Cominciare la ricerca"
#elif defined(PROG_LANGUAGE_DUTCH)
"Begin de zoektocht"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Comece a busca"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Start letingen"
#else
"Start the search"
#endif
	);
	gtk_widget_show(w);

	/* Stop button */
	fw->stop_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_stop_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Parada"
#elif defined(PROG_LANGUAGE_FRENCH)
"Arrêt"
#elif defined(PROG_LANGUAGE_GERMAN)
"Halt"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Fermata"
#elif defined(PROG_LANGUAGE_DUTCH)
"Einde"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Parada"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Stans"
#else
"Stop"
#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(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVFindWinStopCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "enter_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "leave_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_t, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_t);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Pare el procedimiento actual del hallazgo"
#elif defined(PROG_LANGUAGE_FRENCH)
"Arrêter la procédure actuelle de découverte"
#elif defined(PROG_LANGUAGE_GERMAN)
"Halten sie das jetzige fund verfahren auf"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Fermare la corrente trova la procedura"
#elif defined(PROG_LANGUAGE_DUTCH)
"Stop de huidig vondst procedure"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Pare a corrente achar procedimento"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Stans den nåværendee funnprosedyre"
#else
"Stop the current find procedure"
#endif
	);
	gtk_widget_show(w);

	/* Clear button */
	fw->clear_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_clear_20x20_xpm,
#if defined(PROG_LANGUAGE_SPANISH)
"Claro"
#elif defined(PROG_LANGUAGE_FRENCH)
"Clair"
#elif defined(PROG_LANGUAGE_GERMAN)
"Klar"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Chiaro"
#elif defined(PROG_LANGUAGE_DUTCH)
"Helder"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Claro"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Klar"
#else
"Clear"
#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(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVFindWinClearCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "enter_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "leave_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_accel_group_add(
	    accelgrp, GDK_l, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_l);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"La cuerda clara de la búsqueda y la lista de resultados"
#elif defined(PROG_LANGUAGE_FRENCH)
"La ficelle clairs de recherche et la liste de résultats"
#elif defined(PROG_LANGUAGE_GERMAN)
"Klare suche schnur und ergebnisse führen auf"
#elif defined(PROG_LANGUAGE_ITALIAN)
"L'elenco di cordicella di ricerca e risultati chiaro"
#elif defined(PROG_LANGUAGE_DUTCH)
"Helder zoektocht koord en resultaten sommen op"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Barbante clara de busca e lista de resultados"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Klar letingssnor og resultater lister opp"
#else
"Clear search string and results list"
#endif
	);
	gtk_widget_show(w);


	/* Buttons set vbox */
	w = gtk_vbox_new(FALSE, border_minor);
	gtk_box_pack_end(GTK_BOX(parent3), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent4 = w;

	/* Close button */
	fw->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(parent4), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(EDVFindWinCloseCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "enter_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	gtk_signal_connect(
	    GTK_OBJECT(w), "leave_notify_event",
	    GTK_SIGNAL_FUNC(EDVFindWinCrossingCB), fw
	);
	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);
	GUISetWidgetTip(w,
#if defined(PROG_LANGUAGE_SPANISH)
"Cierre esta ventana"
#elif defined(PROG_LANGUAGE_FRENCH)
"Fermer cette fenêtre"
#elif defined(PROG_LANGUAGE_GERMAN)
"Schließen sie dieses fenster"
#elif defined(PROG_LANGUAGE_ITALIAN)
"Vicino questa finestra"
#elif defined(PROG_LANGUAGE_DUTCH)
"Sluit deze raam"
#elif defined(PROG_LANGUAGE_PORTUGUESE)
"Próximo esta janela"
#elif defined(PROG_LANGUAGE_NORWEGIAN)
"Stenge dette vinduet"
#else
"Close this window"
#endif
	);
	gtk_widget_show(w);


	/* Status Bar */
	fw->status_bar = status_bar = EDVStatusBarNew(
	    core, fw->main_vbox
	);
	if(status_bar != NULL)
	{
	    if(fw->status_bar_map_state)
		EDVStatusBarMap(status_bar);
	    else
		EDVStatusBarUnmap(status_bar);
	}


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


	EDVFindWinUpdateMenus(fw);

	return(fw);
}

/*
 *	Updates the Find Window's widgets to reflect current values.
 */
void EDVFindWinUpdateMenus(edv_find_win_struct *fw)
{
	gboolean	write_protect,
			write_protect_changed = FALSE,
			sensitive;
	gint sel_row;
	GList *glist;
	GtkCList *clist;
	const cfg_item_struct *cfg_list;
	edv_core_struct *core;


	if(fw == NULL)
	    return;

	core = fw->core;
	clist = (GtkCList *)fw->results_clist;
	if((core == NULL) || (clist == NULL))
	    return;

	cfg_list = core->cfg_list;

	/* Get last selected row on the results clist */
	glist = clist->selection_end;
	sel_row = (glist != NULL) ? (gint)glist->data : -1;


#define DO_SHOW			\
{ if(w != NULL) { gtk_widget_show(w); } }
#define DO_HIDE			\
{ if(w != NULL) { gtk_widget_hide(w); } }
#define DO_SET_CHECK_STATE	\
{ GUIMenuItemSetCheck(w, state, FALSE); }

	/* Get global write protect state */
	write_protect = EDV_GET_B(EDV_CFG_PARM_WRITE_PROTECT);
	if(fw->last_write_protect_state < 0)
	{
	    write_protect_changed = TRUE;
	}
	else
	{
	    if((write_protect && !fw->last_write_protect_state) ||
	       (!write_protect && fw->last_write_protect_state)
	    )
		write_protect_changed = TRUE;
	}
	fw->last_write_protect_state = write_protect ? 1 : 0;


	/* Set location combo sensitive or not depending on the role */
	if(fw->processing ||
	  (fw->role == EDV_FIND_WIN_ROLE_RECYCLED_OBJECT)
	)
	    sensitive = FALSE;
	else
	    sensitive = TRUE;
	GTK_WIDGET_SET_SENSITIVE(fw->location_combo, sensitive);


	/* Update buttons */
	sensitive = fw->processing;
	GTK_WIDGET_SET_SENSITIVE(fw->stop_btn, sensitive);

	sensitive = !fw->processing;
	GTK_WIDGET_SET_SENSITIVE(fw->search_combo, sensitive);
	GTK_WIDGET_SET_SENSITIVE(fw->case_sensitive_check, sensitive);
	GTK_WIDGET_SET_SENSITIVE(fw->recursive_check, sensitive);
	GTK_WIDGET_SET_SENSITIVE(
	    PUListBoxGetToplevel(fw->find_op_pulistbox),
	    sensitive
	);
	GTK_WIDGET_SET_SENSITIVE(fw->search_btn, sensitive);
	GTK_WIDGET_SET_SENSITIVE(fw->clear_btn, sensitive);
	GTK_WIDGET_SET_SENSITIVE(fw->close_btn, sensitive);

	sensitive = (!fw->processing && (sel_row > -1)) ? TRUE : FALSE;
	GTK_WIDGET_SET_SENSITIVE(fw->open_btn, sensitive);
	GTK_WIDGET_SET_SENSITIVE(fw->results_clist_open_mi, sensitive);
	GTK_WIDGET_SET_SENSITIVE(fw->open_with_btn, sensitive);
	GTK_WIDGET_SET_SENSITIVE(fw->results_clist_open_with_mi, sensitive);

	sensitive = (!fw->processing && (sel_row > -1)) ? TRUE : FALSE;
	GTK_WIDGET_SET_SENSITIVE(fw->goto_btn, sensitive);
	GTK_WIDGET_SET_SENSITIVE(fw->results_clist_goto_mi, sensitive);


	/* Update status bar */
	EDVStatusBarUpdate(fw->status_bar);

#undef DO_SHOW
#undef DO_HIDE
#undef DO_SET_CHECK_STATE
}

/*
 *	Sets the Find Window as busy or ready.
 */
void EDVFindWinSetBusy(edv_find_win_struct *fw, const gboolean is_busy)
{
	GdkCursor *cursor;
	GtkWidget *w;
	edv_core_struct *core;

	if(fw == NULL)
	    return;

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

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

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

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

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

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

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

/*
 *	Checks if the Find Window is mapped.
 */
gboolean EDVFindWinIsMapped(edv_find_win_struct *fw)
{
	GtkWidget *w = (fw != NULL) ? fw->toplevel : NULL;
	return((w != NULL) ? GTK_WIDGET_MAPPED(w) : FALSE);
}

/*
 *	Maps the Find Window.
 */
void EDVFindWinMap(edv_find_win_struct *fw)
{
	GtkWidget *w = (fw != NULL) ? fw->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_show_raise(w);

	w = fw->search_combo;
	w = GTK_COMBO(w)->entry;
	gtk_widget_grab_focus(w);
}

/*
 *	Unmaps the Find Window.
 */
void EDVFindWinUnmap(edv_find_win_struct *fw)
{
	GtkWidget *w = (fw != NULL) ? fw->toplevel : NULL;
	if(w == NULL)
	    return;

	gtk_widget_hide(w);
}

/*
 *	Deletes the Find Window.
 */
void EDVFindWinDelete(edv_find_win_struct *fw)
{
	if(fw == NULL)
	    return;

	EDVStatusBarDelete(fw->status_bar);

	GTK_WIDGET_DESTROY(fw->results_clist_menu);

	PUListBoxDelete(fw->find_op_pulistbox);
	GTK_WIDGET_DESTROY(fw->search_combo);
	GTK_WIDGET_DESTROY(fw->location_combo);
	GTK_WIDGET_DESTROY(fw->case_sensitive_check);
	GTK_WIDGET_DESTROY(fw->recursive_check);

	GTK_WIDGET_DESTROY(fw->search_btn);
	GTK_WIDGET_DESTROY(fw->stop_btn);
	GTK_WIDGET_DESTROY(fw->clear_btn);
	GTK_WIDGET_DESTROY(fw->close_btn);
	GTK_WIDGET_DESTROY(fw->results_clist);
	GTK_WIDGET_DESTROY(fw->open_btn);
	GTK_WIDGET_DESTROY(fw->open_with_btn);
	GTK_WIDGET_DESTROY(fw->goto_btn);

	GTK_WIDGET_DESTROY(fw->main_vbox);
	GTK_WIDGET_DESTROY(fw->toplevel);

	GTK_ACCEL_GROUP_UNREF(fw->accelgrp);

	g_free(fw);
}
