/*
**		BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**
**		dlg_btn.cb:
**
**		This file contains all BRIEF macros for managing dialog box buttons.
*/

#include "dialog.h"
#include "dlg.h"

/*
**		_dialog_check_button:
**
**		Places or removes a checkmark	from the button specified
**	by button label.	If check is nonzero a check mark will be
**	placed in the check box, otherwise a space will be placed in
**	the check box.
**
**	This is a user-accessible function.
*/

void _dialog_check_button (string button_label, int check)
{
	int	row, col;

	save_position ();

	if (_dlg_goto_btn ('C', button_label))
		{
		delete_char ();
		insert (check ? CHECKMARK : NOCHECKMARK);
		}
	restore_position ();
}

/*
**		_dialog_is_checked:
**
**		Determines whether the control specified by button_label
**	has a checkmark next to it.  Returns TRUE if a check mark is
**	present, FALSE otherwise.
**
**		This is a user-accessible function.
*/

int _dialog_is_checked (string button_label)
{
	int 		rval;

	if (_dlg_goto_btn ('C', button_label))
		{
		if (read (1) == CHECKMARK)
			rval = TRUE;
		}

	returns (rval);
}

/*
**		_dialog_check_radio:
**
**		Places a check by the specified radio button and removes the check
**	from all other radio buttons within the specified group.  The group label
** is not required if the dialog box has only one group of radio buttons.
**
**		This is a user-accessible function.
*/

void _dialog_check_radio (string button, ~string group)
{
	int 		curr_buf = inq_buffer ();
	string	label;

	set_buffer (_dialog_radio_buf);
	save_position ();
	top_of_buffer ();

	sprintf (label, FIND_RADIO_GRP, group);

	if (search_fwd (label, TRUE, TRUE) >= 1)
		{
		int		offset;
		string	ctrl = read ();

		offset = index (ctrl, "\"") + 1;
		label = substr (ctrl, offset, rindex (ctrl, "\"") - offset);

		/*
		**		Only do real work when we absolutely have to ...
		**
		**		If the specified button and the current 'ON' button are not the
		**	same, then turn the current 'ON' button off and the specified
		**	button 'ON'.  Update the radio button control file first, then the
		**	display buffer.
		*/

		if (label != button)
			{
			int		row_off = atoi (substr (ctrl, rindex (ctrl, "(") + 1)),
						col_off = atoi (substr (ctrl, rindex (ctrl, ",") + 1)),
						row_on,
						col_on;

			move_rel (0, strlen (ctrl) - 2);
			delete_char ();
			insert ("%c", RADIO_OFF);

			top_of_buffer ();

			sprintf (label, FIND_RADIO_LBL, group, button, RADIO_OFF);

			if (search_fwd (label, TRUE, TRUE) >= 1)
				{
				ctrl = read ();

				row_on = atoi (substr (ctrl, rindex (ctrl, "(") + 1));
				col_on = atoi (substr (ctrl, rindex (ctrl, ",") + 1));

				move_rel (0, strlen (ctrl) - 2);
				delete_char ();
				insert ("%c", RADIO_ON);

				/*
				**		Update the display buffer.
				*/

				set_buffer (_dialog_disp_buf);
				save_position ();

				move_abs (row_off, col_off + 1);
				delete_char ();
				insert ("%c", RADIO_OFF);

				move_abs (row_on, col_on + 1);
				delete_char ();
				insert ("%c", RADIO_ON);

				restore_position ();
				set_buffer (_dialog_radio_buf);
				}
			else
				{
				error ("Unable to locate 'OFF' Radio button in control file.");
				beep ();
				}
			}
		}
	else
		{
		error ("Unable to locate 'ON' Radio button in control file.");
		beep ();
		}

	restore_position ();
	set_buffer (curr_buf);
}

/*
**		_dialog_radio_checked:
**
**		Determines which radio button of the specified group is on.  Returns
**	the label of the 'on' button.  The group lable is not required if the
**	dialog box has only one group of radio buttons.
**
**		This is a user-accessible function.
*/

string _dialog_radio_checked (~string group)
{
	int		curr_buf = inq_buffer ();
	string	label;

	/*
	**		Search the radio button control buffer for the specified button.
	**	If we find it, return its label.  Otherwise, return an empty string.
	*/

	set_buffer (_dialog_radio_buf);
	save_position ();
	top_of_buffer ();

	sprintf (label, FIND_RADIO_GRP, group);

	if (search_fwd (label, TRUE, TRUE) >= 1)
		{
		int		offset;

		label = read ();
		offset = index (label, "\"") + 1;
		label = substr (label, offset, rindex (label, "\"") - offset);
		}
	else
		label = "";

	restore_position ();
	set_buffer (curr_buf);

	returns (label);
}

