/*
**		BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
**		dlg_fld.cb:
**
**		This file contains all BRIEF macros for managing dialog box fields.
*/

#include <dialog.h>
#include <dlg.h>

/*
**		_field_insert:
**
**		Makes sure that there's still room left in the window; if not,
**	removes the last key inserted, beeps and prints an error message.
**	Handles both insert and overstrike mode.
*/

void _field_insert (int key)
{
	int	last_col;

	if (inq_marked ())
		{
		raise_anchor ();
		delete_to_eol ();
		}
	save_position ();

	if (inq_mode ())
		end_of_line ();

	inq_position (NULL, last_col);
	restore_position ();

	if (last_col < _dialog_size)
		self_insert (key);
	else
		{
		error ("Field is full.");
		beep ();
		}
}

/*
**		_field_bksp:
**
**		Backs the cursor up in a typed field (if it's not already at
**		the beginning of the field) and deletes it.	In overstrike
**		mode, this function replaces the deleted character with a space.
*/

void _field_bksp ()
{
	int	cur_col;

	inq_position (NULL, cur_col);

	if (inq_marked ())
		{
		raise_anchor ();
		delete_to_eol ();
		}
	if (cur_col > _dialog_col)
		{
		left ();

		if (!at_eol ())
			{
			delete_char ();

			if (!inq_mode ())
				{
				insert (" ");
				prev_char ();
				}
			}
		}
}

/*
**		_field_left, _field_right:
**
**		Moves the cursor to the left or to the right in the field, if
**	possible.  If the field is marked (which implies that the cursor
**	is still at the beginning of the field), the highlight is removed.
*/

void _field_left ()
{
	int	cur_col;

	raise_anchor ();
	inq_position (NULL, cur_col);

	if (cur_col > _dialog_col)
		left ();
}

void _field_right ()
{
	int	cur_col;

	raise_anchor ();
	inq_position (NULL, cur_col);

	if (cur_col < _dialog_size - 1)
		right ();
}

/*
**		_field_del:
**
**		Deletes a character, as long as it's not a newline.  Works the
**	same way in both insert and overstrike modes.  If the field is still
**	marked, deletes the whole thing.
*/

void _field_del ()
{
	if (!at_eol ())
		if (inq_marked ())
			{
			raise_anchor ();
			delete_to_eol ();
			}
		else
			delete_char ();
}

/*
**		_field_end, _field_home:
**
**		Removes the mark if there is one, then positions the cursor
**	at the end or beginning of the field.
*/

void _field_end ()
{
	raise_anchor ();
	end_of_line ();
}

void _field_home ()
{
	raise_anchor ();
	move_abs (0, _dialog_col);
}

/*
**		_field_del_line, _field_delete_to_eol:
**
**		Deletes either the entire field or the field contents after the
**	cursor position, removing any mark first.
*/

void _field_del_line (void)
{
	move_abs (0, _dialog_col);
	_field_delete_to_eol ();
}

void _field_delete_to_eol (void)
{
	raise_anchor ();
	delete_to_eol ();
}

/*
**		_dialog_validate:
**
**		Determines if the current field meets predefined criteria for
**	being a nonblank string, integer, or file name.  (Used for all typed
**	fields.)  Returns TRUE if the string satisfied the criteria for
**	the current type, _dialog_type, or if the current type was not
**	a nonblank string, integer, or file name type.
*/

int _dialog_validate (string value)
{
	int retval = TRUE;

	switch (_dialog_type)
		{
		case FILENAME:
			if (!(retval = is_filename (value)))
				error ("This field must be a filename.");

		case INTEGER:
			if (!(retval = search_string ("<[ \\t]@{[\\-+][0-9]+}|{[0-9]+}[ \t]@\n", value + "\n", NULL, TRUE)))
				error ("This field must be an integer.");

		case NONBLANK:
			if (!(retval = search_string ("[~ \\t\\n]", value, NULL, TRUE)))
				error ("This field may not be blank.");
		}
	if (!retval)
		beep ();

	returns (retval);
}

/*
**		is_filename:
**
**		Returns TRUE if a string contains a syntactically correct
**	filename.  Note:	this regular expression will catch most, but
**	not all, incorrect file names.  Among the cases that it will not
**	catch are two drive specifiers, extra or misplaced periods, omitted
**	filename (just extension), and name or extension too long.
*/

int is_filename (string name)
{
	returns (search_string ("<{[a-z]:}@[\\\\/]@{[~- \"%*-,/:-?\\[-\\]|]+[\\\\/]}@[~- \"%*-,/:-?\\[-\\]|]+>", name + "\n", NULL, TRUE, FALSE));
}

/*
**		at_eol:
**
**		Returns TRUE if the current position is at the end of a line,
**	FALSE otherwise.
*/

int at_eol ()
{
	returns (read (1) == "\n");
}

/*
**		_field_contents:
**
**		Returns the contents of the current field, not including the
**	newline, and regardless of the cursor position.
*/

string _field_contents ()
{
	string	field;

	save_position ();
	move_abs (0, _dialog_col);
	field = read ();
	restore_position ();
	returns (substr (field, 1, strlen (field) - 1));
}
