release 1.11.2
authorShiar <shiar@shiar.org>
Fri, 29 Oct 2004 09:27:26 +0000 (11:27 +0200)
committerShiar <shiar@shiar.org>
Thu, 10 Jul 2008 19:25:31 +0000 (21:25 +0200)
- when showing values with exponent, also adjust fraction
- redraw inside main loop; automatically called after error
- user variables to module; our %var removed
- main changelog moved to seperate CHANGES file

- modules filenames can contain class; only loads first of any class
- give command name as parameter to pre/postaction hooks
- postaction hook after running commands
- global redraw() to queue a stack/screen refresh

12 files changed:
05_disp_curses.pm [moved from 05_curses.pm with 84% similarity]
06_disp_slang.pm [new file with mode: 0644]
08_disp_stdout.pm [moved from 08_stdout.pm with 64% similarity]
12_bindings.pm
15_menu.pm
25_var.pm [new file with mode: 0644]
28_undo.pm
32_math.pm [moved from 31_math.pm with 73% similarity]
33_trig.pm [new file with mode: 0644]
35_unitconv.pm
CHANGES [new file with mode: 0644]
dct.pl

similarity index 84%
rename from 05_curses.pm
rename to 05_disp_curses.pm
index 73e0d01898b9e0e8a63d71206e8f39f16c91d9f3..e88f6672702fb94b3161cf3278f73d43be3b38cd 100644 (file)
@@ -1,15 +1,13 @@
 # ncurses output for DCT, by Shiar
 
-# 1.10.1 200410140120 - all output functions seperated from main
+# 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;
 
