# ncurses output for DCT, by Shiar

# 1.14.0 200508261248 - SIGWINCH handler to redraw on screen resize
# 1.13.0 200411042100 - hook to display and handle menu
#                     - submenus are named instead of numbered
#                     - refresh hook renamed to showall
# 1.12.0 200410312200 - define main loop (get input from Term::ReadKey)
# 1.11.0 200410152225 - uses class in filename instead of $set{display} check
# 1.10.0 200410140120 - all output functions seperated from main

use strict;
use warnings;

use Curses;
use Term::ReadKey;

use vars qw(%falias $path);
require $path."termcommon.pm";

sub setsize () {
	$set{height} = $LINES-3 if $LINES>=3;
	$set{width} = $COLS if $COLS;
	$set{menushow} = int($set{width}/(4+$set{width}/20))+1;  # menu items to show simultaneously
} # setsize

push @{$hook{init}}, sub {
	initscr;
	ReadMode 3;  # cbreak mode

	END {
		ReadMode 0;
		endwin;
	} # restore terminal on quit

	$SIG{WINCH} = sub {
		endwin;
		refresh;         # setup for new screen size
		setsize();       # adjust for new sizes
		redraw(all=>1);  # queue complete refresh
		draw();          # redraw rightnow
	}; # window change (resize)

	setsize();
}; # init

push @{$hook{showerror}}, sub {
	attron(A_REVERSE);
	addstr(0, 0, shift);
	attroff(A_REVERSE);
	clrtoeol;
	refresh;

	ReadKey; # wait for confirm
	1 while defined ReadKey(-1); # clear key buffer
}; # showerror

push @{$hook{showstack}}, sub {
	for (0..@stack-1) {
		addstr($set{height}-$_, 1, "$_: ".showval($stack[$_], $set{base}));
		clrtoeol;
	} # show stack
	clrtoeol($set{height}-@stack, 1);
}; # showstack

push @{$hook{showmenu}}, sub {
	clrtoeol($set{height}+2, 1);
	my $nr = -1;
	for (grep exists $menu[0][$_], $menu[0][0]+1..$menu[0][0]+$set{menushow}) {
		$nr++;
		next unless defined $menu[0][$_];
		my $sub = (my $s = $menu[0][$_]) =~ s/>\w+$//;
		addstr($set{height}+2, $set{width}/$set{menushow}*$nr, $_);
		attron(A_REVERSE);
		addstr($s);
		attroff(A_REVERSE);
		addch('>') if $sub;  # indicate submenu
	} # display menu txts
}; # showmenu

$action{more} = [-1, sub {
	$menu[0][0] += $set{menushow};
	$menu[0][0] = 0 if $menu[0][0] > @{$menu[0]};
	$_->() for @{$hook{showmenu}};
}]; # tab

unshift @{$hook{precmd}}, sub {
	exists $falias{$_} or return;  # handle function key
	if ($falias{$_}==0) {
		shift @menu if @menu>1;  # remove current submenu
		redraw(menu=>1);
		return 1;
	} # escape (go to parent)
	$_ = $menu[0][$falias{$_}] and return;  # execute found menu item instead
	error("no such menu entry");
	return 1;
}; # precmd (menu item selection)

push @{$hook{showall}}, sub {
	clear;
	addstr($set{height}+1, 0, "> ");  # prompt
}; # showall

push @{$hook{showentry}}, sub {
	addstr($set{height}+1, 2, $_[0]);
	clrtoeol;
	refresh;
}; # showentry

$hook{main} = sub {
	while (1) {
		draw();

		my $key = ReadKey;  # wait for user input
		if ($key eq chr 27) {
			$key .= $_ while defined ($_ = ReadKey(-1));  # read additional keys
		} # escape sequence

		onkey($key);
	} # input loop
}; # main

return {
	author  => "Shiar",
	title   => "curses output",
	version => "1.14",
};

