
/*
 * Copyright 1993, 1994, 1995 by the Regents of the University of California
 * see the file "Copyright" in the distribution for conditions of use.
 */

#include <curses.h>
#include <stdio.h>

#include "actions.h"
#include "getch7.h"
#include "log.h"
#include "menu.h"
#include "misc.h"
#include "node.h"
#include "run_menu.h"

char *getenv();

int die();

extern int short_cut_index;

int cur_level = 0;
int cur_line_no;
static int node_num;

int short_cut_node;
int in_short_cut_menu;

run_menu( main_num )
int main_num;
{
	char temp_str[100];

	MENU *menu, *get_menu(), *enter_menu();
	int action;

	int next_num;
	int next_type;
	int err;
	int ind;

	curses_start();

	node_num = main_num;

	menu = get_menu( node[node_num] );
	cur_line_no = 0;
	display_menu( menu );

	while ( 1 ) {
		action = read_and_move( menu );
		switch( action ) {
		case ACTION_NONE:
			break;
		case ACTION_VIEW_SHORT_CUTS:
			cur_level++;
			if( node[short_cut_index]->nd_n != 0 ) {
				menu = enter_menu( short_cut_index );
			} else {
				ring_bell();
			}
			break;
		case ACTION_SHORT_CUT:
			next_num = short_cut_node;
			log( '+', node[next_num]->nd_label );
			goto enter;
		case ACTION_ENTER:	
			next_num = node[node_num]->nd_nums[cur_line_no];
enter:
			next_type = node[next_num]->nd_type;
			if( next_type == TYPE_MENU ) {
				cur_level++;
				menu = enter_menu( next_num );
			} else if( next_type == TYPE_COMMAND ) {
				log( 'C', node[next_num]->nd_label );
				do_node( node[next_num]->nd_command );
				display_menu( menu );
			}
			break;
		case ACTION_EXIT:
			/* pop_node(): no change if nothing to pop */
action_exit:
			if( cur_level == 0 ) {
				ring_bell();
			} else {
				pop_node( &node_num, &cur_line_no );
				cur_level--;
				menu = get_menu( node[node_num] );
				display_menu( menu );
				in_short_cut_menu =
						(node_num == short_cut_index);
			}
			break;
		case ACTION_MAIN:
			node_num = main_num;
			cur_level = 0;
			cur_line_no = 0;
			menu =  get_menu( node[node_num] );
			display_menu( menu );
			reset_stack();
			break;
		case ACTION_REDRAW:
			wrefresh(curscr);
			break;
		case ACTION_ADD_ITEM:
			ind = node[node_num]->nd_nums[cur_line_no];
			log( 'a', node[ind]->nd_label );
			wants_short_cut( ind );
			break;
		case ACTION_ADD_MENU:
			log( 'A', node[node_num]->nd_label );
			wants_short_cut( node_num );
			break;
		case ACTION_DELETE_ITEM:
			log( 'd', node[node_num]->nd_labs[cur_line_no] );
			/* if nothing left in short cut menu, exit */
			if( delete_short_cut( ) == 0 ) goto action_exit;
			break;
		case ACTION_HELP:
			log( '?', "help" );
			do_node( "=more -d $etc/Help.text" );
			display_menu( menu );
			break;
		case ACTION_LINE_HELP:
			line_help( node[node_num]->nd_nums[cur_line_no],
							menu );
			break;
		case ACTION_QUIT:
			die();
		}
	}
}

MENU *
enter_menu( next_num )
int next_num;
{
	MENU *menu;

	log( 'M', node[next_num]->nd_label );
	push_node( node_num, cur_line_no );
	node_num = next_num;
	in_short_cut_menu = (node_num == short_cut_index);
	menu = get_menu( node[node_num] );
	cur_line_no = 0;
	display_menu( menu );
	return( menu );
}

#define STACK_LIM 100
static int stack[STACK_LIM];
static stack_ind = 0;

push_node( nd_num, line )
int nd_num, line;
{
	if( stack_ind < STACK_LIM - 2 ) {
		stack[stack_ind++] = nd_num;
		stack[stack_ind++] = line;
	}
}

pop_node( nd_num, line )
int *nd_num, *line;
{
	if( stack_ind >= 2 ) {
		*line = stack[--stack_ind];
		*nd_num = stack[--stack_ind];
	}
}

reset_stack()
{
	stack_ind = 0;
}

MENU *
get_menu( cur_node )
NODE *cur_node;
{
	MENU *menu;
	char *malloc();
	int i;

	/*
	 *	collect pointers to titles for menu
	 */

	if( cur_node->nd_menu == NULL ) {
		menu = (MENU *)malloc( sizeof( MENU ) );
		if( menu == NULL ) fatal("malloc() failure");

		menu->mn_title = cur_node->nd_title;

		for ( i = 0; i < MAX_MENU_ENTRIES && i < cur_node->nd_n; i++ ) {
			menu->mn_line[i] = node[cur_node->nd_nums[i]]->nd_title;
		}

		for (  ; i < MAX_MENU_ENTRIES; i++ ) {
			menu->mn_line[i] = " ";
		}

		menu->mn_nrows = cur_node->nd_n;
		cur_node->nd_menu = menu;
	}
	return( cur_node->nd_menu );
}

fatal( string )
char *string;
{
	log( 'T', "errors" );
	fprintf( stderr, "*** fatal error: %s\n", string );
	die();
}