-return 0 if $set{display};
-$set{display} = "curses";
-
 push @{$hook{init}}, sub {
        initscr;
        END { endwin; } # restore terminal on quit
@@ -51,6 +49,6 @@ push @{$hook{showentry}}, sub {
 return {
        author  => "Shiar",
        title   => "curses output",
-       version => "1.10.1",
+       version => "1.11",
 };
 
diff --git a/06_disp_slang.pm b/06_disp_slang.pm
new file mode 100644 (file)
index 0000000..4fa569d
--- /dev/null
@@ -0,0 +1,61 @@
+# s-lang output for DCT, by Shiar
+
+# 1.11.0 200410291300 - 
+
+use strict;
+use warnings;
+
+use Term::Slang qw(:common :screen :term :CONSTANTS);
+
+push @{$hook{init}}, sub {
+       SLtt_get_terminfo and exit;
+       SLang_init_tty(-1, 0, 1);
+       SLsmg_init_smg;
+       
+       END { SLsmg_reset_smg; SLang_reset_tty; } # shutdown display system
+
+       # where are $SLtt_Screen_Rows and $SLtt_Screen_Cols?
+       ($set{height}, $set{width}) = SLtt_get_screen_size;
+       $set{height} -= 2;
+}; # init
+
+push @{$hook{showerror}}, sub {
+       my $error = shift;
+       SLsmg_draw_box(0, 0, 3, length($error)+4);
+       SLsmg_gotorc(1, 1);
+       SLsmg_write_string(" $error ");
+       SLsmg_refresh;
+
+       ReadKey; # wait for confirm
+       1 while defined ReadKey(-1); # clear key buffer
+}; # showerror
+
+push @{$hook{showstack}}, sub {
+       for (0..@stack-1) {
+               SLsmg_gotorc($set{height}-$_, 1);
+               SLsmg_write_string("$_: ".showval($stack[$_], $set{base}));  # prompt
+               SLsmg_erase_eol;
+       } # show stack
+       SLsmg_gotorc($set{height}-@stack, 1);
+       SLsmg_erase_eol;
+}; # showstack
+
+push @{$hook{refresh}}, sub {
+       SLsmg_cls;
+       SLsmg_gotorc($set{height}+1, 0);
+       SLsmg_write_string("> ");  # prompt
+}; # refresh
+
+push @{$hook{showentry}}, sub {
+       SLsmg_gotorc($set{height}+1, 2);
+       SLsmg_write_string($_[0]);
+       SLsmg_erase_eol;
+       SLsmg_refresh;
+}; # showentry
+
+return {
+       author  => "Shiar",
+       title   => "slang output",
+       version => "1.11",
+};
+
similarity index 64%
rename from 08_stdout.pm
rename to 08_disp_stdout.pm
index ededf36b0c18c02be57c921dc9e63106f12c7a45..41614e1be994f2064e1ec6104d13c2fe0aac2947 100644 (file)
@@ -1,16 +1,17 @@
 # console output for DCT, by Shiar
 
-# 1.10.1 200410140120 - print everything to STDOUT
-#     .2              - use escape sequences for clear/reposition/invert
-#     .3              - try to get width/height from environment vars
-#     .4              - never clear screen (just let it scroll)
-#     .5 200410142200 - startup message omitted (now shown by main)
+# 1.11.0 200410152225 - class in file name, so check is not needed anymore
+# 1.10.1 200410142200 - startup message omitted (now shown by main)
+# 1.10.0 200410140120 - never clear screen (just let it scroll)
+#                     - try to get width/height from environment vars
+#                     - use escape sequences for clear/reposition/invert
+#                     - print everything to STDOUT
 
 use strict;
 use warnings;
 
-return 0 if $set{display};
-$set{display} = "stdout";
+#return 0 if $set{display};
+#$set{display} = "stdout";
 
 push @{$hook{init}}, sub {
 #      print "\ec";  # reset (clear screen, go home)
@@ -39,6 +40,6 @@ push @{$hook{showentry}}, sub {
 return {
        author  => "Shiar",
        title   => "console output",
-       version => "1.10.4",
+       version => "1.11",
 };
 
index 9ea8a4f7ef18c55e92878ea33266b36d9dc45bd8..04881763ecc4fd72072fd1204432f220e6aed89c 100644 (file)
@@ -1,10 +1,10 @@
 # key bindings for DCT, by Shiar
 
-# 1.08.1 200409270040 - moved from 1.8 main
-#     .2 200409270049 - single key alias to chs: \ (often close to _)
+# 1.09.3 200410142200 - enter sent as chr 10 on non-curses terminals
+# 1.09.2 200410120145 - alt+backspace and ^W for (hard) drop
 # 1.09.1 200410112145 - function keys moved to menu.pm
-#     .2 200410120145 - alt+backspace and ^W for (hard) drop
-#     .3 200410142200 - enter sent as chr 10 on non-curses terminals
+# 1.08.2 200409270049 - single key alias to chs: \ (often close to _)
+# 1.08.1 200409270040 - moved from 1.8 main
 
 use strict;
 use warnings;
index c75f442deb7e4098665eaaab111e423108425527..7af32dbb8cdf8f01ed4f71f064dc448e84630b4b 100644 (file)
@@ -1,11 +1,13 @@
 # menu for DCT, by Shiar
 
-# 1.06.1 200409152332 - moved @menus from 1.6 main
-# 1.09.1 200410112150 - everything related to menus moved here
+# 1.11.0 200410282200 - display-specific code in evals
+# 1.10.4 200410151900 - remove explicit call to redraw on error
+# 1.10.3 200410150030 - add quit at F10 in main menu (after running other modules)
+#                     - don't show undefined menu entries (skippable)
+# 1.10.2 200410122345 - addmenu() function to add submenus
 # 1.10.1 200410122210 - @menus global; unit+math items added in those modules
-#     .2 200410122345 - addmenu() function to add submenus
-#     .3 200410150030 - don't show undefined menu entries (skippable)
-#     .4 200410150030 - add quit at F10 in main menu (after running other modules)
+# 1.09.1 200410112150 - everything related to menus moved here
+# 1.06.1 200409152332 - moved @menus from 1.6 main
 
 use strict;
 use warnings;
@@ -67,8 +69,8 @@ sub addmenu {
 } # addmenu
 
 #my @menu = [];
-my @menu;
-my $menumin = 0;
+our @menu;
+our $menumin = 0;
 
 push @{$hook{init}}, sub {
        $menus[0][10] = "quit";
@@ -78,19 +80,36 @@ push @{$hook{init}}, sub {
                unless defined $set{menushow};
 }; # init
 
+my %show = (
+       curses => q{
+               clrtoeol($set{height}+2, 1);
+               my $nr = -1;
+               for (grep exists $menu[$_], $menumin+1..$menumin+$set{menushow}) {
+                       $nr++;
+                       next unless defined $menu[$_];
+                       my $sub = (my $s = $menu[$_]) =~ s/>\d+$//;
+                       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
+       },
+       stdout => q{
+               my $nr = -1;
+               for (grep exists $menu[$_], $menumin+1..$menumin+$set{menushow}) {
+                       $nr++;
+                       next unless defined $menu[$_];
+                       my $sub = (my $s = $menu[$_]) =~ s/>\d+$//;
+                       print " $_:$s";
+                       print ">" if $sub;  # indicate submenu
+               } # display menu txts
+               print "\n> ";
+       },
+);
+
 sub showmenu() {
-       clrtoeol($set{height}+2, 1);
-       my $nr = -1;
-       for (grep exists $menu[$_], $menumin+1..$menumin+$set{menushow}) {
-               $nr++;
-               next unless defined $menu[$_];
-               my $sub = (my $s = $menu[$_]) =~ s/>\d+$//;
-               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
+       eval $_ if local $_ = $show{$::modules{disp}{name}};
 } # showmenu
 
 $action{more} = [-1, sub {
@@ -106,8 +125,8 @@ push @{$hook{refresh}}, sub {
 unshift @{$hook{precmd}}, sub {
        return unless exists $falias{$_};  # not a function key
        return if $_ = $menu[$falias{$_}];  # execute found menu item instead
-       error("* no such menu entry *");
-       goto DRAW;
+       error("no such menu entry");
+       return 1;
 }; # precmd
 
 push @{$hook{precmd}}, sub {
@@ -121,6 +140,6 @@ push @{$hook{precmd}}, sub {
 return {
        author  => "Shiar",
        title   => "menu",
-       version => "1.10.4",
+       version => "1.11",
 };
 
diff --git a/25_var.pm b/25_var.pm
new file mode 100644 (file)
index 0000000..44de41b
--- /dev/null
+++ b/25_var.pm
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+
+# 1.10.0 200410151900 - actions sto/?/rcl to copy/assign/recall variable
+
+my %var;
+
+#      "sto"   => [ 1, sub { $var{a} = $_[0] }], # copy
+#      '?'     => [ 1, sub { $var{a} = $_[0] }], # assign
+$action{sto} = [ 1, sub { $var{a} = $_[0] }]; # copy
+$action{rcl} = [ 0, sub { $var{a} }]; # recall
+
+return {
+       author  => "Shiar",
+       title   => "user variables",
+       version => "1.10",
+};
+
index 8a80fc7b1eed99a0642897c8bbeee86ae46603f5..ba39c7f5b0fbb950143df60d2240de5f602504b2 100644 (file)
@@ -1,7 +1,7 @@
 # key bindings for DCT, by Shiar
 
-# 1.10.1 200410150000 - single-level undo from main
-#     .2 200410150045 - set initial value to prevent crash when no undos set
+# 1.10.1 200410150045 - set initial value to prevent crash when no undos set
+# 1.10.0 200410150000 - single-level undo from main
 
 use strict;
 use warnings;
@@ -17,6 +17,6 @@ $action{undo}  = [-1, sub { ($undo, @stack) = ([@stack], @$undo) }]; # undo/redo
 return {
        author  => "Shiar",
        title   => "simple undo",
-       version => "1.10.2",
+       version => "1.10.1",
 };
 
similarity index 73%
rename from 31_math.pm
rename to 32_math.pm
index dd4d7d8f5a247fcee933896017e3b0d93f4d0140..96447e1ff44a360d91133feb6b652b1b0fb349a1 100644 (file)
@@ -1,16 +1,23 @@
 # math for DCT, by Shiar
 
-# 1.09.1 200410022255 - moved from 1.9 main
+# 1.10.4 200410282330 - trig functions from basic menu
+# 1.10.3 200410152245 - rnd, atan, pi
+#                     - trigonometry functions seperated
+# 1.10.2 200410132050 - probability functions: comb, perm, rdz
+# 1.10.1 200410112340 - adds menu items via addmenu() call
 # 1.09.2 200410112050 - functions don't handle stack themselves,
 #                       but behave like real functions
-# 1.10.1 200410112340 - adds menu items via addmenu() call
-#     .2 200410132050 - probability functions: comb, perm, rdz
+# 1.09.1 200410022255 - moved from 1.9 main
+
+#todo: check for errors, eg division by zero
 
 use strict;
 use warnings;
 use utf8;
 
-my %newaction = (
+%action = (
+       %action,
+
        '+'    => [2, sub { $_[1] + $_[0] }], # addition
        '-'    => [2, sub { $_[1] - $_[0] }], # substraction
        '*'    => [2, sub { $_[1] * $_[0] }], # multiplication
@@ -31,21 +38,6 @@ my %newaction = (
        'exp'  => [1, sub { exp $_[0] }], # e^x
        'expm' => [1, sub { exp($_[0]) - 1 }], # exp(x)-1
 
-       # hyperbolic
-       'sin'  => [1, sub { sin $_[0] }], # sine
-       'asin' => [1, sub { atan2($_[0], sqrt(1 - $_[0]*$_[0])) }], # inverse sine
-       'cos'  => [1, sub { cos $_[0] }], # cosine
-       'acos' => [1, sub { atan2(sqrt(1 - $_[0]*$_[0]), $_[0]) }], # inverse cosine
-       'tan'  => [1, sub { sin($_[0]) / cos($_[0]) }], # tangent
-#      'atan' => [1, sub { }], # arctangent
-
-       'sinh' => [1, sub { (exp($_[0]) - exp(-$_[0])) / 2 }], # hyperbolic sine
-       'cosh' => [1, sub { (exp($_[0]) + exp(-$_[0])) / 2 }], # hyperbolic cosine
-       'tanh' => [1, sub { (exp($_[0]) - exp(-$_[0])) / (exp($_[0]) + exp(-$_[0])) }], # hyperbolic tangent (sinh/cosh)
-       'asinh'=> [1, sub { log(sqrt($_[0]**2+1) + $_[0]) }], # inverse hyperbolic sine
-       'acosh'=> [1, sub { log(sqrt($_[0]**2-1) + $_[0]) }], # inverse hyperbolic cosine
-       'atanh'=> [1, sub { log((1+$_[0]) / (1-$_[0])) / 2 }], # inverse hyperbolic tangent
-
        # binary
        'and'  => [2, sub { $_[1] & $_[0] }], # bitwise and
        'or'   => [2, sub { $_[1] | $_[0] }], # bitwise or
@@ -59,12 +51,12 @@ my %newaction = (
 #      '%ch'  => [2, sub { $val{i} = 100*(shift(@_)-$val{i})/$val{i} }], # percentage change
 #      '%t'   => [2, sub { $val{i} = 100*$val{i}/shift(@_) }], # percentage total
 
-       'abs'  => [1, sub { abs $_[0] }], # absolute #todo
+       'abs'  => [1, sub { abs $_[0] }], # absolute
        'sign' => [1, sub { $_[0] <=> 0 }], # sign
        'ip'   => [1, sub { int $_[0] }], # integer part
        'fp'   => [1, sub { $_[0] - int $_[0] }], # fractional part
 
-#      'rnd'  => [1, sub { local $_ = 10**$_[0]; $val{i} = int(($val{i}+.5)*$_)/$_ }], # round
+       'rnd'  => [1, sub { sprintf "%.0f", $_[0] }], # round
 #      'trnc' => [1, sub { local $_ = 10**$_[0]; $val{i} = int($val{i}*$_)/$_ }], # truncate
        'floor'=> [1, sub { int $_[0] }], # floor
        'ceil' => [1, sub { int $_[0]+.9999 }], # ceil
@@ -101,15 +93,12 @@ my %newaction = (
 #      'utpf' => [3], # F distribution
 ); # newaction
 
-#while (my ($cmd, $val) = each %newaction) {$action{$cmd} = $val}
-$action{$_} = $newaction{$_} for keys %newaction;
-
 addmenu(["main", 0], "math",
-       [qw(basic log alog ln exp sin cos tan asin acos atan sq sqrt ^ xroot)],
+       [qw(basic sq sqrt ^ xroot log alog ln exp)],
 #      [qw(vector)],
 #      [qw(matrix)],
 #      [qw(list)],
-       [qw(hyperbolic sinh cosh tanh asinh acosh atanh expm lnp1)],
+#      [qw(hyperbolic sinh cosh tanh asinh acosh atanh expm lnp1)],
        [qw(real % %ch %t min max mod abs sign mant xpon ip fp rnd trnc floor ceil r>d d>r)],
        [qw(base dec bin oct hex),
                [qw(logic and or xor not)],
@@ -125,6 +114,6 @@ addmenu(["main", 0], "math",
 return {
        author  => "Shiar",
        title   => "basic math",
-       version => "1.10.2",
+       version => "1.10.4",
 };
 
diff --git a/33_trig.pm b/33_trig.pm
new file mode 100644 (file)
index 0000000..7736e2d
--- /dev/null
@@ -0,0 +1,61 @@
+# trigonometry for DCT, by Shiar
+
+# 1.11.1 200410282330 - cardial mode setting; rad/deg to switch to radians/degrees
+#                     - convert from/to radians for trig commands if rad mode set
+# 1.11.0 200410152320 - a?(sin|cos|tan)h? actions from math; links in main submenu trig
+
+use strict;
+use warnings;
+
+my $pi = atan2(1, 1) * 4;
+
+$set{card} = 1;  # degrees radians grades
+
+%action = (
+       %action,
+
+       'pi'   => [0, sub { $pi }], # pi constant
+
+       'deg'  => [-1, sub { $set{card} = 1 }], # set degrees
+       'rad'  => [-1, sub { $set{card} = 2 }], # set radians
+
+       # trigonometric
+       'sin'  => [1, sub { sin $_[0] }], # sine
+       'asin' => [1, sub { atan2($_[0], sqrt(1 - $_[0]*$_[0])) }], # inverse sine
+       'cos'  => [1, sub { cos $_[0] }], # cosine
+       'acos' => [1, sub { atan2(sqrt(1 - $_[0]*$_[0]), $_[0]) }], # inverse cosine
+       'tan'  => [1, sub { sin($_[0]) / cos($_[0]) }], # tangent
+       'atan' => [1, sub { atan2($_[0], 1) }], # arctangent
+
+       # hyperbolic
+       'sinh' => [1, sub { (exp($_[0]) - exp(-$_[0])) / 2 }], # hyperbolic sine
+       'cosh' => [1, sub { (exp($_[0]) + exp(-$_[0])) / 2 }], # hyperbolic cosine
+       'tanh' => [1, sub { (exp($_[0]) - exp(-$_[0])) / (exp($_[0]) + exp(-$_[0])) }], # hyperbolic tangent (sinh/cosh)
+       'asinh'=> [1, sub { log(sqrt($_[0]**2+1) + $_[0]) }], # inverse hyperbolic sine
+       'acosh'=> [1, sub { log(sqrt($_[0]**2-1) + $_[0]) }], # inverse hyperbolic cosine
+       'atanh'=> [1, sub { log((1+$_[0]) / (1-$_[0])) / 2 }], # inverse hyperbolic tangent
+); # action
+
+push @{$hook{preaction}}, sub {
+       return unless $set{card}==2;
+       # convert user input from radians if necessary
+       $stack[0] /= 360/$pi if $_[1] =~ /^(?:sin|cos|tan)h?$/;
+}; # preaction
+push @{$hook{postaction}}, sub {
+       return unless $set{card}==2;
+       # convert command output to radians if necessary
+       $stack[0] *= 360/$pi if $_[1] =~ /^a(?:sin|cos|tan)h?$/;
+}; # postaction
+
+addmenu(["main", 0], "trig", #todo: in math, not in main
+       qw(sin cos tan asin acos atan),
+       qw(sinh cosh tanh asinh acosh atanh),
+       qw(expm lnp1),
+);
+
+return {
+       author  => "Shiar",
+       title   => "trigonometry",
+       version => "1.11.1",
+};
+
index 1374ccf529baa91ceb3cfc9e2dc92cc39dce3100..3cf2540540eac540915155a51507410954170f89 100644 (file)
@@ -1,11 +1,13 @@
 # unit convertor for DCT, by Shiar
 
-# 1.09.1 200410022305 - moved %unit specs from 1.9 main
-# 1.09.2 200410112205 - all code moved here as well
+# 1.11.0 200410291000 - use redraw()
+# 1.10.5 200410151900 - data storage units (8 total, including LOC)
+# 1.10.4 200410132300 - hp49 units for mass
+# 1.10.3 200410130000 - fix error when run without menu module
+# 1.10.2 200410122200 - adds submenus with all units
 # 1.10.1 200410122030 - hp49 units for area, volume, time, speed, force, energy, power
-#     .2         2200 - adds submenus with all units
-#     .3     10130000 - fix error when run without menu module
-#     .4     10132300 - hp49 units for mass
+# 1.09.2 200410112205 - all code moved here as well
+# 1.09.1 200410022305 - moved %unit specs from 1.9 main
 
 use strict;
 use warnings;
@@ -177,6 +179,18 @@ do {
 #      [], # light
 #      [], # radiation
 #      [], # viscosity
+
+       [
+               "data storage", # memory
+               ['B', 1, "byte"],
+               ['kB', 1024, "kilobyte"],
+               ['MB', 1024**2, "megabyte"],
+               ['GB', 1024**3, "gigabyte"],
+               ['TB', 1024**4, "terabyte"],
+               ['bit', 1/8, "bit/octet"],
+               ['Mbit', 1024**2/8, "megabit"],
+               ['LOC', 19e12, 'Library of Congress'], # est. 17-20TB
+       ],
 ); # units table
 
 push @{$hook{precmd}}, sub {
@@ -187,7 +201,7 @@ push @{$hook{precmd}}, sub {
 #                      $stack[0] -= $_->{diff} if $_->{diff};
 #                      $stack[0] += $val{unit}{diff}*$val{unit}{val}/$_->{val} if $val{unit}{diff};
                        $stack[0] *= delete($val{unit})->{val} / $_->{val};
-                       showstack();
+                       redraw(1);
                        undef %val;
                } # convert
                else {
@@ -204,6 +218,6 @@ push @{$hook{postentry}}, sub {
 return {
        author  => "Shiar",
        title   => "unit convertor",
-       version => "1.10.4",
+       version => "1.11",
 };
 
diff --git a/CHANGES b/CHANGES
new file mode 100644 (file)
index 0000000..2e8eefa
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,87 @@
+200410291000   1.11.2
+       - global redraw() to queue a stack/screen refresh
+200410282330   1.11.1
+       - postaction hook after running commands
+       - give command name as parameter to pre/postaction hooks
+200410152225   1.11.0
+       - modules filenames can contain class; only loads first of any class
+
+200410151900   1.10.7
+       - main changelog moved to seperate CHANGES file
+       - user variables to module; our %var removed
+       - redraw inside main loop; automatically called after error
+       - when showing values with exponent, also adjust fraction
+200410150015   1.10.6
+       - invalid commands shown as strings instead of character codes
+200410150000   1.10.5
+       - only first module run of multiple with the same name
+       - preaction hook; undo functionality moved to module
+200410142145   1.10.4
+       - display welcome at startup, also showing version and modules
+       - allow modules to not load but without error
+200410132200   1.10.3
+       - digits added/removed to/from integer part in correct number base
+200410130020   1.10.2
+       - altered stack not redrawn after undo
+200410120245   1.10.1
+       - fixed backspace with undef fraction
+
+200410120213   1.09.6
+       - $val{frac} default undefined instead of 0
+200410120150   1.09.5
+       - normal drop command (alt+bs) removes input/stack value at once
+       - backspace becomes "back" (soft drop, like old "drop")
+200410112205   1.09.4
+       - unit conversion out of main program (entirely into unitconv.pm)
+200410112150   1.09.3
+       - all menu related functions moved to menu.pm
+200410112130   1.09.2
+       - hooks allowing for extra code at reload, showentry, and precmd
+200409291215   1.09.1
+       - number of menu items depends on screen width
+200409270057   1.09.0
+       - all key aliases moved to module DCT::Bindings
+
+200409262210   1.08
+       - stack command (cursor up) cycles through values in stack
+       - fixed %
+       - second undo redoes
+       - negative numbers displayed correctly in different bases
+       - additional digits were not correctly applied to negative values
+
+200409242350   1.07
+       - new commands: sr/sr, shortkeys ( )
+       - enter on no value repeats last val on stack
+       - action undo: last stack alteration can be undone
+       - numeric modifiers hardcoded instead of in action hash
+
+200409152310   1.06
+       - x and v shortkeys
+       - new commands: a?(sin|cos|tan)h, inv, !, rand
+       - menu contents in module
+
+200409101945   1.05
+       - q for sq(rt) (formerly quit, now only ^D/quit)
+       - some unit conversion (mostly lengths) from menu
+       - command backspacing
+       - error on insufficient arguments for command
+       - hp48-like drop (backspace but not editing value)
+       200409092200
+               - overhaul in stack handling
+
+200408041445   1.04
+       - ^L redraws screen
+       - manual command input using capital letters
+       - error dialog (don't mess up screen)
+
+20040625       1.03
+       - can enter fractions (.) and negative values (_)
+       - values displayable in arbitrary base
+
+20040620       1.02
+       - backspace to undo last digit
+       - function keys select command/submenu from (sub)menu
+
+20040618       1.01
+       - start (curses, some basic commands)
+
diff --git a/dct.pl b/dct.pl
index b11ca5724c8adba43ae9c850f1c6072fffddd279..d2e411c64b36bdfc696ea29b08766ee1d507b62c 100755 (executable)
--- a/dct.pl
+++ b/dct.pl
@@ -12,16 +12,16 @@ use utf8;
 use Data::Dumper;
 use Term::ReadKey;
 
-our $VERSION = "1.10.6";
+our $VERSION = "1.11.2";
 
-use vars qw(@stack %val %var %set %alias %action %hook);
+use vars qw(@stack %val %set %alias %action %hook);
+my $redraw = 2;  # set flag to refresh whole screen
 
 %set = (
        base     => 10,  # decimal; set using commands bin/oct/dec/hex/base
-       numb     =>  0,  # fixed scientific engineering
-       card     =>  1,  # degrees radians grades
-       coord    =>  0,  # cartesian polar spherical
-       complex  =>  0,  # real complex
+#      numb     =>  0,  # fixed scientific engineering
+#      coord    =>  0,  # cartesian polar spherical
+#      complex  =>  0,  # real complex
 
        height   =>  4,  # stack depth (lines of stack plus one)
        width    => 42,  # limit value precision, stetch menu
@@ -44,49 +44,51 @@ use vars qw(@stack %val %var %set %alias %action %hook);
 
        "swap"  => [ 2, sub { reverse @_ }], # swap x<->y
        "stack" => [-2, sub {
-               $var{stackpos} = 0 unless $var{stackpos};  # initialize
-               $var{stackpos} %= @stack;  # cycle
-               $val{i} = $stack[$var{stackpos}++];
+               my $stackpos if 0;
+               $stackpos = 0 unless $stackpos;  # initialize
+               $stackpos %= @stack;  # cycle
+               $val{i} = $stack[$stackpos++];
        }], # stack
 
-       "sto"   => [ 1, sub { $var{a} = $_[0] }], # copy
-       '?'     => [ 1, sub { $var{a} = $_[0] }], # assign
-
        "version" => [-2, sub {
                error("Desktop Calculator Thingy $VERSION by Shiar"); ()
        }], # version
 ); # %action
 
 
+sub redraw($) {
+       # queue a redraw of level $_[0]
+       $redraw = $_[0] if $_[0]>$redraw;
+} # redraw
+
 sub error($) {
        $_->($_[0]) for @{$hook{showerror}};
+       redraw(2);
 } # error
 
-sub showval($$);
-sub showval($$) {
-       my ($val, $base) = @_;
+sub showval;
+sub showval {
+       my ($val, $base, $baseexp) = @_;
        return '' unless defined $val;
        return $val if $base==10;
 
-       my $sign = $val<0;
-       $val = abs $val;
-       my $int = int $val;
-       my $frac = $val-$int;
-       my $exp = 0;
-
        my $txt = '';
 
+       my $sign = $val<0 and $val = abs $val;
+       my $int = int $val;
+
+       my $exp = $val{ex} || 0;
        while ($int>$base**10) {
                $int /= $base;
                $exp++;
        } # exponent part
 
+       my $frac = $val-$int;
        while ($int>=1) {
                my $char = $int%$base;
-               $txt = ($char<10 ? $char : chr($char+55)).$txt;
+               $txt = ($char<10 ? $char : chr($char+55)) . $txt;
                $int /= $base;
        } # integer part
-
        $txt .= '.' if $frac>0;
        for (my $i = 0; length $txt<$set{width}-2 && $frac>0; $i++) {
                $frac *= $base;
@@ -101,65 +103,63 @@ sub showval($$) {
        return $txt;
 } # showval
 
-sub showstack() {
-       $_->() for @{$hook{showstack}};
-} # showstack
 
-
-my %modules;
+our %modules;
 for my $module (sort glob "*.pm") {
-       next unless $module =~ /^\d{2}_(\w+)\.pm$/;  # filename 00_name.pm
-       next if defined $modules{$1};  # such module already loaded
-       defined ($_ = do $module)
-       ? (ref $_ and $modules{$1} = $_)  # return value means no errors
+       next unless $module =~ /^\d{2}_([a-z0-9-]+)(?:_(\w+))?\.pm$/;  # filename 00_class_name.pm
+       next if defined $modules{$1};  # no such module already loaded
+#      next if $1 eq "disp" and $2 eq "curses";
+       defined ($_ = do $module)  # return value means no errors
+       ? (ref $_ and $modules{$1} = $_, $modules{$1}{name} = $2 || "")
        : print STDERR $@, "error loading $module\n\n";
 } # load modules
 
-printf STDERR "DCT %s by Shiar (%s)\n", $VERSION,
-       join "; ", map {"$_ $modules{$_}{version}"} keys %modules;
+printf STDERR "DCT %s by Shiar (%s)\n", $VERSION, join "; ",
+       map join(" ", grep $_, $_, $modules{$_}{name}, $modules{$_}{version}), keys %modules;
 
 ReadMode 3;  # cbreak mode
 END { ReadMode 0; } # restore terminal on quit
 
 $_->() for @{$hook{init}};
-my $redraw = 1;
 
 LOOP: while (1) {
        if ($redraw) {
-               $_->() for @{$hook{refresh}};
-               showstack();
+               if ($redraw>1) {
+                       $_->() for @{$hook{refresh}};
+               }
+               $_->() for @{$hook{showstack}};
                $redraw = 0;
        } # refresh
 
        {
-               my $entry = showval($val{i}, $set{base});
-               $entry .= $_ for map $_->(), @{$hook{postentry}};
+               my $entry = showval($val{i}, $set{base}, $val{ex});
+               $entry .= $_->() for @{$hook{postentry}};
                $entry .= $val{alpha} if exists $val{alpha};
                $_->($entry) for @{$hook{showentry}};
        } # show entry
 
-       my $key = ReadKey;
+       my $key = ReadKey;  # wait for user input
        if ($key eq chr 27) {
                $key .= $_ while defined ($_ = ReadKey(-1));  # read additional keys
        } # escape sequence
-       $_ = $alias{$key} || $key; #if exists $alias{$key};  # command shortkeys
+       $_ = exists $alias{$key} ? $alias{$key} : $key;  # command (alias maps keys to commands)
        $_ = delete $val{alpha} if $_ eq "enter" and exists $val{alpha};  # use manual command
 
        for my $cmd (@{$hook{precmd}}) {
-               next LOOP if $cmd->();
+               $cmd->() and next LOOP;  # command was handled by function if returns true
        } # precmd functions
 
-       last if $_ eq 'quit';
+       last if $_ eq 'quit';  # break out of loop
 
        if ($_ eq 'refresh') {
-               $redraw++;
+               redraw(2);
        } # refresh
 
        elsif (/^\033?[A-Z]$/ or exists $val{alpha}) {
                if (defined $val{i}) {
                        unshift @stack, $val{i};
                        undef %val;
-                       showstack();
+                       redraw(1);
                } # enter present value
 
                if ($_ eq "back") {
@@ -179,6 +179,7 @@ LOOP: while (1) {
                $_ = -$_ if $val{i}<0;  # substract from negative value
                $val{i} = ($val{frac} and $val{frac} *= 10)
                        ? $val{i}+$_/$val{frac}  # add digit to fraction
+                       : defined $val{ex} ? $val{ex} = $val{ex}*$set{base}+$_  # digit to exponent
                        : $val{i}*$set{base}+$_;  # add digit to integer part
        } # digit
        elsif ($_ eq '.') {
@@ -187,7 +188,7 @@ LOOP: while (1) {
        } # decimal point
        elsif ($_ eq "eex") {
                $val{i} = 1 unless defined $val{i};
-               #todo
+               $val{ex} = 0;
        } # exponent
        elsif ($_ eq "chs" and defined $val{i}) {
                $val{i} = -$val{i};
@@ -199,21 +200,20 @@ LOOP: while (1) {
        } # backspace
 
        elsif (exists $action{$_}) {
-               my ($type, $cmd) = @{$action{$_}};
+               my ($action, $type, $cmd) = ($_, @{$action{$_}});
                unshift @stack, $action{enter}[1]->() if $type>0 and defined $val{i};  # auto enter
 
                if ($type>0 and $type>@stack) {
                        error("insufficient stack arguments for operation");
-                       $redraw++;
                        next;
                } # insufficient arguments
 
-               $_->($type) for @{$hook{preaction}};
-
+               $_->($type, $action) for @{$hook{preaction}};
                # put return value(s) of stack-modifying operations (type>=0) at stack
                $type<0 ? $cmd->() : unshift @stack, $cmd->(splice @stack, 0, $type);
+               $_->($type, $action) for @{$hook{postaction}};
 
-               showstack() if $type>=-1;
+               redraw(1) if $type>=-1;  # redraw stack
        } # some operation
 
        else {
@@ -221,52 +221,6 @@ LOOP: while (1) {
                        "unrecognised command: "  # show string or character codes
                        . (m/^\w*$/ ? qq{"$_"} : join ' ', map ord, split //, $_)
                );
-               $redraw++;  # screen messed up
        } # error
 } # input loop
 
-=cut
-VERSION HISTORY
-1.01 040618     - start (curses, some basic commands)
-1.02 040620     - function keys select command/submenu from (sub)menu
-                - backspace to undo last digit
-1.03 040625     - values displayable in arbitrary base
-                - can enter fractions (.) and negative values (_)
-1.04 0408041445 - error dialog (don't mess up screen)
-                - manual command input using capital letters
-                - ^L redraws screen
-     0409092200 - overhaul in stack handling
-1.05 0409101945 - hp48-like drop (backspace but not editing value)
-                - error on insufficient arguments for command
-                - command backspacing
-                - some unit conversion (mostly lengths) from menu
-                - q for sq(rt) (formerly quit, now only ^D/quit)
-1.06 0409152310 - menu contents in module
-                - new commands: a?(sin|cos|tan)h, inv, !, rand
-                - x and v shortkeys
-1.07 0409242350 - numeric modifiers hardcoded instead of in action hash
-                - action undo: last stack alteration can be undone
-                - enter on no value repeats last val on stack
-                - new commands: sr/sr, shortkeys ( )
-1.08 0409262210 - additional digits were not correctly applied to negative values
-                - negative numbers displayed correctly in different bases
-                - second undo redoes
-                - fixed %
-                - stack command (cursor up) cycles through values in stack
-1.09 0409270057 - all key aliases moved to module DCT::Bindings
-     0409291215 - number of menu items depends on screen width
-     0410112130 - hooks allowing for extra code at reload, showentry, and precmd
-           2150 - all menu related functions moved to menu.pm
-           2205 - unit conversion out of main program (entirely into unitconv.pm)
-     0410120150 - backspace becomes "back" (soft drop, like old "drop")
-                - normal drop command (alt+bs) removes input/stack value at once
-           0213 - $val{frac} default undefined instead of 0
-1.10 0410120245 - fixed backspace with undef fraction
-     0410130020 - altered stack not redrawn after undo
-     0410132200 - digits added/removed to/from integer part in correct number base
-     0410142145 - allow modules to not load but without error
-                - display welcome at startup, also showing version and modules
-     0410150000 - preaction hook; undo functionality moved to module
-                - only first module run of multiple with the same name
-           0015 - invalid commands shown as strings instead of character codes
-=cut