9ae8c03fdfbcecd0dcdfae39e21656cc2aefc3a8
[descalc.git] / 15_menu.pm
1 # menu for DCT, by Shiar
2
3 # 1.11.0 200410282200 - display-specific code in evals
4 # 1.10.4 200410151900 - remove explicit call to redraw on error
5 # 1.10.3 200410150030 - add quit at F10 in main menu (after running other modules)
6 #                     - don't show undefined menu entries (skippable)
7 # 1.10.2 200410122345 - addmenu() function to add submenus
8 # 1.10.1 200410122210 - @menus global; unit+math items added in those modules
9 # 1.09.1 200410112150 - everything related to menus moved here
10 # 1.06.1 200409152332 - moved @menus from 1.6 main
11
12 #todo: merge basics back into main; i/o functions in display modules
13 #      (menu can also be disabled at this level, without too high cost)
14 #todo: always remember parent menus (so no need to store back-item (0)
15 #      and ability to show higher levels)
16 #todo: also store menu hash (to add additional items to a specific submenu)
17
18 use strict;
19 use warnings;
20
21 my %falias = (
22         "\033"                         =>  0, # esc
23         "\033\117\120"                 =>  1, # f1
24         "\033\133\061\061\176"         =>  1, # f1
25         "\033\133\061\062\176"         =>  2, # f2
26         "\033\133\061\063\176"         =>  3, # f3
27         "\033\133\061\064\176"         =>  4, # f4
28         "\033\117\121"                 =>  2, # f2
29         "\033\117\122"                 =>  3, # f3
30         "\033\117\123"                 =>  4, # f4
31         "\033\133\061\065\176"         =>  5, # f5
32         "\033\133\061\067\176"         =>  6, # f6
33         "\033\133\061\070\176"         =>  7, # f7
34         "\033\133\061\071\176"         =>  8, # f8
35         "\033\133\062\060\176"         =>  9, # f9
36         "\033\133\062\061\176"         => 10, # f10
37         "\033\133\062\063\176"         => 11, # f11/F1
38         "\033\133\062\064\176"         => 12, # f12/F2
39         "\033\133\062\065\176"         => 13, # F3
40         "\033\133\062\066\176"         => 14, # F4
41         "\033\133\062\070\176"         => 15, # F5
42         "\033\133\062\071\176"         => 16, # F6
43         "\033\133\063\061\176"         => 17, # F7
44         "\033\133\063\062\176"         => 18, # F8
45         "\033\133\063\063\176"         => 19, # F9
46         "\033\133\063\064\176"         => 20, # F10
47         "\033\133\062\063\073\062\176" => 21, # F11
48         "\033\133\062\064\073\062\176" => 22, # F12
49         "\033\061"                     =>  1, # alt+1
50         "\033\062"                     =>  2, # alt+2
51         "\033\063"                     =>  3, # alt+3
52         "\033\064"                     =>  4, # alt+4
53         "\033\065"                     =>  5, # alt+5
54         "\033\066"                     =>  6, # alt+6
55         "\033\067"                     =>  7, # alt+7
56         "\033\070"                     =>  8, # alt+8
57         "\033\071"                     =>  9, # alt+9
58         "\033\060"                     => 10, # alt+0
59 ); # %falias
60
61 #our @menus = ([qw(refresh quit)]);
62 our @menus = (
63         [qw(refresh prog> mode>1)], # main
64         [qw(main>0 number_format angle_measure coord_system)], #1 mode
65 ); # @menus
66
67 sub addmenu {
68         my $parent = shift;
69         push @menus, ["$parent->[0]>$parent->[1]"];  # create new menu
70         my $menuthis = $#menus;
71         push @{$menus[$parent->[1]]}, shift(@_).">$menuthis";  # link from parent
72         ref $_ ? addmenu([$_->[0], $menuthis], @$_)  # add subsubmenu
73                 : push @{$menus[$menuthis]}, $_ for @_;  # add menu items
74         return $menuthis;
75 } # addmenu
76
77 #my @menu = [];
78 our @menu;
79 our $menumin = 0;
80
81 push @{$hook{init}}, sub {
82         $menus[0][10] = "quit";
83         @menu = @{$menus[0]};
84         $set{height}--;  # make space for menubar
85         $set{menushow} = int($set{width}/(4+$set{width}/20))+1  # menu items to show simultaneously
86                 unless defined $set{menushow};
87 }; # init
88
89 my %show = (
90         curses => q{
91                 clrtoeol($set{height}+2, 1);
92                 my $nr = -1;
93                 for (grep exists $menu[$_], $menumin+1..$menumin+$set{menushow}) {
94                         $nr++;
95                         next unless defined $menu[$_];
96                         my $sub = (my $s = $menu[$_]) =~ s/>\d+$//;
97                         addstr($set{height}+2, $set{width}/$set{menushow}*$nr, $_);
98                         attron(A_REVERSE);
99                         addstr($s);
100                         attroff(A_REVERSE);
101                         addch('>') if $sub;  # indicate submenu
102                 } # display menu txts
103         },
104         stdout => q{
105                 my $nr = -1;
106                 for (grep exists $menu[$_], $menumin+1..$menumin+$set{menushow}) {
107                         $nr++;
108                         next unless defined $menu[$_];
109                         my $sub = (my $s = $menu[$_]) =~ s/>\d+$//;
110                         print " $_:$s";
111                         print ">" if $sub;  # indicate submenu
112                 } # display menu txts
113                 print "\n> ";
114         },
115 );
116
117 sub showmenu() {
118         eval $_ if local $_ = $show{$::modules{disp}{name}};
119 } # showmenu
120
121 $action{more} = [-1, sub {
122         $menumin += $set{menushow};
123         $menumin = 0 if $menumin>=$#menu;
124         showmenu();
125 }]; # tab
126
127 push @{$hook{refresh}}, sub {
128         showmenu();
129 }; # refresh
130
131 unshift @{$hook{precmd}}, sub {
132         return unless exists $falias{$_};  # not a function key
133         return if $_ = $menu[$falias{$_}];  # execute found menu item instead
134         error("no such menu entry");
135         return 1;
136 }; # precmd
137
138 push @{$hook{precmd}}, sub {
139         return unless />(\d+)$/;
140         @menu = @{$menus[$1]};  # go to submenu
141         $menumin = 0;  # reset to first item
142         showmenu();  # redraw
143         return 1;
144 }; # precmd
145
146 return {
147         author  => "Shiar",
148         title   => "menu",
149         version => "1.11",
150 };
151