From 7db84757c6ba80836bc8c2cc9de326f16862a2cd Mon Sep 17 00:00:00 2001 From: Shiar Date: Fri, 29 Oct 2004 11:27:26 +0200 Subject: [PATCH] release 1.11.2 - 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 --- 05_curses.pm => 05_disp_curses.pm | 8 +- 06_disp_slang.pm | 61 ++++++++++++ 08_stdout.pm => 08_disp_stdout.pm | 17 ++-- 12_bindings.pm | 8 +- 15_menu.pm | 63 ++++++++----- 25_var.pm | 18 ++++ 28_undo.pm | 6 +- 31_math.pm => 32_math.pm | 43 ++++----- 33_trig.pm | 61 ++++++++++++ 35_unitconv.pm | 28 ++++-- CHANGES | 87 ++++++++++++++++++ dct.pl | 148 ++++++++++-------------------- 12 files changed, 375 insertions(+), 173 deletions(-) rename 05_curses.pm => 05_disp_curses.pm (84%) create mode 100644 06_disp_slang.pm rename 08_stdout.pm => 08_disp_stdout.pm (64%) create mode 100644 25_var.pm rename 31_math.pm => 32_math.pm (73%) create mode 100644 33_trig.pm create mode 100644 CHANGES diff --git a/05_curses.pm b/05_disp_curses.pm similarity index 84% rename from 05_curses.pm rename to 05_disp_curses.pm index 73e0d01..e88f667 100644 --- a/05_curses.pm +++ b/05_disp_curses.pm @@ -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 index 0000000..4fa569d --- /dev/null +++ b/06_disp_slang.pm @@ -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", +}; + diff --git a/08_stdout.pm b/08_disp_stdout.pm similarity index 64% rename from 08_stdout.pm rename to 08_disp_stdout.pm index ededf36..41614e1 100644 --- a/08_stdout.pm +++ b/08_disp_stdout.pm @@ -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", }; diff --git a/12_bindings.pm b/12_bindings.pm index 9ea8a4f..0488176 100644 --- a/12_bindings.pm +++ b/12_bindings.pm @@ -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; diff --git a/15_menu.pm b/15_menu.pm index c75f442..7af32db 100644 --- a/15_menu.pm +++ b/15_menu.pm @@ -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 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", +}; + diff --git a/28_undo.pm b/28_undo.pm index 8a80fc7..ba39c7f 100644 --- a/28_undo.pm +++ b/28_undo.pm @@ -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", }; diff --git a/31_math.pm b/32_math.pm similarity index 73% rename from 31_math.pm rename to 32_math.pm index dd4d7d8..96447e1 100644 --- a/31_math.pm +++ b/32_math.pm @@ -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 index 0000000..7736e2d --- /dev/null +++ b/33_trig.pm @@ -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", +}; + diff --git a/35_unitconv.pm b/35_unitconv.pm index 1374ccf..3cf2540 100644 --- a/35_unitconv.pm +++ b/35_unitconv.pm @@ -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 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 b11ca57..d2e411c 100755 --- 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 -- 2.30.0