/*
**		BRIEF -- Basic Reconfigurable Interactive Editing Facility
**
**		Written by Dave Nanian and Michael Strickman.
*/

/*
**		routines.cb:
**
**		This file contains macros that allow a programmer to select a
**	C routine from a menu and then go to it.	It makes a few assumptions
**	about programming style:  routines must begin in column one, and
**	the line with the declaration must end with a close paren (")").
*/

#include "dialog.h"

/*
**		routines:
**
**		This macro implements the "go to a routine" feature of BRIEF.	It
**	scans the file for routine declarations, and builds a menu that gets
**	passed to the BRIEF dialog manager.  If a routine is selected from this
**	menu, on exit "_r_line" will have a non-zero value, and we go to that
**	line of the file.
*/

int	_r_line;

void routines ()
{
	int	menu_buf,
			old_buf_id,
			max_width,
			line,
			loc;

	string	menu_line,
				routine_name;

	_r_line = 0;
	save_position ();
	top_of_buffer ();
	old_buf_id = inq_buffer ();
	menu_buf = create_buffer ("Routines", NULL, 1);
	message ("Scanning for routines...");

	while (search_fwd ("<[~ \t#/\\*;\n\\{\\}(]"))
		{
		routine_name = trim (read ());
		loc = strlen (routine_name);

		if (loc > 1 && substr (routine_name, loc, 1) == ")")
			{
			_r_line++;
			message ("Scanning for routines [#%d]...", _r_line);
			loc = search_string ("[~ \t (\\*]\\c[ \t]@(", routine_name);
			routine_name = substr (routine_name, 1, --loc) + "\n";
			routine_name = substr (routine_name, search_string ("[~ \t\\*][~ \t\\*]@>", routine_name));
			routine_name = substr (routine_name, 1, strlen (routine_name) - 1);

			inq_position (line);

			if (strlen (routine_name) > max_width)
				max_width = strlen (routine_name);

			set_buffer (menu_buf);
			insert ("\n%s\t%d;", routine_name, line);
			set_buffer (old_buf_id);
			}
		next_char ();
		}
	_r_line = 0;
	restore_position ();
	set_buffer (menu_buf);
	inq_position (line);
	top_of_buffer ();

	if (line > 1)
		{
		int	num_lines,
				num_cols;

		delete_line ();
		tabs (80);

		inq_screen_size (num_lines, num_cols);

		if ((line += 3) > (num_lines - 5))
			line = num_lines - 5;

		if ((max_width += 2) < 15)
			max_width = 15;

		if (max_width >= num_cols - 3)
			max_width = num_cols - 3;

		max_width = (max_width + 1) / 2;
		num_cols = (num_cols + 1 ) / 2;

		set_buffer (old_buf_id);
		_process_menu (num_cols - max_width, line, num_cols + max_width, 3, NULL, "", NULL, menu_buf, "_r_action", TRUE);

		if (_r_line)
			goto_line (_r_line);
		}
	else
		{
		set_buffer (old_buf_id);
		delete_buffer (menu_buf);
		message ("No routines found.");
		}
}

/*
**		_r_action:
**
**		This routine is called by the dialog manager when a routine is
**	selected.
*/

int _r_action (int event_type, ...)
{
	string button_text;

	get_parm (0, event_type);


	switch (event_type)
		{
		case DIALOG_PICK_MENU:
		case DIALOG_F10:
			{
			get_parm (2, button_text);
			_r_line = atoi (substr (button_text, rindex (button_text, "\t") + 1));
			_dialog_esc ();
			}
		}
	returns (TRUE);
}




