#!/bin/sh
# the next line restarts using wish \
exec wish "$0" "$@"

############################## Setup #####################################
global Hmdir

set Hmdir $env(HOME)/.tkloan
if {![file isdirectory $Hmdir]} {
	exec mkdir $Hmdir
	exec chmod 700 $Hmdir
}
if {![file executable $Hmdir] || ![file readable $Hmdir]
	|| ![file writable $Hmdir]} {
	puts "Can't access $Hmdir!"
	exit 1
}
cd $Hmdir

############################# Globals ####################################

global Bkgrnd
global CompFrgrnd
global Frgrnd
global CompFont
global DefFont
global FxdFont

global Principal
global Interest
global NYears
global StartDate

global ExtraMonAmnt
global ExtraMonStart
global ExtraYrAmnt
global ExtraYrStart

global AccumStart
global AccumFreq

global ExtraPayDate
global ExtraPayPrin

global WinSeq

########################### Default Settings #############################

set Bkgrnd lightgray
set CompFrgrnd red
set Frgrnd navy
set CompFont "-adobe-helvetica-bold-r-*-*-*-120-*-*-*-*-*-*"
set DefFont "-adobe-helvetica-bold-r-*-*-*-100-*-*-*-*-*-*"
set FxdFont "-adobe-courier-bold-r-*-*-*-120-*-*-*-*-*-*"

set ExtraPayDate [exec date +%m/%Y]
set ExtraPayPrin 0.00

set WinSeq 0

############################ Procedures ##################################

proc checkdate date {
	return [regexp {^[0-9][0-9]/[0-9][0-9][0-9][0-9]$} $date]
}

proc clearwin {} {
	.prinentry delete 0 end
	.intentry delete 0 end
	.nyearsentry delete 0 end
	.startentry delete 0 end
	.monamntentry delete 0 end
	.monstartentry delete 0 end
	.yramntentry delete 0 end
	.yrstartentry delete 0 end
	.extralist delete 0 end
	.fdateentry delete 0 end
	.fparmentry delete 0 end
}

proc calc {amorid winid
	principal interest nyears startdate
	extramonamnt extramonstart extrayramnt extrayrstart
	accumstart accumfreq npaymnts paymnts
} {
	puts $amorid ln_reset
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_Amount $principal"
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_Interest $interest"
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_Term $nyears"
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_StDate $startdate"
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_ExMoAmt $extramonamnt"
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_StExMoDate $extramonstart"
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_ExYrAmt $extrayramnt"
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_StExYrDate $extrayrstart"
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_AcFreq $accumfreq"
	flush $amorid
	gets $amorid line

	puts $amorid "set ln_StAcDate $accumstart"
	flush $amorid
	gets $amorid line

	for {set i 0} {$i < $npaymnts} {incr i} {
		set e [lindex $paymnts $i]
		puts $amorid "ln_extrapay [lindex $e 0] [lindex $e 1]"
		flush $amorid
		gets $amorid line
	}

	puts $amorid ln_nextpay
	flush $amorid
	gets $amorid line
	while {$line} {
		puts $amorid ln_printpay
		flush $amorid
		gets $amorid line
		if {[winfo exists $winid]} {
			$winid.list insert end $line
			update
		} else {
			break
		}

		puts $amorid ln_nextpay
		flush $amorid
		gets $amorid line
	}

	puts $amorid exit
	flush $amorid
	close $amorid
}

