
// All scripts on this page are the work of Timothy Edwards, DBA Can2Can, who asserts all author's rights under Copyright law
// permision granted to use _as is, with copyright stement_ as a callable script file on non-commercial sites
// link to your file with "<script language = "Javascript" src="CalcFunc.js">;"
// functions for a Reverse Polish calculator, seven register (c2cjsreg0..6) stack, roman/arab in/out.
// plus an indirection shell to allow emulation of an "algebraic" style calculator.
// only stack and primitive functions, no extended math.
// Global variables for the stack "reg-ister v-ariable Lukasiwicz #"
var regvLuke0 = 0
var regvLuke1 = 0
var regvLuke2 = 0
var regvLuke3 = 0
var regvLuke4 = 0
var regvLuke5 = 0
var regvLuke6 = 0
var fvLukeMode = 0
var fvInMode = 0
var RomanPriorNumber = 0
var fvRpnInfix = 1
var jsvTempStash = 0
var svRomanString = ""
var jsvOldFunc = 1

function PopC2Stack() {
// pop the stack, discard (regvLuke0)
regvLuke0 = regvLuke1
jsvOldFunc = 1
c2PopStack2()
return 1
  }
function c2XYSwap() {
// swap regvLuke1 and regvLuke0
jsvTempStash = regvLuke0
regvLuke0 = regvLuke1
regvLuke1 = jsvTempStash
fvInMode = 3
c2DotSub()
return 1
  }
function c2RollStack() {
// pop the stack, (regvLuke0) to bottom (is this unused?)
jsvTempStash = regvLuke0
regvLuke0 = regvLuke1
c2PopStack2()
regvLuke6 = jsvTempStash
return 1
  }
function c2SumFunction() {
// add-function
regvLuke0 = regvLuke0 + regvLuke1
c2PopStack2()
return 1
  }
function c2SubtractFunction() {
// subtraction function
regvLuke0 = regvLuke1 - regvLuke0
c2PopStack2()
return 1
  }
function c2ProductFunction() {
// multiplication
regvLuke0 = regvLuke0 * regvLuke1
c2PopStack2()
return 1
  }
function c2FloatDivideFunction() {
// deci divide
jsvTempStash = regvLuke1 / regvLuke0
regvLuke0= jsvTempStash
c2PopStack2()
return 1
  }
function c2IntegerDivideFunction() {
// integer divide
jsvTempStash = Math.floor(regvLuke1 / regvLuke0)
regvLuke0= jsvTempStash
c2PopStack2()
return 1
  }
function c2PopStack2() {
// main section of the stack-pop, move everything up one location
// top of stack "lost" an entry, discarded or used in calculation.
regvLuke1 = regvLuke2
regvLuke2 = regvLuke3
regvLuke3 = regvLuke4
regvLuke4 = regvLuke5
regvLuke5 = regvLuke6
regvLuke6 = 0
fvInMode = 3
c2DotSub()
return 0
  }
function c2ClearEntry() {
// only clear reg0
regvLuke0 = 0
fvInMode = 0
jsvOldFunc = 1
c2DotSub()
return 1
  }
function c2PushToStack() {
// put entry on the stack
regvLuke6 = regvLuke5
regvLuke5 = regvLuke4
regvLuke4 = regvLuke3
regvLuke3 = regvLuke2
regvLuke2 = regvLuke1
regvLuke1 = regvLuke0
fvInMode = 0
return 1
  }
function c2ShellCall(ButtonFunction) {
// manage the weirdness of an algebraic entry shell for a stack-calculator
if (fvRpnInfix == 1) { c2RPNDaemon(ButtonFunction) }
if (fvRpnInfix == 0) { c2RPNDaemon(jsvOldFunc) }
jsvOldFunc = ButtonFunction
return 0
  }
