home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1993 #2
/
Image.iso
/
database
/
pk4pak.zip
/
POPCALC.SC
< prev
next >
Wrap
Text File
|
1993-03-15
|
57KB
|
1,532 lines
;==============================================================================
; (c) Copyright Elect Software International Inc., 1992, Toronto. Anyone can
; use this code for anything as long as it is not resold as a software
; development resource, as long as the copyright notice isn't removed, as
; long as changes are clearly marked as to authorship, and as long as users
; indemnify Elect from any liability.
; Comments welcome. Henrik Bechmann, CIS:72701,3717; Tel:416-534-8176.
; Mar-92, Apr-92, Jun-92, Jul-92
;==============================================================================
;==============================================================================
; ESI-PD40B CALCULATOR INTERFACE
;==============================================================================
; Calculator.Constructor() ; This configures the calculator in memory. Since
; ; the key variables are all created here, the
; ; calculator is re-entrant using
; ; Calculator.Dialog(). In other words, the user
; ; is able to hit [Esc] to temporarily leave
; ; the calculator (say to look something up) and then
; ; be able to re-enter it to find it in the same
; ; state as it was when [Esc] was hit.
; ; The constructor should be called at the beginning
; ; of a session, to save time in calling the
; ; calculator during the session.
; Calculator.Dialog() ; This calls the calculator. Returns blanknum() if
; ; the user exited by hitting [Esc], otherwise returns
; ; a number (N).
; Calculator.Destructor() ; Destroys the calculator's global variables (ie.
; ; destroys the calculator) at the end of a session.
; Calculator.Value
; Calculator.IsActive
;==============================================================================
; CALCULATOR IMPLEMENTATION
;==============================================================================
;----------------------------------------------------------------------------
; Calculator.Constructor() Sets up variables and arrays for the calculator
; in memory. These variables are technically global, which makes the
; calculator re-entrant.
;----------------------------------------------------------------------------
Proc Calculator.Constructor()
Private
i,j,
Element
;-------------------------------------------------------------------------
; Provide message to user...
;-------------------------------------------------------------------------
Message "Initializing calculator..."
;-------------------------------------------------------------------------
; Initialize constants, and control variables...
; First, universal null...
;-------------------------------------------------------------------------
Calculator_NULL = 255
;-------------------------------------------------------------------------
; Keystroke types...
;-------------------------------------------------------------------------
Calculator_OPCHAR = 1
Calculator_FUNCCHAR = 2
Calculator_NUMCHAR = 3
Calculator_EDITCHAR = 4
;-------------------------------------------------------------------------
; Token types... (Only FLOATING and OPERATOR are currently used)
;-------------------------------------------------------------------------
; Calculator_TIME = 1
; Calculator_SECONDS = 2
; Calculator_MINUTES = 3
; Calculator_HOURS = 4
; Calculator_DAYS = 5
; Calculator_WEEKS = 6
; Calculator_MONTHS = 7
; Calculator_YEARS = 8
; Calculator_DATE = 9
Calculator_FLOATING = 10
; Calculator_INTEGER = 11
; Calculator_MONEY = 12
; Calculator_STRING = 13
Calculator_OPERATOR = 14
;-------------------------------------------------------------------------
; Input cell states...
;-------------------------------------------------------------------------
Calculator_WAITING = 0
Calculator_CALC = 1
;-------------------------------------------------------------------------
; Token type names... (not currently used.)
;-------------------------------------------------------------------------
; Dynarray Calculator_TokenTypeName[]
; Calculator_TokenTypeName[Calculator_TIME] = "Time"
; Calculator_TokenTypeName[Calculator_SECONDS] = "Seconds"
; Calculator_TokenTypeName[Calculator_MINUTES] = "Minutes"
; Calculator_TokenTypeName[Calculator_HOURS] = "Hours"
; Calculator_TokenTypeName[Calculator_DAYS] = "Days"
; Calculator_TokenTypeName[Calculator_WEEKS] = "Weeks"
; Calculator_TokenTypeName[Calculator_MONTHS] = "Months"
; Calculator_TokenTypeName[Calculator_YEARS] = "Years"
; Calculator_TokenTypeName[Calculator_DATE] = "Date"
; Calculator_TokenTypeName[Calculator_FLOATING] = "Floating"
; Calculator_TokenTypeName[Calculator_INTEGER] = "Integer"
; Calculator_TokenTypeName[Calculator_MONEY] = "Money"
; Calculator_TokenTypeName[Calculator_STRING] = "String"
; Calculator_TokenTypeName[Calculator_OPERATOR] = "Operator"
;-------------------------------------------------------------------------
; Keycode data...
;-------------------------------------------------------------------------
Calculator_Keycode = BlankNum()
Calculator_KeycodeAttribute = Calculator_NULL
;-------------------------------------------------------------------------
; Calculator input cell data...
; Set the Accept statement defualt variables here as well...
;-------------------------------------------------------------------------
Calculator_CellDataType = "N"
Calculator_DecimalFlag = False
Calculator!KeyPadModeLine() ; sets Calculator_KeyPadModeLine
Calculator_CellStatus = Calculator_WAITING
Calculator.Value = 0
Calculator_Value = 0 ; to transfer escaped value to .Value
Calculator_CellAttribute = Calculator_FLOATING ; data type
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
;-------------------------------------------------------------------------
; Expression status...
;-------------------------------------------------------------------------
Calculator_CurrentOperator = Calculator_NULL
Calculator_LastOperator = Calculator_NULL
;-------------------------------------------------------------------------
; Internal token data...
;-------------------------------------------------------------------------
Dynarray Calculator_StackValue[]
Dynarray Calculator_StackAttribute[] ; data type/operator
Calculator_StackPtr = 0
;-------------------------------------------------------------------------
; Classification of characters streaming in...
;-------------------------------------------------------------------------
Dynarray Calculator_KeyCodeType[] ; 32 total
Calculator_KeycodeType[Asc("Del")] = Calculator_EDITCHAR
Calculator_KeycodeType[Asc("Backspace")] = Calculator_EDITCHAR
Calculator_KeycodeType[Asc("CtrlBackspace")] = Calculator_EDITCHAR
Calculator_KeycodeType[Asc("Right")] = Calculator_EDITCHAR
Calculator_KeycodeType[Asc("Left")] = Calculator_EDITCHAR
Calculator_KeycodeType[Asc("Home")] = Calculator_EDITCHAR
Calculator_KeycodeType[Asc("End")] = Calculator_EDITCHAR
Calculator_KeycodeType[Asc("0")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("1")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("2")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("3")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("4")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("5")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("6")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("7")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("8")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("9")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc(".")] = Calculator_NUMCHAR
Calculator_KeycodeType[Asc("%")] = Calculator_FUNCCHAR
Calculator_KeycodeType[Asc(">")] = Calculator_FUNCCHAR
Calculator_KeycodeType[Asc("<")] = Calculator_FUNCCHAR
Calculator_KeycodeType[-16] = Calculator_FUNCCHAR ; Alt-Q, square root
Calculator_KeycodeType[-49] = Calculator_FUNCCHAR ; Alt-N, round
Calculator_KeycodeType[Asc("!")] = Calculator_FUNCCHAR
Calculator_KeycodeType[Asc("^")] = Calculator_OPCHAR
Calculator_KeycodeType[Asc("*")] = Calculator_OPCHAR
Calculator_KeycodeType[Asc("/")] = Calculator_OPCHAR
Calculator_KeycodeType[Asc("+")] = Calculator_OPCHAR
Calculator_KeycodeType[Asc("-")] = Calculator_OPCHAR
Calculator_KeycodeType[Asc("=")] = Calculator_OPCHAR
Calculator_KeycodeType[Asc("Enter")] = Calculator_OPCHAR
Calculator_KeycodeType[Asc("Do_It!")] = Calculator_OPCHAR
Calculator_KeycodeType[Asc("Esc")] = Calculator_OPCHAR
;-------------------------------------------------------------------------
; Set up a key event list for all keycode types. This will be used when
; Calculator_CellStatus = Calculator_WAITING
;-------------------------------------------------------------------------
Array Calculator_CharEventKey[33]
i = 0
ForEach Element In Calculator_KeyCodeType
i = i + 1
Calculator_CharEventKey[i] = Numval(Element)
Endforeach
; j = i
; For i From j + 1 to 31
; Calculator_CharEventKey[i] = Calculator_NULL
; EndFor
;-------------------------------------------------------------------------
; Set up a key event list for operator keycode types. This will be used
; when Calculator_CellStatus = Calculator_CALC
;-------------------------------------------------------------------------
Array Calculator_OpEventKey[15]
Calculator_OpEventKey[1] = Asc("^")
Calculator_OpEventKey[2] = Asc("%")
Calculator_OpEventKey[2] = Asc("<")
Calculator_OpEventKey[2] = Asc(">")
Calculator_OpEventKey[3] = Asc("!")
Calculator_OpEventKey[4] = Asc("*")
Calculator_OpEventKey[5] = Asc("/")
Calculator_OpEventKey[6] = Asc("+")
Calculator_OpEventKey[7] = Asc("-")
Calculator_OpEventKey[8] = Asc("=")
Calculator_OpEventKey[9] = Asc("Enter")
Calculator_OpEventKey[10] = -16 ; Alt-Q, square root
Calculator_OpEventKey[11] = -49 ; Alt-N, round
Calculator_OpEventKey[12] = Asc("<")
Calculator_OpEventKey[13] = Asc(">")
Calculator_OpEventKey[14] = Asc("Do_It!")
Calculator_OpEventKey[15] = Asc("Esc")
;-------------------------------------------------------------------------
; Set up a list of procedures to call in response to the operator
; keystrokes...
;-------------------------------------------------------------------------
Dynarray Calculator_ResponseProc[] ; 20 total
Calculator_ResponseProc[Asc("^")] = "Calculator!Exponent"
Calculator_ResponseProc[Asc("%")] = "Calculator!Percent"
Calculator_ResponseProc[Asc("!")] = "Calculator!Factorial"
Calculator_ResponseProc[Asc("*")] = "Calculator!Multiply"
Calculator_ResponseProc[Asc("/")] = "Calculator!Divide"
Calculator_ResponseProc[Asc("+")] = "Calculator!Add"
Calculator_ResponseProc[Asc("-")] = "Calculator!Subtract"
Calculator_ResponseProc[Asc("=")] = "Calculator!Equals"
Calculator_ResponseProc[Asc("Enter")] = "Calculator!Equals"
Calculator_ResponseProc[Asc("R")] = "Calculator!PlusMinus"
Calculator_ResponseProc[Asc("S")] = "Calculator!Subtotal"
Calculator_ResponseProc[Asc("C")] = "Calculator!Clear"
Calculator_ResponseProc[Asc("√")] = "Calculator!Sqrt"
Calculator_ResponseProc[-16] = "Calculator!Sqrt" ; Alt-Q
Calculator_ResponseProc[-49] = "Calculator!Round" ; Alt-N
Calculator_ResponseProc[Asc("N")] = "Calculator!Round" ; Alt-N
Calculator_ResponseProc[Asc(">")] = "Calculator!SaveMem"
Calculator_ResponseProc[Asc("<")] = "Calculator!GetMem"
Calculator_ResponseProc[Asc("Do_It!")] = "Calculator!OK"
Calculator_ResponseProc[Asc("Esc")] = "Calculator!Escape"
;-------------------------------------------------------------------------
; Define an engine for the DialogProc. This controller directs the thread
; of control with an execproc statement to the procedure matching the
; event.
;-------------------------------------------------------------------------
Dynarray Calculator_EventEngine[]
Calculator_EventEngine["Open"] = "Calculator!Open"
Calculator_EventEngine["Event"] = "Calculator!Event"
;-------------------------------------------------------------------------
; Paper tape facsimile at top of calculator
;-------------------------------------------------------------------------
Array Calculator_Tape[5]
For i From 1 to 5
Calculator_Tape[i] = ""
Endfor
Calculator_TapeFile = "CalcTape.Txt"
Calculator_TapeIsOn = False
Calculator!TapeModeLine() ; calculates Calculator_TapeModeLine
;-------------------------------------------------------------------------
; Explanation file...
;-------------------------------------------------------------------------
Calculator.ExplainFile = "PopCalc.hlp"
;-------------------------------------------------------------------------
; Dialog window information...
;-------------------------------------------------------------------------
Calculator_WindowHandle = Blanknum()
Calculator_WindowBag = Blanknum()
Calculator_WindowRow = Blanknum()
Calculator_WindowCol = Blanknum()
;-------------------------------------------------------------------------
; Memory value...
;-------------------------------------------------------------------------
Calculator_MemoryValue = BlankNum()
Calculator_MemoryAttribute = Calculator_NULL
;-------------------------------------------------------------------------
; Clear message to user...
;-------------------------------------------------------------------------
Calculator.IsActive = True
Message ""
EndProc ; Calculator.Constructor
;----------------------------------------------------------------------------
; To release global variables set up in the constructor...
;----------------------------------------------------------------------------
Proc Calculator.Destructor()
Release Vars
Calculator_NULL,
Calculator_OPCHAR,
Calculator_FUNCCHAR,
Calculator_NUMCHAR,
Calculator_EDITCHAR,
Calculator_TIME,
Calculator_SECONDS,
Calculator_MINUTES,
Calculator_HOURS,
Calculator_DAYS,
Calculator_WEEKS,
Calculator_MONTHS,
Calculator_YEARS,
Calculator_DATE,
Calculator_FLOATING,
Calculator_INTEGER,
Calculator_MONEY,
Calculator_STRING,
Calculator_OPERATOR,
Calculator_WAITING,
Calculator_CALC,
Calculator_TokenTypeName,
Calculator_Keycode,
Calculator_KeycodeAttribute,
Calculator_CellDataType,
Calculator_DecimalFlag,
Calculator_KeyPadModeLine,
Calculator_CellStatus,
Calculator.Value,
Calculator_Value,
Calculator_CellAttribute,
Calculator_CellLastValue,
Calculator_CellLastAttribute,
Calculator_CurrentOperator,
Calculator_LastOperator,
Calculator_StackValue,
Calculator_StackAttribute,
Calculator_StackPtr,
Calculator_KeyCodeType,
Calculator_CharEventKey,
Calculator_OpEventKey,
Calculator_ResponseProc,
Calculator_EventEngine,
Calculator_Tape,
Calculator_TapeFile,
Calculator_TapeModeLine,
Calculator.ExplainFile,
Calculator_WindowHandle,
Calculator_WindowBag,
Calculator_WindowRow,
Calculator_WindowCol,
Calculator_MemoryValue,
Calculator_MemoryAttribute,
Calculator.IsActive
EndProc ; Calculator.Destructor
;----------------------------------------------------------------------------
; Returns blanknum() or a number, depending on user's acceptance of the
; result.
;----------------------------------------------------------------------------
Proc Calculator.Dialog()
Private
CalcKey
ShowDialog "ESI-PD40B Calculator"
Proc "Calculator!DialogProc"
Trigger "Open"
@2,13 Height 20 Width 30
@0,0 ?? Calculator_Tape[1]
@1,0 ?? Calculator_Tape[2]
@2,0 ?? Calculator_Tape[3]
@3,0 ?? Calculator_Tape[4]
@4,0 ?? Calculator_Tape[5]
@5,0 ?? Calculator_TapeModeLine
@7,0 ?? Calculator_KeyPadModeLine
Accept
@6,0 Width 28
Calculator_CellDataType
Required
Tag "Cell"
To Calculator.Value
PushButton
@8,0 Width 5 "7"
Value Calculator!NumKey("7")
Tag "7"
To CalcKey
PushButton
@8,5 Width 5 "8"
Value Calculator!NumKey("8")
Tag "8"
To CalcKey
PushButton
@8,10 Width 5 "9"
Value Calculator!NumKey("9")
Tag "9"
To CalcKey
PushButton
@8,15 Width 7 "~R~ev"
Value Calculator!PlusMinus()
Tag "Rev"
To CalcKey
PushButton
@8,22 Width 5 "/"
Value Calculator!Divide()
Tag "/"
To CalcKey
PushButton
@10,0 Width 5 "4"
Value Calculator!NumKey("4")
Tag "4"
To CalcKey
PushButton
@10,5 Width 5 "5"
Value Calculator!NumKey("5")
Tag "5"
To CalcKey
PushButton
@10,10 Width 5 "6"
Value Calculator!NumKey("6")
Tag "6"
To CalcKey
PushButton
@10,15 Width 7 "C~l~r"
Value Calculator!Clear()
Tag "Clr"
To CalcKey
PushButton
@10,22 Width 5 "*"
Value Calculator!Multiply()
Tag "*"
To CalcKey
PushButton
@12,0 Width 5 "1"
Value Calculator!NumKey("1")
Tag "1"
To CalcKey
PushButton
@12,5 Width 5 "2"
Value Calculator!NumKey("2")
Tag "2"
To CalcKey
PushButton
@12,10 Width 5 "3"
Value Calculator!NumKey("3")
Tag "3"
To CalcKey
PushButton
@12,15 Width 7 "~S~ub"
Value Calculator!Subtotal()
Tag "Sub"
To CalcKey
PushButton
@12,22 Width 5 "-"
Value Calculator!Subtract()
Tag "-"
To CalcKey
PushButton
@14,0 Width 10 "0"
Value Calculator!NumKey("0")
Tag "0"
To CalcKey
PushButton
@14,10 Width 5 "."
Value Calculator!Decimal()
Tag "."
To CalcKey
PushButton
@14,15 Width 7 "="
Value Calculator!Equals()
Tag "="
To CalcKey
PushButton
@14,22 Width 5 "+"
Value Calculator!Add()
Tag "+"
To CalcKey
PushButton
@16,0 Width 6 "~O~K"
OK
Value Calculator!OK()
Tag "OK"
To CalcKey
PushButton
@16,6 Width 7 "~E~sc"
Cancel
Value Calculator!Escape()
Tag "Esc"
To CalcKey
PushButton
@16,13 Width 6 "O~p~"
Value Calculator!Op()
Tag "Op"
To CalcKey
PushButton
@16,19 Width 8 "~M~enu"
Value Calculator!Menu()
Tag "Menu"
To CalcKey
EndDialog
If Not Retval Then
Calculator.Value = Calculator_Value
Endif
Return retval
EndProc ; Calculator.Dialog
Proc Calculator!ViewExplain()
Private
WindowHandle,
WindowBag,
EventBag,
KeyCode
Calculator!GetCoordinates()
Window Move Calculator_WindowHandle To 500,500 ; off the screen
ShowPullDown EndMenu
If IsFile(Calculator.ExplainFile) Then
Editor Open Calculator.ExplainFile
Else
Editor New Calculator.ExplainFile
Endif
Menu {Options}{WordWrap}{Set}
WindowHandle = GetWindow()
Window Select WindowHandle
Window Maximize WindowHandle
Dynarray EventBag[]
Dynarray WindowBag[]
WindowBag["Title"] = "ESI-PD40B Calculator"
WindowBag["CanMaximize"] = False
Window SetAttributes WindowHandle From WindowBag
Echo Normal
Prompt "Hit [F2] or [Esc] to return to the calculator",""
While True
GetEvent To EventBag
Switch
Case EventBag["Type"] = "KEY":
;------------------------------
Keycode = EventBag["Keycode"]
Switch
Case Keycode = Asc("F2"):
ExecEvent EventBag
Quitloop
Case KeyCode = Asc("Esc"):
Window Close
Quitloop
Case KeyCode = Asc("F1"):
; (do nothing; suppress Help)
Case Keycode = Asc("Home") or
Keycode = Asc("End") or
Keycode = Asc("PgUp") or
Keycode = Asc("PgDn") or
Keycode = Asc("Left") or
Keycode = Asc("Right") or
Keycode = Asc("Up") or
Keycode = Asc("Down") or
Keycode = Asc("CtrlPgUp") or
Keycode = Asc("CtrlPgDn") or
Keycode = Asc("CtrlLeft") or
Keycode = Asc("CtrlRight"):
ExecEvent EventBag
OtherWise: ; do nothing
EndSwitch
Case EventBag["Type"] = "MESSAGE":
;----------------------------------
Switch
Case EventBag["Message"] = "CLOSE":
ExecEvent EventBag
Quitloop
Case EventBag["Message"] = "NEXT":
Beep
Message "Close window to return to calculator."
Sleep 2000
Message ""
; do nothing, repress this
Otherwise:
ExecEvent EventBag
EndSwitch
Otherwise:
;---------
ExecEvent EventBag
EndSwitch
EndWhile
Release Vars EventBag
Prompt
Window Move Calculator_WindowHandle To Calculator_Row,Calculator_Col
Echo Off
EndProc ; Calculator!ViewExplain
Proc PopCalc!CloseWindowWithConfirm()
Private
WindowHandle,
EventBag
WindowHandle = GetWindow()
WinClose
While IsWindow(WindowHandle) And (GetWindow() <> WindowHandle)
;--------------------------------------------------------------
; ie. we're on a confirmation menu, so eat events until
; accept or deny of winclose is indirectly confirmed. Accept is
; detected by absence of WindowHandle; deny is detected by
; return to the WindowHandle.
;--------------------------------------------------------------
GetEvent to EventBag
ExecEvent EventBag
EndWhile
If IsWindow(WindowHandle) Then
Return false
Else
Return true
Endif
EndProc ; PopCalc!CloseWindowWithConfirm
Proc Calculator!GetCoordinates()
Window Handle Dialog to Calculator_WindowHandle
Window GetAttributes Calculator_WindowHandle To Calculator_WindowBag
Calculator_Row = Calculator_WindowBag["OriginRow"]
Calculator_Col = Calculator_WindowBag["OriginCol"]
EndProc ; Calculator!GetCoordinates
Proc Calculator!ViewTape()
Private
WindowHandle,
WindowBag,
EventBag
Calculator!GetCoordinates()
Window Move Calculator_WindowHandle To 500,500 ; off the screen
ShowPullDown EndMenu
If IsFile(Calculator_TapeFile) Then
Editor Open Calculator_TapeFile
Else
Editor New Calculator_TapeFile
Endif
Menu {Options}{WordWrap}{Clear}
WindowHandle = GetWindow()
Window Select WindowHandle
Dynarray EventBag[]
Dynarray WindowBag[]
WindowBag["OriginRow"] = Calculator_Row
WindowBag["OriginCol"] = Calculator_Col
WindowBag["Height"] = 20
WindowBag["Width"] = 30
WindowBag["Title"] = "Calculator Tape"
Window SetAttributes WindowHandle From WindowBag
Echo Normal
Prompt "Hit [F2] or [Esc] to return to the calculator",""
While True
GetEvent To EventBag
Switch
Case EventBag["Type"] = "KEY":
;------------------------------
Switch
Case EventBag["Keycode"] = Asc("F2"):
ExecEvent EventBag
Quitloop
Case EventBag["KeyCode"] = Asc("Esc"):
Window Close
Quitloop
Case EventBag["KeyCode"] = Asc("F1"):
; (do nothing; suppress Help)
OtherWise:
ExecEvent EventBag
EndSwitch
Case EventBag["Type"] = "MESSAGE":
;----------------------------------
Switch
Case EventBag["Message"] = "CLOSE":
If PopCalc!CloseWindowWithConfirm() Then
QuitLoop
Endif
Case EventBag["Message"] = "NEXT":
Beep
Message "Close window to return to calculator."
Sleep 2000
Message ""
; do nothing, repress this
Otherwise:
ExecEvent EventBag
EndSwitch
OtherWise:
;---------
ExecEvent EventBag
EndSwitch
EndWhile
Release Vars EventBag
Prompt
Window Move Calculator_WindowHandle To Calculator_Row,Calculator_Col
Echo Off
EndProc ; ViewTape
Proc Calculator!KeyPadModeLine()
If Not Calculator_DecimalFlag Then
Calculator_KeyPadModeLine = Fill("─",28)
Else
Calculator_KeyPadModeLine = "─Decimal flag" + fill("─",15)
Endif
EndProc ; Calculator!KeyPadModeLine
Proc Calculator!TapeModeLine()
If Not Calculator_TapeIsOn Then
Calculator_TapeModeLine = "─Record is off" + fill("─",14)
Else
Calculator_TapeModeLine = "─Record is on" + fill("─",15)
Endif
EndProc ; Calculator!TapeModeLine
Proc Calculator!DialogProc(EventType,TagValue,EventBag,ElementValue)
Private
OK
ExecProc Calculator_EventEngine[EventType]
OK = Retval
Return OK
EndProc ; Calculator!DialogProc
;============================================================================
; Control trigger procs
;============================================================================
;----------------------------------------------------------------------------
; Called once at start of session, ready to take any legal character...
;----------------------------------------------------------------------------
Proc Calculator!Open()
Calculator!SetCharKeys()
Return true
EndProc ; Calculator!Open
;----------------------------------------------------------------------------
; Adds keycode list of all legal calculator keys. Supports the
; Calculator_WAITING state.
;----------------------------------------------------------------------------
Proc Calculator!SetCharKeys()
NewDialogSpec
Key
Calculator_CharEventKey[1],
Calculator_CharEventKey[2],
Calculator_CharEventKey[3],
Calculator_CharEventKey[4],
Calculator_CharEventKey[5],
Calculator_CharEventKey[6],
Calculator_CharEventKey[7],
Calculator_CharEventKey[8],
Calculator_CharEventKey[9],
Calculator_CharEventKey[10],
Calculator_CharEventKey[11],
Calculator_CharEventKey[12],
Calculator_CharEventKey[13],
Calculator_CharEventKey[14],
Calculator_CharEventKey[15],
Calculator_CharEventKey[16],
Calculator_CharEventKey[17],
Calculator_CharEventKey[18],
Calculator_CharEventKey[19],
Calculator_CharEventKey[20],
Calculator_CharEventKey[21],
Calculator_CharEventKey[22],
Calculator_CharEventKey[23],
Calculator_CharEventKey[24],
Calculator_CharEventKey[25],
Calculator_CharEventKey[26],
Calculator_CharEventKey[27],
Calculator_CharEventKey[28],
Calculator_CharEventKey[29],
Calculator_CharEventKey[30],
Calculator_CharEventKey[31],
Calculator_CharEventKey[32],
Calculator_CharEventKey[33]
EndProc ; Calculator!SetCharKeys
;----------------------------------------------------------------------------
; Adds keycode list of legal operator type calculator keys. Supports the
; Calculator_CALC state.
;----------------------------------------------------------------------------
Proc Calculator!SetOpKeys()
NewDialogSpec
Key
Calculator_OpEventKey[1],
Calculator_OpEventKey[2],
Calculator_OpEventKey[3],
Calculator_OpEventKey[4],
Calculator_OpEventKey[5],
Calculator_OpEventKey[6],
Calculator_OpEventKey[7],
Calculator_OpEventKey[8],
Calculator_OpEventKey[9],
Calculator_OpEventKey[10],
Calculator_OpEventKey[11],
Calculator_OpEventKey[12],
Calculator_OpEventKey[13],
Calculator_OpEventKey[14],
Calculator_OpEventKey[15]
EndProc ; Calculator!SetOpKeys
;----------------------------------------------------------------------------
; Traps for EVENT type messages. In particular traps for legal
; keys. Once trapped, they are classified and dispatched, followed
; by processing of the operator or function.
; Numchar and Editchar types cause the CellStatus to be set to CALC
; (something new has happened.), with the associated more limited eventlist.
; This leads to some performance improvement, as well as greater refinement
; in calculator logic.
;----------------------------------------------------------------------------
Proc Calculator!Event()
Private
OK
Switch
Case EventBag["Type"] = "KEY":
Calculator_Keycode = EventBag["Keycode"]
Calculator_KeycodeAttribute = Calculator_KeycodeType[Calculator_Keycode]
If (Calculator_KeyCodeAttribute = Calculator_OPCHAR) or
(Calculator_KeyCodeAttribute = Calculator_FUNCCHAR) Then
If TagValue <> "Cell" and Calculator_KeyCode = Asc("Enter") Then
OK = True ; Allow the keystroke
Else
Calculator.Value = ControlValue("Cell")
ExecProc Calculator_ResponseProc[Calculator_Keycode]
OK = False
Endif
Else ; NUMCHAR or EDITCHAR
Calculator_CellStatus = Calculator_CALC
Calculator!SetOpKeys()
OK = True
Endif
EndSwitch
Return OK
EndProc ; Calculator!Event
;----------------------------------- OPTIONS ----------------------------------
Proc Calculator!Escape()
Calculator_Value = ControlValue("Cell")
CancelDialog
; Calculator!Clear()
Return True
EndProc ; Calculator!Escape
Proc Calculator!OK()
If Calculator_StackPtr > 0 Then
Calculator!Equals()
Endif
AcceptDialog
Return true
EndProc ; Calculator!OK
Proc Calculator!Menu()
Private
OK,
Command,
TapeChoice
OK = True
If Calculator_TapeIsOn Then
TapeChoice = "√ ~T~ape toggle"
Else
TapeChoice = " ~T~ape toggle"
Endif
ShowPopup "Options" Centered
TapeChoice:"Toggle tape on and off":"TapeOn",
" ~V~iew tape":"Full editable view of the \"paper\" tape.":"ViewTape",
Separator,
" ~E~xplain":"A help screen which explains the use of the calculator.":"Explain"
EndMenu
To Command
If Retval Then
Switch
Case Command = "TapeOn":
Calculator_TapeIsOn = Not Calculator_TapeIsOn
Calculator!TapeModeLine()
Case Command = "ViewTape":
Calculator!ViewTape()
Case Command = "Explain":
Calculator!ViewExplain()
EndSwitch
Else
OK = false
Endif
SelectControl "Cell"
Return OK
EndProc ; Calculator!Menu
Proc Calculator!Op()
Private
OK,
Command
ShowPopup "Operators" Centered
"~A~dd":"The operator [+]":"+",
"S~u~btract":"The operator [-]":"-",
"~M~ultiply":"The operator [*]":"*",
"~D~ivide":"The operator [/]":"/",
"~E~xponent":"The operator [^]":"^",
Separator,
"~P~ercent":"The function [%]":"%",
"~F~actorial":"The function [!]":"!",
"~R~everse sign":"The function [Alt-R]":"R",
"S~q~uare root":"The square root function [Alt-Q]":"√",
"Rou~n~d,2":"Round to 2 decimal places [Alt-N]":"N",
Separator,
"Sa~v~e memory":"Save the current cell value to memory [>]":">",
"~G~et memory":"Retrieve the current cell value from memory [<]":"<",
Separator,
"~S~ubtotal":"Subtotal operator [Alt-S]":"S",
"~T~otal":"Total operator [=] or [Enter]":"=",
Separator,
"C~l~ear":"Clear operator [Alt-L]":"C"
EndMenu
To Command
If Retval Then
ExecProc Calculator_ResponseProc[Asc(Command)]
OK = true
Else
OK = false
Endif
SelectControl "Cell"
Return OK
EndProc ; Calculator!Op
;----------------------------------------------------------------------------
; Clear abandons the current calculation, and resets everything as though it
; had just been initialized. Stack items are abandoned (garbage) rather than
; re-initialized or deleted.
;----------------------------------------------------------------------------
Proc Calculator!Clear()
Private
OK
OK = True
Calculator_DecimalFlag = False
Calculator!KeyPadModeLine()
Calculator_CellStatus = Calculator_WAITING
Calculator!SetCharKeys()
Calculator.Value = 0
Calculator!RefreshTape(BlankNum(),"Clear")
Calculator_CellAttribute = Calculator_FLOATING
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
Calculator_StackPtr = 0
ResyncControl "Cell"
SelectControl "Cell"
Return OK
EndProc ; Calculator!Clear
;------------------------------ FUNCTIONS -----------------------------------
Proc Calculator!Percent()
Private
OK
If Not IsBlank(Calculator.Value) Then
OK = True
Calculator_LastOperator = Calculator_CurrentOperator
Calculator_CurrentOperator = "%"
Calculator!RefreshTape(Calculator.Value,"% =")
Calculator.Value = Calculator.Value/100
Calculator!RefreshTape(Calculator.Value,":")
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
Calculator_CellStatus = Calculator_CALC
Calculator!SetOpKeys()
ResyncControl "Cell"
Else
OK = false
Beep
Message "Cannot take percent of blank value."
Sleep 2000
Message ""
Endif
SelectControl "Cell"
Return OK
EndProc ; Calculator!Percent
Proc Calculator!Sqrt()
Private
OK
If Not IsBlank(Calculator.Value) And
Not (Calculator.Value < 0) Then
OK = True
Calculator_LastOperator = Calculator_CurrentOperator
Calculator_CurrentOperator = "√"
Calculator!RefreshTape(Calculator.Value,"√ =")
Calculator.Value = Sqrt(Calculator.Value)
Calculator!RefreshTape(Calculator.Value,":")
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
Calculator_CellStatus = Calculator_CALC
Calculator!SetOpKeys()
ResyncControl "Cell"
Else
OK = false
Beep
Message "Cannot take square root (√) of blank or negative value."
Sleep 2000
Message ""
Endif
SelectControl "Cell"
Return OK
EndProc ; Calculator!Sqrt
Proc Calculator!Round()
Private
OK
If Not IsBlank(Calculator.Value) Then
OK = True
Calculator_LastOperator = Calculator_CurrentOperator
Calculator_CurrentOperator = "N"
Calculator!RefreshTape(Calculator.Value,"rnd,2 =")
Calculator.Value = Round(Calculator.Value,2)
Calculator!RefreshTape(Calculator.Value,":")
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
Calculator_CellStatus = Calculator_CALC
Calculator!SetOpKeys()
ResyncControl "Cell"
Else
OK = false
Beep
Message "Cannot round blank value."
Sleep 2000
Message ""
Endif
SelectControl "Cell"
Return OK
EndProc ; Calculator!Round
Proc Calculator!SaveMem()
Private
OK
OK = True
Calculator_MemoryValue = Calculator.Value
Calculator_MemoryAttribute = Calculator_CellAttribute
Calculator!RefreshTape(Calculator.Value,">")
SelectControl "Cell"
Return OK
EndProc ; Calculator!SaveMem
Proc Calculator!GetMem()
Private
OK
OK = True
Calculator_LastOperator = Calculator_CurrentOperator
Calculator_CurrentOperator = "<"
Calculator.Value = Calculator_MemoryValue
Calculator_CellAttribute = Calculator_MemoryAttribute
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
Calculator!RefreshTape(Calculator.Value,"<")
Calculator_CellStatus = Calculator_CALC
Calculator!SetOpKeys()
ResyncControl "Cell"
SelectControl "Cell"
Return OK
EndProc ; Calculator!GetMem
Proc Calculator!Factorial()
Private
OK,i
If Not IsBlank(Calculator.Value) Then
OK = True
If Int(Calculator.Value) > 170 Then
Beep
Message "Cannot take factorial of > 170."
Sleep 2000
Message ""
Else
Calculator_LastOperator = Calculator_CurrentOperator
Calculator_CurrentOperator = "!"
Calculator!RefreshTape(Calculator.Value,"! =")
Calculator.Value = Int(Calculator.Value)
For i From Calculator.Value To 2 Step - 1
Calculator.Value = Calculator.Value * (i - 1)
EndFor
Calculator!RefreshTape(Calculator.Value,":")
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
Calculator_DecimalFlag = False
Calculator!KeyPadModeLine()
Calculator_CellStatus = Calculator_CALC
Calculator!SetOpKeys()
ResyncControl "Cell"
Endif
Else
OK = false
Beep
Message "Cannot take factorial of blank value."
Sleep 2000
Message ""
Endif
SelectControl "Cell"
Return OK
EndProc ; Calculator!Factorial
Proc Calculator!PlusMinus() ; Reverse
Private
OK
If Not IsBlank(Calculator.Value) Then
OK = True
Calculator_LastOperator = Calculator_CurrentOperator
Calculator_CurrentOperator = "R"
Calculator!RefreshTape(Calculator.Value,"+/- =")
Calculator.Value = -Calculator.Value
Calculator!RefreshTape(Calculator.Value,":")
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
Calculator_CellStatus = Calculator_CALC
Calculator!SetOpKeys()
ResyncControl "Cell"
Else
OK = false
Beep
Message "Cannot reverse sign of blank value."
Sleep 2000
Message ""
Endif
SelectControl "Cell"
Return OK
EndProc ; Calculator!PlusMinus
;------------------------------ OPERATORS -----------------------------------
Proc Calculator!Exponent()
Private
OK
OK = Calculator!InfixOperator("^")
Return OK
EndProc ; Calculator!Exponent
;------------------------------ MULTIPLY/DIVIDE -----------------------------
Proc Calculator!Multiply()
Private
OK
OK = Calculator!InfixOperator("*")
Return OK
EndProc ; Multiply
Proc Calculator!Divide()
Private
OK
OK = Calculator!InfixOperator("/")
Return OK
EndProc ; Divide
Proc Calculator!InfixOperator(Operator)
Private
OK
If isBlank(Calculator.Value) Then
Beep
Message "Cannot use [",Operator,"] with blank value."
Sleep 2000
Message ""
OK = false
Else
Calculator!PrepStackForOp()
Calculator.Value = Calculator_StackValue[Calculator_Stackptr]
Calculator_CellAttribute = Calculator_StackAttribute[Calculator_Stackptr]
Calculator_StackPtr = Calculator_StackPtr + 1
Calculator_StackValue[Calculator_StackPtr] = Operator
Calculator_StackAttribute[Calculator_Stackptr] = Calculator_OPERATOR
ResyncControl "Cell"
Calculator_DecimalFlag = False
Calculator!KeyPadModeLine()
Calculator_CellStatus = Calculator_WAITING
Calculator!SetCharKeys()
OK = True
Endif
SelectControl "Cell"
Return OK
EndProc ; InfixOperator
Proc Calculator!PrepStackForOp()
Calculator_LastOperator = Calculator_CurrentOperator
Calculator_CurrentOperator = Operator
If (Calculator_CellStatus = Calculator_WAITING) Then
Calculator.Value = Calculator_CellLastValue
Calculator_CellAttribute = Calculator_CellLastAttribute
Else
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
Endif
Calculator_StackPtr = Calculator_StackPtr + 1
Calculator_StackValue[Calculator_StackPtr] = Calculator.Value
Calculator_StackAttribute[Calculator_StackPtr] = Calculator_CellAttribute
OK = Calculator!DoInfixOperator() ; to resolve existing expressions
If OK Then
Calculator!RefreshTape(Calculator.Value,"=")
Calculator!RefreshTape(Calculator_StackValue[Calculator_StackPtr],
Operator)
Calculator_CellLastValue = Calculator_StackValue[Calculator_StackPtr]
Calculator_CellLastAttribute = Calculator_StackValue[Calculator_StackPtr]
Else
Calculator!RefreshTape(Calculator.Value,Operator)
Endif
Endproc ; Calculator!PrepStackForOp
Proc Calculator!DoInfixOperator()
Private
Operator,
OK
OK = false
;-------------------------------------------------------------------------
; Operation must be binary...
;-------------------------------------------------------------------------
If (Calculator_StackPtr > 2) And
(Calculator_StackAttribute[Calculator_StackPtr - 2] <>
Calculator_OPERATOR) Then
Operator = Calculator_StackValue[Calculator_StackPtr - 1]
If Operator = "*" or Operator = "/" Or Operator = "^" Then
OK = True
;-------------------------------------------------------------------
; Perform the operation. The resultant Stack attribute is not
; changed for now.
;-------------------------------------------------------------------
Switch
Case Operator = "*":
Calculator_StackValue[Calculator_StackPtr - 2] =
Calculator_StackValue[Calculator_StackPtr - 2] *
Calculator_StackValue[Calculator_StackPtr]
Case Operator = "/":
Calculator_StackValue[Calculator_StackPtr - 2] =
Calculator_StackValue[Calculator_StackPtr - 2] /
Calculator_StackValue[Calculator_StackPtr]
Case Operator = "^":
Calculator_StackValue[Calculator_StackPtr - 2] =
Pow(Calculator_StackValue[Calculator_StackPtr - 2],
Calculator_StackValue[Calculator_StackPtr])
If Calculator_StackValue[Calculator_StackPtr - 2] =
"Error" Then
Calculator_StackValue[Calculator_StackPtr - 2] = 0
Calculator!RefreshTape(BlankNum(),"Error")
Endif
EndSwitch
Calculator_StackPtr = Calculator_StackPtr - 2
Endif
Endif
Return OK
EndProc ; DoInfixOperator
;------------------------------- ADD/SUBTRACT -------------------------------
Proc Calculator!Add()
Private
OK
OK = Calculator!AddSubtract("+")
Return OK
EndProc ; Add
Proc Calculator!Subtract()
Private
OK
OK = Calculator!AddSubtract("-")
Return OK
EndProc ; Subtract
Proc Calculator!AddSubtract(Operator)
Private
OK
If isBlank(Calculator.Value) Then
Beep
Message "Cannot use [",Operator,"] with blank value."
Sleep 2000
Message ""
OK = false
Else
Calculator!PrepStackForOp()
Calculator_StackPtr = Calculator_StackPtr + 1
Calculator_StackValue[Calculator_StackPtr] = Operator
Calculator_StackAttribute[Calculator_StackPtr] = Calculator_OPERATOR
Calculator!DoAddSubtract()
Calculator.Value = Calculator_StackValue[Calculator_Stackptr]
Calculator_CellAttribute = Calculator_StackAttribute[Calculator_StackPtr]
ResyncControl "Cell"
Calculator_DecimalFlag = False
Calculator!KeyPadModeLine()
Calculator_CellStatus = Calculator_WAITING
Calculator!SetCharKeys()
OK = True
Endif
SelectControl "Cell"
Return OK
EndProc ; AddSubtract
Proc Calculator!DoAddSubtract()
Private
Operator
Operator = Calculator_StackValue[Calculator_StackPtr]
If Operator = "+" or Operator = "-" Then
If Calculator_StackPtr = 2 Or
Calculator_StackAttribute[Calculator_StackPtr - 2] =
Calculator_OPERATOR Then ; This is a unary Plus or minus
If Operator = "-" Then
Calculator_StackValue[Calculator_StackPtr - 1] =
-Calculator_StackValue[Calculator_StackPtr - 1]
Endif
Calculator_StackPtr = Calculator_StackPtr - 1
Else
If Operator = "+" Then
Calculator_StackValue[Calculator_StackPtr - 2] =
Calculator_StackValue[Calculator_StackPtr - 2] +
Calculator_StackValue[Calculator_Stackptr - 1]
Else
Calculator_StackValue[Calculator_StackPtr - 2] =
Calculator_StackValue[Calculator_StackPtr - 2] -
Calculator_StackValue[Calculator_Stackptr - 1]
Endif
Calculator_StackPtr = Calculator_StackPtr - 2
Endif
Endif
EndProc ; DoAddSubtract
;------------------------------ TERMINATORS ---------------------------------
;----------------------------------------------------------------------------
; Equals deterministically terminates the current calculation. If there is a
; blank value in the CellValue, it is set to 0. Outstanding expressions on
; the stack are resolved, and the result of the calculation is saved to
; CellLastValue for the use of the next calculation.
;----------------------------------------------------------------------------
Proc Calculator!Equals()
Private
OK
Calculator_LastOperator = Calculator_CurrentOperator
Calculator_CurrentOperator = "="
Calculator!ResolveStack()
;-------------------------------------------------------------------------
; At this point, the only possible unresolved expressions are subtotal
; adds, so we do them now...
;-------------------------------------------------------------------------
Calculator!DoSubTotal()
Calculator.Value = Calculator_StackValue[Calculator_StackPtr]
Calculator_CellAttribute = Calculator_StackAttribute[Calculator_StackPtr]
Calculator!RefreshTape(Calculator.Value,"Total")
;-------------------------------------------------------------------------
; Remember the result of this calculation to use as the result value of
; the next operation if a WAITING cell is operated upon...
;-------------------------------------------------------------------------
Calculator_CellLastValue = Calculator.Value
Cakculator_CellLastAttribute = Calculator_CellAttribute
Calculator_StackPtr = Calculator_StackPtr - 1
If Calculator_StackPtr <> 0 Then
Beep
Debug ; Stack pointer should be 0 with equals
Endif
Calculator_DecimalFlag = False
Calculator!KeyPadModeLine()
Calculator_CellStatus = Calculator_WAITING
Calculator!SetCharKeys()
ResyncControl "Cell"
SelectControl "Cell"
OK = true
Return OK
EndProc ; Equals
;----------------------------------------------------------------------------
; Subtotal resolves outstanding expressions for the subtotal, leaves the sub-
; total on the stack, and tops the stack with an "S" operator, which can only
; be resolved by DoSubTotal() as called by Equals, the ultimate terminator.
;----------------------------------------------------------------------------
Proc Calculator!Subtotal()
Calculator_LastOperator = Calculator_CurrentOperator
Calculator_CurrentOperator = "S"
Calculator!ResolveStack()
Calculator.Value = Calculator_StackValue[Calculator_StackPtr]
Calculator_CellAttribute = Calculator_StackAttribute[Calculator_StackPtr]
Calculator!RefreshTape(Calculator.Value,"Subtotal")
Calculator_CellLastValue = Calculator.Value
Calculator_CellLastAttribute = Calculator_CellAttribute
Calculator_StackPtr = Calculator_StackPtr + 1
Calculator_StackValue[Calculator_StackPtr] = "S"
Calculator_StackAttribute[Calculator_StackPtr] = Calculator_OPERATOR
Calculator_DecimalFlag = False
Calculator!KeyPadModeLine()
Calculator_CellStatus = Calculator_WAITING
Calculator!SetCharKeys()
ResyncControl "Cell"
SelectControl "Cell"
OK = true
Return OK
EndProc ; SubTotal
Proc Calculator!DoSubTotal()
Private
Operator
While Calculator_StackPtr > 1
Operator = Calculator_StackValue[Calculator_StackPtr - 1]
If Operator = "S" Then
Calculator_StackValue[Calculator_StackPtr - 2] =
Calculator_StackValue[Calculator_StackPtr - 2] +
Calculator_StackValue[Calculator_Stackptr]
Calculator_StackPtr = Calculator_StackPtr - 2
Else
Beep
Debug ; expecting Subtotal operator
Endif
EndWhile
EndProc ; DoSubTotal
Proc Calculator!ResolveStack()
;-------------------------------------------------------------------------
; Anticipate add operation to resolve unresolved expressions...
;-------------------------------------------------------------------------
If IsBlank(Calculator.Value) Then
Calculator.Value = 0
Endif
;-------------------------------------------------------------------------
; if the current value of CellValue is carried forward from the results
; of the previous operation, then neutralize it.
;-------------------------------------------------------------------------
If Calculator_CellStatus = Calculator_WAITING Then
;----------------------------------------------------------------------
; if the stackpointer is greater than 0 then there has been a previous
; operation, so neutralize the carried forward result...
;----------------------------------------------------------------------
If Calculator_Stackptr > 0 Then
;-------------------------------------------------------------------
; There may be an operator on top of the stack...
;-------------------------------------------------------------------
If (Calculator_StackAttribute[Calculator_StackPtr] = Calculator_OPERATOR) Then
If (Calculator_CurrentOperator = "S") Or
(Calculator_StackValue[Calculator_StackPtr] <> "S") Then
Calculator_StackPtr = Calculator_StackPtr + 1
Calculator_StackValue[Calculator_StackPtr] = Calculator_CellLastValue
Calculator_StackAttribute[Calculator_StackPtr] = Calculator_CellLastAttribute
Calculator.Value = Calculator_CellLastValue
Calculator_CellAttribute = Calculator_CellLastAttribute
Else ; current operator is "=" and top of stack = "S"
Calculator_StackPtr = Calculator_StackPtr - 1
Endif
Endif
Else
Calculator.Value = Calculator_CellLastValue
Calculator_CellAttribute = Calculator_CellLastAttribute
Calculator_CellStatus = Calculator_CALC
Endif
Endif
;-------------------------------------------------------------------------
; The only WAITING state that can arrive here is a held over result from
; an [Enter] before any operators were used in this calculation. This
; causes the result of the previous calculation to be used as the result
; of the current calculation.
;-------------------------------------------------------------------------
If Calculator_CellStatus = Calculator_CALC Then
Calculator!Add()
Else
OK = Calculator!DoInfixOperator() ; anything unresolved
If OK Then
Calculator!RefreshTape(Calculator.Value,"=")
Calculator!RefreshTape(Calculator_StackValue[Calculator_StackPtr],"+")
Endif
If Calculator_StackPtr > 0 Then
If Calculator_StackAttribute[Calculator_StackPtr] <> Calculator_OPERATOR Then
Calculator_StackPtr = Calculator_StackPtr + 1
Calculator_StackValue[Calculator_StackPtr] = "+"
Calculator_StackAttribute[Calculator_StackPtr] = Calculator_OPERATOR
Endif
Endif
Calculator!DoAddSubtract()
Endif
EndProc ; ResolveStack
;--------------------------- NUMERIC KEYPAD ---------------------------------
;----------------------------------------------------------------------------
; It would be better to stuff the keyboard here, as this doesn't cope with ".",
; nor does it recognize the position of the cursor within the input string,
; but keystroke initiation within ShowDialog is not available in Paradox 4
;----------------------------------------------------------------------------
Proc Calculator!NumKey(Numeral)
Private
String,
OriginalValue
OriginalValue = Calculator.Value
If Calculator_CellStatus = Calculator_WAITING Then
Calculator.Value = BlankNum()
Calculator_CellStatus = Calculator_CALC
Calculator!SetOpKeys()
Endif
String = StrVal(Calculator.Value)
If Calculator_DecimalFlag then
OK = Match(String,"..\".\"..")
If Not OK Then
String = String + "."
Endif
Endif
Calculator.Value = NumVal(String + Numeral)
If Calculator.Value = "Error" Then
Beep
Message "Error"
Sleep 2000
Message ""
Calculator.Value = OriginalValue
OK = False
Else
OK = True
Endif
ResyncControl "Cell"
SelectControl "Cell"
Return OK
EndProc ; Calculator!NumKey
Proc Calculator!Decimal()
If Calculator_DecimalFlag Then
Calculator_DecimalFlag = False
Else
Calculator_DecimalFlag = True
Endif
Calculator!KeyPadModeLine()
RepaintDialog ; to repaint the keypad mode line
SelectControl "Cell"
Return true
EndProc ; Calculator!Decimal
;----------------------------------------------------------------------------
; PAPER TAPE
;----------------------------------------------------------------------------
Proc Calculator!RefreshTape(Amount,OperationName)
Private
TapeString,
i
TapeString = Format("W21.2,EC",Amount) + " " + OperationName
For i From 2 to 5
Calculator_Tape[i-1] = Calculator_Tape[i]
EndFor
Calculator_Tape[5] = TapeString
If Calculator_TapeIsOn Then
Print File Calculator_TapeFile
TapeString,"\n"
Endif
RepaintDialog
EndProc ; Calculator!RefreshTape
;----------------------------------------------------------------------------
; MAINLINE
;----------------------------------------------------------------------------
Proc Closed Calculator.Show()
useVArs autolib
Calculator.Constructor()
If Calculator.Dialog() Then
If (SysMode() = "Edit" or SysMode() = "CoEdit") And
ImageType() = "Display" Then
If (Not IsFieldView()) And
(FieldType() = "N" or FieldType() = "$") Then
[] = Calculator.Value
Endif
If IsFieldView() And
Substr(FieldType(),1,1) = "M" Then
Editor Insert Calculator.Value
Endif
If Substr(FieldType(),1,1) = "A" Then
Typein Calculator.Value
Endif
Endif
Endif
Calculator.Destructor()
EndProc ; Calculator.Show()
If Not IsAssigned(Librarian.HasControl) Then
Calculator.Show()
Endif