release 1.14pre0
[descalc.git] / 04_disp_curses.pm
diff --git a/04_disp_curses.pm b/04_disp_curses.pm
new file mode 100644 (file)
index 0000000..be3da3c
--- /dev/null
@@ -0,0 +1,126 @@
+# ncurses output for DCT, by Shiar
+
+# 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
+       };
+
+       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.13",
+};
+