#include <string.h>
#include <sys/stat.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

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

#include "guiutils.h"
#include "cdialog.h"
#include "pdialog.h"
#include "csd.h"
#include "fsd.h"

#include "pref.h"
#include "prefcb.h"
#include "prefop.h"
#include "manedit.h"


void PrefDestroyItem(gpointer data);
void PrefDrawingAreaDestroyCB(GtkObject *object, gpointer data);

void PrefDestroyCB(GtkObject *widget, gpointer data);
gint PrefCloseCB(GtkWidget *widget, GdkEvent *event, gpointer data);
void PrefCloseMCB(GtkWidget *widget, gpointer data);
void PrefOKCB(GtkWidget *widget, gpointer data);
void PrefApplyCB(GtkWidget *widget, gpointer data);
void PrefSaveCB(GtkWidget *widget, gpointer data);

gint PrefMenuMapCB(GtkWidget *widget, GdkEvent *event, gpointer data);

void PrefSelectColorCB(GtkWidget *widget, gpointer data);
void PrefSelectFontCB(GtkWidget *widget, gpointer data);
void PrefBrowsePathCB(GtkWidget *widget, gpointer data);

void PrefCatagoryCTreeSelectCB(
	GtkCTree *ctree, GtkCTreeNode *branch, gint column, gpointer data
);
void PrefCatagoryCTreeUnselectCB(
	GtkCTree *ctree, GtkCTreeNode *branch, gint column, gpointer data
);
void PrefCatagoryCTreeExpandCB(
	GtkCTree *ctree, GtkCTreeNode *node, gpointer data
);

gchar *PrefManPageDirPromptBrowseCB(
	gpointer dialog, gpointer data, gint prompt_num
);
void PrefManPageDirsAddCB(GtkWidget *widget, gpointer data);
void PrefManPageDirsEditCB(GtkWidget *widget, gpointer data);
void PrefManPageDirsRemoveCB(GtkWidget *widget, gpointer data);
void PrefManPageDirsCListSelectCB(
	GtkWidget *widget, gint row, gint column,
	GdkEventButton *event, gpointer data
);
void PrefManPageDirsCListUnselectCB(
	GtkWidget *widget, gint row, gint column,
	GdkEventButton *event, gpointer data
);


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


/*
 *	Item destroy callback.
 */
void PrefDestroyItem(gpointer data)
{
	pref_item_struct *item = PREF_ITEM(data);
	if(item == NULL)
	    return;

	g_free(item);
}


/*
 *	Drawing area destroy callback.
 *
 *	This is just to Delete its associated csd_color_struct.
 */
void PrefDrawingAreaDestroyCB(GtkObject *object, gpointer data)
{
	csd_color_struct *c = (csd_color_struct *)data;
	if(c == NULL)
	    return;

	g_free(c);
}

/*
 *	Destroy callback.
 */
void PrefDestroyCB(GtkObject *widget, gpointer data)
{

}

/*
 *	Close callback.
 */
gint PrefCloseCB(GtkWidget *widget, GdkEvent *event, gpointer data)
{
	static gboolean reenterant = FALSE;
	pref_struct *pref = PREF(data);
	if(pref == NULL)
	    return(TRUE);

	if(!pref->initialized)
	    return(TRUE);

	if(reenterant)
	    return(TRUE);
	else
	    reenterant = TRUE;

	/* Check if currently processing */
	if(pref->processing)
	{
	    reenterant = FALSE;
	    return(TRUE);
	}   

	/* Unmap preferences window */
	PrefUnmap(pref);

	reenterant = FALSE;
	return(TRUE);
}


/*
 *      Close callback from menu item.
 */
void PrefCloseMCB(GtkWidget *widget, gpointer data)
{
	PrefCloseCB(widget, NULL, data);
}

/*
 *      OK callback.
 */
void PrefOKCB(GtkWidget *widget, gpointer data)
{
	pref_struct *pref = PREF(data);
	if(pref == NULL)
	    return;

	PrefSetBusy(pref);
	PrefDoApply(pref);
	PrefSetReady(pref);

	PrefUnmap(pref);
}

/*
 *	Apply callback.
 */     
