#!/usr/locl/bin/wish

# Name: oratk
# Description: Oracle/Tk browser
# Author: Don Libes <libes@nist.gov>

package require Oratcl

wm iconify .

proc history_resize {incr} {
    global ora

    set num [expr $ora(historySize) + $incr]
    if {$num<$ora(minHistorySize)} return
    if {$num>$ora(maxHistorySize)} return

    set ora(historySize) $num

    set cmd .cmds.cmdf   ; # this is the prefix for each cmd frame

    for {set i 1} {$i<=$ora(maxHistorySize)} {incr i} {
	pack unpack $cmd$i
    }

    for {set i 1} {$i <= $num} {incr i} {
	pack $cmd$i -expand 1 -fill x
    }
}

proc process_autocommit {} {
    global ora

    if {$ora(autocommit)} {
	pack forget .menu.commit
	oraautocom $ora(login) on
    } else {
	pack .menu.commit -side left
	oraautocom $ora(login) off
    }
}

proc oraquit {} {
    global ora

    oraclose $ora(cursor)
    oralogoff $ora(login)
    exit
}

proc log_reset {} {
    .result.log config -state normal
    .result.log delete 1.0 end
    .result.log config -state disabled
}

proc log_add {msg} {
    .result.log config -state normal
    .result.log insert end $msg
    .result.log config -state disabled
}

proc execute {num} {
    global ora
    global oramsg

    log_reset
    log_add "Processing..."

    update

    if 0==[catch {open $ora(historyFile) w} fid] {
	for {set i 1} {$i<=$ora(historySize)} {incr i} {
	    puts $fid $ora(cmd$i)
	}
	close $fid
    }

    set cmd $ora(cmd$num)
    if [catch {orasql $ora(cursor) $cmd} msg] {
	# oerr takes a while to run sometimes so warn user
	log_add "Fetching error message - wait..."
	update
	log_reset
	set msg2 [exec oerr ora $oramsg(rc)]
	log_add $msg\n$msg2
    } else {
	log_reset
	orafetch $ora(cursor) {
	    log_add [list @0]\n
	}
    }
}

##################################################
# create login dialog
##################################################

if [catch {set user $env(ORACLE_USER)}] {
    set env(ORACLE_USER) ""
}
if [catch {set password $env(ORACLE_PASSWORD)}] {
    set env(ORACLE_PASSWORD) ""
}
if 0==[info exists env(ORACLE_SID)] {
    set env(ORACLE_SID) ""
    if 0==[string compare [exec hostname].[exec domainname] pitch.nist.gov] {
	set env(ORACLE_SID) fork
    }
}
if 0==[info exists env(ORACLE_HOME)] {
    set env(ORACLE_HOME) ""
    if 0==[string compare [exec hostname].[exec domainname] pitch.nist.gov] {
	set env(ORACLE_HOME) /u01/oracle/product/7322
    }
}

