/*	Copyright (c) 1988 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

/*
 *      Copyright (c) 1997, by Sun Microsystems, Inc.
 *      All rights reserved.
 */

#pragma ident	"@(#)chg_field.c	1.5	97/09/17 SMI" /* SVr4.0 1.2 */

/*LINTLIBRARY*/

#include <sys/types.h>
#include "utility.h"

#define	first(f)	(f->field [Pmin(f, P(f))])
#define	last(f)		(f->field [Pmax(f, P(f))])
#define	sfirst(f)	(f->field [Smin(f, P(f))])
#define	slast(f)	(f->field [Smax(f, P(f))])

#define	Active(f)	(Opt(f, O_ACTIVE) && Opt(f, O_VISIBLE))

/* next - return next active field on page after f(user defined order) */
static FIELD *
next(FIELD *f)
{
	FORM	*t	= f->form;
	FIELD	**p	= t->field + f->index;
	FIELD	**pmin	= t->field + Pmin(t, P(t));
	FIELD	**pmax	= t->field + Pmax(t, P(t));

	do
		p = p == pmax ? pmin : p+1;

	while ((!Active(*p)) && (*p != f));

	return (*p);
}

/* prev - return previous active field on page before f */
static FIELD *
prev(FIELD *f)
{
	FORM  *t	= f->form;
	FIELD **p	= t->field + f->index;
	FIELD **pmin	= t->field + Pmin(t, P(t));
	FIELD **pmax	= t->field + Pmax(t, P(t));

	do
		p = p == pmin ? pmax : p-1;

	while ((!Active(*p)) && (*p != f));

	return (*p);
}

/* snext - return next active field on page after f(sorted order) */
static FIELD *
snext(FIELD *f)
{
	FIELD *x = f;

	do
		f = f->snext;

	while ((!Active(f)) && (f != x));

	return (f);
}

/* sprev - return previous active field on page before f(sorted order) */
static FIELD *
sprev(FIELD *f)
{
	FIELD *x = f;

	do
		f = f->sprev;

	while ((!Active(f)) && (f != x));

	return (f);
}

/* left - return active field on page left of f */
static FIELD *
left(FIELD *f)
{
	int row = f->frow;

	do
		f = sprev(f);

	while (f->frow != row);

	return (f);
}

/* right - return active field on page right of f */
static FIELD *
right(FIELD *f)
{
	int row = f->frow;

	do
		f = snext(f);

	while (f->frow != row);

	return (f);
}

/* up - return active field on page above f */
static FIELD *
up(FIELD *f)
{
	int row = f->frow;
	int col = f->fcol;

	do
		f = sprev(f);

	while (f->frow == row && f->fcol != col);

	if (f->frow != row) {
		row = f->frow;

		while (f->frow == row && f->fcol > col)
			f = sprev(f);

		if (f->frow != row)
			f = snext(f);
	}
	return (f);
}

/* down - return active field on page below f */
static FIELD *
down(FIELD *f)
{
	int row = f->frow;
	int col = f->fcol;

	do
		f = snext(f);

	while (f->frow == row && f->fcol != col);

	if (f->frow != row) {
		row = f->frow;

		while (f->frow == row && f->fcol < col)
			f = snext(f);

		if (f ->frow != row)
			f = sprev(f);
	}
	return (f);
}

	/*
	 *  _next_field
	*/

int
_next_field(FORM *f)
{
	return (_set_current_field(f, next(C(f))));
}

int
_prev_field(FORM *f)
{
	return (_set_current_field(f, prev(C(f))));
}

int
_first_field(FORM *f)
{
	return (_set_current_field(f, next(last(f))));
}

int
_last_field(FORM *f)
{
	return (_set_current_field(f, prev(first(f))));
}

int
_snext_field(FORM *f)
{
	return (_set_current_field(f, snext(C(f))));
}

int
_sprev_field(FORM *f)
{
	return (_set_current_field(f, sprev(C(f))));
}

int
_sfirst_field(FORM *f)
{
	return (_set_current_field(f, snext(slast(f))));
}

int
_slast_field(FORM *f)
{
	return (_set_current_field(f, sprev(sfirst(f))));
}

int
_left_field(FORM *f)
{
	return (_set_current_field(f, left(C(f))));
}

int
_right_field(FORM *f)
{
	return (_set_current_field(f, right(C(f))));
}

int
_up_field(FORM *f)
{
	return (_set_current_field(f, up(C(f))));
}

int
_down_field(FORM *f)
{
	return (_set_current_field(f, down(C(f))));
}

FIELD *
_first_active(FORM *f)
{
	return (next(last(f)));
}