void PrefApplyCB(GtkWidget *widget, gpointer data)
{       
	pref_struct *pref = PREF(data);
	if(pref == NULL)
	    return;

	PrefSetBusy(pref);
	PrefDoApply(pref);
	PrefSetReady(pref);
}

/*
 *	Save callback.
 */     
void PrefSaveCB(GtkWidget *widget, gpointer data)
{
	pref_struct *pref = PREF(data);
	if(pref == NULL)
	    return;


}


/*
 *	Menu map callback.
 */
gint PrefMenuMapCB(GtkWidget *widget, GdkEvent *event, gpointer data)
{



	return(TRUE);
}

/*
 *	Select color callback.
 *
 *	When a select color GtkButton is pressed, the color selection
 *	dialog will be mapped to select a color.
 *
 *	If a color is selected the color values will be updated on
 *	the GtkDrawingArea widget.
 *
 *	Input for data is the GtkDrawingArea, not a pref_struct!
 */
void PrefSelectColorCB(GtkWidget *widget, gpointer data)
{
	static gboolean reenterant = FALSE;
	GtkWidget *da = (GtkWidget *)data;
	csd_color_struct *start_color, *color_rtn;
	if(da == NULL)
	    return;

	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	start_color = gtk_object_get_user_data(GTK_OBJECT(da));
	if(start_color == NULL)
	{
	    reenterant = FALSE;
	    return;
	}
	if(CSDGetResponse(
	    "Select Color",
	    "Select", "Cancel",
	    start_color, &color_rtn,
	    NULL, NULL
	))
	{
	    if((color_rtn != NULL) && !GTK_WIDGET_NO_WINDOW(da))
	    {
		GdkColormap *colormap = gdk_window_get_colormap(da->window);
		GdkColor gdk_color;

		gdk_color.red = (guint16)(color_rtn->r * 65535.0);
		gdk_color.green = (guint16)(color_rtn->g * 65535.0);
		gdk_color.blue = (guint16)(color_rtn->b * 65535.0);

		gdk_color_alloc(colormap, &gdk_color);
		gdk_window_set_background(da->window, &gdk_color);
		gdk_window_clear(da->window);

		/* Update csd_color_struct on GtkDrawingArea widget */
		if(start_color != color_rtn)
		    memcpy(start_color, color_rtn, sizeof(csd_color_struct));
	    }
	}

	reenterant = FALSE;
}

/*
 *      Select font callback.
 *
 *      When a select font GtkButton is pressed, the font selection
 *      dialog will be mapped to select a font.
 *
 *      If a font name is selected the font name will be updated on
 *      the GtkEntry widget's value.
 *
 *      Input for data is the GtkEntry, not a pref_struct!  
 */
void PrefSelectFontCB(GtkWidget *widget, gpointer data)
{
	static gboolean reenterant = FALSE;
	gchar *font_name, *font_name_rtn;
	GtkEntry *entry = (GtkEntry *)data;
	if(entry == NULL)
	    return;

	/* Get font name from entry widget, and make a copy */
	font_name = STRDUP(gtk_entry_get_text(entry));

	if(FSDGetResponse(
	    "Select Font",
	    "Select", "Cancel",
	    font_name,
	    &font_name_rtn
	))
	{
	    if(font_name_rtn != NULL)
	    {
		gtk_entry_set_text(entry, font_name_rtn);
	    }
	}

	g_free(font_name);

	reenterant = FALSE;
}

/*
 *	Browse path callback.
 *
 *	Maps the file browser and query's for a new path, starting with
 *	the current path prefix from the GtkEntry (taken as data).
 *
 *      Input for data is a GtkEntry, not a pref_struct!
 */