function c2RPNDaemon(oper) {
// activate the original functions from the new buttons
if (oper == 1) { c2PushToStack() }
if (oper == 2) { c2SumFunction() }
if (oper == 3) { c2SubtractFunction() }
if (oper == 4) { c2ProductFunction() }
if (oper == 5) { c2FloatDivideFunction() }
if (oper == 6) { c2IntegerDivideFunction() }
return 0
  }
function c2SetModeSub(dispm){
// set readout mode
fvLukeMode = dispm
c2DotSub()
  return 0
 }
function c2SetRpnYN(calmode){
// set operation mode
fvRpnInfix = calmode
if ( fvRpnInfix == 1 ){ document.nero.ljc.value=("ENTER"); document.nero.ajc.value=("   ")}
if ( fvRpnInfix == 0 ){ document.nero.ljc.value=("     "); document.nero.ajc.value=(" = ")}
jsvOldFunc = 1
  return 0
 }
function c2DotSub(){
// in Forth, this is the "." operation, except we don't pop it
// test for readout mode, and do arab mode
if ( fvLukeMode == 0 ) {document.nero.nums.value = (regvLuke0)}
// test for roman numeral mode, and call string builder
if ( fvLukeMode == 1 ) {c2DotRoman()}
if ( fvLukeMode == 1 ) {document.nero.nums.value=(svRomanString)}
return 1
 }
function c2Val2RChar(temp,step,chr) {
// concat a character to string, subtract value from work-copy
temp = temp - step
svRomanString = svRomanString + chr
return temp
  }
function c2DotRoman(){
// build roman mode readout "RomanNumeralSTRinG"
svRomanString = "Roman overflow"
var tem1 = regvLuke0
if ( tem1 >= 9000 ) { return 0 }
svRomanString = ""
while ( tem1 >= 1000 ) {tem1 = c2Val2RChar(tem1,1000,"M")}
while ( tem1 >= 900 ) {tem1 = c2Val2RChar(tem1,900,"CM")}
while ( tem1 >= 500 ) {tem1 = c2Val2RChar(tem1,500,"D")}
while ( tem1 >= 400 ) {tem1 = c2Val2RChar(tem1,400,"CD")}
while ( tem1 >= 100 ) {tem1 = c2Val2RChar(tem1,100,"C")}
while ( tem1 >= 90 ) {tem1 = c2Val2RChar(tem1,90,"XC")}
while ( tem1 >= 50 ) {tem1 = c2Val2RChar(tem1,50,"L")}
while ( tem1 >= 40 ) {tem1 = c2Val2RChar(tem1,40,"XL")}
while ( tem1 >= 10 ) {tem1 = c2Val2RChar(tem1,10,"X")}
while ( tem1 >= 9 ) {tem1 = c2Val2RChar(tem1,9,"IX")}
while ( tem1 >= 5 ) {tem1 = c2Val2RChar(tem1,5,"V")}
while ( tem1 >= 4 ) {tem1 = c2Val2RChar(tem1,4,"IV")}
while ( tem1 >= 1 ) {tem1 = c2Val2RChar(tem1,1,"I")}
return 1
 }
function c2RCRomIn(val){
// accept roman numeral entry
if ( fvInMode == 3 ) c2PushToStack()
if ( fvInMode != 1 ) regvLuke0 = 0
if ( fvInMode != 1 ) RomanPriorNumber = 0
fvInMode = 1
if ( (RomanPriorNumber == 1) && ( val == 5 )) { val = 3 }
if ( (RomanPriorNumber == 1) && ( val == 10 )) { val = 8 }
if ( (RomanPriorNumber == 10) && ( val == 50 )) { val = 30 }
if ( (RomanPriorNumber == 10) && ( val == 100 )) { val = 80 }
regvLuke0 = regvLuke0 + val
RomanPriorNumber = val
c2DotSub()
return 1
  }
function c2RCArabIn(val){
// accept arab numeral entry
if ( fvInMode == 3 ) c2PushToStack()
if ( fvInMode != 2 ) regvLuke0 = 0
fvInMode = 2
var temp = regvLuke0 * 10
regvLuke0 = temp + val
c2DotSub()
return 1
  }


