[http://www.hpmuseum.org/simulate/15_1_205.zipLarry 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 vdelete stack(x) w 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 variable stack(x) w 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 variable stack(x) w show_x
trace variable curdisp w disp_update
trace variable FLAG(9) w 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 [1]. 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 OSXLarry 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:52Torsten 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.03Please 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.