void PrefBrowsePathCB(GtkWidget *widget, gpointer data)
{
	static gboolean reenterant = FALSE;
	gboolean status;
	gchar *old_path, *s;
	fb_type_struct **ext_type;
	gint total_ext_types;
	gchar **path_rtn;
	gint path_total_rtns;
	fb_type_struct *ext_type_rtn;
	GtkEntry *entry = (GtkEntry *)data;
	if(entry == NULL)
	    return;

	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	/* Record old path, as a coppied string */
	old_path = STRDUP(gtk_entry_get_text(entry));

	/* Parse old path */
	if(old_path != NULL)
	{
	    struct stat stat_buf;

	    s = strchr(old_path, ' ');
	    if(s == NULL)
		s = strchr(old_path, '\t');
	    if(s != NULL)
		*s = '\0';

	    /* Old path exists? */
	    if(!stat(old_path, &stat_buf))
	    {
		/* Old path not a directory? */
		if(!S_ISDIR(stat_buf.st_mode))
		{
		    /* Reduce to parent path */
		    s = strrchr(old_path, G_DIR_SEPARATOR);
		    if(s != NULL)
			*s = '\0';
		}
	    }
	}

	/* Allocate file extension types list */
	ext_type = NULL;
	total_ext_types = 0;
	FileBrowserTypeListNew(
	    &ext_type, &total_ext_types,
	    "*.*", "All files"
	);

	/* Map file browser and get response */
	status = FileBrowserGetResponse(
	    "Select Path",
	    "Select", "Cancel",
	    old_path,
	    ext_type, total_ext_types,
	    &path_rtn, &path_total_rtns, &ext_type_rtn
	);

	/* Delete file extension types list */
	FileBrowserDeleteTypeList(ext_type, total_ext_types);
	ext_type = NULL;
	total_ext_types = 0;

	/* Got response? */
	if(status)
	{
	    if(path_total_rtns > 0)
	    {
		gchar *new_path = path_rtn[0];

		if(new_path != NULL)
		    gtk_entry_set_text(entry, new_path);
	    }
	}

	/* Delete old path */
	g_free(old_path);
	old_path = NULL;

	reenterant = FALSE;
}               


/*
 *	Catagory ctree branch select callback.
 */
void PrefCatagoryCTreeSelectCB(
	GtkCTree *ctree, GtkCTreeNode *branch, gint column, gpointer data
)
{
	static gboolean reenterant = FALSE;
	gint row;
	GtkCList *clist;
	pref_item_struct *item; 
	GtkWidget *panel_parent;
	pref_struct *pref = PREF(data);
	if((pref == NULL) || (ctree == NULL))
	    return;

	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	if((gpointer)ctree == (gpointer)pref->catagory_ctree)
	{
	    clist = (GtkCList *)ctree;

	    PrefSetBusy(pref);

	    /* A branch selected previously? */
	    if(pref->selected_branch != NULL)
	    {
		/* Unselect signal will have the values applied, we don't
		 * need to apply values here.
		 */
	    }

	    /* Scroll if row not visibile */
	    row = gtk_clist_find_row_from_data(
		clist,
		(gpointer)PrefBranchGetData(ctree, branch)
	    );
	    if(row > -1)
	    {
		if(gtk_clist_row_is_visible(clist, row) !=
		    GTK_VISIBILITY_FULL
		)
		    gtk_clist_moveto(
			clist,
			row, 0,         /* Row, column */
			0.5, 0.0        /* Row, column */
		    );
	    }

	    /* Newly selected branch valid? */
	    if(branch != NULL)
	    {
		/* Get catagory branch item pointer */
		item = PrefBranchGetData(
		    ctree, branch
		);
		if(item != NULL)
		{
		    /* Get panel parent widget corresponding to the
		     * catagory index
		     */
		    panel_parent = PrefPanelGetWidget(
			pref, item->catagory
		    );

		    /* Unmap panel parent */
		    if(panel_parent != NULL)
			gtk_widget_show(panel_parent);
		}
	    }

	    /* Update selected branch pointer */
	    pref->selected_branch = branch;

	    PrefSetReady(pref);
	}

	reenterant = FALSE;
}

/*
 *	Preferences catagory ctree unselect callback.
 */
