MB 2008-11-20 : Thank you for that calculator ! I did some updates so that it can be used on a PDA.
#http://wiki.tcl.tk/10854 # DKF # # rpncalc.tcl -- # A Programmable RPN Calculator # Usage : # rpncalc.tcl key value ... # Arguments # -size size : the size of the calculator : tiny, small, medium or large or PDA # Default size is "small" or PDA for Windows CE system. # History # 2008-11-20, MB : small updates to make it usable on PDAs under Windows CE. # package require Tk proc init { arglist } { set rest {} foreach { var val } $arglist { set var [ string range $var 1 end ] uplevel 1 set $var \{$val\} lappend varlist $var } return "" } switch -- $::tcl_platform(os) { "Windows CE" { set size "PDA" } default { set size "small" } } init $::argv set stdmenu "1/X X! % %ch ABS \u03c0" set xstack 0 set SIGMODE 0 set numbase DEC set anglemode DEG label .dummy -text "xxx" set dummyfont [.dummy cget -font] destroy .dummy array set attributes [font actual $dummyfont] switch $size { PDA { #wm geometry . 240x360 set attributes(-size) 8 set attributes(-family) "Tahoma" set attributes(-weight) normal set minsize 20 set iw 6 } tiny { set attributes(-size) 5 set attributes(-weight) bold set minsize 20 set iw 6 } small { set attributes(-size) 8; set attributes(-weight) bold set minsize 80 set iw 12 } medium { set attributes(-size) 12; set attributes(-weight) bold set minsize 110 set iw 12 } large { set attributes(-size) 18; set attributes(-weight) bold set minsize 130 set iw 12 } default { error "Unknown size $size" } } set font [eval font create [array get attributes]] option add *font $font option add *background gray option add *activebackground gray option add *highlightbackground gray option add *highlightcolor gray label .tl -text "DEC" -anchor w -background lightgray -width $iw label .tn -text "T:" -anchor e -background lightgray label .tt -background lightgray -foreground black -anchor w -relief sunken label .zl -text "DEG" -anchor w -background lightgray -width $iw label .zn -text "Z:" -anchor e -background lightgray label .zt -background lightgray -foreground black -anchor w -relief sunken label .yl -text "4STK" -anchor w -background lightgray -width $iw label .yn -text "Y:" -anchor e -background lightgray label .yt -background lightgray -foreground black -anchor w -relief sunken label .xl -text "\u03a3LIN" -anchor w -background lightgray -width $iw label .xn -text "X:" -anchor e -background lightgray label .xt -background lightgray -foreground black -anchor w -relief sunken grid config .tl -row 0 -column 0 -sticky "nsw" grid config .tn -row 0 -column 0 -sticky "nse" grid config .tt -row 0 -column 1 -columnspan 5 -sticky "nsew" grid config .zl -row 1 -column 0 -sticky "nsw" grid config .zn -row 1 -column 0 -sticky "nse" grid config .zt -row 1 -column 1 -columnspan 5 -sticky "nsew" grid config .yl -row 2 -column 0 -sticky "nsw" grid config .yn -row 2 -column 0 -sticky "nse" grid config .yt -row 2 -column 1 -columnspan 5 -sticky "nsew" grid config .xl -row 3 -column 0 -sticky "nsw" grid config .xn -row 3 -column 0 -sticky "nse" grid config .xt -row 3 -column 1 -columnspan 5 -sticky "nsew" set udklist { udk1 udk2 udk3 udk4 udk5 udk6 } set shiftlist { func invf g h spare alpha } set label(func) f set label(invf) f\u00af\u00b9 set label(g) g set label(h) h set label(spare) spare set label(alpha) \u03b1 set bg(func) yellow set bg(invf) yellow set bg(g) slateblue set bg(h) black set bg(spare) darkgreen set bg(alpha) white set bg(unshifted) black set fg(func) black set fg(invf) black set fg(g) white set fg(h) white set fg(spare) white set fg(alpha) black set fg(unshifted) black set funcname(\u03c0) const-pi set funcname(\u2190) backsp set funcname(.) decimal set btnlist { 0 1 2 3 4 5 \ 6 7 8 9 10 11 \ 12 13 14 15 16 17 \ 18 19 20 21 22 23 \ 24 25 26 27 28 29 } set unshifted { "PRINT" "X\u2194Y" "CHS" "EEX" "\u2190" "\u00f7" \ "7" "8" "9" "0xA" "0xD" "\u00d7" \ "4" "5" "6" "0xB" "0xE" "-" \ "1" "2" "3" "0xC" "0xF" "+" \ "ON/OFF" "0" "." "DO" "MOD" "ENTER" } set func { "( )" "INT" "D\u2192H" "R\u2192P" "D\u2192R" "\u03a3+" \ "STO" "X\u00b2" "Y\u2191X" "LN" "LOG" "( )" \ "ST0@" "( )" "( )" "( )" "ISG" "R\u2191" \ "FS?" "M\u2192E" "( )" "( )" "( )" "\u03a3ALL" \ "EXIT" "XSTK+" "SF#" "( )" "SST" "( )" } set invf { "( )" "FRAC" "D\u2190H" "R\u2190P" "D\u2190R" "\u03a3-" \ "RCL" "\u221aX" "Y\u221aX" "e\u2191X" "10\u2191X" "( )" \ "RCL@" "( )" "( )" "( )" "DSZ" "R\u2193" \ "FC?" "M\u2190E" "( )" "( )" "( )" "\u03a3LIN"\ "EXIT" "XSTK-" "CF#" "( )" "BST" "( )" } set g { "HYP" "PROG" "TEST" "IF" "GTO" "SHL" \ "TRIG" "LBL" "DISP" "LOOP" "GSB" "SHR" \ "BASE" "DRG" "P\u2194S" "( )" "RTN" "AND" \ "CLEAR" "STDM" "( )" "( )" "NOT" "XOR" \ "EXIT" "RND#" "2'sC" "( )" "LstX" "OR" } set h { "SOLVE" "" "SD" "PSD" "AVG" "\u222bf(x)" \ "L.R." "AVGxy" "s,\u03c3" "SUMS" "CFIT" "NPV" \ "N" "Int" "PMT" "PV" "FV" "DATE-" \ "IRR" "BOND" "DEPR" "BAL" "%T" "DATE+" \ "EXIT" "( )" "( )" "( )" "ACCi" "ENTER" } set spare { "( )" "( )" "( )" "( )" "( )" "( )" \ "( )" "( )" "( )" "( )" "( )" "( )" \ "( )" "( )" "( )" "( )" "( )" "( )" \ "( )" "( )" "( )" "( )" "( )" "( )" \ "( )" "( )" "( )" "( )" "( )" "( )" } set alpha { "A" "B" "C" "D" "E" "F" \ "G" "H" "I" "J" "K" "L" \ "M" "N" "O" "P" "Q" "R" \ "S" "T" "U" "V" "W" "X" \ "EXIT" "Y" "Z" "punc" "cap" "ENTER" } set lock 0 set curshift "" proc setlabels { newshift } { global btnlist func invf alpha g h unshifted spare lock curshift bg if [ string equal $newshift $curshift ] { set lock [ expr !$lock ] if $lock return setlabels unshifted return } set curshift $newshift set lock 0 set n 0 foreach btn $btnlist { set text [ lindex [ set $newshift ] $n ] set fg $bg($curshift) .$btn configure -text $text -foreground $fg -activeforeground $fg incr n } } proc call { func } { global funcname if [ info exists funcname($func) ] { set func $funcname($func) } if [string match $func [ info commands $func ]] { if ![string equal $func ""] $func } else { puts "no such func: $func" } } proc dispatch { key } { global lock curshift shiftlist menupick if [ regexp udk(.) $key mpos ] { if $menupick { set temp [ .$key cget -text ] if [ string equal $temp "" ] return if [ string equal $temp >> ] { next } elseif [ string equal $temp << ] { prev } else { set menupick $temp } return } set function [ .$key cget -text ] call $function return } if { $menupick } { if { $key != 24 } return set menupick "" } if { [ lsearch -exact $shiftlist $key ] != -1 } { setlabels $key return } global $curshift set function [ lindex [set $curshift] $key ] if ![ string equal $function "" ] { if [ string equal $curshift alpha ] { puts "function: $function" if { [ string length $function ] > 1 } { call $function } else { puts "inpchar $function" } } else { call $function } } if !$lock { setlabels unshifted } } set curmenu "" set oldmenu "" set menubase 0 set menupick 0 proc updudks { } { global menubase curmenu set i $menubase set menulen [ llength $curmenu ] for { set j 1 } { $j <= 6 } { incr j } { if { $j > $menulen } { .udk$j configure -text "" } else { .udk$j configure -text [ lindex $curmenu [ expr $menubase + $j -1 ]] } } } proc menu { args } { global curmenu oldmenu menubase stdmenu if [string equal $args ""] { set args $stdmenu } set oldmenu $curmenu set curmenu $args set menubase 0 set page 6 while { [ llength $curmenu ] > $page } { set curmenu [ linsert $curmenu [ expr $page - 1] >> << ] incr page 6 } updudks } proc resume { } { global curmenu oldmenu menubase set curmenu $oldmenu set oldmenu "" set menubase 0 updudks } proc pick { args } { global menupick oldmenu set menupick 1 eval menu $args vwait menupick set result $menupick set menupick 0 resume return $result } proc next { } { global menubase incr menubase 6 updudks } proc prev { } { global menubase incr menubase -6 updudks } set row 4 ; set col 0 set keylist "$udklist $shiftlist $btnlist" foreach fn $keylist { set lbl $fn if [ info exists label($fn) ] { set lbl $label($fn) } set color "" if [ info exists fg($fn) ] { set color " -foreground $fg($fn) -background $bg($fn) " set color "$color -activeforeground $fg($fn) -activebackground $bg($fn) " } else { set color "-foreground black -activeforeground black" } if [ info exists label($fn) ] { set lbl $label($fn) } eval button .$fn $color -text $lbl -pady 0 -borderwidth 1 .$fn configure -command [ list dispatch $fn ] grid config .$fn -row $row -column $col -sticky "nsew" incr col if { $col > 5 } { set col 0 incr row } } wm protocol . WM_DELETE_WINDOW {OFF} set hyptrig 0 set invtrig 1 proc TRIG {} { global invtrig hyptrig set hyptrig 0 if $invtrig { menu INV SIN COS TAN } else { menu INV ASIN ACOS ATAN } } proc HYP {} { global invtrig hyptrig set hyptrig 1 if $invtrig { menu INV SINH COSH TANH } else { menu INV ASINH ACOSH ATANH } } proc INV {} { global invtrig hyptrig set invtrig [ expr !$invtrig ] if $hyptrig then HYP else TRIG } proc SUMS {} { global SIGMODE if { ${SIGMODE} } { set which [ pick n X Y X² Y² XY \ "lnX" "(lnX)²" "lnY" "(lnY)²" \ "(lnX)(lnY)" "X×lnY" "Y×lnX" ] # [DKF]: Not sure if the last two were fixed correctly... } else { set which [ pick n X Y X² Y² XY ] } puts "SUMS: $which" } proc punc {} { set ch [ pick ? , : \; ! ( ) \[ \] \{ \} spc _ * \" ' @ # $ % ^ & * = ~ ] puts "selected '$ch'" } proc BASE {} { set base [ pick HEX DEC OCT BIN ] .tl configure -text "$base" puts "new base: $base" } proc DISP {} { set disp [ pick ALL FIX SCI ENG ] puts "disp is: $disp" } proc EXIT {} { setlabels unshifted } proc DRG {} { global anglemode set anglemode [ pick DEG RAD GRD ] .zl configure -text "$anglemode" } proc CLEAR {} { global x y z t set what [ pick REGS \u03a3REG FIN PROG STACK X ALL ] if [ string equal $what ALL ] { set sure [ pick "DO IT" EXIT ] if [ string equal $sure "DO IT" ] { puts "clearing all" } } else { switch $what { REGS {} \u03a3REG {} FIN {} PROG {} STACK { set x 0 ; set y 0; set z 0; set t 0; end } X { set x 0; end } } puts "clearing $what" } } proc XSTK+ {} { global xstack set xstack 1 .yl configure -text "XSTK" } proc XSTK- {} { global xstack set xstack 0 .yl configure -text "4STK" } proc \u03a3ALL {} { global SIGMODE set SIGMODE 1 .xl configure -text "\u03a3ALL" } proc \u03a3LIN {} { global SIGMODE set SIGMODE 0 .xl configure -text "\u03a3LIN" } proc L.R. {} { set which [ pick ESTx ESTy r m b ] puts "Linear Regression: $which" } proc AVGxy {} { set which [ pick AVGx AVGy AVGxw ] puts "AVGxy: $which" } proc s,\u03c3 {} { set which [ pick sx sy \u03c3x \u03c3y ] puts "s,\u03c3: $which" } proc CFIT {} { set which [ pick MODL ... ] puts "CFIT: $which" } proc BOND {} { set which [ pick PRICE YTM ] puts "BOND: $which" } proc DEPR {} { set which [ pick SL SOYD DB ] puts "DEPRECIATION: $which" } proc STDM {} { menu } proc TEST {} { set which [ pick X?0 X?Y FS? FC? FS?C FC?S ] set func "" switch $which { X?0 { set func [ pick < \u2264 = \u2260 \u2265 > ] } X?Y { set func [ pick < \u2264 = \u2260 \u2265 > ] } } if [ string equal $func "" ] { puts "test: $which" } else { set which [ string replace $which 1 1 $func ] puts "test: $which" } } proc IF {} { set which [ pick TEST ELSE ELSIF ENDIF ] if [ string equal $which "TEST" ] TEST puts "IF $which" } proc LOOP {} { set which [ pick BEGIN BREAK NEXT ENDL ] puts "LOOP: $which" } proc M\u2192E {} { set which [ pick in ft yds miles degF gals lbs ] } proc E\u2192M {} { set which [ pick cm m km degC ltrs kgs ] } proc ON/OFF {} { exit } proc OFF {} { exit } proc ON {} { set which [ pick OFF EXIT ] if [ string equal $which OFF ] OFF } setlabels unshifted menu grid columnconfigure . 0 -minsize $minsize grid columnconfigure . 1 -minsize $minsize grid columnconfigure . 2 -minsize $minsize grid columnconfigure . 3 -minsize $minsize grid columnconfigure . 4 -minsize $minsize grid columnconfigure . 5 -minsize $minsize wm title . "HP-43" set x 0 set y 0 set z 0 set t 0 proc upddisp {} { global x y z t .tt configure -text $t .zt configure -text $z .yt configure -text $y .xt configure -text $x } proc pull {} { global needpush x y z t set x $y set y $z set z $t set needpush 1 } proc ENTER {} { global needpush wipex x y z t set t $z set z $y set y $x set wipex 1 set needpush 0 upddisp } set needpush 1 set wipex 0 proc key n { global needpush wipex x y z t rcl_pending sto_pending puts "key: $n rp:$rcl_pending sp:$sto_pending" if { $rcl_pending || $sto_pending } { register $n return } if $needpush ENTER if { $wipex } { set x "" set wipex 0 } if [ string equal $x "0" ] { set x $n } else { set x "${x}$n" } upddisp } proc backsp {} { global x needpush if $needpush { pull } else { set len [ expr [ string length $x ] - 2 ] set x [ string range $x 0 $len ] if [ string equal $x "" ] { pull set needpush 1 } } upddisp } proc 0 {} { key 0 } proc 1 {} { key 1 } proc 2 {} { key 2 } proc 3 {} { key 3 } proc 4 {} { key 4 } proc 5 {} { key 5 } proc 6 {} { key 6 } proc 7 {} { key 7 } proc 8 {} { key 8 } proc 9 {} { key 9 } proc decimal {} { key . } proc float { args } { foreach var $args { upvar 1 $var tmp if [ string is integer $tmp ] { set tmp [ expr double($tmp) ] } } } proc end {} { global needpush set needpush 1 upddisp } proc binop { op { real 0 } } { global x y needpush if $real { float x y } set result [ expr $y $op $x ] pull set x $result end } proc + {} { binop + } proc - {} { binop - } proc \u00d7 {} { binop * } proc \u00f7 {} { binop / 1 } proc X\u2194Y {} { global x y needpush set tmp $x set x $y set y $tmp end } proc 1/X {} { global x set x [ expr 1.0 / double($x) ] end } proc ABS {} { global x set x [ expr abs($x) ] end } proc const-pi {} { global x needpush if $needpush ENTER set x "3.141592653589792" end } proc gamma { c } { set cof(0) 76.18009172947146 set cof(1) -86.50532032941677 set cof(2) 24.01409824083091 set cof(3) -1.231739572450155 set cof(4) 0.1208650973866179e-2 set cof(5) -0.5395239384953e-5 set xx [ expr double($c) ] set yy [ expr double($c) ] set tmp [ expr $xx + 5.5 - ($xx + 0.5) * log($xx + 5.5) ] set ser 1.000000000190015 for {set j 0 } { $j<=5 } { incr j } { set yy [ expr $yy + 1.0 ] set ser [ expr $ser + ($cof($j) / $yy) ] } return [ expr exp(log(2.5066282746310005*$ser/$xx)-$tmp) ] } proc X! {} { global x set result 1 set j 0 if [ string is integer $x ] { if { $x > 29 } { float result x j } for { set j 2 } { $j <= $x } { incr j } { set result [ expr { $result * $j } ] } } else { set result [ gamma [ expr double($x) + 1.0 ] ] } set x $result end } proc PRINT {} { global x y z t set what [ pick X Y Z T STK ] switch $what { X { puts "X = $x" } Y { puts "Y = $y" } Z { puts "Z = $z" } T { puts "T = $t" } STK { foreach reg { t z y x } { puts "[ string toupper $reg ] = [set $reg]" } } } } proc trig { func } { global anglemode x switch $anglemode { DEG { set x [ expr ${func}($x*3.141592653489792/180.0) ] } RAD { set x [ expr ${func}($x) ] } GRD { set x [ expr ${func}($x*3.141592653489792/200.0) ] } } end } proc atrig { func } { global anglemode x switch $anglemode { DEG { set x [ expr a${func}($x)/3.141592653489792*180.0 ] } RAD { set x [ expr a${func}($x) ] } GRD { set x [ expr a${func}($x)/3.141592653489792/200.0 ] } } end } proc htrig { func } { global anglemode x switch $anglemode { DEG { set x [ expr ${func}h($x*3.141592653489792/180.0) ] } RAD { set x [ expr ${func}h($x) ] } GRD { set x [ expr ${func}h($x*3.141592653489792/200.0) ] } } end } proc setglob { name value } { global $name ; set $name $value } proc SIN {} { trig sin } proc COS {} { trig cos } proc TAN {} { trig tan } proc ASIN {} { atrig sin } proc ACOS {} { atrig cos } proc ATAN {} { atrig tan } proc SINH {} { htrig sin } proc COSH {} { htrig cos } proc TANH {} { htrig tan } proc STO {} { puts "sto"; setglob sto_pending 1 } proc STO@ {} { setglob sto_pending 1 ; setglob indirect 1 } proc RCL {} { setglob rcl_pending 1 } proc RCL@ {} { setglob rcl_pending 1 ; setglob indirect 1 } set reg_base 0 set alt_base 10 proc register { digit } { puts "register $digit" global alt_reg reg_base alt_base sto_pending rcl_pending x if [ string equal $digit "." ] { set alt_reg 1 return } if $alt_reg { set regnum [ expr $digit + $alt_base ] set alt_base 0 } else { set regnum [ expr $digit + $reg_base ] } global reg$regnum if $sto_pending { set reg$regnum $x } else { ENTER set x [ set reg$regnum ] } set sto_pending 0 set rcl_pending 0 end } # init regs for { set j 0 } { $j < 1000 } { incr j } { set reg$j 0 } set alt_reg 0 set sto_pending 0 set rcl_pending 0 set indirect 0 set tcl_precision 17 upddisp wm resizable . 0 0 vwait forever
Here's a Mac OS X screenshot: Larry Smith Looks nice in Aqua. But why don't the shift key colors show properly?jcw - I'm not sure Aqua supports colors (buttons tend to be gray, plus a blue default). Or maybe Tk Aqua has no hooks for this yet.Larry Smith Bummer. Sure wrecks a useful feature. Can you change the font color?
See also A little calculator - RPN