# Memory code for Tk-based RPN calculator
#
# This code is in the public domain. See the main program
# file for a disclaimer of liability.
#
# $Header: /home/neil/src/tcl/calc/RCS/calcmem,v 1.4 2000/12/28 14:40:42 neil Exp $

# MakeMemBox makes a "memory" box in the widget given by
# "path". "pushProc" is the procedure to call to push a
# number on the calculator's stack; it must accept a single
# floating-point argument. "stackTopProc" is the procedure
# to call to get the value on top of the stack; it takes no
# arguments, and returns a float. "n_cells" is the number of
# memory cells to create; the default is 4.

proc MakeMemBox {path pushProc stackTopProc {n_cells 4}} {
    global calcMemInfo

    # Just in case "path" is "."

    set pathpref $path
    if {[string compare $path "."] == 0} {
	set pathpref ""
    }

    # Make the top labels.

    label $pathpref.opslbl -text "Memory Ops"
    label $pathpref.datalbl -text "Data"
    label $pathpref.lbllbl -text "Label"
    grid $pathpref.opslbl -row 0 -column 0 -columnspan 5
    grid $pathpref.datalbl -row 0 -column 5
    grid $pathpref.lbllbl -row 0 -column 6

    # Make the individual memory areas.

    for {set row 1} {$row <= $n_cells} {incr row} {
	button $pathpref.clr$row -text Clr \
			-command [list ClearMem $path $row]
	button $pathpref.sto$row -text Sto \
			-command [list StoreMem $path $row $stackTopProc]
	button $pathpref.rcl$row -text Rcl \
			-command [list RecallMem $path $row $pushProc]
	button $pathpref.plus$row -text "+" \
			-command [list AddToMem $path $row $stackTopProc]
	button $pathpref.minus$row -text "-" \
			-command [list SubFromMem $path $row $stackTopProc]

	entry $pathpref.data$row -width 20
	entry $pathpref.label$row -width 20

	grid $pathpref.clr$row -row $row -column 0
	grid $pathpref.sto$row -row $row -column 1
	grid $pathpref.rcl$row -row $row -column 2
	grid $pathpref.plus$row -row $row -column 3
	grid $pathpref.minus$row -row $row -column 4
	grid $pathpref.data$row -row $row -column 5 -sticky ew
	grid $pathpref.label$row -row $row -column 6 -sticky ew
    }

    grid columnconfigure $path 6 -weight 1
}

# ClearMem clears cell "row" in memory box "path".

proc ClearMem {path row} {
    set pathpref $path
    if {[string compare $path "."] == 0} {
	set pathpref ""
    }

    $pathpref.data$row delete 0 end
}

# StoreMem stores the current value on top of the stack
# into cell "row" in memory box "path".

proc StoreMem {path row stackTopProc} {
    set pathpref $path
    if {[string compare $path "."] == 0} {
	set pathpref ""
    }

    set val [$stackTopProc]
    $pathpref.data$row delete 0 end
    $pathpref.data$row insert end $val
}

# RecallMem pushes the value in cell "row" of memory box
# "path" onto the operation stack.

proc RecallMem {path row pushProc} {
    set pathpref $path
    if {[string compare $path "."] == 0} {
	set pathpref ""
    }

    $pushProc [$pathpref.data$row get]
}

# AddToMem adds the item on top of the stack to the current
# contents of memory cell "row" of memory box "path".

proc AddToMem {path row stackTopProc} {
    set pathpref $path
    if {[string compare $path "."] == 0} {
	set pathpref ""
    }

    set origData [$pathpref.data$row get]
    if {[string compare "" [string trim $origData]] == 0} {
	set origData 0.0
    }
    set val [expr {$origData + [$stackTopProc]}]
    $pathpref.data$row delete 0 end
    $pathpref.data$row insert end $val
}

# SubFromMem subtracts the item on top of the stack from the current
# contents of memory cell "row" of memory box "path".

proc SubFromMem {path row stackTopProc} {
    set pathpref $path
    if {[string compare $path "."] == 0} {
	set pathpref ""
    }

    set origData [$pathpref.data$row get]
    if {[string compare "" [string trim $origData]] == 0} {
	set origData 0.0
    }
    set val [expr {$origData - [$stackTopProc]}]
    $pathpref.data$row delete 0 end
    $pathpref.data$row insert end $val
}