/*
**		_dlg_goto_btn:
**	
**		Positions the cursor at the second character of the control text
**	in the display buffer.  If the control is a checkbox, the cursor will
**	be below the check area.  If the control is a push button, the cursor
**	will be below the white space before the push button label.  This function
**	set the current buffer to the display buffer at exit.
*/

int _dlg_goto_btn (int btn_type, string button_label, ~string group)
{
	string	line;
	int 		row, col,
				rval;

	set_buffer (_dialog_data_buf);
	save_position ();
	top_of_buffer ();

	sprintf (line, BTN_SRCH_STRN, btn_type, button_label, group);

	if (search_fwd (line, TRUE, FALSE))
		{
		row = atoi (line = read ());
		col = atoi (substr (line, index (line, ",") + 1)) + 1;
		rval = TRUE;
		}

	restore_position ();
	set_buffer (_dialog_disp_buf);

	if (rval)
		move_abs (row, col);

	returns (rval);
}

/*
**		_dlg_check_btn, _dlg_push_btn, _dlg_radio_btn:
**
**		Returns the label of the current check, push or radio button.
**	Assumes that the current buffer is the display buffer.
*/

string _dlg_check_btn ()
{
	string	line;

	line = read ();
	line = trim (substr (line, index (line, CHECK_RGT_SRCH) + 2));
	line = substr (line, 1, search_string ("[\t\n]", line) - 1);
	returns (line);
}

string _dlg_push_btn ()
{
	string	line;

	line = read ();
	line = trim (substr (line, 2, search_string (PUSH_RGT_SRCH, line) - 2));
	returns (line);
}

string _dlg_radio_btn ()
{
	int		offset;
	string 	label;

	set_buffer (_dialog_radio_buf);
	top_of_buffer ();
	sprintf (label, FIND_RADIO_POS, _dialog_row, _dialog_col - 1);

	if (search_fwd (label, TRUE, TRUE) >= 1)
		{
		label = read ();
		offset = index (label, "\"") + 1;
		label = substr (label, offset, rindex (label, "\"") - offset);
		}
	else
		{
		error ("Unable to locate Radiobutton in control file.");
		beep ();
		}

	set_buffer (_dialog_disp_buf);
	returns (label);
}

/*
**		_dlg_radio_group:
**
**		Returns the current radio button's group label.  Returns NULL if the
**	the current button is not a radio button.
*/

string _dlg_radio_grp (void)
{
	string	group;

	if (_dialog_type == RADIO)
		{

		set_buffer (_dialog_radio_buf);
		top_of_buffer ();
		sprintf (group, FIND_RADIO_POS, _dialog_row, _dialog_col - 1);

		if (search_fwd (group, TRUE, TRUE) >= 1)
			{
			group = read ();
			group = substr (group, 1, index (group, "\"") - 1);
			}
		else
			{
			error ("Unable to locate current Radiobutton in control file.");
			beep ();
			}

		set_buffer (_dialog_disp_buf);
		}

	returns (group);
}
/*
**		_dlg_pick_btn:
**
**		Generates the event for a pick button.  Passes the row number and
**	the button label to the user.
*/

void _dlg_pick_btn (void)
{
	switch (_dialog_type)
		{
		case CHECK:
			execute_macro (_dialog_action_func, DIALOG_PICK_CHECK, _dialog_row, _dlg_check_btn ());
		case PUSH:
			execute_macro (_dialog_action_func, DIALOG_PICK_PUSH, _dialog_row, _dlg_push_btn ());
		case RADIO:
			execute_macro (_dialog_action_func, DIALOG_PICK_RADIO, _dialog_row, _dlg_radio_btn (), _dlg_radio_grp ());
		}
}

/*
**		_dlg_select_push:
**
**		Selects or deselects the push button specified by button label.
**	If select is nonzero, the push button is selected, otherwise it is
**	deselected.
*/

void _dlg_select_push (string button_label, int select)
{
	int		len;

	if (button_label != "")
		{
		if (button_label == _dialog_default_pb)
			_dialog_pb_state = select;

		if (_dlg_goto_btn ('P', button_label))
			{
			/* position over the left delimiter of the push button */
			move_rel( 0,-1 );			
			delete_char (len = (strlen (button_label) + 4));

			if (select)
				insert (PUSH_BUTTON_DEF, button_label);
			else
				insert (PUSH_BUTTON, button_label);

			move_rel (0, -(len - 1));
			}
		}
}