void PrefCatagoryCTreeUnselectCB(
	GtkCTree *ctree, GtkCTreeNode *branch, gint column, gpointer data
)
{
	static gboolean reenterant = FALSE;
	pref_item_struct *item;
	GtkWidget *panel_parent;
	pref_struct *pref = PREF(data);
	if((pref == NULL) || (ctree == NULL))
	    return;

	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	if((gpointer)ctree == (gpointer)pref->catagory_ctree)
	{
	    /* Get catagory branch item pointer */
	    item = PrefBranchGetData(
		ctree, branch
	    );
	    if(item != NULL)
	    {
		/* Get panel parent widget corresponding to the
		 * catagory index.
		 */
		panel_parent = PrefPanelGetWidget(
		    pref, item->catagory
		);

		/* Unmap panel parent */
		if(panel_parent != NULL)
		    gtk_widget_hide(panel_parent);
	    }

	    /* Mark selected branch as unselected if this unselected
	     * branch was the selected branch.
	     */
	    if(branch == pref->selected_branch)
		pref->selected_branch = NULL;
	}

	reenterant = FALSE;
}

/*
 *      Catagory ctree branch expand (and collapse) callback, called
 *      whenever a branch is expanded or collapsed.
 */
void PrefCatagoryCTreeExpandCB(
	GtkCTree *ctree, GtkCTreeNode *node, gpointer data
)
{
	static gboolean reenterant = FALSE;
	pref_struct *pref = PREF(data);
	if((pref == NULL) || (ctree == NULL))
	    return;

	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	if((gpointer)ctree == (gpointer)pref->catagory_ctree)
	{
	    /* Update catagory clist column width */
	    gtk_clist_set_column_width(
		(GtkCList *)ctree,
		0,                      /* Column */
		gtk_clist_optimal_column_width((GtkCList *)ctree, 0)
	    );

	}

	reenterant = FALSE;
}


/*
 *	Manual page directory prompt browse callback.
 */
gchar *PrefManPageDirPromptBrowseCB(
	gpointer dialog, gpointer data, gint prompt_num
)
{
	static gboolean reenterant = FALSE;
	gboolean status;
	gchar *s, *old_path;
	fb_type_struct **ext_type;
	gint total_ext_types; 
	gchar **path_rtn;
	gint path_total_rtns;
	fb_type_struct *ext_type_rtn;
	pref_struct *pref = PREF(data);
	static gchar rtn_path[PATH_MAX + NAME_MAX];
	if(pref == NULL)
	    return(NULL);

	if(reenterant)
	    return(NULL);
	else
	    reenterant = TRUE;


	/* Get old path, coppied */
	s = PDialogGetPromptValue(prompt_num);
	old_path = STRDUP((s != NULL) ? s : "");

	/* Reset return path */
	*rtn_path = '\0';

	/* Allocate file extension types list */
	ext_type = NULL;
	total_ext_types = 0;
	FileBrowserTypeListNew(
	    &ext_type, &total_ext_types,
	    "*.*", "All files"
	);

	/* Map file browser and get response */
	status = FileBrowserGetResponse(
	    "Select Path",
	    "Select", "Cancel",
	    old_path,
	    ext_type, total_ext_types,
	    &path_rtn, &path_total_rtns, &ext_type_rtn
	);

	/* Delete file extension types list */
	FileBrowserDeleteTypeList(ext_type, total_ext_types);
	ext_type = NULL;
	total_ext_types = 0;

	/* Got response? */
	if(status)
	{
	    if(path_total_rtns > 0)
	    {
		strncpy(rtn_path, path_rtn[0], PATH_MAX + NAME_MAX);
		rtn_path[PATH_MAX + NAME_MAX - 1] = '\0';
	    }
	}

	/* Delete old path */
	g_free(old_path);
	old_path = NULL;

	reenterant = FALSE;
	return(rtn_path);
}

/*
 *	Sets up prompt dialog with request to add a new item into the
 *	manpage dirs clist.
 */
