/*
** 1999-05-10 -	A module to deal with the command group DpFocus, the purpose of which is
**		to (finally!) make keyboard navigation possible in gentoo. Should at least
**		give people something else to mail me about. :^)
*/

#include "gentoo.h"

#include "dirpane.h"
#include "cmdarg.h"
#include "cmdseq_config.h"
#include "cmd_dpfocus.h"

/* ----------------------------------------------------------------------------------------- */

typedef struct {
	gboolean	modified;
	gboolean	edge_wrap;		/* Wrap focus at upper/lower edge? */
} OptDpFocus;

static OptDpFocus	dpfocus_options;
static CmdCfg		*dpfocus_cmc = NULL;

/* ----------------------------------------------------------------------------------------- */

#define	CMD_NONE	(0)
#define	CMD_SAME	(1)
#define	CMD_PREV	(2)
#define	CMD_NEXT	(3)
#define	CMD_FIRST	(4)
#define	CMD_LAST	(5)
#define	CMD_ACTIVATE	(6)

/* ----------------------------------------------------------------------------------------- */

/* 1999-05-10 -	Do some focusing. */
int cmd_dpfocus(MainInfo *min, DirPane *src, DirPane *dst, CmdArg *ca)
{
	gboolean	sel = car_keyword_get_boolean(ca, "select", FALSE),
			center = car_keyword_get_boolean(ca, "center", FALSE);
	guint		cmd = car_bareword_get_enum(ca, 0, CMD_SAME, "none", "same", "prev", "next",
							"first", "last", "activate", NULL);

	if((sel == TRUE) && (cmd >= CMD_SAME && cmd <= CMD_LAST))
		dp_toggle(src, src->focus_row);

	switch(cmd)
	{
		case CMD_NONE:
			dp_unfocus(src);
			src->old_focus_row = -1;		/* None really means none. */
			break;
		case CMD_SAME:
			break;
		case CMD_PREV:
			if(src->focus_row == -1)
				dp_focus(src, src->dir.num_lines - 1);
			else
			{
				gint	dest = src->focus_row - 1;

				if(dest < 0)
				{
					if(dpfocus_options.edge_wrap)
						dest = src->dir.num_lines - 1;
					else
						dest = 0;
				}
				if(dest != src->focus_row)
					dp_focus(src, dest);
			}
			break;
		case CMD_NEXT:
			if(src->focus_row == -1)
				dp_focus(src, 0);
			else
			{
				gint	dest = src->focus_row + 1;

				if(dest >= src->dir.num_lines)
				{
					if(dpfocus_options.edge_wrap)
						dest = 0;
					else
						dest = src->dir.num_lines - 1;
				}
				if(dest != src->focus_row)
					dp_focus(src, dest);
			}
			break;
		case CMD_FIRST:
			dp_focus(src, 0);
			break;
		case CMD_LAST:
			dp_focus(src, src->dir.num_lines - 1);
			break;
		case CMD_ACTIVATE:
			dp_activate_row(src, src->focus_row);
			break;
	}

	if((center == TRUE) && (src->focus_row != -1))
		gtk_clist_moveto(src->list, src->focus_row, -1, 0.5, 0.0);

	gtk_widget_grab_focus(GTK_WIDGET(min->gui->top));

	return 1;
}

/* ----------------------------------------------------------------------------------------- */

void cfg_dpfocus(MainInfo *min)
{
	if(dpfocus_cmc == NULL)
	{
		dpfocus_options.modified  = FALSE;
		dpfocus_options.edge_wrap = FALSE;

		dpfocus_cmc = cmc_config_new("DpFocus", &dpfocus_options);
		cmc_field_add_boolean(dpfocus_cmc, "modified", NULL, offsetof(OptDpFocus, modified));
		cmc_field_add_boolean(dpfocus_cmc, "edge_wrap", "Wrap Around at Top and Bottom?", offsetof(OptDpFocus, edge_wrap));
		cmc_config_register(dpfocus_cmc);
	}
}
