HP-15C Torsten Manz
[http://www.hpmuseum.org/simulate/15_1_205.zip]
Larry Smith I see no HP-15C_Simulator_Font.ttf file in the above link.
Torsten Manz has written a GPL'd HP-15C simulation entirely in Tcl/Tk. This version requires one install the included HP-15C simulation font.
Larry Smith took Torsten's work and added a version of LCD hexa panel and removed the need to install a font. I also changed the name to IQ-15C, since Torsten's version was so faithful to the actual calculator I got nervous about trademark issues.
My website is just too unstable right now.
#!/bin/sh #-*-tcl-*- # the next line restarts using wish \ exec wish "$0" -- ${1+"$@"} # ----------------------------------------------------------------------------- # # H E W L E T T · P A C K A R D 15C # # A simulator written in Tcl/TK # # © 1997-2006 Torsten Manz # © 2008 LCD code Larry Smith # # ----------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # # ----------------------------------------------------------------------------- package require Tk # proc announce args { tk_messageBox -message "$args" -icon info -type ok } # ----------------------------------------------------------------------------- # Hide window until everything is ready wm withdraw . ### LCD NUMBER DISPLAY ENGINE ### package require Tk # hex segment set dx 2 set 2dx 4 set dy 2 set 2dy 4 set seglen 8 set dheight [expr 2*$seglen+4*$dy] set dwidth 25 set digits 10 set coord1 "0 0" set coord2 "$dx -$dy" set coord3 "[expr $dx+$seglen] -$dy" set coord4 "[expr $2dx+$seglen] 0" set coord5 "[expr $dx+$seglen] $dy" set coord6 "$dx $dy" set horseg "$coord1 $coord2 $coord3 $coord4 $coord5 $coord6" set coord1 "0 0" set coord2 "$dx -$dy" set coord3 "$2dx 0" set coord4 "$2dx $seglen" set coord5 "$dx [expr $seglen+$dy]" set coord6 "0 $seglen" set verseg "$coord1 $coord2 $coord3 $coord4 $coord5 $coord6" proc getseg { xoffset yoffset isHorizontal } { global horseg verseg dx dx 2dx 2dy seglen set xoffset [ expr $xoffset ] set yoffset [ expr $yoffset ] if $isHorizontal { set result $horseg } else { set result $verseg } for {set j 0 } { $j < 12 } { incr j } { set result [ lreplace $result $j $j [ expr [lindex $result $j] + $xoffset] ] incr j set result [ lreplace $result $j $j [ expr [lindex $result $j] + $yoffset] ] } return $result } # The shapes of individual elements of a digit set lcdshape(a) [ getseg 0 0 0 ] set lcdshape(b) [ getseg $dx -$dy 1 ] set lcdshape(c) [ getseg $2dx+$seglen 0 0 ] set lcdshape(d) [ getseg $2dx+$seglen $2dy+$seglen 0 ] set lcdshape(e) [ getseg $dx 3*$dy+2*$seglen 1 ] set lcdshape(f) [ getseg 0 $2dy+$seglen 0 ] set lcdshape(g) [ getseg $dx $dy+$seglen 1 ] set lcdshape(h) {18 22 18 28 23 28 23 22 } set lcdshape(i) {18 28 23 28 16 34} # Which elements are turned on for a given digit? array set llcd { 0 {a b c d e f} 1 {c d} 2 {b c e f g} 3 {b c d e g} 4 {a c d g} 5 {a b d e g} 6 {a b d e f g} 7 {b c d} 8 {a b c d e f g} 9 {a b c d e g} A {a b c d f g} B {a d e f g} C {a b e f} D {c d e f g} E {a b e f g} F {a b f g} - {g} . {h} , {h i} r {a b} u {a g c} n {a b c} i { c } g {a b c d e g} e {a b e f g} o {a b c g} { } {} } # Displays a decimal str using LCD digits in the top-left of the canvas set eurostyle 0 proc disp_update { args } { global curdisp llcd lcdshape eurostyle dwidth # uncomment this line and comment next to switch from LCD to LED # set colors {#000000 #ff0000 #000000 #333333 } set colors {#929292 #000000 #929292 #A2A2A2} set lcdoffset 0 .display delete lcd foreach {onRim onFill offRim offFill} $colors {break} set len [ string length $curdisp ] for { set j 0 } { $j < $len } { incr j } { set glyph [ string index $curdisp $j ] set next [ string index $curdisp [ expr $j+1 ] ] foreach symbol {a b c d e f g} { if {[lsearch $llcd($glyph) $symbol] != -1} { .display move [.display create polygon $lcdshape($symbol) -tags lcd \ -outline $onRim -fill $onFill] $lcdoffset 8 } else { .display move [.display create polygon $lcdshape($symbol) -tags lcd \ -outline $offRim -fill $offFill] $lcdoffset 8 } } if { $next eq "." } { .display move [.display create polygon $lcdshape(h) -tags lcd \ -outline $onRim -fill $onFill] $lcdoffset 0 if $eurostyle { .display move [.display create polygon $lcdshape(i) -tags lcd \ -outline $onRim -fill $onFill] $lcdoffset 0 } incr j } elseif { $next eq "," } { .display move [.display create polygon $lcdshape(h) -tags lcd \ -outline $onRim -fill $onFill] $lcdoffset 0 if !$eurostyle { .display move [.display create polygon $lcdshape(i) -tags lcd \ -outline $onRim -fill $onFill] $lcdoffset 0 } incr j } incr lcdoffset $dwidth } update } # ------------------------------------------------------------------------------ # Application data: All non persistent parameters set useiq 0 array set APPDATA { title "HEWLETT·PACKARD 15C" titlewide "H E W L E T T · P A C K A R D 15C" titleverywide " H E W L E T T · P A C K A R D " titleshort " HP-15c " Char1 h Char1x 15 Char1y 12 Char2 p Char2x 22 Char2y 14 version 1.2.05 copyright "COPYRIGHT \u00A9 1997-2006, Torsten Manz" copyright2 "LCD Addition \u00A92008 by Larry Smith" filetypes {{"HP-15C Programs" {.15c}} {"Text files" {.txt}}} } if $useiq { array set APPDATA { title "INTELLIGENCE QUOTIENT 15C" titlewide "I N T E L L I G E N C E Q U O T I E N T 1 5 C" titleverywide " I N T E L L I G E N C E · Q U O T I E N T " titleshort " IQ-15c " Char1 h Char1 I Char1x 14 Char1y 12 Char2 Q Char2x 21 Char2y 15 version 1.2.05 copyright "COPYRIGHT \u00A9 1997-2006, Torsten Manz" copyright2 "LCD Addition \u00A92008 by Larry Smith" filetypes {{"IQ-15C Programs" {.15c}} {"Text files" {.txt}}} } } set APPDATA(SerialNo) "9931G0[string map {. {}} $APPDATA(version)]" # ------------------------------------------------------------------------------ # Check on required minimum Tcl/TK version and font option add *Dialog.msg.font "Helvetica 10" userDefault option add *Dialog.msg.wrapLength 600 userDefault if {$tk_version < "8.0"} { puts $APPDATA(titlewide) puts "ERROR: This program requires Tcl/Tk 8.4 or higher." exit } elseif {$tk_version < "8.4"} { tk_messageBox -type ok -icon error -default ok -title $APPDATA(titlewide) \ -message "This program requires Tcl/Tk 8.4 or higher." exit } # ------------------------------------------------------------------------------ # Default program settings array set HP15 { breakstomenu 1 browser "" clpbrdc 0 dataregs 19 delay 100 flash 200 freebytes 0 gsbmax 7 maxval 9.999999999e99 mnemonics 1 pause 1000 prgmcoloured 1 prgmmenubreak 30 prgmname "" prgmregsfree 46 prgmregsused 0 prgmstounicode 1 saveonexit 1 strictHP15 1 totregs 65 } # Used by preferences dialogue box to hold changed values until Ok or Apply. array set hp15tmp {} # ------------------------------------------------------------------------------ # Platform independent interface settings array set LAYOUT { display #9E9E87 display_outer_frame #F2F5F5 display_inner_frame #D9DEDD keypad_bg #484848 button_bg #434343 keypad_frame #E0E0E0 fbutton_bg #E1A83E gbutton_bg #6CB7BD BtnWidth 4 BtnPadX 1 BtnPadY 5 } if $useiq { array set LAYOUT { display #A2A699 display_outer_frame #C0C0C0 display_inner_frame #D9DEDD keypad_bg #484848 button_bg #434343 keypad_frame #E0E0E0 fbutton_bg #FFFF00 gbutton_bg #BBBBFF BtnWidth 5 BtnPadX 1 BtnPadY 5 } } # Predefined, well adjusted font sets set FONTSET { { {"unix" "UNIX Standard fonts, small" 70 80} { FnDisplay "{Sans} 25" FnStatus "Helvetica 8" FnButton "Helvetica 11 bold" FnEnter "Helvetica 11 bold" FnFGBtn "Helvetica 9" FnBrand "{Bitstream Vera Sans} 8" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier} 12 bold" FnScale 1.35 }} { {"unix" "UNIX Standard fonts" 70 80} { FnDisplay "{Sans} 29" FnStatus "Helvetica 9" FnButton "Helvetica 12 bold" FnEnter "Helvetica 12 bold" FnFGBtn "Helvetica 10" FnBrand "Helvetica 11 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier} 12 bold" FnScale 1.35 }} { {"unix" "Microsoft fonts" 70 80} { FnDisplay "{Sans} 28" FnStatus "Arial 9" FnButton "Arial 12 bold" FnEnter "Arial 11 bold" FnFGBtn "{Microsoft Sans Serif} 9" FnBrand "Tahoma 9" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier New} 12 bold" FnScale 1.35 }} { {"unix" "UNIX standard fonts, small" 81 135} { FnDisplay "{Sans} 24" FnStatus "Helvetica 8" FnButton "Helvetica 10 bold" FnEnter "Helvetica 10 bold" FnFGBtn "Helvetica 8" FnBrand "Helvetica 9 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier} 10 bold" FnScale 1.35 }} { {"unix" "UNIX standard fonts" 81 135} { FnDisplay "{Sans} 26" FnStatus "Helvetica 9" FnButton "Helvetica 12 bold" FnEnter "Helvetica 11 bold" FnFGBtn "Helvetica 9" FnBrand "Helvetica 9" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier} 12 bold" FnScale 1.35 }} { {"unix" "Microsoft fonts, small" 81 135} { FnDisplay "{Sans} 22" FnStatus "{Microsoft Sans Serif} 7" FnButton "Arial 9 bold" FnEnter "Arial 9 bold" FnFGBtn "Arial 8" FnBrand "Arial 8 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier New} 12 bold" FnScale 1.35 }} { {"unix" "Microsoft fonts" 81 135} { FnDisplay "{Sans} 26" FnStatus "{Microsoft Sans Serif} 8" FnButton "Arial 12 bold" FnEnter "Arial 10 bold" FnFGBtn "Arial 9" FnBrand "Arial 9 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier New} 12 bold" FnScale 1.35 }} { {"windows" "Microsoft fonts, small" 91 119} { FnDisplay "{Sans} 22" FnStatus "{Microsoft Small Fonts} 6" FnButton "Arial 9 bold" FnEnter "Arial 8 bold" FnFGBtn "{Microsoft Sans Serif} 6" FnBrand "Arial 7 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier New} 10 bold" FnScale 1.35 }} { {"windows" "Microsoft fonts" 91 119} { FnDisplay "{Sans} 23" FnStatus "{Microsoft Sans Serif} 7" FnButton "Arial 10 bold" FnEnter "Arial 9 bold" FnFGBtn "{Microsoft Sans Serif} 7" FnBrand "Arial 8 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier New} 10 bold" FnScale 1.35 }} { {"windows" "URW fonts, small" 91 119} { FnDisplay "{Sans} 22" FnStatus "{Nimbus Sans L} 7" FnButton "{Nimbus Sans L} 9 bold" FnEnter "{Nimbus Sans L} 8 bold" FnFGBtn "{Bitstream Vera Sans} 7" FnBrand "{Nimbus Sans L} 7 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier New} 10 bold" FnScale 1.35 }} { {"windows" "Microsoft fonts, small" 120 140} { FnDisplay "{Sans} 21" FnStatus "{Microsoft Small Fonts} 6" FnButton "Arial 9 bold" FnEnter "Arial 8 bold" FnFGBtn "{Microsoft Sans Serif} 6" FnBrand "Arial 7 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier New} 10 bold" FnScale 1.69 }} { {"windows" "Microsoft fonts" 120 140} { FnDisplay "{Sans} 22" FnStatus "{Microsoft Sans Serif} 7" FnButton "Arial 10 bold" FnEnter "Arial 9 bold" FnFGBtn "{Microsoft Sans Serif} 7" FnBrand "Arial 8 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier New} 10 bold" FnScale 1.69 }} { {"windows" "URW fonts, small" 120 140} { FnDisplay "{Sans} 19" FnStatus "{Nimbus Sans L} 6" FnButton "{Nimbus Sans L} 8 bold" FnEnter "{Nimbus Sans L} 7 bold" FnFGBtn "{Bitstream Vera Sans} 6" FnBrand "{Nimbus Sans L} 6 bold" FnLogo1 "{Chancery} 10 bold italic" FnLogo2 "{Sans} 10" FnMenu "{Courier New} 9 bold" FnScale 1.69 }} } # Labels for preferences. Used both in dialogue and message boxes. array set PREFTEXT { breakstomenu "Two column storage menu" browser "Help file browser" clpbrdc "Use C locale for clipboard" delay {Delay value [ms]} fonthint \ "Changes to font settings take effect when you\nrestart the simulator." frm_browser "Help file browser" frm_fontset "Font settings" frm_os "System settings" frm_simulator "Simulator settings" mnemonics "Program mnemonics" pause {Pause length [ms]} prgmcoloured "Coloured program menu" prgmmenubreak "Lines per column in program menu" prgmstounicode "Encode programs in UNICODE" saveonexit "Save memory on exit" strictHP15 "Strict HP-15C behaviour" } # ------------------------------------------------------------------------------ # Platform specific settings switch $::tcl_platform(platform) { windows { set APPDATA(memfile) "HP-15C.mem" set APPDATA(exetypes) {{"Executable files" {.exe}}} set APPDATA(browserlist) {mozilla firefox netscape opera start iexplore hh} switch -glob "$::tcl_platform(os) $::tcl_platform(osVersion)" { "Windows 95 *" {set APPDATA(HOME) $env(windir)} "Windows NT 4.0" {set APPDATA(HOME) $env(homedrive)$env(homepath)} "Windows NT 5.*" {set APPDATA(HOME) $env(APPDATA)} -- { tk_messageBox -type ok -icon error -default ok \ -title $APPDATA(titlewide) -message \ "$::tcl_platform(os) $::tcl_platform(osVersion) is not supported." } } set HP15(prgmdir) $APPDATA(HOME) set HP15(fontset) [expr round([tk scaling]*72) < 120 ? 8 : 11] if {[file exists hp-15c.ico]} { set iconFile hp-15c.ico wm iconbitmap . $iconFile } } unix { set APPDATA(memfile) ".hp-15c.mem" set APPDATA(exetypes) {{"All files" {*}}} set APPDATA(browserlist) {firefox mozilla netscape opera konqueror} set APPDATA(HOME) $env(HOME) set HP15(fontset) [expr round([tk scaling]*72) < 81 ? 1 : 4] set HP15(prgmdir) $APPDATA(HOME) } -- { tk_messageBox -type ok -icon error -default ok \ -title $APPDATA(titlewide) \ -message "Platform '$::tcl_platform(platform)' not supported." } } # ------------------------------------------------------------------------------ # Initialize processor, stack and storage registers set PI [expr acos(0)*2.0] array set status { f 0 g 0 user 0 BEGIN 0 RAD {} DMY 0 PRGM 0 integrate 0 solve 0 num 1 liftlock 1 dispmode FIX dispprec 4 comma , dot . error 0 seed 0 } # Must do this outside of "array set" to become evaluated set status(RADfactor) [expr $PI/180.0] # During execution two additional registers are added to the stack: # s: general scratchpad register that stores the last operand # u: used by helper functions in complex mode array set stack { x 0.0 y 0.0 z 0.0 t 0.0 LSTx 0.0 } array set istack { x 0.0 y 0.0 z 0.0 t 0.0 LSTx 0.0 } array set prgstat { curline 0 running 0 interrupt 0 rtnadr {0} maxiter {10000} } set PRGM {""} # Flags array set FLAG { 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 } # Test menu labels. Also used for mnemonics. set TEST { "x \u2260 0" "x > 0" "x < 0" "x \u2265 0" "x \u2264 0" "x = y" \ "x \u2260 y" "x > y" "x < y" "x \u2265 y" "x \u2264 y" "x = 0" } # ------------------------------------------------------------------------------ # Global program control variables set curdisp 0 set keyseq "" set isseq 0 # ------------------------------------------------------------------------------ # List of HP-15C keys # Key definitions # Each key definition consists of 10 elements: # row column : Row [1-4] and column [1-10] on the key pad # rowspan : Numbers of rows a key spans (normally 1 but 2 for ENTER) # key-code : Normally row+column, but numeric keys return number # f-label label g-label : The keys labels. Encoded in UNICODE. # f-binding binding g-binding : List of X11-keysyms bound to a key # set HP15_KEYS { { 1 1 1 11 A \u221ax x\u00B2 {Alt-a} {q} {Alt-x} } { 1 2 1 12 B e\u2191x LN {Alt-b} {e} {Alt-n} } { 1 3 1 13 C 10\u2191x LOG {Alt-c} {x} {Alt-g} } { 1 4 1 14 D y\u2191x % {Alt-d} {y} {percent} } { 1 5 1 15 E 1/x \u0394% {Alt-e} {Alt-slash backslash ssharp} {d} } { 1 6 1 16 MATRIX CHS ABS {} {Alt-plus Alt-minus} {bar brokenbar} } { 1 7 1 7 FIX 7 DEG {} {7 KP_7} {} } { 1 8 1 8 SCI 8 RAD {} {8 KP_8} {} } { 1 9 1 9 ENG 9 GRD {} {9 KP_9} {} } { 1 10 1 10 SOLVE \u00F7 x\u2264y {} {slash KP_Divide} {} } { 2 1 1 21 LBL SST BST {F8} {} {} } { 2 2 1 22 HYP GTO HYP\u002D\u00B9 {h} {F2} {Alt-h} } { 2 3 1 23 DIM SIN SIN\u002D\u00B9 {} {s} {} } { 2 4 1 24 (i) COS COS\u002D\u00B9 {} {c} {} } { 2 5 1 25 I TAN TAN\u002D\u00B9 {I j} {t} {} } { 2 6 1 26 RESULT EEX \u03C0 {} {E} {p} } { 2 7 1 4 x\u2194? 4 SF {Alt-less Alt-greater} {4 KP_4} {} } { 2 8 1 5 DSE 5 CF {} {5 KP_5} {} } { 2 9 1 6 ISG 6 F? {} {6 KP_6} {} } { 2 10 1 20 \u222Bxy \u00D7 x=0 {} {asterisk KP_Multiply} {} } { 3 1 1 31 PSE R/S P/R {F6} {F5} {F9} } { 3 2 1 32 \u2211 GSB RTN {} {F3} {F4} } { 3 3 1 33 PRGM R\u2193 R\u2191 {} {Down} {Up} } { 3 4 1 34 REG x\u2194y RND {} {less greater} {} } { 3 5 1 35 PREFIX \u2190 CLx {} {BackSpace} {Escape} } { 3 6 2 36 "RAN #" ENTER LSTx {numbersign} {Return KP_Enter} {l} } { 3 7 1 1 \u2192R 1 \u2192P {} {1 KP_1} {} } { 3 8 1 2 \u2192H.MS 2 \u2192H {} {2 KP_2} {} } { 3 9 1 3 \u2192RAD 3 \u2192DEG {} {3 KP_3} {} } { 3 10 1 30 Re\u2194Im - TEST {Tab} {minus KP_Subtract} {} } { 4 1 1 41 "" ON "" {} {} {} } { 4 2 1 42 "" f "" {} {} {} } { 4 3 1 43 "" g "" {} {} {} } { 4 4 1 44 FRAC STO INT {} {m} {} } { 4 5 1 45 USER RCL MEM {u} {r} {} } { 4 7 1 0 x! 0 x {exclam} {0 KP_0} {} } { 4 8 1 48 \u0177,r . s {} {comma period KP_Decimal} {} } { 4 9 1 49 L.R. \u2211+ \u2211- {} {Insert} {Delete} } { 4 10 1 40 Py,x + Cy,x {} {plus KP_Add} {} } } # HP-15C Key sequence, corresponding functions and function attributes # Key sequence: A regular expression describing a set of key sequences # Function name: The Tcl function. # Attributes (0|1): # LSTx: Operand is saved in the LSTx register. # End input: Function terminates input. Thus we have a number. # Programmable: Function is programmable. set HP15_KEY_FUNCS { { { 0 "func_digit 0" 0 0 1} { 1 "func_digit 1" 0 0 1} { 2 "func_digit 2" 0 0 1} { 3 "func_digit 3" 0 0 1} { 4 "func_digit 4" 0 0 1} { 5 "func_digit 5" 0 0 1} { 6 "func_digit 6" 0 0 1} { 7 "func_digit 7" 0 0 1} { 8 "func_digit 8" 0 0 1} { 9 "func_digit 9" 0 0 1} {10 "func_div" 1 1 1} {11 "func_sqrt" 1 1 1} {12 "func_exp" 1 1 1} {13 "func_10powx" 1 1 1} {14 "func_ypowx" 1 1 1} {15 "func_inv" 1 1 1} {16 "func_chs" 0 0 1} {20 "func_mult" 1 1 1} {21 "func_sst" 0 0 0} {22_([0-9]) "func_gto " 0 1 1} {22_1([1-5]) "func_gto -" 0 1 1} {22_25 "func_gto I" 0 1 1} {22_48_([0-9]) "func_gto 1" 0 1 1} {22_16_([0-9]) "func_gto_chs " 0 0 0} {23 "func_trign sin" 1 1 1} {24 "func_trign cos" 1 1 1} {25 "func_trign tan" 1 1 1} {26 "func_digit e+0" 0 0 1} {30 "func_minus" 1 1 1} {31 "func_rs" 0 1 1} {32_([0-9]) "func_gsb " 0 1 1} {32_1([1-5]) "func_gsb -" 0 1 1} {32_25 "func_gsb I" 0 1 1} {32_48_([0-9]) "func_gsb 1" 0 1 1} {33 "func_roll 1" 0 1 1} {34 "func_xy" 0 1 1} {35 "func_bs" 0 0 0} {36 "func_enter" 0 1 1} {40 "func_plus" 1 1 1} {41 "func_on" 0 0 0} {48 "func_digit ." 0 0 1} {49 "func_sum_plus" 1 1 1} } { {42_0 "func_faculty" 1 1 1} {42_1 "func_rectangular" 1 1 1} {42_1([1-5]) "dispatch_key 32_1" 0 0 0} {42_10_([0-9]) "func_solve " 0 1 1} {42_10_1([1-5]) "func_solve -" 0 1 1} {42_10_48_([0-9]) "func_solve 1" 0 1 1} {42_16 "# not implemented" 0 0 0} {42_2 "func_hms" 1 1 1} {42_20_([0-9]) "func_integrate " 0 0 1} {42_20_1([1-5]) "func_integrate -" 0 0 1} {42_20_48_([0-9]) "func_integrate 1" 0 0 1} {42_21_([0-9]) "func_label " 0 1 1} {42_21_1([1-5]) "func_label " 0 1 1} {42_21_48_([0-9]) "func_label 1" 0 1 1} {42_22_23 "func_hyp sin" 1 1 1} {42_22_24 "func_hyp cos" 1 1 1} {42_22_25 "func_hyp tan" 1 1 1} {42_23_1([1-5]) "# not implemented" 0 0 0} {42_23_24 "func_dim_mem" 0 1 1} {42_24 "func_i" 0 1 0} {42_25 "func_I" 0 1 1} {42_26 "# not implemented" 0 0 0} {42_3 "func_rad" 1 1 1} {42_30 "func_re_im" 0 1 1} {42_31 "func_pse" 0 1 1} {42_32 "func_clearsumregs" 0 1 1} {42_33 "func_clearprgm" 0 1 0} {42_34 "func_clearreg" 0 1 1} {42_35 "func_prefix" 0 1 0} {42_36 "func_random" 0 1 1} {42_4_([0-9]) "func_xexchg " 0 1 1} {42_4_24 "func_xexchg (i)" 0 1 1} {42_4_25 "func_xexchg I" 0 1 1} {42_4_48_([0-9]) "func_xexchg 1" 0 1 1} {42_40 "func_Pyx" 1 1 1} {42_44 "func_frac" 1 1 1} {42_45 "set_status user" 0 1 0} {42_48 "func_linexpolation" 0 1 1} {42_49 "func_linreg" 0 1 1} {42_5_([0-9]) "func_dse " 0 1 1} {42_5_24 "func_dse (i)" 0 1 1} {42_5_25 "func_dse I" 0 1 1} {42_5_48_([0-9]) "func_dse 1" 0 1 1} {42_6_([0-9]) "func_isg " 0 1 1} {42_6_24 "func_isg (i)" 0 1 1} {42_6_25 "func_isg I" 0 1 1} {42_6_48_([0-9]) "func_isg 1" 0 1 1} {42_7_([0-9]) "func_dsp_mode FIX " 0 1 1} {42_7_25 "func_dsp_mode FIX I" 0 1 1} {42_8_([0-9]) "func_dsp_mode SCI " 0 1 1} {42_8_25 "func_dsp_mode SCI I" 0 1 1} {42_9_([0-9]) "func_dsp_mode ENG " 0 1 1} {42_9_25 "func_dsp_mode ENG I" 0 1 1} } { {43_0 "func_avg" 0 1 1} {43_1 "func_polar" 1 1 1} {43_10 "func_test 10" 0 1 1} {43_11 "func_xpow2" 1 1 1} {43_12 "func_ln" 1 1 1} {43_13 "func_log10" 1 1 1} {43_14 "func_percent" 1 1 1} {43_15 "func_dpercent" 1 1 1} {43_16 "func_abs" 1 1 1} {43_2 "func_h" 1 1 1} {43_20 "func_test 11" 0 1 1} {43_21 "func_bst" 0 0 0} {43_22_23 "func_ahyp sin" 1 1 1} {43_22_24 "func_ahyp cos" 1 1 1} {43_22_25 "func_ahyp tan" 1 1 1} {43_23 "func_atrign sin" 1 1 1} {43_24 "func_atrign cos" 1 1 1} {43_25 "func_atrign tan" 1 1 1} {43_26 "func_pi" 0 1 1} {43_3 "func_deg" 1 1 1} {43_30_([0-9]) "func_test " 0 1 1} {43_31 "func_pr" 0 0 0} {43_32 "func_rtn" 0 1 1} {43_33 "func_roll 3" 0 1 1} {43_34 "func_rnd" 1 1 1} {43_35 "func_clx" 0 1 1} {43_36 "func_lastx" 0 1 1} {43_4_([0-9]) "func_sf " 0 1 1} {43_4_25 "func_sf I" 0 1 1} {43_40 "func_Cyx" 1 1 1} {43_44 "func_int" 1 1 1} {43_45 "func_mem" 0 1 0} {43_48 "func_stddev" 0 1 1} {43_49 "func_sum_minus" 1 1 1} {43_5_([0-9]) "func_cf " 0 1 1} {43_5_25 "func_cf I" 0 1 1} {43_6_([0-9]) "func_Finq " 0 1 1} {43_6_25 "func_Finq I" 0 1 1} {43_7 "set_status DEG" 0 1 1} {43_8 "set_status RAD" 0 1 1} {43_9 "set_status GRAD" 0 1 1} } { {44_([0-9]) "func_sto " 0 1 1} {44_25 "func_sto I" 0 1 1} {44_24 "func_sto (i)" 0 1 1} {44_48_([0-9]) "func_sto 1" 0 1 1} {44_10_([0-9]) "func_sto_oper / " 0 1 1} {44_10_24 "func_sto_oper / (i)" 0 1 1} {44_10_25 "func_sto_oper / I" 0 1 1} {44_10_48_([0-9]) "func_sto_oper / 1" 0 1 1} {44_20_([0-9]) "func_sto_oper * " 0 1 1} {44_20_24 "func_sto_oper * (i)" 0 1 1} {44_20_25 "func_sto_oper * I" 0 1 1} {44_20_48_([0-9]) "func_sto_oper * 1" 0 1 1} {44_30_([0-9]) "func_sto_oper - " 0 1 1} {44_30_24 "func_sto_oper - (i)" 0 1 1} {44_30_25 "func_sto_oper - I" 0 1 1} {44_30_48_([0-9]) "func_sto_oper - 1" 0 1 1} {44_*36 "func_storandom" 0 1 1} {44_40_([0-9]) "func_sto_oper + " 0 1 1} {44_40_24 "func_sto_oper + (i)" 0 1 1} {44_40_25 "func_sto_oper + I" 0 1 1} {44_40_48_([0-9]) "func_sto_oper + 1" 0 1 1} } { {45_([0-9]) "func_rcl " 0 1 1} {45_25 "func_rcl I" 0 1 1} {45_24 "func_rcl (i)" 0 1 1} {45_48_([0-9]) "func_rcl 1" 0 1 1} {45_10_([0-9]) "func_rcl_oper / " 0 1 1} {45_10_24 "func_rcl_oper / (i)" 0 1 1} {45_10_25 "func_rcl_oper / I" 0 1 1} {45_10_48_([0-9]) "func_rcl_oper / 1" 0 1 1} {45_20_([0-9]) "func_rcl_oper * " 0 1 1} {45_20_24 "func_rcl_oper * (i)" 0 1 1} {45_20_25 "func_rcl_oper * I" 0 1 1} {45_20_48_([0-9]) "func_rcl_oper * 1" 0 1 1} {45_30_([0-9]) "func_rcl_oper - " 0 1 1} {45_30_24 "func_rcl_oper - (i)" 0 1 1} {45_30_25 "func_rcl_oper - I" 0 1 1} {45_30_48_([0-9]) "func_rcl_oper - 1" 0 1 1} {45_36 "func_rclrandom" 0 1 1} {45_40_([0-9]) "func_rcl_oper + " 0 1 1} {45_40_24 "func_rcl_oper + (i)" 0 1 1} {45_40_25 "func_rcl_oper + I" 0 1 1} {45_40_48_([0-9]) "func_rcl_oper + 1" 0 1 1} {45_49 "func_rclsum" 0 1 1} } } # ------------------------ End of variable definitions ------------------------- # ------------------------------------------------------------------------------ proc commify { num {sign ,} } { if {$sign == "."} {regsub {[.]} $num "," num} set trg "\\1$sign\\2\\3" while {[regsub {^([-+ ]?[0-9]+)([0-9][0-9][0-9])([- ][0-9][0-9])?} \ $num $trg num]} {} return $num } # ------------------------------------------------------------------------------ proc format_exponent { expo } { if {$expo != ""} { regsub {^([-+ ]?)0([1-9][0-9]?)} $expo {\1\2} expo set expo [expr $expo >= 0 ? \" \" : \"-\"][format "%02d" [expr abs($expo)]] } return $expo } # ------------------------------------------------------------------------------ proc format_number { var } { global HP15 status set prec $status(dispprec) set eexprecmax 6 set eex 1 # calculate mantissa and exponent parameters set log [expr $var != 0 ? int(floor(log10(abs($var)))) : 0] switch $status(dispmode) { FIX { if {$log >= -$prec && $log <= 9} { set eex 0 if {$log+$prec > 9} {set prec [expr 9-$log]} } } SCI { # Nothing to do here } ENG { append ff "%1." $prec "e" set var [format $ff $var] set log [expr int($log/3)*3] } } # format mantissa append fmt "% ." $prec "f" if {[expr $var >= $HP15(maxval)]} { set mantissa " [string range $HP15(maxval) 0 7]" } elseif {[expr $var <= -$HP15(maxval)]} { set mantissa "-[string range $HP15(maxval) 0 7]" } elseif {$eex == 1} { set mantissa [format $fmt [expr $var/pow(10, $log)]] if {$status(dispmode) != "ENG" && $mantissa >= 10.0 && $log < 99} { incr log set mantissa [format $fmt [expr $var/pow(10, $log)]] } set len [expr ($prec > $eexprecmax ? $eexprecmax : $prec)+2] if {$status(dispmode) == "ENG" && $prec == 0} {incr len} set mantissa [string range $mantissa 0 $len] } else { set mantissa [format $fmt $var] } if {[string first "." $mantissa] <= 0} {set mantissa "$mantissa."} # format exponent if {$eex == 0} { set expo "" } else { set expo [format_exponent $log] } set filler [string repeat " " [expr 12-[string length "$mantissa$expo"]]] # return concatenated number return [commify "$mantissa$filler$expo" $status(dot)] } # ------------------------------------------------------------------------------ proc format_input { var } { global status regsub {(e[+-]$)} $var {\10} var regexp {^([-+ ]?[.0-9]+)e?([+-][0-9]+)?} $var all mantissa expo if {[string index $mantissa 0] != "-"} {set mantissa " $mantissa"} set expo [format_exponent $expo] set filler [string repeat " " \ [expr 11-[string length [string map {. ""} "$mantissa$expo"]]]] return [commify [format "%s%s%s" $mantissa $filler $expo] $status(dot)] } # ------------------------------------------------------------------------------ proc format_prgm { lnum wid } { global status PRGM set kl [split [lindex $PRGM $lnum] "_"] switch [llength $kl] { 1 - 2 { set st [join $kl] } 3 { if {[lindex $kl 1] == 48} { set st [format " %2d $status(comma)%1d" [lindex $kl 0] [lindex $kl 2]] } else { set st [format "%2d$status(dot)%2d$status(dot)%2d" \ [lindex $kl 0] [lindex $kl 1] [lindex $kl 2]] } } 4 { set st [format "%2d$status(dot)%2d$status(dot) %2s" \ [lindex $kl 0] [lindex $kl 1] "$status(comma)[lindex $kl 3]"] } default { set st "" } } return "[format "%03d-%$wid\s" $lnum $st]" } # ------------------------------------------------------------------------------ proc error_handler { errinfo } { global APPDATA HP15 FLAG stack istack status prgstat curdisp errorInfo errorCode set errnum -1 set status(num) 1 if {[lindex $errinfo 0] == "ARITH"} { switch [lindex $errinfo 1] { IOVERFLOW - OVERFLOW { set stack(x) $HP15(maxval) set istack(x) $HP15(maxval) set FLAG(9) 1 show_x } NOVERFLOW { set stack(x) -$HP15(maxval) set istack(x) -$HP15(maxval) set FLAG(9) 1 show_x } UNDERFLOW { set stack(x) 0.0 show_x } INVALID - default { set errnum 0 } } } else { switch [lindex $errinfo 0] { SUM { set errnum 2 } INDEX { set errnum 3 } ADDRESS { set errnum 4 } RTN { set errnum 5 } FLAG { set errnum 6 } RECURSION { set status(solve) 0 set status(integrate) 0 set errnum 7 } SOLVE { set errnum 8 } DIM { set errnum 10 } INTERRUPT { set prgstat(running) 0 set prgstat(interrupt) 0 show_x } FILEIO { switch [lindex $errinfo 1] { ECREATE { set errmsg "Could not write file" } ENOENT { set errmsg "No such file" } EOPEN { set errmsg "Could not open file" } NONE - EFMT { set errmsg "Error parsing line [lindex $errinfo 3]" } INVCMD { set errmsg "Invalid command in line [lindex $errinfo 3]" } default { set errmsg "$errorInfo" } } set errnum 98 tk_messageBox -type ok -icon error -default ok \ -title $APPDATA(titlewide) -message "$errmsg: [lindex $errinfo 2]" } default { set errnum 99 tk_messageBox -type ok -icon error -default ok \ -title $APPDATA(titlewide) \ -message "Internal Tcl/Tk Error:\n$errorInfo" set stack(x) 0.0 } } } if {$errnum >= 0} { set status(error) 1 set prgstat(running) 0 set curdisp " ERRoR [format "%2d" $errnum]" } } # ------------------------------------------------------------------------------ proc show_x { args } { global HP15 status stack curdisp if {[catch { if {abs($stack(x)) > 0.0 && abs($stack(x)) < 1E-99} { error_handler {ARITH UNDERFLOW} } elseif {[expr $stack(x) > $HP15(maxval)]} { error_handler {ARITH OVERFLOW} } elseif {[expr $stack(x) < -$HP15(maxval)]} { error_handler {ARITH NOVERFLOW} } else { if {$status(num)} { set curdisp [format_number $stack(x)] } else { set curdisp [format_input $stack(x)] } } } errorCode]} {} # {error_handler $errorCode} disp_update } # ------------------------------------------------------------------------------ proc disp_flash { p1 p2 p3 } { global LAYOUT HP15 FLAG if {$FLAG(9)} { if {[.display itemcget d0 -fill] == "black"} { .display itemconfigure all -fill $LAYOUT(display) .status itemconfigure all -fill $LAYOUT(display) } else { .display itemconfigure all -fill black .status itemconfigure all -fill black } after $HP15(flash) disp_flash 1 1 1 } else { .display itemconfigure all -fill black .status itemconfigure all -fill black } } # ------------------------------------------------------------------------------ proc mem_save {} { global APPDATA HP15 stack istack storage prgstat PRGM FLAG # Keep global status but set status to be saved as for shut-off! array set status [array get ::status] set status(error) 0 set status(f) 0 set status(g) 0 set status(num) 1 set status(solve) 0 set status(integrate) 0 set status(PRGM) 0 set prgstat(interrupt) 0 set prgstat(running) 0 set FLAG(9) 0 set sepline "# [string repeat - 78]" set fid [open "$APPDATA(HOME)/$APPDATA(memfile)" {RDWR CREAT TRUNC}] puts $fid $sepline puts $fid "# Tcl/Tk $APPDATA(title) memory file" puts $fid "# The Simulator is $APPDATA(copyright)" puts $fid "# Version $APPDATA(version)" puts $fid "# Memory saved on [clock format [clock seconds] -format "%c"]" puts $fid $sepline puts $fid "" foreach aa {HP15 status stack istack storage FLAG prgstat} { puts $fid $sepline puts $fid "# $aa" puts $fid "array set $aa {" foreach ii [lsort -dictionary [array names $aa]] { puts $fid " $ii {[set ${aa}($ii)]}" } puts $fid "}\n" } puts $fid $sepline puts $fid "# Program" puts $fid "set PRGM {" foreach ii $PRGM { puts $fid " {$ii}" } puts $fid "}" puts $fid $sepline close $fid } # ------------------------------------------------------------------------------ proc mem_load {} { global APPDATA HP15 status stack istack storage prgstat PRGM FLAG set fnam "$APPDATA(HOME)/$APPDATA(memfile)" if {[file exists $fnam]} { if {[catch {source $fnam} err]} { error_handler [list FILEIO EFMT $fnam $err] } } # Refresh status line set_status NIL } # ------------------------------------------------------------------------------ proc prgm_save {} { global APPDATA HP15 PRGM set sepline "# [string repeat - 44]" set fnam [tk_getSaveFile -title "$APPDATA(title): Save program" \ -defaultextension ".15C" -filetypes $APPDATA(filetypes) \ -initialdir "$HP15(prgmdir)" -initialfile "$HP15(prgmname)"] if {$fnam != ""} { if {[catch {set fid [open $fnam {RDWR CREAT TRUNC}]}]} { error_handler [list FILEIO ECREATE $fnam] close $fid return } if {$HP15(prgmstounicode)} { puts -nonewline $fid "\377\376" fconfigure $fid -encoding unicode } puts $fid $sepline puts $fid "# Tcl/Tk $APPDATA(title) Simulator program" puts $fid "# Created with version $APPDATA(version)" puts $fid "$sepline\n" for {set ii 0} {$ii < [llength $PRGM]} {incr ii} { set seq "" foreach cc [split [lindex $PRGM $ii] "_"] { append seq [format {%3d} $cc] } puts $fid "[format " %03d {%12s } %s" $ii $seq \ [build_mnemonic [lindex $PRGM $ii] 0]]" } puts $fid "\n$sepline" close $fid set HP15(prgmdir) [file dirname $fnam] set HP15(prgmname) [file tail $fnam] } } # ------------------------------------------------------------------------------ proc prgm_open {} { global APPDATA HP15 status prgstat PRGM errorCode set fnam [tk_getOpenFile -initialdir "$HP15(prgmdir)" \ -title "$APPDATA(title): Open program" -defaultextension ".15C" \ -filetypes $APPDATA(filetypes)] if {$fnam != ""} { if {[catch {set fid [open "$fnam" {RDONLY}]}]} { error_handler [list FILEIO EOPEN $fnam] close $fid return } # Check whether file is UNICODE or ASCII encoded set unic [read $fid 2] if {[string compare $unic "\377\376"] == 0 || \ [string index $unic 1] == "\000"} { fconfigure $fid -encoding unicode } if {"$unic" != "\377\376"} {seek $fid 0} set lcnt 0 set PRGMtmp {} if {[catch { while {[gets $fid curline] >= 0} { incr lcnt set curline [string trim $curline] if {[string length $curline] > 0 && [string index $curline 0] != "#"} { if {[regexp "\{(.*)\}" $curline all step] == 0} { error "" "" {EFMT} } set step [string map {" " _ " " _} [string trim $step]] if {[lookup_keyseq $step 1] == "" && [llength $PRGMtmp] > 0} { error "" "" {INVCMD} } lappend PRGMtmp $step unset step } } }]} { error_handler [list FILEIO $::errorCode $fnam $lcnt] return } close $fid # Insert empty step 000 if first step is not empty if {[lindex $PRGMtmp 0] != ""} {set PRGMtmp [linsert $PRGMtmp 0 ""]} set prgstat(curline) 0 set prgstat(rtnadr) {0} set PRGM $PRGMtmp if {$status(PRGM)} {show_curline} set HP15(prgmdir) [file dirname $fnam] set HP15(prgmname) [file tail $fnam] } } # ------------------------------------------------------------------------------ proc clipboard_set { reg } { global HP15 status stack if {[string compare $::tcl_platform(platform) "unix"]} { clipboard clear if {$HP15(clpbrdc)} { clipboard append $stack($reg) } else { clipboard append [string map ". $status(comma)" $stack($reg)] } } else { selection handle -selection PRIMARY . clipboard_transfer selection own -selection PRIMARY . } } # ------------------------------------------------------------------------------ proc clipboard_transfer { offset maxchars } { global HP15 status stack if {$HP15(clpbrdc)} { return $stack(x) } else { return [string map ". $status(comma)" $stack(x)] } } # ---------------------------------------------------------------------------- proc clipboard_get {} { global HP15 status stack # On Windows only CLIPBOARD selection exists. On UNIX most applications use # PRIMARY selection, some use CLIPBOARD (or both). We will check for both... if {[catch {set clpbrd [selection get -selection PRIMARY]}]} { catch {set clpbrd [selection get -selection CLIPBOARD]} } if {[info exists clpbrd]} { if {$HP15(clpbrdc)} { set clpbrd [string map {, ""} $clpbrd] } else { set clpbrd [string map {. "" , .} $clpbrd] } if {[string is double $clpbrd]} { if {$status(num)} {lift} set status(num) 1 set stack(x) $clpbrd } } } # ------------------------------------------------------------------------------ proc exchange_seps {} { global status set tmp $status(comma) set status(comma) $status(dot) set status(dot) $tmp if {$status(PRGM)} { show_curline } else { show_x } } # ------------------------------------------------------------------------------ proc help { topic } { global APPDATA HP15 argv0 errorInfo switch $topic { simulator { # Differentiate between running from a starpack or from wish if {[info exists starkit::topdir]} { set helpdir [file dirname $starkit::topdir] } else { set helpdir [file dirname $argv0] } if {[string compare $helpdir "."] == 0} {set helpdir [pwd]} set helpfile "$helpdir/doc/index.htm" } prgm { set helpfile "$HP15(prgmdir)/[file rootname $HP15(prgmname)].htm" } } catch {set helpfile [file nativename [lindex [glob "$helpfile*"] 0]]} if {[string length $HP15(browser)] == 0} { set msg "No help file browser configured.\nSee Preferences dialogue box." preferences } elseif {$topic == "prgm" && $HP15(prgmname) == ""} { set msg "No help file available or\nno name given for current program." } elseif {![file exists $helpfile]} { set msg "Help file not found:\n$helpfile" } if {[info exists msg]} { tk_messageBox -type ok -icon error -default ok \ -title $APPDATA(titlewide) -message $msg if [winfo exists .prefs] {focus .prefs} } else { if {[catch {eval exec $HP15(browser) [list $helpfile] &} exerr]} { tk_messageBox -type ok -icon error -default ok \ -title $APPDATA(titlewide) \ -message "Could not display help file:\n$exerr" } } } # ------------------------------------------------------------------------------ proc show_on_options { trigger } { global LAYOUT status if {[winfo exists .onm]} {destroy .onm} menu .onm -tearoff 0 -title "Options" -font $LAYOUT(FnMenu) .onm add command -label "Open program\u2026" -underline 0 \ -command "prgm_open" .onm add command -label "Save program\u2026" -underline 0 \ -command "prgm_save" .onm add separator .onm add command -label "Save memory" -underline 5 -command "mem_save" .onm add command -label "Load memory" -underline 0 -command "mem_load" if {$status(PRGM)} { set st disabled } else { set st normal } .onm add command -label "Clear all" -underline 0 -command "clearall" \ -state $st .onm add separator .onm add command \ -label "[format "1%s000%s00 \u2192 1%s000%s00" $status(dot) $status(comma) \ $status(comma) $status(dot)]" -underline 0 -command "exchange_seps" .onm add command -label "Preferences\u2026" -underline 0 \ -command "preferences" .onm add separator .onm add command -label "Help\u2026" -underline 0 -command "help simulator" .onm add command -label "About\u2026" -underline 0 -command "about" .onm add separator .onm add command -label "Exit" -underline 1 -command "exit_handler" if {$trigger == 3} { tk_popup .onm [winfo pointerx .] [winfo pointery .] } else { tk_popup .onm [winfo rootx .btn_41.btn] \ [expr [winfo rooty .btn_41.btn]+[winfo height .btn_41.btn]] } } # ------------------------------------------------------------------------------ proc show_storage { function trigger } { global LAYOUT HP15 storage if {[winfo exists .storage]} {destroy .storage} menu .storage -tearoff 0 -title "Storage" -font $LAYOUT(FnMenu) set regmax [expr $HP15(dataregs) < 19 ? $HP15(dataregs) : 19] for {set ii 0} {$ii <= $regmax} {incr ii} { .storage add command \ -label "R[format "%2d" $ii]: [format_number $storage($ii)]" if {$ii < 10} { .storage entryconfigure $ii -underline 2 \ -command "dispatch_key $function\_$ii" } else { .storage entryconfigure 10 -columnbreak $HP15(breakstomenu) .storage entryconfigure $ii \ -command "dispatch_key $function\_48_[expr $ii-10]" } } .storage add command .storage entryconfigure $ii -label "RI : [format_number $storage(I)]" \ -underline 1 -command "dispatch_key $function\_25" if {$trigger == 3} { tk_popup .storage [winfo pointerx .] [winfo pointery .] } else { tk_popup .storage [winfo rootx .btn_$function.gbtn] \ [winfo rooty .btn_$function.gbtn] } } # ------------------------------------------------------------------------------ proc show_content { trigger } { global status if {$status(error)} { show_error $trigger } elseif {$status(PRGM)} { show_prgm $trigger } else { show_stack $trigger } } # ------------------------------------------------------------------------------ proc show_stack { trigger } { global FLAG LAYOUT stack istack if {[winfo exists .stack]} {destroy .stack} menu .stack -tearoff 0 -title "Stack" -font $LAYOUT(FnMenu) set sts 3 foreach ii {t z y x} { if {$FLAG(8)} { .stack add command -command "func_roll $sts" -hidemargin 1 -label \ [format {%5s: %-15s %5s: %-15s} $ii [format_number $stack($ii)] \ i$ii [format_number $istack($ii)]] } else { .stack add command -command "func_roll $sts" -hidemargin 1 -label \ [format {%5s: %-15s} $ii [format_number $stack($ii)]] } incr sts -1 } .stack add separator if {$FLAG(8)} { .stack add command -command "dispatch_key 43_36" -hidemargin 1 -label \ [format { LSTx: %-15s iLSTX: %-15s} [format_number $stack(LSTx)] \ [format_number $istack(LSTx)]] } else { .stack add command -label " LSTx: [format_number $stack(LSTx)]" \ -command "dispatch_key 43_36" -hidemargin 1 } if {$trigger == 3} { tk_popup .stack [winfo pointerx .] [winfo pointery .] } else { tk_popup .stack [winfo rootx .status] \ [expr [winfo rooty .status] + [winfo height .status]] } } # ------------------------------------------------------------------------------ proc show_error { trigger } { global LAYOUT stack if {![winfo exists .error]} { menu .error -tearoff 0 -title "Error" -font $LAYOUT(FnMenu) .error add command -label " 0 : y \u00F7 0, LN 0, \u2026" -state disabled .error add command -label " 1 : LN A, SIN A, \u2026" -state disabled .error add command -label " 2 : \u2211 Error" -state disabled .error add command -label " 3 : R?, Aij?" -state disabled .error add command -label " 4 : LBL?, GTO > MEM, PRGM > MEM" -state disabled .error add command -label " 5 : > 7 RTN" -state disabled .error add command -label " 6 : SF > 9, CF > 9, F? > 9" -state disabled .error add command -label " 7 : SOLVE(SOLVE), \u222Bxy(\u222Bxy)" \ -state disabled .error add command -label " 8 : SOLVE ?" -state disabled .error add command -label " 9 : ON / \u00D7" -state disabled .error add command -label "10 : DIM > MEM" -state disabled .error add command -label "11 : DIM A \u2260 DIM B" -state disabled .error add separator .error add command -label "98 : File I/O error" -state disabled .error add command -label "99 : Tcl/Tk error" -state disabled .error configure -disabledforeground [.error cget -foreground] } if {$trigger == 3} { tk_popup .error [winfo pointerx .] [winfo pointery .] } else { tk_popup .error [winfo rootx .status] \ [expr [winfo rooty .status] + [winfo height .status]] } } # ------------------------------------------------------------------------------ proc lift {} { foreach ii {stack istack} { upvar #0 $ii st set st(t) $st(z) set st(z) $st(y) set st(y) $st(x) } } # ------------------------------------------------------------------------------ proc drop {} { foreach ii {stack istack} { upvar #0 $ii st set st(x) $st(y) set st(y) $st(z) set st(z) $st(t) } } # ------------------------------------------------------------------------------ proc move { from to } { global stack istack set stack($to) $stack($from) set istack($to) $istack($from) } # ------------------------------------------------------------------------------ proc populate { val } { foreach ii {stack istack} { upvar #0 $ii st foreach jj {x y z t} { set st($jj) $val } } } # ------------------------------------------------------------------------------ proc set_status { st } { global status FLAG PI switch $st { user { set status(user) [expr !$status(user)] set status(f) 0 toggle_user $status(user) show_x } f { if {!$status(f)} { set status(f) [expr !$status(f)] set status(g) 0 } } g { if {!$status(g)} { set status(g) [expr !$status(g)] set status(f) 0 } } fg_off { set status(f) 0 set status(g) 0 } BEGIN { set status(BEGIN) [expr !$status(BEGIN)] } DEG { set status(RAD) "" set status(RADfactor) [expr $PI/180.0] show_x } RAD { set status(RAD) $st set status(RADfactor) 1.0 show_x } GRAD { set status(RAD) $st set status(RADfactor) [expr 0.9*$PI/180.0] show_x } PRGM { set status(PRGM) [expr !$status(PRGM)] } } if [winfo exists .status] { .status itemconfigure suser -text [expr $status(user) ? \"USER\" : \"\"] .status itemconfigure sf -text [expr $status(f) ? \"f\" : \" \"] .status itemconfigure sg -text [expr $status(g) ? \"g\" : \" \"] .status itemconfigure sbegin -text [expr $status(BEGIN) ? \"BEGIN\" : \" \"] .status itemconfigure srad -text $status(RAD) .status itemconfigure scomplex -text [expr $FLAG(8) ? \"C\" : \" \"] .status itemconfigure sprgm -text [expr $status(PRGM) ? \"PRGM\" : \"\"] } } # ------------------------------------------------------------------------------ proc count_digits { var } { set rc 0 for {set ii 0} {$ii < [string length $var]} {incr ii} { if {[string is digit [string index $var $ii]]} { incr rc } elseif {[string index $var $ii] == "e"} { break } } return $rc } # ------------------------------------------------------------------------------ proc func_digit { digit } { global status stack istack if {$status(num)} { if {!$status(liftlock)} {lift} if {$status(liftlock) < 2} {set istack(x) 0.0} set status(num) 0 if {$digit == "e+0"} { set digit "1$digit" } elseif {$digit == "."} { set digit "0." } set stack(x) $digit } else { set stack_x $stack(x) if {$digit == "e+0" && ([string first "e" $stack_x] > 0 || [count_digits $stack_x] > 7)} { set digit "" } set comma [string first "." $stack_x] if {[count_digits $stack_x] < 10 && !($digit == "." && $comma != -1)} { if {[string first "e" $stack_x] > 0} { regsub {([-+ ]?[0-9]+e[+-])[0-9]([0-9])$} $stack_x {\1\2} stack_x } set stack_x "$stack_x$digit" # Avoid integer overflow for 10-digit integers. Obsolete with Tcl/Tk >= 8.4? if {[count_digits $stack_x] == 10 && $comma == -1 && \ [string first "e" $stack_x] < 0} { set stack_x "$stack_x." } set stack(x) $stack_x } } set status(liftlock) 0 } # ------------------------------------------------------------------------------ proc func_sqrt {} { global FLAG stack if {$FLAG(8)} { move x u csqrt move u x } else { set stack(x) [expr sqrt($stack(x))] } } # ------------------------------------------------------------------------------ proc func_xpow2 {} { global FLAG stack istack if {$FLAG(8)} { set stack(x) [expr 1.0*$stack(x)*$stack(x) - $istack(x)*$istack(x)] set istack(x) [expr 2.0*$stack(s)*$istack(x)] } else { set stack(x) [expr pow($stack(x), 2)] } } # ------------------------------------------------------------------------------ proc func_exp {} { global FLAG stack istack if {$FLAG(8)} { set stack(x) [expr exp($stack(x))*cos($istack(x))] set istack(x) [expr exp($stack(s))*sin($istack(x))] } else { set stack(x) [expr exp($stack(x))] } } # The following are helper functions for the complex mode. They solely operate # on stack register u. # ------------------------------------------------------------------------------ proc cabs {} { global stack istack return [expr sqrt(1.0*$stack(u)*$stack(u) + 1.0*$istack(u)*$istack(u))] } # ------------------------------------------------------------------------------ proc cphi {} { global PI stack istack set ret [expr atan($istack(u)/$stack(u))] if {$stack(u) < 0.0} { set mod [expr $istack(u) >= 0.0 ? $PI : -$PI] } else { set mod 0.0 } set ret [expr $ret+$mod] return $ret } # ------------------------------------------------------------------------------ proc csqrt {} { global stack istack set tmp $stack(u) set xb [cabs] set stack(u) [expr sqrt(($stack(u) + $xb)/2.0)] set istack(u) [expr ($istack(u) < 0 ? -1.0 : 1.0)*sqrt((-$tmp + $xb)/2.0)] } # ------------------------------------------------------------------------------ proc cln {} { global PI stack istack set tmp $stack(u) set stack(u) [expr 0.5*log(1.0*$stack(u)*$stack(u)+1.0*$istack(u)*$istack(u))] if {$tmp != 0.0} { set mod 0.0 if {$tmp < 0.0} {set mod [expr $istack(u) >= 0.0 ? $PI : -$PI]} set istack(u) [expr atan($istack(u)/$tmp) + $mod] } else { set istack(u) [expr $istack(x) >= 0.0 ? $PI/2.0 : -$PI/2.0] } } # ------------------------------------------------------------------------------ proc func_ln {} { global FLAG stack istack if {$FLAG(8)} { if {$stack(x) == 0.0 && $istack(x) == 0.0} { error "" "" {ARITH INVALID} } else { move x u cln move u x } } else { if {$stack(x) == 0.0} { error "" "" {ARITH INVALID} } else { set stack(x) [expr log($stack(x))] } } } # ------------------------------------------------------------------------------ proc func_10powx {} { global FLAG stack istack if {$FLAG(8)} { set stack(x) [expr pow(10.0,$stack(x))*cos($istack(x)*log(10.0))] set istack(x) [expr pow(10.0,$stack(s))*sin($istack(s)*log(10.0))] } else { set stack(x) [expr pow(10.0, $stack(x))] } } # ------------------------------------------------------------------------------ proc func_log10 {} { global FLAG stack istack if {$FLAG(8)} { if {$stack(x) == 0.0 && $istack(x) == 0.0} { error "" "" {ARITH INVALID} } else { move x u cln set stack(x) [expr $stack(u)/log(10.0)] set istack(x) [expr $istack(u)/log(10.0)] } } else { if {$stack(x) == 0.0} { error "" "" {ARITH INVALID} } else { set stack(x) [expr log10($stack(x))] } } } # ------------------------------------------------------------------------------ proc func_ypowx {} { global FLAG stack istack if {$FLAG(8)} { move y u set stack(y) [expr pow([cabs],$stack(x))*exp(-$istack(x)*[cphi])] set istack(y) [expr $stack(x)*[cphi] + $istack(x)*log([cabs])] set lx $stack(y) set stack(y) [expr cos($istack(y))*$stack(y)] set istack(y) [expr sin($istack(y))*$lx] } else { set stack(y) [expr pow($stack(y), $stack(x))] } drop } # ------------------------------------------------------------------------------ proc func_percent {} { global stack set stack(x) [expr ($stack(y)/100.0) * $stack(x)] } # ------------------------------------------------------------------------------ proc func_inv {} { global FLAG stack istack if {$FLAG(8)} { move x u set xb [expr pow([cabs],2)] set stack(x) [expr $stack(x)/$xb] set istack(x) [expr -$istack(s)/$xb] } else { set stack(x) [expr 1.0/$stack(x)] } } # ------------------------------------------------------------------------------ proc func_dpercent {} { global stack set stack(x) [expr ($stack(x)-$stack(y))/($stack(y)/100.0)] } # ------------------------------------------------------------------------------ proc func_dsp_mode { mode param } { global status storage if {$param == "I"} { if {$storage(I) < 0} { set param 0 } else { set param [expr int($storage(I)) > 9 ? 9 : int($storage(I))] } } set status(dispmode) $mode set status(dispprec) $param show_x } # ------------------------------------------------------------------------------ proc lookup_label { lbl } { global prgstat PRGM if {$lbl < 0} { set target "42_21_1[expr abs($lbl)]" } elseif {$lbl > 9} { set target "42_21_48_[expr int($lbl - 10)]" } else { set target "42_21_$lbl" } set tl -1 set wrap 0 set ll [expr $prgstat(curline)+1] while {!$wrap} { if {$ll > [llength $PRGM]} {set ll 0} if {[lindex $PRGM $ll] == "$target"} { set tl $ll break } elseif {$ll == $prgstat(curline)} { set wrap 1 } incr ll } return $tl } # ------------------------------------------------------------------------------ proc func_label { lbl } { show_x } # ------------------------------------------------------------------------------ proc func_sst { {ev 0} } { global HP15 status prgstat PRGM if {$status(PRGM)} { if {$ev == 0 || $ev == 2 || $ev == 4} { incr prgstat(curline) if {$prgstat(curline) >= [llength $PRGM]} { set prgstat(curline) 0 } show_curline } } else { if {$ev == 0 || $ev == 2 || $ev == 4} { if {$prgstat(curline) == 0 && [llength $PRGM] > 1} {incr prgstat(curline)} show_curline if {$ev == 0} {after $HP15(pause) {show_x}} } else { set prgstat(running) 1 prgm_step set prgstat(running) 0 show_x } } } # ------------------------------------------------------------------------------ proc func_bst { {ev 0} } { global HP15 status prgstat PRGM if {$status(PRGM) || $ev == 0 || $ev == 2 || $ev == 4} { if {$prgstat(curline) > 0} { incr prgstat(curline) -1 } else { set prgstat(curline) [expr [llength $PRGM] - 1] } show_curline } if {!$status(PRGM)} { if {$ev == 0 || $ev == 2 || $ev == 4} { set status(num) 1 if {$ev == 0} {after $HP15(pause) {show_x}} } else { show_x } } } # ------------------------------------------------------------------------------ proc func_gto_chs { trigger } { global status if {!$status(error)} {show_prgm $trigger} } # ------------------------------------------------------------------------------ proc func_gto { lbl } { global HP15 storage prgstat PRGM if {$lbl == "I"} { set lbl [expr int($storage(I))] if {$lbl < 0 && abs($lbl) <= [llength $PRGM]} { set ll [expr abs($lbl)] } elseif {$lbl >= 0 && $lbl <= $HP15(dataregs)} { set ll [lookup_label $lbl] } elseif {$lbl >= 20 && $lbl <= 24} { set ll [lookup_label [expr 19-$lbl]] } else { set ll -1 } } else { set ll [lookup_label $lbl] } if {$ll == -1} { error "" "" {ADDRESS} } else { set prgstat(curline) $ll } } # ------------------------------------------------------------------------------ proc func_gsb { lbl } { global HP15 prgstat if {$lbl == "I"} { set lbl [expr int($storage(I))] if {$lbl < 0 && abs($lbl) <= [llength $PRGM]} { set ll [expr abs($lbl)] } elseif {$lbl >= 0 && $lbl <= $HP15(dataregs)} { set ll [lookup_label $lbl] } elseif {$lbl >= 20 && $lbl <= 24} { set ll [lookup_label [expr 19-$lbl]] } else { set ll -1 } } else { set ll [lookup_label $lbl] } if {$ll == -1} { error "" "" {ADDRESS} } elseif {$prgstat(running)} { if {[llength $prgstat(rtnadr)] <= $HP15(gsbmax)} { lappend prgstat(rtnadr) [expr $prgstat(curline)+1] set prgstat(curline) $ll } else { error "" "" {RTN} } } else { prgm_run $ll } } # ------------------------------------------------------------------------------ proc func_hyp { func } { global FLAG stack istack if {$FLAG(8)} { switch $func { sin { set stack(x) [expr sinh($stack(x))*cos($istack(x))] set istack(x) [expr cosh($stack(s))*sin($istack(x))] } cos { set stack(x) [expr cosh($stack(x))*cos($istack(x))] set istack(x) [expr sinh($stack(s))*sin($istack(x))] } tan { set divi [expr pow(cosh($stack(x))*cos($istack(x)),2)+ \ pow(sinh($stack(s))*sin($istack(x)),2)] set stack(x) [expr sinh($stack(x))*cosh($stack(x))/$divi] set istack(x) [expr sin($istack(x))*cos($istack(x))/$divi] } } } else { set stack(x) [expr $func\h($stack(x))] } } # ------------------------------------------------------------------------------ proc func_ahyp { func } { global FLAG stack istack if {$FLAG(8)} { set stack(u) [expr 1.0*$stack(x)*$stack(x) - $istack(x)*$istack(x)] set istack(u) [expr 2.0*$stack(x)*$istack(x)] switch $func { sin { set stack(u) [expr $stack(u)+1.0] csqrt set stack(u) [expr $stack(x)+$stack(u)] set istack(u) [expr $istack(x)+$istack(u)] cln move u x } cos { set stack(u) [expr $stack(u)-1.0] csqrt set stack(u) [expr $stack(x)+$stack(u)] set istack(u) [expr $istack(x)+$istack(u)] cln set sg [expr $stack(s) < 0.0 ? -1.0 : 1.0] set stack(x) [expr $sg*$stack(u)] set istack(x) [expr $sg*$istack(u)] } tan { set divi [expr 1.0-2.0*$stack(x)+pow($stack(x),2)-pow($istack(x),2)] set stack(u) [expr (1.0-pow($stack(x),2)+pow($istack(x),2))/$divi] set istack(u) [expr -2.0*$stack(x)*$istack(x)/$divi] cln set stack(x) [expr 0.5*$stack(u)] set istack(x) [expr 0.5*$istack(u)] } } } else { switch $func { sin { set stack(x) [expr log($stack(x) + sqrt($stack(x)*$stack(x) + 1.0))] } cos { set stack(x) [expr log($stack(x) - sqrt($stack(x)*$stack(x) - 1.0))] } tan { set stack(x) [expr log(sqrt((1.0 + $stack(x)) / (1.0 - $stack(x))))] } } } } # ------------------------------------------------------------------------------ proc func_trign { func } { global status FLAG stack istack if {$FLAG(8)} { switch $func { sin { set stack(x) [expr sin($stack(x))*cosh($istack(x))] set istack(x) [expr cos($stack(s))*sinh($istack(x))] } cos { set stack(x) [expr cos($stack(x))*cosh($istack(x))] set istack(x) [expr -sin($stack(s))*sinh($istack(x))] } tan { set divi [expr cos(2.0*$stack(x))+cosh(2.0*$istack(x))] set stack(x) [expr sin(2.0*$stack(x))/$divi] set istack(x) [expr sinh(2.0*$istack(x))/$divi] } } } else { set stack(x) [expr $func\($stack(x)*$status(RADfactor))] } } # ------------------------------------------------------------------------------ proc func_atrign { func } { global status FLAG stack istack if {$FLAG(8)} { set stack(u) [expr $stack(x)*$stack(x) - $istack(x)*$istack(x)] set istack(u) [expr 2.0*$stack(x)*$istack(x)] switch $func { sin { set stack(u) [expr 1.0-$stack(u)] set istack(u) [expr -$istack(u)] csqrt set stack(u) [expr -$istack(x)+$stack(u)] set istack(u) [expr $stack(x)+$istack(u)] cln set stack(x) $istack(u) set istack(x) [expr -$stack(u)] } cos { set stack(u) [expr $stack(u)-1.0] csqrt set stack(u) [expr $stack(x)+$stack(u)] set istack(u) [expr $istack(x)+$istack(u)] cln set sg [expr $stack(s)*$istack(s) < 0.0 ? -1.0 : 1.0] set stack(x) [expr $sg*$istack(u)] set istack(x) [expr -$sg*$stack(u)] } tan { set divi [expr 1.0+2.0*$istack(x)+pow($istack(x),2)+pow($stack(x),2)] set stack(u) [expr (1.0-pow($istack(x),2)-pow($stack(x),2))/$divi] set istack(u) [expr 2.0*$stack(x)/$divi] cln set stack(x) [expr 0.5*$istack(u)] set istack(x) [expr -0.5*$stack(u)] } } } else { set stack(x) [expr a$func\($stack(x))/$status(RADfactor)] } } # ------------------------------------------------------------------------------ proc func_dim_mem {} { global HP15 stack storage set rr [expr abs(int($stack(x)))] if {$rr < 1} {set rr 1} if {$rr > $HP15(dataregs) + $HP15(prgmregsfree)} { error "" "" {DIM} } else { for {set ii [expr $rr+1]} {$ii <= $HP15(dataregs)} {incr ii} { array unset storage $ii } for {set ii [expr $HP15(dataregs)+1]} {$ii <= $rr} {incr ii} { set storage($ii) 0.0 } set HP15(dataregs) $rr mem_recalc } show_x } # ------------------------------------------------------------------------------ proc func_i { {ev 0} } { global HP15 status FLAG istack curdisp if {!$status(PRGM)} { if {$FLAG(8)} { if {$ev == 0 || $ev == 2 || $ev == 4} { set curdisp [format_number $istack(x)] if {$ev == 0} {after $HP15(pause) {show_x}} } else { after $HP15(pause) {show_x} } } else { if {$ev == 0 || $ev == 3 || $ev ==5} {error_handler {INDEX}} } } } # ------------------------------------------------------------------------------ proc func_I {} { global FLAG stack istack if {!$FLAG(8)} {func_sf 8} set istack(y) $stack(x) drop } # ------------------------------------------------------------------------------ proc func_pi {} { global stack istack PI lift set stack(x) $PI set istack(x) 0.0 } # ------------------------------------------------------------------------------ proc func_sf { flag } { global HP15 FLAG storage if {$flag == "I"} {set flag [expr int($storage(I))]} if {$flag == 8 && $HP15(prgmregsfree) < 5} { error "" "" {DIM} } if {$flag >= 0 && $flag <= 9} { set FLAG($flag) 1 set_status NIL show_x } else { error "" "" {FLAG} } } # ------------------------------------------------------------------------------ proc func_cf { flag } { global FLAG istack storage if {$flag == "I"} {set flag [expr int($storage(I))]} if {$flag >= 0 && $flag <= 9} { if {$flag == 8} {foreach ii {LSTx x y z t u s} {set istack($ii) 0.0 }} set FLAG($flag) 0 set_status NIL show_x } else { error "" "" {FLAG} } } # ------------------------------------------------------------------------------ proc show_flags { trigger } { global LAYOUT status FLAG if {[winfo exists .flags]} {destroy .flags} menu .flags -tearoff 0 -title "Flags" -font $LAYOUT(FnMenu) if {$status(PRGM)} { set st normal } else { set st disabled } for {set ii 0} {$ii <= 9} {incr ii} { .flags add command -label "$ii: $FLAG($ii)" -state $st \ -command "dispatch_key 43_6_$ii" } if {$trigger == 3} { tk_popup .flags [winfo pointerx .] [winfo pointery .] } else { tk_popup .flags [winfo rootx .btn_29.gbtn] \ [expr [winfo rooty .btn_29.gbtn]+[winfo height .btn_29.gbtn]] } } # ------------------------------------------------------------------------------ proc func_Finq { flag } { global prgstat storage FLAG if {$prgstat(running)} { if {$flag == "I"} {set flag [expr int($storage(I))]} if {$flag >= 0 && $flag <= 9} { if {$FLAG($flag) == 0} {incr prgstat(curline) 2} } else { error "" "" {FLAG} } } } # ------------------------------------------------------------------------------ proc func_clearsumregs {} { global HP15 stack istack storage if {$HP15(dataregs) < 7} { error "" "" {INDEX} } else { for {set ii 2} {$ii < 7} {incr ii} { set storage($ii) 0.0 } } foreach ii {x y z t} { set stack($ii) 0.0 set istack($ii) 0.0 } } # ------------------------------------------------------------------------------ proc disp_scroll { inc } { global status if {$status(PRGM)} { if {$inc >= 0.0} { dispatch_key 21 } else { dispatch_key 43_21 } } else { func_roll [expr $inc >= 0 ? 3 : 1] } } # ------------------------------------------------------------------------------ proc func_roll { cnt } { global status set status(num) 1 for {set ii 0} {$ii < $cnt} {incr ii} { foreach jj {stack istack} { upvar #0 $jj st set tmp $st(y) set st(y) $st(z) set st(z) $st(t) set st(t) $st(x) set st(x) $tmp } } show_x } # ------------------------------------------------------------------------------ proc func_chs {} { global status stack if {$status(num)} { set stack(x) [expr -$stack(x)] } else { if {[string first "e" $stack(x)] > 0} { set stack(x) [string map {e+ e- e- e+} $stack(x)] } else { if {[string index $stack(x) 0] == "-"} { set stack(x) [string range "$stack(x)" 1 end] } else { set stack(x) "-$stack(x)" } } } } # ------------------------------------------------------------------------------ proc func_abs {} { global FLAG stack istack if {$FLAG(8)} { move x u set stack(x) [cabs] set istack(x) 0.0 } else { set stack(x) [expr abs($stack(x))] } } # ------------------------------------------------------------------------------ proc func_xexchg { param } { global stack storage set param [GETREG $param] set tmp $storage($param) set storage($param) $stack(x) set stack(x) $tmp } # ------------------------------------------------------------------------------ proc func_dse { param } { global storage prgstat PRGM set param [GETREG $param] set nn [expr int($storage($param))] set yy [expr abs(($storage($param) - $nn)*1E3)] set xx [expr int($yy)] set yy [expr int(100.0 * ($yy - $xx))] set nn [expr $nn-[expr $yy == 0.0 ? 1 : $yy]] if {$nn <= $xx} { if {$prgstat(curline) < [llength $PRGM]} {incr prgstat(curline) 2} } set storage($param) "$nn.[format "%03d" $xx][format "%02d" $yy]" } # ------------------------------------------------------------------------------ proc func_isg { param } { global storage prgstat PRGM set param [GETREG $param] set nn [expr int($storage($param))] set yy [expr abs(($storage($param) - $nn)*1E3)] set xx [expr int($yy)] set yy [expr int(100.0 * ($yy - $xx))] if {$yy == 0.0} {set yy 1} set nn [expr $nn+[expr $yy == 0.0 ? 1 : $yy]] if {$nn > $xx} { if {$prgstat(curline) < [llength $PRGM]} {incr prgstat(curline) 2} } set storage($param) "$nn.[format "%03d" $xx][format "%02d" $yy]" } # ------------------------------------------------------------------------------ proc regula_falsi { lbl x0 x1 } { global stack prgstat set ebs 1E-14 set iter 0 while {1} { populate $x1 func_gsb $lbl set f_x1 $stack(x) populate $x0 func_gsb $lbl set f_x0 $stack(x) set x2 [expr $x0 - $f_x0 * (($x0 - $x1)/($f_x0 - $f_x1))] populate $x2 func_gsb $lbl set f_x2 $stack(x) if {$f_x0 == $f_x2 || [incr iter] > $prgstat(maxiter)} { error "" "" {SOLVE} } set x0 $x1 set x1 $x2 if {[expr abs($x0 - $x1)] <= $ebs} {break} } set stack(z) $f_x2 set stack(y) $x1 set stack(x) $x2 } # ------------------------------------------------------------------------------ proc func_solve { lbl } { global HP15 status stack if {$status(solve)} {error "" "" {RECURSION}} set status(solve) 1 set ll [lookup_label $lbl] if {$HP15(prgmregsfree) < 5} { error "" "" {DIM} } elseif {$ll == -1} { error "" "" {ADDRESS} } else { if {$stack(x) < $stack(y)} {func_xy} regula_falsi $lbl $stack(y) $stack(x) } set status(solve) 0 } # ------------------------------------------------------------------------------ proc simpson { lbl lb ub steps } { global stack set st [expr ($ub-$lb)/($steps*1.0)] set res 0.0 for {set ii 0} {$ii < $steps} {incr ii 2} { populate [expr $lb+$ii*$st] func_gsb $lbl set res [expr $res+$stack(x)] populate [expr $lb+($ii+1)*$st] func_gsb $lbl set res [expr $res+4.0*$stack(x)] populate [expr $lb+($ii+2)*$st] func_gsb $lbl set res [expr $res+$stack(x)] } return [expr $res*$st/3.0] } # ------------------------------------------------------------------------------ proc func_integrate { lbl } { global HP15 status stack if {$status(integrate)} {error "" "" {RECURSION}} set status(integrate) 1 set ll [lookup_label $lbl] if {$HP15(prgmregsfree) < 23} { error "" "" {DIM} } elseif {$ll == -1} { error "" "" {ADDRESS} } else { set lb $stack(y) set ub $stack(x) set steps 32 set res1 0.0 set res2 0.0 set delta 0.0 while {1} { if {[catch {set res [simpson $lbl $lb $ub $steps]} einf]} { error "" "" {INTERRUPT} return } if {$status(dispmode) == "FIX"} { set log 0 } else { set log [expr $res != 0 ? int(floor(log10(abs($res)))) : 0] } set prec [expr 0.5 * pow(10, -$status(dispprec)+$log)] set delta [expr $delta + (($ub - $lb) / $steps * $prec)] if {[expr abs($res1-$res)] < $delta || [expr abs($res2-$res)] < $delta} { break } else { set res1 $res2 set res2 $res } set steps [expr 2*$steps] } set stack(t) $lb set stack(z) $ub set status(integrate) 0 set status(num) 1 set stack(y) $delta set stack(x) $res } } # ------------------------------------------------------------------------------ proc func_clearprgm {} { global HP15 status prgstat PRGM set prgstat(curline) 0 set prgstat(interrupt) 0 if {$status(PRGM)} { set HP15(prgmname) "" set prgstat(running) 0 set prgstat(rtnadr) {0} set PRGM {{}} show_curline mem_recalc } else { show_x } } # ------------------------------------------------------------------------------ proc func_clearreg {} { global HP15 storage for {set ii 0} {$ii <= $HP15(dataregs)} {incr ii} { set storage($ii) 0.0 } set storage(I) 0.0 } # ------------------------------------------------------------------------------ proc func_rnd {} { global status stack set stack(x) [format "%.$status(dispprec)f" $stack(x)] } # ------------------------------------------------------------------------------ proc func_xy {} { global status foreach ii {stack istack} { upvar #0 $ii st set tmp $st(y) set st(y) $st(x) set st(x) $tmp } } # ------------------------------------------------------------------------------ proc func_prefix { {ev 0} } { global HP15 status stack curdisp if {!$status(PRGM)} { if {$ev == 0 || $ev == 2 || $ev == 4} { announce func_prefix: ev=$ev set curdisp " [string map {. ""} [format "%.10e" [expr abs($stack(x))]]]" if {$ev == 0} {after $HP15(pause) {show_x}} } else { after $HP15(pause) {show_x} } } } # ------------------------------------------------------------------------------ proc func_bs {} { global status stack FLAG prgstat PRGM if {$status(PRGM)} { if {$prgstat(curline) > 0} { set PRGM [lreplace $PRGM $prgstat(curline) $prgstat(curline)] incr prgstat(curline) -1 mem_recalc show_curline } } else { if {$FLAG(9)} { set FLAG(9) 0 } elseif {$status(num)} { set stack(x) 0.0 set status(liftlock) 2 } else { regsub {e[+-]0?$} $stack(x) "e" temp regsub {^-[0-9]$} $temp "" temp if {[string length $temp] > 1} { # Remove period added to 10-digit integers in 'func_digit' if {[count_digits $temp] == 10 && [string index $temp end] == "."} { set temp "[string range $temp 0 end-1]" } set stack(x) "[string range $temp 0 end-1]" } else { set status(liftlock) 2 set status(num) 1 set stack(x) 0.0 } } } } # ------------------------------------------------------------------------------ proc func_clx {} { global status stack set stack(x) 0.0 set status(liftlock) 3 } # ------------------------------------------------------------------------------ proc clearall {} { populate 0.0 func_clearreg func_clx func_digit 0 dispatch_key 20 move x u move x m } # ------------------------------------------------------------------------------ proc func_frac {} { global stack set stack(x) [expr ($stack(x) - int($stack(x)))*1.0] } # ------------------------------------------------------------------------------ proc GETREG { param } { global HP15 storage if {$param == "(i)"} {set param [expr int($storage(I))]} if {($param < 0 || $param > $HP15(dataregs)) && $param != "I"} { error "" "" {INDEX} return } return $param } # ------------------------------------------------------------------------------ proc func_sto { param } { global stack storage set storage([GETREG $param ]) [expr $stack(x)*1.0] show_x } # ------------------------------------------------------------------------------ proc func_sto_oper { fn param } { global stack storage set param [GETREG $param ] set storage($param) [expr $storage($param) $fn $stack(x)*1.0] show_x } # ------------------------------------------------------------------------------ proc func_int {} { global stack set stack(x) [expr 1.0*int($stack(x))] } # ------------------------------------------------------------------------------ proc toggle_user { mode } { if {$mode} { for {set ii 1} {$ii < 5} {incr ii} { bind .btn_1$ii.fbtn "<Button-1>" "dispatch_key 1$ii" bind .btn_1$ii.btn "<Button-1>" "key_event 1$ii 42_1$ii" } } else { for {set ii 1} {$ii < 5} {incr ii} { bind .btn_1$ii.fbtn "<Button-1>" "dispatch_key 42_1$ii" bind .btn_1$ii.btn "<Button-1>" "key_event 1$ii 1$ii" } } } # ------------------------------------------------------------------------------ proc func_rcl { param } { global stack istack storage lift set stack(x) $storage([GETREG $param]) set istack(x) 0.0 } # ------------------------------------------------------------------------------ proc func_rcl_oper { fn param } { global stack istack storage set stack(x) [expr $stack(x)*1.0 $fn $storage([GETREG $param])] set istack(x) 0.0 } # ------------------------------------------------------------------------------ proc func_rclsum {} { global HP15 status stack istack storage if {$HP15(dataregs) < 7} { error "" "" {INDEX} } else { lift if {!$status(liftlock)} {lift} set stack(y) $storage(5) set istack(y) 0.0 set stack(x) $storage(3) set istack(x) 0.0 } } # ------------------------------------------------------------------------------ proc mem_recalc {} { global HP15 PRGM set HP15(prgmregsused) [expr int(ceil(([llength $PRGM]-1)/7.0))] set HP15(freebytes) [expr int(($HP15(prgmregsused)*7)-[llength $PRGM]+1)] set HP15(prgmregsfree) \ [expr $HP15(totregs)-$HP15(dataregs)-$HP15(prgmregsused)] } # ------------------------------------------------------------------------------ proc func_mem { {ev 0} } { global HP15 curdisp if {$ev == 0 || $ev == 2 || $ev == 4} { mem_recalc set curdisp [format " %2d %2d %2d-%d" \ $HP15(dataregs) $HP15(prgmregsfree) $HP15(prgmregsused) $HP15(freebytes)] } if {$ev == 0 || $ev == 3 || $ev == 5} { after $HP15(pause) { if {$status(PRGM)} { show_curline } else { show_x } } } } # ------------------------------------------------------------------------------ proc func_random {} { global stack istack lift set stack(x) [expr rand()] set istack(x) 0.0 } # ------------------------------------------------------------------------------ proc func_storandom {} { global status stack set ax [expr abs($stack(x))] set log [expr $ax > 1.0 ? int(log10($ax))+1 : 0] set status(seed) [expr $ax / pow(10.0, $log)] expr srand(int($ax)) show_x } # ------------------------------------------------------------------------------ proc func_rclrandom {} { global status stack set stack(x) $status(seed) set istack(x) 0.0 } # ------------------------------------------------------------------------------ proc func_polar {} { global PI status FLAG stack istack if {$FLAG(8)} { move x u set stack(x) [cabs] set istack(x) [expr [cphi]/$status(RADfactor)] } else { set stack(x) [expr sqrt(1.0*$stack(x)*$stack(x) + 1.0*$stack(y)*$stack(y))] set stack(y) [expr (180.0/$PI)*asin($stack(y)/$stack(x))] } } # ------------------------------------------------------------------------------ proc faculty { var } { set res 1.0 set var [expr int($var)] for {set ii $var} {$ii > 1} {incr ii -1} { set res [expr $res * $ii] } return $res } # ------------------------------------------------------------------------------ proc gamma { var } { global PI set var [expr $var+1.0] if {$var >= 0.0} { set step 0.01 set res 0.0 for {set ii -20.0} {$ii <= 20.0 + $var} {set ii [expr $ii + $step]} { set old $res set res [expr $res + (exp($var*$ii)*exp(-exp($ii))*$step)] if {$old == $res} {break} } set ret $res } else { if {[expr abs($var - int($var))] > 0} { set var [expr abs($var)] set ret [gamma [expr $var-1.0]] set ret [expr -$PI/($var*$ret*sin($PI*$var))] } else { error "" "" {ARITH OVERFLOW} } } return $ret } # ------------------------------------------------------------------------------ proc func_faculty {} { global stack if {$stack(x) < 0.0 || [expr abs($stack(x) - int($stack(x)))] > 0} { set stack(x) [gamma $stack(x)] } else { set stack(x) [faculty $stack(x)] } } # ------------------------------------------------------------------------------ proc func_avg {} { global HP15 status stack storage if {$HP15(dataregs) < 7} { error "" "" {INDEX} } elseif {abs($storage(2)) > 0.0} { lift if {!$status(liftlock)} {lift} set stack(y) [expr $storage(5)/$storage(2)] set istack(y) 0.0 set stack(x) [expr $storage(3)/$storage(2)] set istack(x) 0.0 } else { error "" "" {SUM} } } # ------------------------------------------------------------------------------ proc func_linexpolation {} { global HP15 status stack storage if {$HP15(dataregs) < 7} { error "" "" {INDEX} } elseif {abs($storage(2)) >= 1} { lift if {!$status(liftlock)} {lift} set M [expr $storage(2)*$storage(4)-$storage(3)*$storage(3)] set N [expr $storage(2)*$storage(6)-$storage(5)*$storage(5)] set P [expr $storage(2)*$storage(7)-$storage(3)*$storage(5)] set stack(x) [expr ($M*$storage(5) + \ $P*($storage(2)*$stack(x) - $storage(3)) ) / ($storage(2)*$M)] set istack(x) set stack(y) [expr $P/sqrt($M*$N)] set istack(y) } else { error "" "" {SUM} } } # ------------------------------------------------------------------------------ proc func_linreg {} { global HP15 status stack storage if {$HP15(dataregs) < 7} { error "" "" {INDEX} } elseif {abs($storage(2)) >= 1} { lift if {!$status(liftlock)} {lift} set M [expr $storage(2)*$storage(4)-$storage(3)*$storage(3)] set N [expr $storage(2)*$storage(6)-$storage(5)*$storage(5)] set P [expr $storage(2)*$storage(7)-$storage(3)*$storage(5)] set stack(y) [expr $P/$M] set istack(y) 0.0 set stack(x) [expr ($M*$storage(5) - $P*$storage(3))/($storage(2)*$M)] set istack(x) 0.0 } else { error "" "" {SUM} } } # ------------------------------------------------------------------------------ proc func_stddev {} { global HP15 status stack storage if {$HP15(dataregs) < 7} { error "" "" {INDEX} } elseif {abs($storage(2)) > 0.0} { lift if {!$status(liftlock)} {lift} set DIVISOR [expr $storage(2)*($storage(2)-1.0)] set stack(y) \ [expr sqrt(($storage(2)*$storage(6)-$storage(5)*$storage(5))/$DIVISOR)] set istack(y) 0.0 set stack(x) \ [expr sqrt(($storage(2)*$storage(4)-$storage(3)*$storage(3))/$DIVISOR)] set istack(x) 0.0 } else { error "" "" {SUM} } } # ------------------------------------------------------------------------------ proc func_sum_plus {} { global HP15 status stack storage if {$HP15(dataregs) < 7} { error "" "" {INDEX} } else { set storage(2) [expr $storage(2) + 1] set storage(3) [expr $storage(3) + $stack(x)] set storage(4) [expr $storage(4) + $stack(x)*$stack(x)] set storage(5) [expr $storage(5) + $stack(y)] set storage(6) [expr $storage(6) + $stack(y)*$stack(y)] set storage(7) [expr $storage(7) + $stack(x)*$stack(y)] set stack(x) $storage(2) set status(liftlock) 2 } } # ------------------------------------------------------------------------------ proc func_sum_minus {} { global HP15 status stack storage if {$HP15(dataregs) < 7} { error "" "" {INDEX} } else { set storage(2) [expr $storage(2) - 1] set storage(3) [expr $storage(3) - $stack(x)] set storage(4) [expr $storage(4) - $stack(x)*$stack(x)] set storage(5) [expr $storage(5) - $stack(y)] set storage(6) [expr $storage(6) - $stack(y)*$stack(y)] set storage(7) [expr $storage(7) - $stack(x)*$stack(y)] set stack(x) $storage(2) set status(liftlock) 2 } } # ------------------------------------------------------------------------------ proc func_Pyx {} { global stack if {[expr $stack(x) - int($stack(x))] > 0 || $stack(x) < 0 || \ [expr $stack(y) - int($stack(y))] > 0 || $stack(y) < 0 || \ [expr $stack(x) > $stack(y)]} { error "" "" {ARITH INVALID} } else { set stack(y) [expr [faculty $stack(y)]/ \ [faculty [expr int($stack(y)-$stack(x))]]] drop } } # ------------------------------------------------------------------------------ proc func_Cyx {} { global stack if {[expr $stack(x) - int($stack(x))] > 0 || $stack(x) < 0 || \ [expr $stack(y) - int($stack(y))] > 0 || $stack(y) < 0 || \ [expr $stack(x) > $stack(y)]} { error "" "" {ARITH INVALID} } else { set stack(y) [expr [faculty $stack(y)]/ \ ([faculty $stack(x)]*[faculty [expr int($stack(y)-$stack(x))]])] drop } } # ------------------------------------------------------------------------------ proc func_enter {} { global status FLAG stack istack if {[string first "." "$stack(x)"] == -1 && \ [string first "e" "$stack(x)"] == -1} { append stack(x) "." } if {$FLAG(8) && [string first "." "$stack(x)"] == -1 && \ [string first "e" "$stack(x)"] == -1} { append istack(x) "." } lift set status(liftlock) 2 show_x } # ------------------------------------------------------------------------------ proc func_lastx {} { global status FLAG stack istack lift set stack(x) $stack(LSTx) if {$FLAG(8)} {set istack(x) $istack(LSTx)} } # ------------------------------------------------------------------------------ proc func_rectangular {} { global status FLAG stack istack if {$FLAG(8)} { set stack(x) [expr cos($istack(x)*$status(RADfactor))*$stack(x)] set istack(x) [expr sin($istack(x)*$status(RADfactor))*$stack(s)] } else { set stack(x) [expr cos($stack(y)*$status(RADfactor))*$stack(x)] set stack(y) [expr sin($stack(y)*$status(RADfactor))*$stack(s)] } } # ------------------------------------------------------------------------------ proc func_hms {} { global stack set hours [expr int($stack(x))] set m [expr ($stack(x) - $hours)*60.0] set minutes [expr int([string range $m 0 [string last "." $m]])/100.0] set seconds [expr ($stack(x) - $hours - $minutes*60.0/36.0)*0.36] set stack(x) [expr $hours + $minutes + $seconds] } # ------------------------------------------------------------------------------ proc func_h {} { global stack set hours [expr int($stack(x))] set m [expr ($stack(x) - $hours)*100.0] set minutes [expr int([string range $m 0 [string last "." $m]])] set seconds [expr ($stack(x) - $hours - $minutes/100.0)*10000.0] set stack(x) [expr $hours + ($minutes*60+$seconds)/3600.0] } # ------------------------------------------------------------------------------ proc func_rad {} { global stack PI set stack(x) [expr $stack(x)*$PI/180.0] } # ------------------------------------------------------------------------------ proc func_deg {} { global stack PI set stack(x) [expr $stack(x)*180.0/$PI] } # ------------------------------------------------------------------------------ proc func_re_im {} { global FLAG stack istack if {!$FLAG(8)} {func_sf 8} set tmp $stack(x) set stack(x) $istack(x) set istack(x) $tmp } # ------------------------------------------------------------------------------ proc show_test_options { trigger } { global LAYOUT status TEST if {$status(PRGM)} { if {[winfo exists .testops]} {destroy .testops} menu .testops -tearoff 0 -title "Test" -font $LAYOUT(FnMenu) for {set ii 0} {$ii <= 9} {incr ii} { .testops add command -label "$ii: [lindex $TEST $ii]" \ -command "dispatch_key 43_30_$ii" -underline 0 } if {$trigger == 3} { tk_popup .testops [winfo pointerx .] [winfo pointery .] } else { tk_popup .testops [winfo rootx .btn_310.gbtn] \ [expr [winfo rooty .btn_310.gbtn]+[winfo height .btn_310.gbtn]] } } } # ------------------------------------------------------------------------------ proc func_test { op } { global status FLAG stack istack prgstat PRGM if {$prgstat(running)} { switch $op { 0 {if {$FLAG(8)} { set rc [expr $stack(x) != 0.0 || $istack(x) != 0.0] } else { set rc [expr $stack(x) != 0.0] } } 1 {set rc [expr $stack(x) > 0.0]} 2 {set rc [expr $stack(x) < 0.0]} 3 {set rc [expr $stack(x) >= 0.0]} 4 {set rc [expr $stack(x) <= 0.0]} 5 {if {$FLAG(8)} { set rc [expr $stack(x) == $stack(y) && $istack(x) == $istack(y) ] } else { set rc [expr $stack(x) == $stack(y)] } } 6 {if {$FLAG(8)} { set rc [expr $stack(x) != $stack(y) || $istack(x) != $istack(y) ] } else { set rc [expr $stack(x) != $stack(y)] } } 7 {set rc [expr $stack(x) > $stack(y)]} 8 {set rc [expr $stack(x) < $stack(y)]} 9 {set rc [expr $stack(x) >= $stack(y)]} 10 {set rc [expr $stack(x) <= $stack(y)]} 11 {if {$FLAG(8)} { set rc [expr $stack(x) == 0.0 && $istack(x) == 0.0] } else { set rc [expr $stack(x) == 0.0] } } } if {!$rc} { if {$prgstat(curline) < [llength $PRGM]} {incr prgstat(curline) 2} } } else { show_x } } # ------------------------------------------------------------------------------ proc func_plus {} { global FLAG stack istack set stack(y) [expr $stack(y) + (1.0 * $stack(x))] if {$FLAG(8)} {set istack(y) [expr $istack(y) + (1.0 * $istack(x))]} drop } # ------------------------------------------------------------------------------ proc func_minus {} { global FLAG stack istack set stack(y) [expr $stack(y) - $stack(x)] if {$FLAG(8)} {set istack(y) [expr $istack(y) - (1.0 * $istack(x))]} drop } # ------------------------------------------------------------------------------ proc func_mult {} { global FLAG stack istack if {$FLAG(8)} { set tmp $stack(y) set stack(y) [expr $stack(x)*$stack(y) - $istack(x)*$istack(y)] set istack(y) [expr $stack(x)*$istack(y) + $istack(x)*$tmp] } else { set stack(y) [expr 1.0 * $stack(x) * $stack(y)] } drop } # ------------------------------------------------------------------------------ proc func_div {} { global FLAG stack istack if {$FLAG(8)} { set tmp $stack(y) set divi [expr $stack(x)*$stack(x) + $istack(x)*$istack(x)] set stack(y) [expr ($stack(x)*$stack(y) + $istack(x)*$istack(y))/$divi] set istack(y) [expr ($stack(x)*$istack(y) - $tmp*$istack(x))/$divi] } else { set stack(y) [expr $stack(y) / (1.0 * $stack(x))] } drop } # ------------------------------------------------------------------------------ proc lookup_keyname { mod code } { global status HP15_KEYS TEST set kname $code switch $mod { "f DIM" - "STO +" - "STO -" - "STO \u00D7" - "STO \u00F7" - "STO" - "RCL +" - "RCL -" - "RCL \u00D7" - "RCL \u00F7" - "RCL" { set ind [expr [lsearch {24 25} $code] == -1 ? 5 : 4] } "GTO" - "GSB" - "f LBL" { set ind [expr [lsearch {11 12 13 14 15 25} $code] == -1 ? 5 : 4] } "f DSE" - "f ISG" - "f FIX" { set ind [expr (($code == 25) | ($code == 24)) ? 4 : 5] } "f" { set ind 4 } "g" { set ind 6 } "g TEST" { return [string map {" " ""} [lindex $TEST $code]] } "g SF" - "g CF" - "g F?" { set ind [expr $code == 25 ? 4 : 5] } default { set ind 5 } } foreach kk $HP15_KEYS { if {[lindex $kk 3] == $code} { set kname [lindex $kk $ind] break } } return $kname } # ------------------------------------------------------------------------------ proc build_mnemonic { step wid } { set rc {} while {[regexp {([0-9][0-9]?)_?(.*)} $step all key rest]} { set step $rest lappend rc [lookup_keyname [join $rc] $key] } return [format "%$wid\s" [string map {". " "."} [join $rc]]] } # ------------------------------------------------------------------------------ proc show_prgm { trigger } { global LAYOUT HP15 status prgstat PRGM if {[winfo exists .program]} {destroy .program} menu .program -tearoff 0 -title "Program" -font $LAYOUT(FnMenu) for {set ii 0} {$ii < [llength $PRGM]} {incr ii} { set cs [lindex $PRGM $ii] if {$HP15(mnemonics)} { set lbl "[format "%03d" $ii]-[build_mnemonic $cs 10]" } else { set lbl "[format_prgm $ii 9]" } if {$status(PRGM)} { set cmd "set prgstat(curline) $ii\nshow_curline" } else { set cmd "set prgstat(curline) $ii" } .program add command -label "$lbl" -command $cmd if {$HP15(prgmmenubreak) && $ii % $HP15(prgmmenubreak) == 0} { .program entryconfigure $ii -columnbreak 1 } if {$HP15(prgmcoloured)} { if {[string first "42_21" $cs] == 0} { .program entryconfigure $ii -foreground $LAYOUT(fbutton_bg) \ -background $LAYOUT(button_bg) } if {[string first "43_32" $cs] == 0} { .program entryconfigure $ii -foreground $LAYOUT(gbutton_bg) \ -background $LAYOUT(button_bg) } if {[string first "22_" $cs] == 0 || [string first "32_" $cs] == 0} { .program entryconfigure $ii -foreground white \ -background $LAYOUT(button_bg) } } } if {$trigger == 3} { tk_popup .program [winfo pointerx .] [winfo pointery .] } else { tk_popup .program [winfo rootx .status] \ [expr [winfo rooty .status] + [winfo height .status]] } } # ------------------------------------------------------------------------------ proc show_curline {} { global curdisp prgstat set curdisp " [format_prgm $prgstat(curline) 6]" } # ------------------------------------------------------------------------------ proc prgm_addstep { step } { global HP15 prgstat PRGM if {$HP15(prgmregsfree) + $HP15(freebytes) > 0} { set PRGM [linsert $PRGM [expr $prgstat(curline)+1] $step] incr prgstat(curline) show_curline mem_recalc } else { error_handler ADDRESS } } # ------------------------------------------------------------------------------ proc prgm_interrupt {} { global status prgstat set status(solve) 0 set status(integrate) 0 set prgstat(interrupt) 1 } # ------------------------------------------------------------------------------ proc prgm_step {} { global status prgstat PRGM set oldline $prgstat(curline) dispatch_key [lindex $PRGM $prgstat(curline)] if {$prgstat(curline) == 0} { set prgstat(running) 0 } elseif {$prgstat(curline) == [llength $PRGM]} { # Implicit return at end of program code if {$oldline == $prgstat(curline)} { dispatch_key 43_32 dispatch_key [lindex $PRGM $prgstat(curline)] } } else { if {$oldline == $prgstat(curline) && !$status(error)} { incr prgstat(curline) } } } # ------------------------------------------------------------------------------ proc prgm_run { start } { global HP15 stack curdisp status prgstat # disable stack tracing for smoother display updates and performance reasons trace remove variable stack(x) write show_x # any key or button event will interrupt a running program grab .logo focus .logo bind .logo <KeyPress> {prgm_interrupt} bind .logo <ButtonPress> {prgm_interrupt} set iter 0 set status(num) 1 set prgstat(running) 1 set prgstat(curline) $start while {$prgstat(running)} { if {$curdisp == ""} { set curdisp " running" } else { set curdisp "" } update after $HP15(delay) prgm_step if {[incr iter]> $prgstat(maxiter)} {set prgstat(running) 0} if {$prgstat(interrupt)} {set prgstat(running) 0} } # re-enable tracing on stack(x) and reset interrupt handling trace add variable stack(x) write show_x grab release .logo focus . set status(num) 1 if {$prgstat(interrupt)} { error "" "" {INTERRUPT} } elseif {!$status(error)} { show_x } } # ------------------------------------------------------------------------------ proc func_pse {} { global HP15 status if {!$status(PRGM)} { show_x update after $HP15(pause) } } # ------------------------------------------------------------------------------ proc func_rs {} { global prgstat if {$prgstat(running)} { set prgstat(running) 0 update } else { if {$prgstat(curline) == 0} {incr prgstat(curline)} prgm_run $prgstat(curline) } } # ------------------------------------------------------------------------------ proc func_pr {} { global status FLAG set_status PRGM if {$status(PRGM)} { set FLAG(9) 0 show_curline } else { set status(num) 1 show_x } } # ------------------------------------------------------------------------------ proc func_rtn {} { global prgstat set prgstat(curline) [lindex $prgstat(rtnadr) end] if {[llength $prgstat(rtnadr)] > 1} { set prgstat(rtnadr) [lreplace $prgstat(rtnadr) end end] } } # ------------------------------------------------------------------------------ proc func_on {} { global APPDATA set answer [tk_messageBox -type okcancel -icon question -default ok \ -title $APPDATA(titlewide) \ -message "Exit Tcl/Tk $APPDATA(title) Simulator?"] if {"$answer" == "ok"} {exit_handler} } # ------------------------------------------------------------------------------ proc lookup_keyseq { keyseq by_func } { global HP15_KEY_FUNCS set rc "" set ind [lsearch {0 42 43 44 45} [string range $keyseq 0 1]] if {$ind == -1} {set ind 0} set funclist [lindex $HP15_KEY_FUNCS $ind] if {$by_func == 1} { foreach ff $funclist { if {[regexp "^[lindex $ff 0]\$" $keyseq]} { set rc $ff break } } } else { foreach ff $funclist { if {[string match "$keyseq\_*" $ff]} { set rc $ff break } } } return $rc } # ------------------------------------------------------------------------------ proc check_attributes { func num } { global status stack # Numbers with leading zeros are interpreted as octal number by the Tcl/Tk # interpreter. Must manipulate stack(x) value for most of the functions. if {!$status(num)} { if {$stack(x) != 0.0 && [lsearch {func_bs func_chs func_digit} $func] == -1} { regsub {^\-0+} $stack(x) {-} tmp regsub {^0+} $tmp {} stack(x) } } move x s if {$num} {set status(num) 1} } # ------------------------------------------------------------------------------ proc dispatch_key { kcode args } { global status FLAG isseq keyseq errorCode set fmatch "" set svar "" if {$status(error)} { set status(error) 0 if {$status(PRGM)} { show_curline } else { show_x } return } if {$keyseq != ""} { if {[string match {4[23]} $kcode] && [string match {4[23]} $keyseq]} { set keyseq $kcode } else { set_status fg_off set keyseq $keyseq\_$kcode # This will allow abbreviated key sequences regsub {_4[23]} $keyseq "" keyseq } } else { set keyseq $kcode } set fmatch [lookup_keyseq $keyseq 1] if {$fmatch != ""} { # Key sequence matches a function foreach {kseq func alstx anum aprgm} $fmatch { regexp $kseq$ $keyseq mvar svar if {$status(PRGM) && $aprgm} { prgm_addstep $keyseq } else { set keyseq "" check_attributes [lindex $func 0] $anum # This is where all func_tions are executed if {[catch { # Args are not passed through if we have a sequence. if {$isseq} { eval $func$svar } else { eval $func$svar $args } }]} {error_handler $errorCode} if {!$status(error) && $status(num) && $alstx} {move s LSTx} } } set keyseq "" if {$aprgm && $status(liftlock)} {incr status(liftlock) -1} } else { # If key sequence doesn´t match exactly check for longer one. set seq [lookup_keyseq $keyseq 0] # Sequence doesn´t match. Start new sequence with last key typed in. if {$seq == "" && $kcode != ""} { set keyseq "" set isseq 0 if {$status(f)} {set kcode 42_$kcode} if {$status(g)} {set kcode 43_$kcode} if {"$args" == ""} { dispatch_key $kcode } else { dispatch_key $kcode $args } } else { set isseq 1 } } } # ------------------------------------------------------------------------------ proc check_on_num {len name el op} { global $name ${name}_oldval if {[string compare $el {}]} { set old ${name}_oldval\($el) set name $name\($el) } else { set old ${name}_oldval } if {([string length [set $name]] > $len) || \ [regexp {^[0-9]*$} [set $name]] == 0} { set $name [set $old] } else { set $old [set $name] } } # ------------------------------------------------------------------------------ proc isInt { ii len } { # return [regexp {^[1234567890]*$} "$ii"] expr {[string is integer $ii] && [string length [string trim $ii]] <= $len} } # ------------------------------------------------------------------------------ proc browser_lookup {} { global APPDATA set bl {} foreach bw $APPDATA(browserlist) { set bwf [auto_execok $bw] if [string length $bwf] { lappend bl "$bw" "$bwf" } } return $bl } # ------------------------------------------------------------------------------ proc browser_select { wid browser } { global APPDATA set nbw [tk_getOpenFile -parent .prefs -initialdir "[file dirname $browser]" \ -title "$APPDATA(title): Select help file browser" \ -filetypes $APPDATA(exetypes)] if {[string length $nbw] > 0} { $wid configure -state normal $wid delete 0 end $wid insert 0 $nbw $wid xview end $wid configure -state disabled } } # ------------------------------------------------------------------------------ proc fontset_list {} { global APPDATA LAYOUT FONTSET set rc {} set fsn 0 set dpi [expr round([tk scaling]*72)] foreach fs $FONTSET { set cfs [lindex $fs 0] if {$::tcl_platform(platform) == [lindex $cfs 0] && \ $dpi >= [lindex $cfs 2] && $dpi <= [lindex $cfs 3]} { lappend rc [concat $fsn $cfs] } incr fsn } return $rc } # ------------------------------------------------------------------------------ proc fontset_apply { fsn } { global APPDATA HP15 LAYOUT FONTSET set found 0 set fntlst [fontset_list] foreach fs $fntlst { if {$fsn == [lindex $fs 0]} { set found 1 } } if {!$found} { tk_messageBox -type ok -icon error -default ok -title $APPDATA(titlewide) \ -message "Error in memory file: Invalid fontset - using default set. Check preferences for valid sets." set fsn [lindex [lindex $fntlst 1] 0] set HP15(fontset) $fsn } foreach {fs fnt} [lindex [lindex $FONTSET $fsn] 1] { set LAYOUT($fs) $fnt } } # ------------------------------------------------------------------------------ proc preferences_apply { andExit ww } { global APPDATA HP15 HP15tmp PREFTEXT set prefs_ok true foreach vv {prgmmenubreak pause delay} { if {[string length [string trim $HP15tmp($vv)]] == 0} { tk_messageBox -type ok -icon error -default ok -title $APPDATA(titlewide) \ -message "Invalid settings for '$PREFTEXT($vv)'." set prefs_ok false break } } if {$prefs_ok} { array set HP15 [array get HP15tmp] if {$andExit} {destroy $ww} } } # ------------------------------------------------------------------------------ proc preferences {} { global APPDATA HP15 HP15tmp PREFTEXT array set HP15tmp [array get HP15] if [winfo exists .prefs] { wm deiconify .prefs } else { toplevel .prefs frame .prefs.outer -relief flat # Calculator and OS settings set fpo .prefs.outer.hp15 labelframe $fpo -relief groove -borderwidth 2 -text $PREFTEXT(frm_os) checkbutton $fpo.clpbrdc -text $PREFTEXT(clpbrdc) \ -variable HP15tmp(clpbrdc) -indicatoron 1 checkbutton $fpo.mnemonics -text $PREFTEXT(mnemonics) \ -variable HP15tmp(mnemonics) -indicatoron 1 checkbutton $fpo.prgmcoloured -text $PREFTEXT(prgmcoloured) \ -variable HP15tmp(prgmcoloured) -indicatoron 1 frame $fpo.prgm label $fpo.prgm.label -text $PREFTEXT(prgmmenubreak) -anchor w spinbox $fpo.prgm.sb -width 2 -justify right -from 5 -to 45 -increment 1\ -textvariable HP15tmp(prgmmenubreak) -validate all -vcmd "isInt %P 2" checkbutton $fpo.breakstomenu -text $PREFTEXT(breakstomenu) \ -variable HP15tmp(breakstomenu) -indicatoron 1 checkbutton $fpo.prgmstounicode -text $PREFTEXT(prgmstounicode) \ -variable HP15tmp(prgmstounicode) -indicatoron 1 pack $fpo.prgm.label -side left pack $fpo.prgm.sb -side right -padx 5 pack $fpo.clpbrdc $fpo.mnemonics $fpo.prgmcoloured -anchor nw -padx 10 pack $fpo.prgm -side top -anchor nw -expand no -fill x -padx 10 pack $fpo.breakstomenu $fpo.prgmstounicode -side top -anchor nw -padx 10 # Behaviour set fpo .prefs.outer.behave labelframe $fpo -relief groove -borderwidth 2 -text $PREFTEXT(frm_simulator) checkbutton $fpo.behaviour -text $PREFTEXT(strictHP15) \ -variable HP15tmp(strictHP15) -indicatoron 1 -state disabled checkbutton $fpo.saveonexit -text $PREFTEXT(saveonexit) \ -variable HP15tmp(saveonexit) frame $fpo.pause label $fpo.pause.label -text $PREFTEXT(pause) \ -anchor w spinbox $fpo.pause.sb -width 4 -justify right -from 0 -to 2000 \ -increment 1 -textvariable HP15tmp(pause) -validate all -vcmd "isInt %P 4" frame $fpo.delay label $fpo.delay.label -text $PREFTEXT(delay) -anchor w spinbox $fpo.delay.sb -width 3 -justify right -from 0 -to 999 \ -increment 1 -textvariable HP15tmp(delay) -validate all -vcmd "isInt %P 3" pack $fpo.behaviour $fpo.saveonexit -side top -anchor w -padx 5 pack $fpo.pause.label -side left pack $fpo.pause.sb -side right -padx 5 pack $fpo.delay.label -side left pack $fpo.delay.sb -side right -padx 5 pack $fpo.pause $fpo.delay -expand yes -fill both -side top \ -anchor w -padx 5 -pady 2 # Font settings set fpo .prefs.outer.fontset labelframe $fpo -relief groove -borderwidth 2 -text $PREFTEXT(frm_fontset) label $fpo.info -anchor nw -justify left \ -text "Available font sets for $::tcl_platform(os) at \ [expr round([tk scaling]*72)] dpi:" frame $fpo.fs foreach fs [fontset_list] { set fsn [lindex $fs 0] radiobutton $fpo.fs.$fsn -text "[lindex $fs 2]" -value $fsn \ -variable HP15tmp(fontset) pack $fpo.fs.$fsn -side top -anchor w -padx 10 } label $fpo.hint -anchor nw -justify left -text $PREFTEXT(fonthint) pack $fpo.info $fpo.fs $fpo.hint -side top -anchor w -expand no -fill x \ -padx 10 # Browser settings set fpo .prefs.outer.browser labelframe $fpo -relief groove -borderwidth 2 -text $PREFTEXT(browser) frame $fpo.bw foreach {bw bwf} [browser_lookup] { radiobutton $fpo.bw.$bw -text "$bw" -value "$bwf" \ -variable HP15tmp(browser) pack $fpo.bw.$bw -side top -anchor w -padx 10 } button $fpo.sel -text "Browse\u2026" \ -anchor w -borderwidth 1 -highlightthickness 0 \ -command "browser_select {$fpo.entry} {$HP15tmp(browser)}" entry $fpo.entry -width 32 -justify left -textvariable HP15tmp(browser) pack $fpo.bw -side top -anchor w pack $fpo.sel -side left -padx 10 -anchor n pack $fpo.entry -side left -anchor n # Lay out dialogue set fpo .prefs.outer grid $fpo.hp15 -column 0 -row 0 -sticky nsew -padx 3 -pady 3 grid $fpo.behave -column 0 -row 1 -sticky nsew -padx 3 -pady 3 grid $fpo.fontset -column 1 -row 0 -sticky nsew -padx 3 -pady 3 grid $fpo.browser -column 1 -row 1 -sticky nsew -padx 3 -pady 3 pack .prefs.outer -side top set fbtn .prefs.btn frame $fbtn -relief flat button $fbtn.ok -text "OK" -width 6 -default active \ -command "preferences_apply true .prefs" button $fbtn.apply -text "Apply" -width 6 \ -command "preferences_apply false .prefs" button $fbtn.cancel -text "Cancel" -width 6 -command "destroy .prefs" pack $fbtn.cancel $fbtn.apply $fbtn.ok -side right -padx 5 -anchor e pack $fbtn -in .prefs -side top -expand no -fill x -pady 5 wm title .prefs "$APPDATA(title): Preferences" wm transient .prefs . wm resizable .prefs false false wm geometry .prefs +[expr [winfo x .]+10]+[expr [winfo y .]+10] bind .prefs <Return> "preferences_apply true .prefs" bind .prefs <Escape> "destroy .prefs" raise .prefs focus .prefs } } # ------------------------------------------------------------------------------ proc exit_handler {} { global HP15 status FLAG prgstat if {$HP15(saveonexit)} { if {$status(error)} {func_clx} mem_save } destroy . } # ------------------------------------------------------------------------------ proc about {} { global APPDATA LAYOUT if [winfo exists .about] {destroy .about} toplevel .about wm title .about "About: $APPDATA(title) Simulator" frame .about.frm1 -background $LAYOUT(display_outer_frame) -relief sunken \ -borderwidth 2 frame .about.frm2 -background $LAYOUT(display_inner_frame) -relief sunken \ -borderwidth 2 frame .about.frm3 -background $LAYOUT(display) -relief sunken \ -borderwidth 2 text .about.text -background $LAYOUT(display) -height 26 -width 65 \ -relief flat -font $LAYOUT(FnButton) -highlightthickness 0 frame .about.bfrm -background $LAYOUT(keypad_bg) -relief sunken -height 20 button .about.bfrm.off -text "OK" -default active -font $LAYOUT(FnButton) \ -background $LAYOUT(button_bg) -foreground white -command "destroy .about" \ -width $LAYOUT(BtnWidth) -borderwidth 2 \ .about.text insert 0.0 "\n$APPDATA(titlewide)\n\nA Simulator written in Tcl/Tk" \ Ttitle .about.text tag configure Ttitle -font $LAYOUT(FnButton) -justify center set text "\n\n$APPDATA(copyright)\n\nSerial No. $APPDATA(SerialNo)\n" .about.text insert end $text copyright .about.text tag configure copyright -font $LAYOUT(FnButton) -justify center .about.text insert end "\n[string repeat "_" 65]\n" seperator .about.text tag configure seperator -font $LAYOUT(FnButton) -justify center set text "\nThis program is free software; you can redistribute it and/or\ modify it under the terms of the GNU General Public License as published by \ the Free Software Foundation; either version 2 of the License, or any later\ version.\n\n\This program is distributed in the hope that it will be useful,\ but without any warranty; without even the implied warranty of merchantability \ or fitness for a particular purpose. See the GNU General Public License for \ more details." .about.text insert end $text warranty .about.text tag configure warranty -font $LAYOUT(FnButton) -justify left \ -wrap word .about.text insert end "\n[string repeat "_" 65]\n" seperator .about.text tag configure seperator -font $LAYOUT(FnButton) -justify center set text "\nThis program is not a Hewlett-Packard product.\n HP and the HP logo are trademarks of Hewlett-Packard." .about.text insert end $text warranty .about.text tag configure warranty -font $LAYOUT(FnButton) -justify left \ -wrap word .about.text configure -state disabled pack .about.text -in .about.frm3 -side top -expand no -fill x -padx 10 pack .about.frm3 -in .about.frm2 -side top -expand no -padx 14 -pady 0 pack .about.frm2 -in .about.frm1 -side left -expand yes pack .about.frm1 -in .about -side top -expand yes -fill x \ -ipadx 10 -ipady 10 pack .about.bfrm.off -in .about.bfrm -side right -expand no -fill none \ -padx 15 -pady 10 pack .about.bfrm -in .about -side top -expand no -fill x wm resizable .about false false wm geometry .about +[expr [winfo x .]+15]+[expr [winfo y .]+10] wm transient .about . bind .about <Return> "destroy .about" bind .about <Escape> "destroy .about" raise .about grab .about focus .about } # ------------------------------------------------------------------------------ proc key_event { kname code } { if {[.btn_$kname.btn cget -relief] == "raised"} { .btn_$kname.btn configure -relief sunken .btn_$kname.gbtn configure -relief flat after 100 " .btn_$kname.btn configure -relief raised .btn_$kname.gbtn configure -relief raised " dispatch_key $code } } # ------------------------------------------------------------------------------ proc key_press { kname code ev } { global isseq .btn_$kname.btn configure -relief sunken .btn_$kname.gbtn configure -relief flat dispatch_key $code $ev } # ------------------------------------------------------------------------------ proc key_release { kname code ev } { global isseq .btn_$kname.btn configure -relief raised .btn_$kname.gbtn configure -relief raised # Do not execute release event if key is part of a sequence. if {!$isseq} {dispatch_key $code $ev} } # ------------------------------------------------------------------------------ proc kp_key_press { state kcode } { # Dispatch key-pad key as digit key if NumLock is on. if {[expr $state & 16] == 16} { dispatch_key $kcode } } # ------------------------------------------------------------------------------ proc hp_key { kname utext mtext ltext kcode fbnd bnd gbnd} { global LAYOUT frame .btn_$kname -relief flat -background $LAYOUT(keypad_bg) # upper (gold) function label .btn_$kname.fbtn -text $utext -anchor center -font $LAYOUT(FnFGBtn) \ -foreground $LAYOUT(fbutton_bg) -background $LAYOUT(keypad_bg) \ -borderwidth 0 -highlightthickness 0 if {$utext != ""} { bind .btn_$kname.fbtn "<Button-1>" "key_event $kname 42_$kcode" } foreach kk $fbnd { bind . <$kk> "key_event $kname 42_$kcode" } # basic function label .btn_$kname.btn -relief raised -width $LAYOUT(BtnWidth) -text $mtext \ -anchor center -font $LAYOUT(FnButton) -foreground white \ -background $LAYOUT(button_bg) -borderwidth 2 -foreground white \ -highlightbackground $LAYOUT(button_bg) -highlightthickness 0 bind .btn_$kname.btn "<Button-1>" "key_event $kname $kcode" foreach kk $bnd { if {[string is digit $kk]} { bind . <Key-$kk> "key_event $kname $kcode" } else { bind . <$kk> "key_event $kname $kcode" } } # lower (blue) function label .btn_$kname.gbtn -text $ltext -anchor center -relief raised \ -font $LAYOUT(FnFGBtn) -foreground $LAYOUT(gbutton_bg) \ -background $LAYOUT(button_bg) \ -borderwidth 1 -highlightthickness 0 -width $LAYOUT(BtnWidth) if {$ltext != ""} { bind .btn_$kname.gbtn "<Button-1>" "key_event $kname 43_$kcode" } foreach kk $gbnd { bind . <$kk> "key_event $kname 43_$kcode" } pack .btn_$kname.fbtn -side top -expand no -fill x if {$ltext == ""} { pack .btn_$kname.btn -side top -expand no -fill both -padx 7 } else { pack .btn_$kname.btn -side top -expand no -fill both -padx 7 pack .btn_$kname.gbtn -side top -expand no -fill x -padx 7 } return .btn_$kname } # ------------------------------------------------------------------------------ proc gui_draw {} { global LAYOUT HP15_KEYS HP15 APPDATA digits fontset_apply $HP15(fontset) . configure -background $LAYOUT(keypad_bg) # Calculate positions for X register display set dwid [font measure $LAYOUT(FnDisplay) "8"] set swid [expr int($dwid * 0.5)] set ypos 8 set dspheight \ [expr round([font actual $LAYOUT(FnDisplay) -size]*$LAYOUT(FnScale)+$ypos)] frame .dframe1 -background $LAYOUT(display_outer_frame) -relief sunken \ -borderwidth 2 frame .dframe2pad -background $LAYOUT(display_outer_frame) -relief sunken \ -borderwidth 0 frame .dframe2 -background $LAYOUT(display_inner_frame) -relief sunken \ -borderwidth 2 frame .dframe3 -background $LAYOUT(display) -relief sunken -borderwidth 3 canvas .display -background $LAYOUT(display) -highlightthickness 0 \ -width [expr $dwid+($dwid+$swid)*$digits] -height $dspheight set id [.display create text 0 $ypos -font $LAYOUT(FnDisplay) -anchor nw] .display addtag d0 withtag $id for {set ii 1} {$ii < 11} {incr ii} { set jj [expr $ii-1] set id [.display create text [expr $dwid*$ii + $swid*$jj] $ypos \ -font $LAYOUT(FnDisplay) -anchor nw] .display addtag d$ii withtag $id set id [.display create text [expr $dwid*($ii+1) + $swid*$jj] $ypos \ -font $LAYOUT(FnDisplay) -anchor nw] .display addtag p$ii withtag $id } # Calculate positions for status display canvas .status -background $LAYOUT(display) -highlightthickness 0 \ -width [expr $dwid+($dwid+$swid)*$digits] \ -height [expr [font actual $LAYOUT(FnStatus) -size] * 1.5*$LAYOUT(FnScale)] set ypos 0 foreach {tname xpos} {user 1.4 f 2.25 g 3.0 begin 4.6 rad 6.4 dmy 7.2 \ complex 8.25 prgm 9.9} { set id [.status create text [expr $dwid + ($dwid + $swid)*$xpos] $ypos \ -font $LAYOUT(FnDisplay) -anchor ne] .status addtag s$tname withtag $id } .status itemconfigure all -font $LAYOUT(FnStatus) pack .display .status -in .dframe3 -side top -anchor center \ -expand no -padx 3 pack .dframe3 -in .dframe2 -side top -expand no -padx 14 pack .dframe2pad .dframe2 -in .dframe1 -side left -expand no -pady 11 set logoscale [expr $LAYOUT(FnScale)/1.35] set logosize [expr int(41*$LAYOUT(FnScale)/1.35)] canvas .logo -relief sunken -bd 0 -highlightthickness 0 -borderwidth 0 \ -background $LAYOUT(display_inner_frame) -width $logosize \ -height [expr $logosize+1] .logo create oval 9 3 28 23 -fill $LAYOUT(keypad_bg) \ -outline $LAYOUT(keypad_bg) .logo create rectangle 16 2 21 3 -fill $LAYOUT(keypad_bg) \ -outline $LAYOUT(keypad_bg) .logo create rectangle 16 22 21 22 -fill $LAYOUT(keypad_bg) \ -outline $LAYOUT(keypad_bg) .logo create text $APPDATA(Char1x) $APPDATA(Char1y)\ -anchor center -text $APPDATA(Char1) -font $LAYOUT(FnLogo1) \ -fill $LAYOUT(display_inner_frame) .logo create text $APPDATA(Char2x) $APPDATA(Char2y)\ -anchor center -text $APPDATA(Char2) -font $LAYOUT(FnLogo1) \ -fill $LAYOUT(display_inner_frame) .logo create rectangle 0 24 36 25 -fill black -outline $LAYOUT(keypad_bg) .logo create text 19 32 -anchor center -text 15C \ -font $LAYOUT(FnLogo2) -fill $LAYOUT(keypad_bg) .logo create rectangle 1 1 37 38 -outline $LAYOUT(keypad_bg) -width 3 .logo scale all 0 0 $logoscale $logoscale pack .logo -in .dframe1 -expand no -side right -padx 10 -pady 10 -anchor n pack .dframe1 -side top -expand yes -fill x frame .sep1 -background $LAYOUT(keypad_bg) -height 6p -relief raised \ -borderwidth 2 pack .sep1 -side top -expand no -fill both # Layout the keypad frame .fkey -background $LAYOUT(keypad_bg) -relief groove frame .fkplu -background $LAYOUT(keypad_frame) -relief flat -width 3 frame .fkpcu -background $LAYOUT(keypad_frame) -relief flat -height 3 frame .keys -background $LAYOUT(keypad_bg) -relief flat foreach kk $HP15_KEYS { grid [hp_key "[lindex $kk 0][lindex $kk 1]" [lindex $kk 4] [lindex $kk 5]\ [lindex $kk 6] [lindex $kk 3] [lindex $kk 7] [lindex $kk 8]\ [lindex $kk 9]]\ -in .keys -row [lindex $kk 0] -column [lindex $kk 1] \ -rowspan [lindex $kk 2] -stick ns } for {set ii 1} {$ii <= 10} {incr ii} { grid configure .btn_1$ii -padx $LAYOUT(BtnPadX) } for {set ii 1} {$ii <= 10} {incr ii} { grid configure .btn_2$ii -pady $LAYOUT(BtnPadY) if {$ii != 6} {grid configure .btn_4$ii -pady $LAYOUT(BtnPadY)} } # Re-configure keys that differ from standard layout # Depending on operating system, font and Tcl/Tk version the ENTER button is # sometimes slightly to high because of its vertical label. Use small font here. .btn_36.btn configure -font $LAYOUT(FnEnter) -wraplength 1 -height 5 .btn_41.btn configure -height 2 .btn_42.btn configure -background $LAYOUT(fbutton_bg) -foreground black \ -height 2 .btn_42.gbtn configure -background $LAYOUT(fbutton_bg) -foreground black .btn_43.btn configure -background $LAYOUT(gbutton_bg) -foreground black \ -height 2 .btn_43.gbtn configure -background $LAYOUT(gbutton_bg) -foreground black frame .fkpcll -background $LAYOUT(keypad_frame) -relief flat \ -width 7 -height 6 label .fkpclc -background $LAYOUT(keypad_bg) -text $APPDATA(titleverywide) \ -font $LAYOUT(FnBrand) -foreground $LAYOUT(keypad_frame) frame .fkpclr -background $LAYOUT(keypad_frame) -relief flat update .fkpclr configure -width \ [expr [winfo reqwidth .keys] - [winfo reqwidth .fkpcll] - \ [winfo reqwidth .fkpclc]] frame .fkpru -background $LAYOUT(keypad_frame) -relief flat -width 3 # Gridding grid .fkplu -in .fkey -row 0 -column 0 -rowspan 4 -sticky ns grid .fkpcu -in .fkey -row 0 -column 1 -columnspan 3 -sticky nsew grid .keys -in .fkey -row 1 -column 1 -columnspan 3 grid .fkpcll -in .fkey -row 3 -column 1 -sticky nsw grid .fkpclc -in .fkey -row 2 -column 2 -rowspan 3 -sticky w -ipadx 1 grid .fkpclr -in .fkey -row 3 -column 3 -sticky nsew grid .fkpru -in .fkey -row 0 -column 4 -rowspan 4 -sticky ns pack .fkey -side top -expand yes -fill both -pady 2 -padx 2 # Align display according to font settings, especially scale factor .dframe2pad configure -width \ [expr round([winfo x .btn_11] + [winfo reqwidth .btn_11] + 12)] # Additional keyboard and mouse bindings not done in procedure 'hp_key'. # Distinguish between KeyPress and KeyRelease for some of the keys. bind . <KeyPress-Right> "key_press 21 21 %T" bind . <KeyRelease-Right> "key_release 21 21 %T" bind .btn_21.btn <ButtonPress-1> "key_press 21 21 %T" bind .btn_21.btn <ButtonRelease-1> "key_release 21 21 %T" bind . <KeyPress-Left> "key_press 21 43_21 %T" bind . <KeyRelease-Left> "key_release 21 43_21 %T" bind .btn_21.gbtn <ButtonPress-1> "key_press 21 43_21 %T" bind .btn_21.gbtn <ButtonRelease-1> "key_release 21 43_21 %T" # bind . <KeyPress-space> "key_press 35 42_35 %T" # bind . <KeyRelease-space> "key_release 35 42_35 %T" bind .btn_35.fbtn <ButtonPress-1> "key_press 35 42_35 %T" bind .btn_35.fbtn <ButtonRelease-1> "key_release 35 42_35 %T" bind . <KeyPress-i> "key_press 24 42_24 %T" bind . <KeyRelease-i> "key_release 24 42_24 %T" bind .btn_24.fbtn <ButtonPress-1> "key_press 24 42_24 %T" bind .btn_24.fbtn <ButtonRelease-1> "key_release 24 42_24 %T" bind .btn_45.gbtn <ButtonPress-1> "key_press 45 43_45 %T" bind .btn_45.gbtn <ButtonRelease-1> "key_release 45 43_45 %T" # We must handle NumLock state on our own under UNIX but not OSX if {$::tcl_platform(platform) == "unix"} { if {$::tcl_platform(os) == "darwin"} { foreach {kpk kcode} {Home 7 Up 8 Prior 9 Left 4 Begin 5 Right 6 \ End 1 Down 2 Next 3 Insert 0} { bind . <KeyPress-KP_$kpk> "kp_key_press %s $kcode" } bind . <KeyPress-KP_Delete> "kp_key_press %s 48" } } # Pop-up menu bindings bind .btn_41.btn <ButtonPress-3> "show_on_options %b" bind .dframe1 <ButtonPress-3> "show_on_options %b" bind . <Alt-o> "show_on_options %b" bind . <F10> "show_on_options %b" bind .btn_42.btn <ButtonPress-1> "set_status f \n key_event 42 42" bind .btn_42.gbtn <ButtonPress-1> "set_status f \n key_event 42 42" bind . <f> "key_event 42 42\n set_status f" bind .btn_43.btn <ButtonPress-1> "set_status g \n key_event 43 43" bind .btn_43.gbtn <ButtonPress-1> "set_status g \n key_event 43 43" bind . <g> "key_event 43 43 \n set_status g" bind .btn_44.btn <ButtonPress-3> "show_storage 44 %b" bind . <Alt-m> "show_storage 44 %b" bind .btn_45.btn <ButtonPress-3> "show_storage 45 %b" bind . <Alt-r> "show_storage 45 %b" bind .btn_29.gbtn <ButtonPress-3> "show_flags %b" bind . <Alt-f> "show_flags %b" bind .btn_310.gbtn <ButtonPress-3> "show_test_options %b" bind . <Alt-t> "show_test_options %b" bind .btn_22.btn <ButtonPress-3> "func_gto_chs %b" bind .display <ButtonPress-3> "show_content %b" bind .status <ButtonPress-3> "show_content %b" bind . <Alt-s> "show_content %b" # Miscellaneous HP-15C function bindings bind . <Alt-period> "exchange_seps" bind . <Alt-comma> "exchange_seps" for {set ii 0} {$ii < 10} {incr ii} { bind . <Alt-Key-$ii> "dispatch_key 32_$ii" } bind . <MouseWheel> "disp_scroll %D" bind . <F11> {set HP15(mnemonics) [expr !$HP15(mnemonics)]} bind . <Alt-F11> {set HP15(prgmcoloured) [expr !$HP15(prgmcoloured)]} # Operating system related bindings bind . <F1> {help simulator} bind . <Control-F1> {help prgm} bind . <Control-c> "clipboard_set x" bind . <Control-v> "clipboard_get" bind . <ButtonPress-2> "clipboard_get" bind . <Control-m> "mem_save" bind . <Control-l> "mem_load" bind . <Control-o> "prgm_open" bind . <Control-s> "prgm_save" } # ------------------------------------------------------------------------------ # Startup procedure # Clear everything and reload previous session clearall mem_load # Draw the GUI and define key bindings gui_draw trace add variable stack(x) write show_x trace add variable curdisp write disp_update trace add variable FLAG(9) write disp_flash # Update the display show_x set_status NIL # Check for browser configuration if ![string length $HP15(browser)] { set HP15(browser) [lindex [browser_lookup] 1] } # ------------------------------------------------------------------------------ # Window manager configuration & communication wm protocol . WM_DELETE_WINDOW {exit_handler} wm title . " $APPDATA(titleshort) " wm iconname . " $APPDATA(titleshort) " wm resizable . false false option add *Dialog.msg.font $LAYOUT(FnMenu) userDefault # ------------------------------------------------------------------------------ # And now show the interface in all it's beauty... wm deiconify .
New version 1.2.05 available from the MoHPC (see link above) - Torsten Above code now 1.2.05. I also made the "IQ" vs "HP" thing optional - Larry Smith
I am currently very happy to use 1.2.02 but wanted to upgrade since I found a bug: launch the calculator and hit space. You get some "Internal Tcl/Tk Error: can't set "curdisp": can't read "llcd(+)": no such element in array, while executing... etc ...
Larry SmithFixed in this version. I hope. The code was reacting to a space by trying to output more than 11 character spaces of the display. When using the font, there is a flicker and then something more reasonable is displayed, but the LCD engine blew up. To fix it I removed the space dispatch binding (commented out above). Hope it doesn't break anything else.
"Link above" meant the link at the very top (sorry). A more general link is [L1 ]. The error when hitting the space bar is specific to Larry's version.
Version 1.2.08 of the original simulator should be out in a week or so. Several bug fixes and support for Windows Vista. - Torsten Larry Smith Looking forward to it.
Replace the lines at approx 4430-4436 with this:
# We must handle NumLock state on our own under UNIX but not OSX
Larry Smith Corrected above.
I am having some problems running this on OSX 10.4.11. The logic works fine but the display is very odd with some (not all) unicode characters displaying as empty boxes. I upgraded to TclTKAqua-8.4.10 but this did not fix the problem. Any suggestions? Larry Smith I think this implies that there is no version of the desired glyph in any of Tcl's font search.
DaveUssell - 2012-08-20 14:42:52
Torsten Manz has done an excellent job on the HP-15 simulation but yesterday I noticed the arctangent of 1 is not 0.79 grads/0.79 radians and 0.79 degrees. It is 50 grads/0.79 radians and 45°. There may be other errors. Please let me know if this has been corrected in an updated version. Thanks. Dave Ussell dave(at)ussell.org
dcd Did you switch to the desired angle mode before you computed the answer? It's giving me the correct answers.
Torsten - 2012.09.03
Please be aware that Larry's work is based on a very old version of the simulator. With each update I update the wiki at HP-15 Simulation.
For support requests and bug reports an e-mail to the mail address on the simulator home page is the most efficient way to communicate with me.