void PrefManPageDirsAddCB(GtkWidget *widget, gpointer data)
{
	static gboolean reenterant = FALSE;
	gint row;
	gchar **response_value;
	gint total_response_values;
	GtkCList *clist;
	pref_struct *pref = PREF(data);
	if((widget == NULL) || (pref == NULL))
	    return;

	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	row = pref->selected_manpage_dirs_clist_item;

	clist = (GtkCList *)PrefParmGetWidget(
	    pref, MEDIT_PREF_PARM_LOCATIONS_MAN_DIRS
	);
	if(clist == NULL)
	{
	    reenterant = FALSE;
	    return;
	}

	/* Reset all prompt dialog prompts */
	PDialogDeleteAllPrompts();

	/* Add a new prompt for the path to the manual page directory,
	 * set a default value to give the user an idea.
	 */
	PDialogAddPromptWithBrowse(
	    NULL, "Path:",
#if defined(__FreeBSD__)
	    "/usr/share/man",
#else
	    "/usr/man",
#endif
	    pref,
	    PrefManPageDirPromptBrowseCB
	);
	PDialogAddPrompt(
	    NULL, "Label:", "General"
	);

	/* Prompt for user response */
	response_value = PDialogGetResponse(
	    "Add Manual Page Directory",
	    "Add Manual Page Directory",
	    NULL,
	    PDIALOG_ICON_QUESTION,
	    "Add", "Cancel",
	    PDIALOG_BTNFLAG_SUBMIT | PDIALOG_BTNFLAG_CANCEL,
	    PDIALOG_BTNFLAG_SUBMIT,
	    &total_response_values
	);
	if((response_value != NULL) && (total_response_values >= 2))
	{
	    gchar *text[2];
	    gint new_row = -1;
	    struct stat stat_buf;

	    text[0] = response_value[0];
	    text[1] = response_value[1];

	    /* Begin adding clist row */
	    gtk_clist_freeze(clist);
	    if((row < 0) || (row >= (clist->rows - 1)))
	    {
		new_row = gtk_clist_append(clist, text);
	    }
	    else
	    {
		new_row = gtk_clist_insert(clist, row + 1, text);
	    }
	    gtk_clist_thaw(clist);

	    gtk_clist_select_row(clist, new_row, 0);

	    /* Check if response dir path exists */
	    if(response_value[0] != NULL)
	    {
		if(stat(response_value[0], &stat_buf)) 
		{
		    gchar *s = g_strdup_printf(
			"Warning, directory `%s' does not exist.",
			response_value[0]
		    );
		    CDialogGetResponse(
"Directory not found!",
			s,
"The specified directory does not appear to exist,\n\
verify that the given path exists and is specified\n\
correctly.",
			CDIALOG_ICON_WARNING,
			CDIALOG_BTNFLAG_OK | CDIALOG_BTNFLAG_HELP,
			CDIALOG_BTNFLAG_OK
		    );
		    g_free(s);
		}
	    }
	}

	reenterant = FALSE;
}

/*
 *      Sets up prompt dialog with request to edit selected item on the
 *      manpage dirs clist.
 */
void PrefManPageDirsEditCB(GtkWidget *widget, gpointer data)
{
	static gboolean reenterant = FALSE;
	gint row;
	gchar **response_value;
	gint total_response_values;
	GtkCList *clist;
	gchar *cur_path, *cur_label;
	pref_struct *pref = PREF(data);
	if((widget == NULL) || (pref == NULL))
	    return;

	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	row = pref->selected_manpage_dirs_clist_item;

	clist = (GtkCList *)PrefParmGetWidget(
	    pref, MEDIT_PREF_PARM_LOCATIONS_MAN_DIRS
	);
	if(clist == NULL)
	{
	    reenterant = FALSE;
	    return;
	}

	if((row < 0) || (row >= clist->rows))
	{
	    reenterant = FALSE;
	    return;
	}

	/* Get current values of row from clist, coppied */
	if(!gtk_clist_get_text(clist, row, 0, &cur_path))
	    cur_path = NULL;
	cur_path = STRDUP(cur_path);

	if(!gtk_clist_get_text(clist, row, 1, &cur_label))
	    cur_label = NULL;
	cur_label = STRDUP(cur_label);


	PDialogDeleteAllPrompts();
	PDialogAddPromptWithBrowse(
	    NULL, "Path:", cur_path,
	    pref,
	    PrefManPageDirPromptBrowseCB
	);
	PDialogAddPrompt(
	    NULL, "Label:", cur_label
	);
	response_value = PDialogGetResponse(
	    "Edit Manual Page Directory Properties",
	    "Edit Manual Page Directory Properties",
	    NULL,
	    PDIALOG_ICON_QUESTION,
	    "Set", "Cancel",
	    PDIALOG_BTNFLAG_SUBMIT | PDIALOG_BTNFLAG_CANCEL,
	    PDIALOG_BTNFLAG_SUBMIT,
	    &total_response_values
	);

	if((response_value != NULL) && (total_response_values >= 2))
	{
	    struct stat stat_buf;

	    /* Begin updating values to selected clist row */
	    gtk_clist_freeze(clist);
	    gtk_clist_set_text(
		clist, row, 0, response_value[0]
	    );
	    gtk_clist_set_text(
		clist, row, 1, response_value[1]
	    );
	    gtk_clist_thaw(clist);

	    gtk_clist_select_row(clist, row, 0);

	    /* Check if response dir path exists */
	    if(response_value[0] != NULL)
	    {
	        if(stat(response_value[0], &stat_buf))
	        {
		    gchar *s = g_strdup_printf(
			"Warning, directory `%s' does not exist.",
			response_value[0]
		    );
		    CDialogGetResponse(
"Directory not found!",
			s,
"The specified directory does not appear to exist,\n\
verify that the given path exists and is specified\n\
correctly.",
			CDIALOG_ICON_WARNING,
			CDIALOG_BTNFLAG_OK | CDIALOG_BTNFLAG_HELP,
			CDIALOG_BTNFLAG_OK
		    );
		    g_free(s);
		}
	    }
	}


	g_free(cur_path);
	g_free(cur_label);

	reenterant = FALSE;
}