set firsttime 1
while {1} {
    set rc [catch {oralogon $env(ORACLE_USER)/$env(ORACLE_PASSWORD)} result]
    if $rc==0 break

    if !$firsttime {
	tk_dialog .error "Login Failed" "Login failed: Check password and other values.  Actual message from oracle: $result" error 0 Dismiss
    } else {
	set firsttime 0
	set w .login

	toplevel $w -class Dialog
	wm title $w "Log in to Oracle"

	frame $w.sid
	label $w.sid.text -text "SID:"
	entry $w.sid.entry -textvar env(ORACLE_SID)
	pack $w.sid.text -side left
	pack $w.sid.entry -side left -fill x -expand 1
	pack $w.sid -fill x -expand 1

	frame $w.home
	label $w.home.text -text "Home:"
	entry $w.home.entry -textvar env(ORACLE_HOME)
	pack $w.home.text -side left
	pack $w.home.entry -side left -fill x -expand 1
	pack $w.home -fill x -expand 1

	frame $w.user
	label $w.user.text -text "User:"
	entry $w.user.entry -textvar env(ORACLE_USER)
	pack $w.user.text -side left
	pack $w.user.entry -side left -fill x -expand 1
	pack $w.user -fill x -expand 1

	frame $w.password
	label $w.password.text -text "Password:"
	entry $w.password.entry -textvar env(ORACLE_PASSWORD) -show *
	pack $w.password.text -side left
	pack $w.password.entry -side left -fill x -expand 1
	pack $w.password -fill x -expand 1

	frame $w.buttons
	button $w.buttons.login -text "log in" -command {set wait 1}
	button $w.buttons.quit -text "quit" -command {exit}
	pack $w.buttons.login $w.buttons.quit -side left -fill x -expand 1
	pack $w.buttons -fill x -expand 1

	bind $w.sid.entry <Return> "focus $w.home.entry"
	bind $w.home.entry <Return> "focus $w.user.entry"
	bind $w.user.entry <Return> "focus $w.password.entry"
	bind $w.password.entry <Return> {set wait 1}

	text $w.help -relief groove -wrap word -width 40 -height 6
	$w.help insert end "Hints: Pressing <return> after entering password automatically performs login.  Automate this dialog by prestoring values in the environment variables ORACLE_SID, ORACLE_HOME, ORACLE_USER, and ORACLE_PASSWORD."
	$w.help config -state disabled
	pack $w.help
	grab $w

    }
    # try to focus on first empty entry or password if none empty
    focus $w.password.entry
    if 0==[string compare $env(ORACLE_USER) ""] {focus $w.user.entry}
    if 0==[string compare $env(ORACLE_HOME) ""] {focus $w.home.entry}
    if 0==[string compare $env(ORACLE_SID) ""] {focus $w.sid.entry}

    tkwait variable wait
}

catch {destroy .login}
set ora(login) $result

##################################################
# user logged in to Oracle, so create main transaction window
##################################################

wm title . "Oracle user: $env(ORACLE_USER)"
set ora(cursor) [oraopen $ora(login)]

frame .menu
button .menu.quit -command {oraquit} -text quit
set history .menu.historycntrl
frame $history -relief groove -bd 2 -highlightthickness 2
label $history.label -text "history" -relief flat -pady 0
button $history.plus -text "+" -padx 1 -pady 0 -command {history_resize 1}
button $history.minus -text "-" -padx 1 -pady 0 -command {history_resize -1}
pack $history.label $history.plus $history.minus -side left

checkbutton .menu.autocommit -text "autocommit" -variable ora(autocommit) -command process_autocommit -relief raised

pack .menu.quit $history .menu.autocommit -side left -fill y
pack .menu -fill x

button .menu.commit -text commit -command {oracommit $ora(login)}
# will be packed later


# create some history but initially only display the first
# frame all cmds together so we can insert them later without losing our place
frame .cmds
set cmd .cmds.cmdf   ; # this is the prefix for each cmd frame
set ora(historySize) 0
set ora(historyFile) [glob ~]/.oratk.history
set ora(minHistorySize) 1
set ora(maxHistorySize) 9
for {set i 1} {$i<=$ora(maxHistorySize)} {incr i} {
    frame $cmd$i -relief raised

    button $cmd$i.x -text "X" -command "execute $i" -pady 0 -padx 2
    entry $cmd$i.entry -textvar ora(cmd$i) -relief sunken
    bind $cmd$i.entry <Return> "execute $i"
    bind $cmd$i.entry <Control-u> "set ora(cmd$i) {}"
    pack $cmd$i.x -side left
    pack $cmd$i.entry -side left -fill x -expand 1
}
pack .cmds -fill x

history_resize 1

# load from saved history
if 0==[catch {open $ora(historyFile) r} fid] {
    for {set i $ora(minHistorySize)} {$i<=$ora(maxHistorySize)} {incr i} {
	gets $fid ora(cmd$i)
    }
    close $fid
}


set ora(autocommit) 1
process_autocommit

frame .result
set log [text .result.log -width 60 -height 15 -borderwidth 2 \
	-state disabled \
        -relief sunken -setgrid true -yscrollcommand {.result.scroll set}]
scrollbar .result.scroll -command {.result.log yview}
pack .result.scroll -side right -fill y
pack .result.log -side left -fill both -expand true
pack .result -side top -fill both -expand true
wm deiconify .