proc compute {} {
	global Principal
	global Interest
	global NYears
	global StartDate

	global ExtraMonAmnt
	global ExtraMonStart
	global ExtraYrAmnt
	global ExtraYrStart

	global AccumStart
	global AccumFreq

	global WinSeq

	if {![string compare $Principal ""]} {
		putmsg {Compute Error} {No principal is specified.}
		return
	} elseif {![string compare $Interest ""]} {
		putmsg {Compute Error} {No interest is specified.}
		return
	} elseif {![string compare $NYears ""]} {
		putmsg {Compute Error} {No # years is specified.}
		return
	} elseif {![string compare $StartDate ""]} {
		putmsg {Compute Error} {No start date is specified.}
		return
	}

	if {$Principal <= 0} {
		putmsg {Compute Error} {Principal must be greater than 0.}
		return
	} elseif {$Interest <= 0} {
		putmsg {Compute Error} {Interest must be greater than 0.}
		return
	} elseif {$NYears <= 0} {
		putmsg {Compute Error} {# years must be greater than 0.}
		return
	} elseif {![checkdate $StartDate]} {
		putmsg {Compute Error} {Start date is in wrong format.}
		return
	} elseif {[string compare $ExtraMonAmnt ""] && $ExtraMonAmnt <= 0} {
		putmsg {Compute Error} {Monthly amount must be greater than 0.}
		return
	} elseif {($ExtraMonAmnt > 0) && ![string compare $ExtraMonStart ""]} {
		putmsg {Compute Error} {Monthly start date must be specified.}
		return
	} elseif {[string compare $ExtraMonStart ""]
		&& ![checkdate $ExtraMonStart]} {
		putmsg {Compute Error} {Monthly start date is in wrong format.}
		return
	} elseif {[string compare $ExtraYrAmnt ""] && $ExtraYrAmnt <= 0} {
		putmsg {Compute Error} {Yearly amount must be greater than 0.}
		return
	} elseif {($ExtraYrAmnt > 0) && ![string compare $ExtraYrStart ""]} {
		putmsg {Compute Error} {Yearly start date must be specified.}
		return
	} elseif {[string compare $ExtraYrStart ""]
		&& ![checkdate $ExtraYrStart]} {
		putmsg {Compute Error} {Yearly start date is in wrong format.}
		return
	} elseif {[string compare $AccumStart ""]
		&& ![checkdate $AccumStart]} {
		putmsg {Compute Error} {Consolidation start date is in wrong format.}
		return
	} elseif {[string compare $AccumFreq ""] && $AccumFreq <= 0} {
		putmsg {Compute Error} {# months in a line must be greater than 0.}
		return
	}

	set amorid -1
	set amorid [open |tclloan r+]
	if {$amorid <= 0} {
		puts "Can't execute tclloan; the amortization algorithm script!"
		putmsg {Execution Error} {Can't execute tclloan; the amortization algorithm script!}
		return
	}

	set WinSeq [expr $WinSeq+1]
	set npaymnts [.extralist size]
	list paymnts
	if {$npaymnts > 0} {
		for {set i 0} {$i < $npaymnts} {incr i} {
			lappend paymnts [.extralist get $i]
		}
	} else {
		lappend paymnts dummy
	}
	after 500 [list calc $amorid [dispamor $amorid $WinSeq]		\
		$Principal $Interest $NYears $StartDate			\
		$ExtraMonAmnt $ExtraMonStart $ExtraYrAmnt $ExtraYrStart	\
		$AccumStart $AccumFreq $npaymnts $paymnts]
}

proc dispamor {amorid seqno} {
	global Bkgrnd
	global CompFrgrnd
	global Frgrnd
	global CompFont
	global DefFont
	global FxdFont

	set winid ".winamor$seqno"
	toplevel $winid
	frame $winid.top -relief groove -bd 3 -bg $Bkgrnd
	frame $winid.base -relief groove -bd 3 -bg $Bkgrnd
	frame $winid.butn -relief groove -bd 3 -bg $Bkgrnd

	label $winid.label -font $FxdFont -bg $Bkgrnd

	puts $amorid ln_printhead
	flush $amorid
	gets $amorid line
	$winid.label configure -text "$line    "

	listbox $winid.list -relief sunken -bd 2			\
		-yscrollcommand "$winid.scroll set" -font $FxdFont	\
		-bg $Bkgrnd
	scrollbar $winid.scroll -command "$winid.list yview" -bg $Bkgrnd

	button $winid.ok -text OK -font $DefFont -bg $Bkgrnd		\
		-fg $Frgrnd -command "destroy $winid"
	bind $winid <Return> "destroy $winid"

	pack $winid.label -in $winid.top -side left -fill x -expand yes

	pack $winid.list -in $winid.base -side left -fill x -expand yes
	pack $winid.scroll -in $winid.base -side left -fill y

	pack $winid.ok -in $winid.butn -side left -fill x -expand yes

	pack $winid.top $winid.base $winid.butn -in $winid	\
		-side top -fill both
	wm title $winid "Amortization $seqno"
	wm protocol $winid WM_DELETE_WINDOW { }
	wm geom $winid +250+250
	focus $winid.list
	update
	return $winid
}

proc disphelp {type} {
	global Bkgrnd
	global CompFrgrnd
	global Frgrnd
	global CompFont
	global DefFont
	global FxdFont

	toplevel .winhelp
	frame .winhelp.base -relief groove -bd 3 -bg $Bkgrnd
	frame .winhelp.butn -relief groove -bd 3 -bg $Bkgrnd

	text .winhelp.text -height 21 -width 60 -relief sunken -bd 2	\
		-yscrollcommand ".winhelp.scroll set" -font $FxdFont	\
		-bg $Bkgrnd
	scrollbar .winhelp.scroll -command ".winhelp.text yview" -bg $Bkgrnd

	set helpid -1
	set helpid [open "|hlploan $type" r]
	if {$helpid <= 0} {
		puts "Can't execute hlploan; the help text script!"
		putmsg {Execution Error} {Can't execute hlploan; the help text script!}
		return
	}

	set nc [gets $helpid line]
	while {$nc >= 0} {
		if {$nc == 0} {
			.winhelp.text insert end "\n\n"
		} else {
			.winhelp.text insert end "$line "
		}
		set nc [gets $helpid line]
	}
	close $helpid

	.winhelp.text configure -state disabled

	button .winhelp.ok -text OK -font $DefFont -bg $Bkgrnd		\
		-fg $Frgrnd -command "destroy .winhelp"
	bind .winhelp <Return> "destroy .winhelp"

	pack .winhelp.text -in .winhelp.base -side left -fill x -expand yes
	pack .winhelp.scroll -in .winhelp.base -side left -fill y

	pack .winhelp.ok -in .winhelp.butn -side left -fill x -expand yes

	pack .winhelp.base .winhelp.butn -in .winhelp -side top -fill both
	wm title .winhelp "Amortization Help"
	wm protocol .winhelp WM_DELETE_WINDOW { }
	wm geom .winhelp +250+250
	focus .winhelp.text
}

proc fmtextrapay {} {
	global ExtraPayDate
	global ExtraPayPrin

	return [format "%-7.7s   %10.2f" $ExtraPayDate $ExtraPayPrin]
}

proc getextrapay {isupd title} {
	global Bkgrnd
	global CompFrgrnd
	global Frgrnd
	global CompFont
	global DefFont
	global FxdFont

	global ExtraPayDate
	global ExtraPayPrin

	toplevel .extrawin
	frame .extrawin.base -relief groove -bd 3 -bg $Bkgrnd
	frame .extrawin.date -relief flat -bg $Bkgrnd
	frame .extrawin.prin -relief flat -bg $Bkgrnd
	frame .extrawin.butn -relief groove -bd 3 -bg $Bkgrnd

	label .extrawin.datelabel -text "Date Applied:" -font $DefFont	\
		-bg $Bkgrnd
	entry .extrawin.dateentry -relief sunken -width 10		\
		-textvariable ExtraPayDate -font $FxdFont -bg $Bkgrnd

	label .extrawin.prinlabel -text "Payment:" -font $DefFont	\
		-bg $Bkgrnd
	entry .extrawin.prinentry -relief sunken -width 10		\
		-textvariable ExtraPayPrin -font $FxdFont -bg $Bkgrnd

	button .extrawin.ok -text OK -font $DefFont -bg $Bkgrnd		\
		-fg $Frgrnd -command "putextrapay $isupd"
	bind .extrawin <Return> "putextrapay $isupd"
	button .extrawin.cancel -text Cancel -font $DefFont		\
		-bg $Bkgrnd -fg $Frgrnd -command {
		destroy .extrawin
	}

	pack .extrawin.dateentry -in .extrawin.date -side right
	pack .extrawin.datelabel -in .extrawin.date -side right -fill x

	pack .extrawin.prinentry -in .extrawin.prin -side right
	pack .extrawin.prinlabel -in .extrawin.prin -side right -fill x

	pack .extrawin.ok .extrawin.cancel -in .extrawin.butn		\
		-side left -fill x -expand yes

	pack .extrawin.date .extrawin.prin -in .extrawin.base		\
		-side top -fill both

	pack .extrawin.base .extrawin.butn -in .extrawin -side top -fill both
	wm title .extrawin $title
	wm protocol .extrawin WM_DELETE_WINDOW { }
	wm transient .extrawin [winfo toplevel [winfo parent .extrawin]]
	wm geom .extrawin +250+250
	grab set .extrawin
	focus .extrawin.dateentry
}

proc getfile {} {
	global Hmdir
	global Bkgrnd
	global CompFrgrnd
	global Frgrnd
	global CompFont
	global DefFont
	global FxdFont

	toplevel .getfilewin
	frame .getfilewin.base -relief groove -bd 3 -bg $Bkgrnd
	frame .getfilewin.butn -relief groove -bd 3 -bg $Bkgrnd

	listbox .getfilewin.list -relief sunken -bd 2			\
		-yscrollcommand ".getfilewin.scroll set" -font $FxdFont	\
		-bg $Bkgrnd
	scrollbar .getfilewin.scroll -command ".getfilewin.list yview"	\
		 -bg $Bkgrnd
	foreach fname [lsort [glob -nocomplain {*.xln}]] {
		regsub {.xln$} $fname {} name
		.getfilewin.list insert end $name
	}
	.getfilewin.list select set 0
	bind .getfilewin <Double-1> rdloanfile

	button .getfilewin.ok -text OK -font $DefFont -bg $Bkgrnd	\
		-fg $Frgrnd -command rdloanfile
	bind .getfilewin <Return> rdloanfile
	button .getfilewin.cancel -text Cancel -font $DefFont		\
		-bg $Bkgrnd -fg $Frgrnd -command {
		destroy .getfilewin
	}

	pack .getfilewin.list -in .getfilewin.base -side left
	pack .getfilewin.scroll -in .getfilewin.base -side left -fill y

	pack .getfilewin.ok .getfilewin.cancel -in .getfilewin.butn		\
		-side left -fill x -expand yes

	pack .getfilewin.base .getfilewin.butn -in .getfilewin		\
		-side top -fill both
	wm title .getfilewin {Open Loan File}
	wm protocol .getfilewin WM_DELETE_WINDOW { }
	wm transient .getfilewin [winfo toplevel [winfo parent .getfilewin]]
	wm geom .getfilewin +250+250
	grab set .getfilewin
	focus .getfilewin
}

proc putextrapay isupd {
	global ExtraPayDate
	global ExtraPayPrin

	if {![checkdate $ExtraPayDate]} {
		putmsg {Date Error} {Date is in wrong format.}
	} elseif {$ExtraPayPrin <= 0.0} {
		putmsg {Payment Error} {Payment must be greater than zero.}
	} elseif {$isupd} {
		set idx [.extralist curselection]
		.extralist insert $idx [fmtextrapay]
		.extralist delete [.extralist curselection]
		.extralist selection set $idx
		destroy .extrawin
	} else {
		set idx [.extralist curselection]
		if {[string compare $idx ""]} {
			set idx [expr $idx + 1]
			.extralist insert $idx [fmtextrapay]
			setlpos .extralist $idx
		} else {
			.extralist insert -1 [fmtextrapay]
			.extralist selection set 0
		}
		destroy .extrawin
	}
}

proc putfile {} {
	global Hmdir
	global Bkgrnd
	global CompFrgrnd
	global Frgrnd
	global CompFont
	global DefFont
	global FxdFont

	toplevel .putfilewin
	frame .putfilewin.base -relief groove -bd 3 -bg $Bkgrnd
	frame .putfilewin.file -relief groove -bd 3 -bg $Bkgrnd
	frame .putfilewin.butn -relief groove -bd 3 -bg $Bkgrnd

	listbox .putfilewin.list -relief sunken -bd 2			\
		-yscrollcommand ".putfilewin.scroll set" -font $FxdFont	\
		-bg $Bkgrnd
	scrollbar .putfilewin.scroll -command ".putfilewin.list yview"	\
		-bg $Bkgrnd
	foreach fname [lsort [glob -nocomplain {*.xln}]] {
		regsub {.xln$} $fname {} name
		.putfilewin.list insert end $name
	}
	.putfilewin.list select set 0
	bind .putfilewin.list <Double-1> {
		.putfilewin.fileentry delete 0 end
		.putfilewin.fileentry insert 0 [.putfilewin.list get	\
			[.putfilewin.list curselection]]
	}

	label .putfilewin.filelabel -text "File:" -font $DefFont -bg $Bkgrnd
	entry .putfilewin.fileentry -relief sunken -font $FxdFont -bg $Bkgrnd
	.putfilewin.fileentry insert 0 [.putfilewin.list get 0]

	button .putfilewin.ok -text OK -font $DefFont -bg $Bkgrnd	\
		-fg $Frgrnd -command svloanfile
	bind .putfilewin <Return> "svloanfile"
	button .putfilewin.cancel -text Cancel -font $DefFont		\
		-bg $Bkgrnd -fg $Frgrnd -command {
		destroy .putfilewin
	}

	pack .putfilewin.list -in .putfilewin.base -side left
	pack .putfilewin.scroll -in .putfilewin.base -side left -fill y

	pack .putfilewin.filelabel -in .putfilewin.file -side left
	pack .putfilewin.fileentry -in .putfilewin.file -side left -fill x

	pack .putfilewin.ok .putfilewin.cancel -in .putfilewin.butn	\
		-side left -fill x -expand yes

	pack .putfilewin.base .putfilewin.file .putfilewin.butn		\
		-in .putfilewin -side top -fill both
	wm title .putfilewin {Open Loan File}
	wm protocol .putfilewin WM_DELETE_WINDOW { }
	wm transient .putfilewin [winfo toplevel [winfo parent .putfilewin]]
	wm geom .putfilewin +250+250
	grab set .putfilewin
	focus .putfilewin.fileentry
}

proc putmsg {title text} {
	global Bkgrnd
	global CompFrgrnd
	global Frgrnd
	global CompFont
	global DefFont
	global FxdFont

	toplevel .msgwin
	frame .msgwin.base -relief groove -bd 3 -bg $Bkgrnd
	frame .msgwin.msg -relief flat -bg $Bkgrnd
	frame .msgwin.butn -relief flat

	message .msgwin.mesg -text $text -font $DefFont -justify center	\
		-width 40c -bg $Bkgrnd

	button .msgwin.ok -text OK -font $DefFont -bg $Bkgrnd		\
		-fg $Frgrnd -command {
		destroy .msgwin
	}
	bind .msgwin <Return> {
		destroy .msgwin
	}

	pack .msgwin.mesg -in .msgwin.base -side top -fill both
	pack .msgwin.ok -in .msgwin.butn -side left -expand 1
	pack .msgwin.base .msgwin.butn -in .msgwin -side top -fill both

	wm title .msgwin $title
	wm protocol .msgwin WM_DELETE_WINDOW { }
	wm transient .msgwin [winfo toplevel [winfo parent .msgwin]]
	wm geom .msgwin +250+250
	grab set .msgwin
	focus .msgwin
}

proc rdloanfile {} {
	if {![string compare [.getfilewin.list curselection] ""]} {
		putmsg {File Selection Error} {No file is selected.}
	} else {
		source [.getfilewin.list get [.getfilewin.list	\
			curselection]].xln
		destroy .getfilewin
	}
}

proc setlpos {lb pos} {
	set cc [$lb curselection]
	if {[string compare $cc ""]} {
		$lb selection clear $cc
	}
	$lb selection set $pos
}

proc svloanfile {} {
	if {![string compare [.putfilewin.fileentry get] ""]} {
		putmsg {File Selection Error} {No file name has been entered.}
	} else {
		set fid [open [.putfilewin.fileentry get].xln w 0600]
		puts $fid ".prinentry delete 0 end"
		puts $fid ".prinentry insert 0 \{[.prinentry get]\}"
		puts $fid ".intentry delete 0 end"
		puts $fid ".intentry insert 0 \{[.intentry get]\}"
		puts $fid ".nyearsentry delete 0 end"
		puts $fid ".nyearsentry insert 0 \{[.nyearsentry get]\}"
		puts $fid ".startentry delete 0 end"
		puts $fid ".startentry insert 0 \{[.startentry get]\}"
		puts $fid ".monamntentry delete 0 end"
		puts $fid ".monamntentry insert 0 \{[.monamntentry get]\}"
		puts $fid ".monstartentry delete 0 end"
		puts $fid ".monstartentry insert 0 \{[.monstartentry get]\}"
		puts $fid ".yramntentry delete 0 end"
		puts $fid ".yramntentry insert 0 \{[.yramntentry get]\}"
		puts $fid ".yrstartentry delete 0 end"
		puts $fid ".yrstartentry insert 0 \{[.yrstartentry get]\}"
		puts $fid ".extralist delete 0 end"
		set nl [.extralist size]
		for {set i 0} {$i < $nl} {incr i} {
			puts $fid ".extralist insert end \{[.extralist get $i]\}"
		}
		puts $fid ".fdateentry delete 0 end"
		puts $fid ".fdateentry insert 0 \{[.fdateentry get]\}"
		puts $fid ".fparmentry delete 0 end"
		puts $fid ".fparmentry insert 0 \{[.fparmentry get]\}"
		close $fid
		destroy .putfilewin
	}
}

############################# Menu Bar ###################################

# Menu bar

frame .menubar -relief groove -bd 3 -bg $Bkgrnd
pack .menubar -side top -expand yes -fill x

# File menu entry

menubutton .menubar.file -text "File" -underline 0			\
	-menu .menubar.file.menu -bg $Bkgrnd -fg $Frgrnd -font $DefFont
menu .menubar.file.menu -bg $Bkgrnd -fg $Frgrnd -font $DefFont
.menubar.file.menu add command -label "New" -underline 0 -command clearwin
.menubar.file.menu add command -label "Open" -underline 0 -command getfile
.menubar.file.menu add command -label "Save" -underline 0 -command putfile
.menubar.file.menu add command -label "Exit" -underline 0 -command "exit 0"

# Help menu entry

menubutton .menubar.help -text "Help" -underline 0			\
	-menu .menubar.help.menu -bg $Bkgrnd -fg $Frgrnd -font $DefFont
menu .menubar.help.menu -bg $Bkgrnd -fg $Frgrnd -font $DefFont
.menubar.help.menu add command -label "About" -underline 0		\
	-command {
		after 500 [list disphelp 1]
	}
.menubar.help.menu add command -label "Description"			\
	-underline 0 -command {
		after 500 [list disphelp 2]
	}

# Pack in menu buttons and set focus

pack .menubar.file -side left
pack .menubar.help -side right
tk_menuBar .menubar .menubar.file .menubar.help
focus .menubar

############################## Frames ####################################

frame .prmdat -relief flat -bd 3 -bg $Bkgrnd

frame .left -bg $Bkgrnd
frame .right -bg $Bkgrnd

frame .base -relief raised -bd 2 -bg $Bkgrnd
frame .accum -relief raised -bd 2 -bg $Bkgrnd
frame .early -relief raised -bd 2 -bg $Bkgrnd
frame .extra -relief raised -bd 2 -bg $Bkgrnd

frame .principal -relief flat -bg $Bkgrnd
frame .interest -relief flat -bg $Bkgrnd
frame .nyears -relief flat -bg $Bkgrnd
frame .startdate -relief flat -bg $Bkgrnd

frame .monamnt -relief flat -bg $Bkgrnd
frame .monstart -relief flat -bg $Bkgrnd
frame .yramnt -relief flat -bg $Bkgrnd
frame .yrstart -relief flat -bg $Bkgrnd

frame .extrapay -relief flat -bg $Bkgrnd
frame .extrabut -relief flat -bg $Bkgrnd

frame .accumstart -relief flat -bg $Bkgrnd
frame .accumfreq -relief flat -bg $Bkgrnd

############################## Fields ####################################

# 1. Principal parameter

label .prinlabel -text "Principal:" -font $DefFont -bg $Bkgrnd
entry .prinentry -relief sunken -width 10 -textvariable Principal	\
	-font $FxdFont -bg $Bkgrnd

# 2. Interest parameter

label .intlabel -text "Interest:" -font $DefFont -bg $Bkgrnd
entry .intentry -relief sunken -width 10 -textvariable Interest		\
	-font $FxdFont -bg $Bkgrnd

# 3. Number of years parameter

label .nyearslabel -text "# Years:" -font $DefFont -bg $Bkgrnd
entry .nyearsentry -relief sunken -width 10 -textvariable NYears	\
	-font $FxdFont -bg $Bkgrnd

# 4. Start date parameter

label .startlabel -text "Start Date (mm/yyyy):" -font $DefFont -bg $Bkgrnd
entry .startentry -relief sunken -width 10 -textvariable StartDate	\
	-font $FxdFont -bg $Bkgrnd

# 5. Early payment monthly amount

label .monamntlabel -text "Monthly Amount:" -font $DefFont -bg $Bkgrnd
entry .monamntentry -relief sunken -width 10 -textvariable ExtraMonAmnt	\
	-font $FxdFont -bg $Bkgrnd

# 6. Early payment monthly start date

label .monstartlabel -text "Monthly Start Date (mm/yyyy):"		\
	-font $DefFont -bg $Bkgrnd
entry .monstartentry -relief sunken -width 10				\
	-textvariable ExtraMonStart -font $FxdFont -bg $Bkgrnd

# 7. Early payment yearly amount

label .yramntlabel -text "Yearly Amount:" -font $DefFont -bg $Bkgrnd
entry .yramntentry -relief sunken -width 10 -textvariable ExtraYrAmnt	\
	-font $FxdFont -bg $Bkgrnd

# 8. Early payment yearly start date

label .yrstartlabel -text "Yearly Start Date (mm/yyyy):"		\
	-font $DefFont -bg $Bkgrnd
entry .yrstartentry -relief sunken -width 10 -textvariable ExtraYrStart	\
	-font $FxdFont -bg $Bkgrnd

# 9. Extra payment list

listbox .extralist -relief sunken -bd 2					\
	-yscrollcommand ".extrascroll set" -font $FxdFont -bg $Bkgrnd
scrollbar .extrascroll -command ".extralist yview" -bg $Bkgrnd

# 10. Extra payment buttons

button .extraadd -text Add -underline 0 -font $DefFont -bg $Bkgrnd	\
	-fg $Frgrnd -command {
	getextrapay 0 "Add Payment"
}
bind . <Alt-a> {
	getextrapay 0 "Add Payment"
}
button .extradel -text Del -underline 0 -font $DefFont -bg $Bkgrnd	\
	-fg $Frgrnd -command {
	if {![string compare [.extralist curselection] ""]} {
		putmsg {Delete Error} {No payment is selected.}
	} else {
		set idx [.extralist curselection]
		.extralist delete $idx
		setlpos .extralist $idx
	}
}
bind . <Alt-d> {
	if {![string compare [.extralist curselection] ""]} {
		putmsg {Delete Error} {No payment is selected.}
	} else {
		set idx [.extralist curselection]
		.extralist delete $idx
		setlpos .extralist $idx
	}
}
button .extraupd -text Upd -underline 0 -font $DefFont -bg $Bkgrnd	\
	-fg $Frgrnd -command {
	if {![string compare [.extralist curselection] ""]} {
		putmsg {Update Error} {No payment is selected.}
	} else {
		set item [.extralist get [.extralist curselection]]
		set ExtraPayDate [string range $item 0 6]
		set ExtraPayPrin [string trimleft [string range $item 7 end]]
		getextrapay 1 "Update Payment"
	}
}
bind . <Alt-u> {
	if {![string compare [.extralist curselection] ""]} {
		putmsg {Update Error} {No payment is selected.}
	} else {
		set item [.extralist get [.extralist curselection]]
		set ExtraPayDate [string range $item 0 4]
		set ExtraPayPrin [string trimleft [string range $item 5 end]]
		getextrapay 1 "Update Payment"
	}
}

# 11. Accumulation frequency start date parameter

label .fdatelabel -text "Start Date (mm/yyyy):" -font $DefFont -bg $Bkgrnd
entry .fdateentry -relief sunken -width 10 -textvariable AccumStart	\
	-font $FxdFont -bg $Bkgrnd

# 12. Accumulation frequency parameter

label .fparmlabel -text "# Months in a Line:" -font $DefFont -bg $Bkgrnd
entry .fparmentry -relief sunken -width 10 -textvariable AccumFreq	\
	-font $FxdFont -bg $Bkgrnd

# 13. Compute button

button .compbut -text COMPUTE -underline 0 -font $CompFont		\
	-bg $CompFrgrnd -command {
	compute
}
bind . <Alt-c> {
	compute
}

############################## Groups ####################################

# 1. Base parameter label and parameters

label .baselabel -text "Base Parameters" -font $DefFont -bg $Bkgrnd

pack .prinentry -in .principal -side right
pack .prinlabel -in .principal -side right -fill x

pack .intentry -in .interest -side right
pack .intlabel -in .interest -side right -fill x

pack .nyearsentry -in .nyears -side right
pack .nyearslabel -in .nyears -side right -fill x

pack .startentry -in .startdate -side right
pack .startlabel -in .startdate -side right -fill x

# 2. Early payment parameter label and parameters

label .earlylabel -text "Early Payments (optional)" -font $DefFont -bg $Bkgrnd

pack .monamntentry -in .monamnt -side right
pack .monamntlabel -in .monamnt -side right -fill x

pack .monstartentry -in .monstart -side right
pack .monstartlabel -in .monstart -side right -fill x

pack .yramntentry -in .yramnt -side right
pack .yramntlabel -in .yramnt -side right -fill x

pack .yrstartentry -in .yrstart -side right
pack .yrstartlabel -in .yrstart -side right -fill x

# 3. Extra payment list

label .extralabel -text "Extra Payments (optional)" -font $DefFont -bg $Bkgrnd

pack .extralist -in .extrapay -side left
pack .extrascroll -in .extrapay -side left -fill y

pack .extraadd .extradel .extraupd -in .extrabut -side left -fill x	\
	-expand yes

# 4. Accumulation parameter label and parameters

label .accumlabel -text "Line Consolidation (optional)" -font $DefFont	\
	-bg $Bkgrnd

pack .fdateentry -in .accumstart -side right
pack .fdatelabel -in .accumstart -side right -fill x

pack .fparmentry -in .accumfreq -side right
pack .fparmlabel -in .accumfreq -side right -fill x

########################### Outer Groups #################################

pack .base -side left -pady 1m
pack .baselabel .principal .interest .nyears .startdate -in .base	\
	-side top -fill both

pack .early -side left -pady 1m
pack .earlylabel .monamnt .monstart .yramnt .yrstart -in .early		\
	-side top -fill both

pack .extra -side left -pady 1m
pack .extralabel .extrapay .extrabut -in .extra -side top -fill both

pack .accum -side left -pady 1m
pack .accumlabel .accumstart .accumfreq -in .accum -side top -fill both

###################### Overall Group Position ############################

pack .base .early .accum -in .left -side top -fill x

pack .extra -in .right -side top -fill x
pack .compbut -in .right -side top -fill both -expand yes

###################### Overall Data Group ################################

pack .left .right -in .prmdat -side left -fill both
pack .prmdat -side top -fill both

wm geom . +200+200
focus .prinentry