/*
 *      Removes selected row from manpage dirs clist.
 */
void PrefManPageDirsRemoveCB(GtkWidget *widget, gpointer data)
{
	static gboolean reenterant = FALSE;
	gint status, row;
	GtkCList *clist;
	pref_struct *pref = PREF(data);
	if((widget == NULL) || (pref == NULL))
	    return;
 
	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	clist = (GtkCList *)PrefParmGetWidget(
	    pref, MEDIT_PREF_PARM_LOCATIONS_MAN_DIRS
	);
	row = pref->selected_manpage_dirs_clist_item;
	if((clist == NULL) || (row < 0))
	{
	    reenterant = FALSE;
	    return;
	}

	status = CDialogGetResponse(
"Remove Manual Page Directory?",
"Are you sure you want to remove the selected\n\
Manual Page directory?",
"You are being asked if you want to remove the\n\
selected Manual Page directory from the list of\n\
global Manual Page directories that this program\n\
will work with.",
	    CDIALOG_ICON_WARNING,
	    CDIALOG_BTNFLAG_YES | CDIALOG_BTNFLAG_NO |
	    CDIALOG_BTNFLAG_HELP,
	    CDIALOG_BTNFLAG_NO
	);
	switch(status)
	{
	  case CDIALOG_RESPONSE_YES:
	  case CDIALOG_RESPONSE_YES_TO_ALL:
	  case CDIALOG_RESPONSE_OK:
	    gtk_clist_freeze(clist);
	    gtk_clist_remove(clist, row);
	    gtk_clist_thaw(clist);
	    break;
	}

	reenterant = FALSE;
}

/*
 *	Preferences global manual page directories clist select callback.
 */
void PrefManPageDirsCListSelectCB(
	GtkWidget *widget, gint row, gint column,
	GdkEventButton *event, gpointer data
)
{
	static gboolean reenterant = FALSE;
	GtkWidget *w;
	pref_struct *pref = PREF(data);
	if((widget == NULL) || (pref == NULL))
	    return;

	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_LOCATIONS_MAN_DIRS);
	if(widget == w)
	{
	    pref->selected_manpage_dirs_clist_item = row;
	}

	reenterant = FALSE;
}

/*
 *      Preferences global manual page directories clist unselect
 *	callback.
 */
void PrefManPageDirsCListUnselectCB(  
	GtkWidget *widget, gint row, gint column,
	GdkEventButton *event, gpointer data
)
{
	static gboolean reenterant = FALSE;
	GtkWidget *w;
	pref_struct *pref = PREF(data);
	if((widget == NULL) || (pref == NULL))
	    return;

	if(reenterant)
	    return;
	else
	    reenterant = TRUE;

	w = PrefParmGetWidget(pref, MEDIT_PREF_PARM_LOCATIONS_MAN_DIRS);
	if(widget == w)    
	{
	    pref->selected_manpage_dirs_clist_item = -1;
	}

	reenterant = FALSE;
}
