/*
**		BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
**		dlg_list.cb:
**
**		This file contains all BRIEF macros for managing dialog box lists.
*/

#include <dialog.h>
#include <dlg.h>

/*
**		_list_next, _list_prev:
**
**		Moves the mark from one button to the next or previous button
**	on a list.	Lists do not wrap.
*/

void _list_next ()
{
	raise_anchor ();
	save_position ();
	search_fwd ("{\\t\\c[~\\t]}|\\n", TRUE);
	restore_position (at_eol ());
	_list_highlight ();
}

void _list_prev ()
{
	int	col,
			len;

	raise_anchor ();
	inq_position (NULL, col);

	/*
	**		If we move past the beginning of the list when we move two
	**	columns left, there is no previous button.  If we are still
	**	in the list, we are at the end of the previous button.
	**	All we have to do is move one past the previous tab character.
	**	This we do in 2 steps because we have to read, starting at
	**	the beginning of the list.
	*/

	if ((len = (col -= 2) - _dialog_col) > 0)
		{
		move_abs (0, _dialog_col);
		move_rel (0, rindex (read (len), "\t"));
		}
	_list_highlight ();
}

/*
**		_list_highlight:
**
**		Highlights the list button where the cursor is.  Also, since
**	this function is called by all the functions that change the value
**	of a list, calls the action function with that code.
*/

void _list_highlight ()
{
	string	value;

	int	len = index (value = read (), "\t") - 2;
	move_rel (0, len);
	drop_anchor ();
	move_rel (0, 0 - len);
	execute_macro (_dialog_action_func, DIALOG_ALTER_LIST, _dialog_row, substr (value, 1, len+1));
}

/*
**		_list_home, _list_end:
**
**		Moves the highlight to the first or last button on a list.
*/

void _list_home ()
{
	move_abs (0, _dialog_col);
	_list_next ();
}

void _list_end ()
{
	end_of_line ();
	_list_prev ();
}

/*
**		_list_go:
**
**		Reads a character (that was just inserted; _list_go is
**	called as a type 0 registered macro) from the buffer and deletes
**	it, then looks for a matching button before the end of the list.
**	If there is none, looks for one starting with the first item.
**	If there is still none, stays put.	(If a button is found,
**	_list_go moves to it and highlights it.)
**
**		Note that alphabetic keys pressed will only find buttons
**	beginning with the upper case versions of the letters.
*/

void _list_go (int key)
{
	int	col,
			offset;

	string	pattern;

	raise_anchor ();
	sprintf (pattern, "%c", key);
	pattern = "\t" + upper (pattern);

	if (offset = index (read (), pattern))
		move_rel (0, offset);
	else
		{
		save_position ();
		move_abs (0, _dialog_col);

		if (offset = index (read (), pattern))
			move_rel (0, offset);
		else
			beep ();

		restore_position (!offset);
		}
	_list_highlight ();
}

/*
**		_list_button:
**
**		Returns the text of the current list button, excluding any
**	surrounding parentheses or tabs.
*/

string _list_button ()
{
	string	button = read ();

	returns (substr (button, 1, index (button, "\t") - 1));
}
/*
** _is_list_
**
** Determine if the given line and column position is in
** a dialog manager list.  Called by mouse_dialog to determin
** if the user clicked in a list.
**
** Input:
** 	Current buffer equal _dialog_disp_buf
**		buf_line - the line position of a click.
**		buf_col - the column position of the click
**
** Returns
**		TRUE if a list entry was clicked on.  Returns FALSE
**		if a list was not clicked on OR if a tab in a list was
** 	clicked on OR if the () in a list was clicked on. Returns
** 	with the current buffer equal to _dialog_disp_buf.  In
**		_dialog_data_buf the position is the beginning of the line
**		of the line containing the list control that was clicked on.
**
*/
int _is_list( int buf_line, int buf_col )
{

	int list_left, len;
	string ctrl_string, temp, list_text;

	/* Are there any lists specified for the line that the user clicked on?? */
	set_buffer (_dialog_data_buf);		// switch to the data buffer
	top_of_buffer();
	sprintf( ctrl_string,
		      "list[ \t]@([ \t]@%d[ \t]@,[ \t]@[0-9]*[ \t]@)", buf_line );
	while ( search_fwd( ctrl_string, TRUE, FALSE ) ) {
		/*
		** Yes - there are list(s) specified for this line.
		** See if the position was in this one
		*/
		temp = read();			// get the control spec for the list

		/*
		** Extract the text of the list.  Compute the length of
		** text without any leading or trailing ().
 		** Note: The first entry in the
		** list is placed at the list's starting position.
		*/
		list_text = substr( temp,index( temp, "\"")+1);
		len = strlen( list_text ) - 2; 		// dont include trailing " and \n
		if ( rindex( list_text, ")") == len ) len--;
		if ( index( list_text, "(") == 1 ) {
			len--;
			list_text = substr( list_text, 2 );		// delete leading (
		}
		list_left = atoi( substr( temp, (index(temp,",")+1) ) );
		if ( list_left <= buf_col && buf_col <= (list_left+len-1) ) {
			beginning_of_line();			// beginning of line of the control spec
			/*
			** Found the clicked on list, make sure an entry and not
			**	a tab was clicked on.  If a () was clicked on just ignore it
			*/
			set_buffer( _dialog_disp_buf );
			temp = read(1);		// get the char under the mouse cursor.
			if ( temp != "\t" &&
				  temp != "(" && temp != ")" ) {
				return( TRUE );
			}
			break; 					// exit the search
		}
		move_rel( 1,0);		// move to next entry in the information buffer
	}
	set_buffer( _dialog_disp_buf );
	return( FALSE );
}