/*
**		_dlg_btn_tab_next, _dlg_btn_tab_prev, _dlg_btn_next, _dlg_btn_prev:
**
**		Moves the cursor from button control to button control.  Check and
**	push buttons work just like other controls.  Radio buttons are different.
**
**		Pressing the Tab or Shift-Tab key when a radio button has the focus
**	will move the focus to the next control not in that radio button's group.
**
** 	The cursor keys also work a little differently for radio buttons.  If
** the current control is a radio button, pressing Up/Left or Right/Down
**	moves the focus to the next radio button in the same group of radio
**	buttons.  When the current radio button is the first or last button in
**	the group, the cursor will 'wrap-around' to the last or first button in
**	the group.
*/


void _dlg_btn_tab_next (void)
{
	if (_dialog_type == RADIO)
		{
		if (_dialog_exit ())
			{
			/*
			**		Find next radio button group or other control.  If the next
			**	control found is another set of radio buttons, make the first
			** button of the group the current control.
			*/

			set_buffer (_dialog_data_buf);
			next_char ();

			if (search_fwd (FIND_NEXT, TRUE, FALSE))
				{
				if (upper (read (1)) == "G")
					search_fwd ("<[ \t]@\\cR", TRUE, FALSE);
				}
			else
				prev_char ();

			_dialog_enter ();
			}
		}
	else
		_dialog_next ();
}

void _dlg_btn_tab_prev (void)
{
	if (_dialog_type == RADIO)
		{
		if (_dialog_exit ())
			{

			set_buffer (_dialog_data_buf);

			/*
			**		Find previous radio button group or other control.  If the
			**	previous control found is another set of radio buttons, make the
			** last button of the group the current control.
			*/

			if (prev_char ())
				{
				if (search_back (FIND_PREV, TRUE, FALSE))
					{
					if (upper (read (1)) == "E")
						search_back ("<[ \t]@\\cR", TRUE, FALSE);
					}
				else
					next_char ();
				}

			_dialog_enter ();
			}
		}
	else
		_dialog_prev ();
}

void _dlg_btn_next (void)
{
	if (_dialog_type == RADIO)
		{
		if (_dialog_exit ())
			{
			set_buffer (_dialog_data_buf);

			search_fwd ("<[ \t]@\\c[RE]", TRUE, FALSE);

			if (read (1) == "E")
				{
				search_back ("<[ \t]@\\cG", TRUE, FALSE);
				search_fwd ("<[ \t]@\\cR", TRUE, FALSE);
				}

			_dialog_enter ();
			}
		}
	else
		_dialog_next ();
}

void _dlg_btn_prev (void)
{
	if (_dialog_type == RADIO)
		{
		if (_dialog_exit ())
			{
			set_buffer (_dialog_data_buf);

			up ();

			search_back ("<[ \t]@\\c[RG]", TRUE, FALSE);

			if (read (1) == "G")
				{
				search_fwd ("<[ \t]@\\cE", TRUE, FALSE);
				search_back ("<[ \t]@\\cR", TRUE, FALSE);
				}

			_dialog_enter ();
			}
		}
	else
		_dialog_prev ();
}

/*
** _is_push_button
**
** Search the current line of the dialog display buffer
** and determine if the user clicked on a push button.
**
** Input:
** 	Current buffer equal _dialog_disp_buf
**		col - the column position of the click
**
** Returns
**		the position of the left delimiter of the push button
**		if a push button was clicked in; otherwise zero.  On
**		exit the current position in _dialog_disp_buf is the
** 	position of the click.
**
*/
int _is_push_button( int col )
{
	int i, btn_left, btn_right, len;
	string temp;

	i = 0;						// adjustment for position on original line
	beginning_of_line();
	temp = read();				// get the whole line

	/*
	** Look thru the whole line finding each push button on the line
	** and checking if the given column position is inside that button
	*/

	btn_left = search_string( PUSH_SRCH, temp, len);	// look for a push button
	while ( btn_left && col > btn_right ) {
		btn_left = btn_left + i;
		btn_right = btn_left + len - 1;
		/* was the click on this push button?? */
		if ( btn_left <= col && col <= btn_right ) {
			break;
		} else {
			/* No - check for the next push button */
			i = btn_right++;			// look for another push button
			temp = substr( temp, btn_right );
			btn_left = search_string( PUSH_SRCH, temp, len);	// look for the btn_right delimiter
		}
	}
	move_abs( 0, col );			// return to original position
	return( btn_left );
}


