#!/bin/sh

# Setting the user defined enviroment
# \
if [ -r ~/.pgaccess/pgaccess.env ]
# \
then
# \
	. ~/.pgaccess/pgaccess.env
# \
fi

# the next line restarts using wish \
exec wish "$0" "$@"

#------------------------------------------------------------
# $Id:$
#
#------------------------------------------------------------
#

# creating the .pgaccess directory and pgaccess.env file if they are missing
switch $tcl_platform(platform) {
	windows {
		puts "No enviroment variable needed."
	}
	unix {
		catch {
			file mkdir "~/.pgaccess"
			if {![file exists "~/.pgaccess/pgaccess.env"]} {
				puts -nonewline "No ~/.pgaccess/pgaccess.env, trying to create... "
				set fid [open "~/.pgaccess/pgaccess.env" w]
				puts $fid "# pgaccess enviroment settings"
				puts $fid ""

				puts $fid "# path to libpgtcl"
				if {![info exists env(PGLIB)]} {
					set env(PGLIB) "/usr/lib/tcl"
				}
				puts $fid "PGLIB=$env(PGLIB)"
				puts $fid ""

				puts $fid "# pgaccess home directory"
				if {![info exists env(PGACCESS_HOME)]} {
					set env(PGACCESS_HOME) "/usr/lib/pgaccess"
				}
				puts $fid "PGACCESS_HOME=$env(PGACCESS_HOME)"
				puts $fid ""
			
				puts $fid "export PGLIB PGACCESS_HOME"
				close $fid
				puts "done"
			}
		}
	}
	mac {
		puts "Is this the name for Macintosh platform? Send comment to developers@pgaccess.org."
	}
}

image create bitmap dnarw -data  {
#define down_arrow_width 15
#define down_arrow_height 15
static char down_arrow_bits[] = {
	0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,
	0x00,0x80,0xf8,0x8f,0xf0,0x87,0xe0,0x83,
	0xc0,0x81,0x80,0x80,0x00,0x80,0x00,0x80,
	0x00,0x80,0x00,0x80,0x00,0x80
	}
}

#----------------------------------------------------------
# registerPlugin --
#
#    Takes care of registering the plugin
#
# Arguments:
#    name_    the name to appear in the plugins menu
#    cmd_     the command to invoke the plugin
#
# Results:
#    none returned.
#----------------------------------------------------------
#
proc registerPlugin {name_ cmd_} {

    if {![info exists ::PgAcVar(plugin,list)]} {
        set ::PgAcVar(plugin,list) [list]
    }
   
    lappend ::PgAcVar(plugin,list) $name_
    set ::PgAcVar(plugin,$name_) $cmd_

    return
    
}; # end proc registerPlugin

proc {say} {msg} {
	tk_messageBox -message $msg
}

proc {intlmsg} {msg} {
global PgAcVar Messages
	if {$PgAcVar(pref,language)=="english"} { return $msg }
	if { ! [array exists Messages] } { return $msg }
	if { ! [info exists Messages($msg)] } { return $msg }
	return $Messages($msg)
}

proc {PgAcVar:clean} {prefix} {
global PgAcVar
	foreach key [array names PgAcVar $prefix] {
		set PgAcVar($key) {}
		unset PgAcVar($key)
	}
}


proc {find_PGACCESS_HOME} {} {
global PgAcVar env
	if {! [info exists env(PGACCESS_HOME)]} {
		set home [file dirname [info script]]
		puts "PGACCESS_HOME enviroment variable is not set, setting it to '$home'."
		switch [file pathtype $home] {
			absolute {set env(PGACCESS_HOME) $home}
			relative {set env(PGACCESS_HOME) [file join [pwd] $home]}
			volumerelative {
				set curdir [pwd]
				cd $home
				set env(PGACCESS_HOME) [file join [pwd] [file dirname [file join [lrange [file split $home] 1 end]]]]
				cd $curdir
			}
		}
	}
	if {![file isdir $env(PGACCESS_HOME)]} {
		puts "PGACCESS_HOME enviroment variable is not \n\
                  pointing to a directory, setting it to \n\
                  '[file dirname [info script]]'."

		set env(PGACCESS_HOME) [file dirname [info script]]
	}
	set PgAcVar(PGACCESS_HOME) $env(PGACCESS_HOME)
}


proc init {argc argv} {
global PgAcVar CurrentDB
	find_PGACCESS_HOME
	# Loading all defined namespaces
	#puts -nonewline "Loading namespaces:"
	foreach module {mainlib stack syntax database tables queries visualqb forms views functions reports scripts users sequences diagrams help preferences printer importexport connections graphs} {
		source [file join $PgAcVar(PGACCESS_HOME) lib $module.tcl]
		#puts -nonewline " $module"
	}

        ##
        ##  Load in the plugins
        ##
        foreach P [glob -nocomplain [file join $PgAcVar(PGACCESS_HOME) lib plugins *.tcl]] {
           source $P
        }

	puts ""
	set PgAcVar(currentdb,host) [default_pg_host]
	set PgAcVar(currentdb,pgport) [default_pg_port]
	set CurrentDB {}
	set PgAcVar(tablist) [list Tables Queries Views Sequences Functions Reports Graphs Forms Scripts Users Diagrams]
	set PgAcVar(activetab) {}
	set PgAcVar(query,tables) {}
	set PgAcVar(query,links) {}
	set PgAcVar(query,results) {}
	set PgAcVar(mwcount) 0
	Preferences::load
	Connections::load
    
    return

}; # end proc init

proc default_pg_host {} {
    # By default, return an empty string; this will force pgaccess to
    # connect with UNIX sockets instead of TCP/IP.
    # return localhost
    return ""
}

proc default_pg_port {} {
global env
	if {[info exists env(PGPORT)]} {
		return $env(PGPORT)
	} else {
		return 5432
	}
}

proc {wpg_exec} {db cmd} {
global PgAcVar
	set PgAcVar(pgsql,cmd) "never executed"
	set PgAcVar(pgsql,status) "no status yet"
	set PgAcVar(pgsql,errmsg) "no error message yet"
	if {[catch {
		Mainlib::sqlw_display $cmd
		set PgAcVar(pgsql,cmd) $cmd
		set PgAcVar(pgsql,res) [pg_exec $db $cmd]
		set PgAcVar(pgsql,status) [pg_result $PgAcVar(pgsql,res) -status]
		set PgAcVar(pgsql,errmsg) [pg_result $PgAcVar(pgsql,res) -error]
	} tclerrmsg]} {
		showError [format [intlmsg "Tcl error executing pg_exec %s\n\n%s"] $cmd $tclerrmsg]
		return 0
	}
	return $PgAcVar(pgsql,res)
}


proc {wpg_select} {args} {
	Mainlib::sqlw_display "[lindex $args 1]"
	uplevel pg_select $args
}


proc {create_drop_down} {base x y w} {
global PgAcVar
	if {[winfo exists $base.ddf]} return;
	frame $base.ddf -borderwidth 1 -height 75 -relief raised -width 55
	listbox $base.ddf.lb -background #fefefe -foreground #000000 -selectbackground #c3c3c3 -borderwidth 1  -font $PgAcVar(pref,font_normal)  -highlightthickness 0 -selectborderwidth 0 -yscrollcommand [subst {$base.ddf.sb set}]
	scrollbar $base.ddf.sb -borderwidth 1 -command [subst {$base.ddf.lb yview}] -highlightthickness 0 -orient vert
	place $base.ddf -x $x -y $y -width $w -height 185 -anchor nw -bordermode ignore
	place $base.ddf.lb -x 1 -y 1 -width [expr $w-18] -height 182 -anchor nw -bordermode ignore
	place $base.ddf.sb -x [expr $w-15] -y 1 -width 14 -height 183 -anchor nw -bordermode ignore
}


proc {setCursor} {{type NORMAL}} {
	if {[lsearch -exact "CLOCK WAIT WATCH" [string toupper $type]] != -1} {
		set type watch
	} else {
		set type left_ptr
	}
	foreach wn [winfo children .] {
		catch {$wn configure -cursor $type}
	}
	update ; update idletasks 
}


proc {parameter} {msg} {
global PgAcVar
	Window show .pgaw:GetParameter
	focus .pgaw:GetParameter.e1
	set PgAcVar(getqueryparam,var) ""
	set PgAcVar(getqueryparam,flag) 0
	set PgAcVar(getqueryparam,msg) $msg
	bind .pgaw:GetParameter <Destroy> "set PgAcVar(getqueryparam,flag) 1"
	grab .pgaw:GetParameter
	tkwait variable PgAcVar(getqueryparam,flag)
	if {$PgAcVar(getqueryparam,result)} {
		return $PgAcVar(getqueryparam,var)
	} else {
		return ""
	}
}


# show the error
# provide a link to help if one was specified
proc {showError} {emsg {helptopic {}}} {
	bell ; 
	puts $emsg
	if {[string length $helptopic]>0} {
		append emsg "\n\n" [intlmsg "Would you like help on this error?"]
		set help [tk_messageBox -default no -type yesno -title [intlmsg Error] -icon error -message $emsg]
		if {[string match $help "yes"]} {
			Help::load $helptopic		
		}
	} else {
		tk_messageBox -type ok -title [intlmsg Error] -icon error -message $emsg 
	}
}


proc {sql_exec} {how cmd} {
global PgAcVar CurrentDB
	if {[set pgr [wpg_exec $CurrentDB $cmd]]==0} {
		return 0
	}
	if {($PgAcVar(pgsql,status)=="PGRES_COMMAND_OK") || ($PgAcVar(pgsql,status)=="PGRES_TUPLES_OK")} {
		pg_result $pgr -clear
		return 1
	}	
	if {$how != "quiet"} {
		showError [format [intlmsg "Error executing query\n\n%s\n\nPostgreSQL error message:\n%s\nPostgreSQL status:%s"] $cmd $PgAcVar(pgsql,errmsg) $PgAcVar(pgsql,status)]
	}
	pg_result $pgr -clear
	return 0
}



proc {main} {argc argv} {
global PgAcVar CurrentDB tcl_platform env
	if {[info exists env(PGLIB)]} {
		set libpgtclpath [file join $env(PGLIB) libpgtcl.so.2]
	} else {
		puts "PGLIB enviroment variable is not set, setting it to 'libpgtcl'."
		set libpgtclpath {libpgtcl.so.2}
	}

        set shlib ${libpgtclpath}

        if {![file exists $shlib]} {
            puts "\nError: Shared library file: '$shlib' does not exist. \n\
                  Check this file, or check PGLIB variable (in pgaccessrc)\n"

            exit
        }

	if {[catch {load $shlib} err]} {
	    puts "Error: can not load $shlib shared library."
		puts "You need to make sure that the library exists and"
		puts "the environment variable PGLIB points to the directory"
		puts "where it is located.\n"
		puts "If you use Windows, be sure that the needed libpgtcl.dll"
		puts "and libpq.dll files are copied in the Windows/System"
		puts "directory"
                puts "\nERROR MESSAGE: $err\n"
		exit
	}

    set tdb ""
    set thost ""

    if {[info exists PgAcVar(pref,lastdb)] \
        && [info exists PgAcVar(pref,lasthost)]} {
        set tdb $PgAcVar(pref,lastdb)
        set thost $PgAcVar(pref,lasthost)
    }

    set PgAcVar(opendb,host) {}
    set PgAcVar(opendb,dbname) {}
    set PgAcVar(opendb,pgport) 5432
    set PgAcVar(opendb,username) {}
    set PgAcVar(opendb,password) {}

    ##
    ## Check to see if connections should be opened automagically
    ##
    if {$PgAcVar(pref,autoload)} {
        ##
        ##  Load all dbs that are in the connections file
        ##
        foreach H [::Connections::getHosts] {

            foreach d [::Connections::getDbs $H] {

                set i [::Connections::getIds $H $d]

                if {[llength $i] != 1} {
                    puts stderr "\nERROR: There seems to be a problem with your connections file."
                    puts stderr "A host/db combination should be unique and the db should not be empty string"
                    puts stderr "Check host/db:  $H/$d with ids: $i"
                    puts stderr "Try removing the ~/.pgaccess/connections file"
                    puts stderr "Skipping this host/db combination\n"
                    continue
                }

                if {![info exists ::Connections::Conn(autoload,$i)]} {
                    set ::Connections::Conn(autoload,$i) 1
                }

                if {$::Connections::Conn(autoload,$i) == 0} {
                     continue
                }

                if {![::Connections::openConn $i]} {
                    puts "$::Connections::Msg($i)"
                    # display the open conn window
                    if {![::Connections::openConn $i 1]} {
                        continue
                    }
                }

                ::Mainlib::addDbNode $H $d

            }; # end foreach DB

        }; # end foreach host

        #Connections::check

       ##
       ##  Open up the tree node for the last db
       ##
       if {[string match "" $thost]} {set thost sockets}

       if {(![string match "" $tdb]) && ([$::Mainlib::Win(tree) exists __db__-${thost}-${tdb}])} {

               $::Mainlib::Win(tree) opentree __host__-$thost 0
               $::Mainlib::Win(tree) opentree __db__-${thost}-$tdb
               ::Mainlib::select 1 __db__-${thost}-$tdb
       }
    }; # end if autoload

    wm protocol . WM_DELETE_WINDOW {
        ::Mainlib::Exit
    }

    return
}


proc {Window} {args} {
global vTcl
	set cmd [lindex $args 0]
	set name [lindex $args 1]
	set newname [lindex $args 2]
	set rest [lrange $args 3 end]
	if {$name == "" || $cmd == ""} {return}
	if {$newname == ""} {
		set newname $name
	}
	set exists [winfo exists $newname]
	switch $cmd {
		show {
			if {$exists == "1" && $name != "."} {wm deiconify $name; return}
			if {[info procs vTclWindow(pre)$name] != ""} {
				eval "vTclWindow(pre)$name $newname $rest"
			}
			if {[info procs vTclWindow$name] != ""} {
				eval "vTclWindow$name $newname $rest"
			}
			if {[info procs vTclWindow(post)$name] != ""} {
				eval "vTclWindow(post)$name $newname $rest"
			}
		}
		hide    { if $exists {wm withdraw $newname; return} }
		iconify { if $exists {wm iconify $newname; return} }
		destroy { if $exists {destroy $newname; return} }
	}
}

proc vTclWindow. {base} {
	if {$base == ""} {
		set base .
	}
	wm focusmodel $base passive
	wm geometry $base 1x1+0+0
	wm maxsize $base 1009 738
	wm minsize $base 1 1
	wm overrideredirect $base 0
	wm resizable $base 1 1
	wm withdraw $base
	wm title $base "vt.tcl"
}


init $argc $argv

##
##  Load some extra packages
##
lappend auto_path [file join $PgAcVar(PGACCESS_HOME) lib] [file join $PgAcVar(PGACCESS_HOME) lib widgets]
package require tablelist 2.7

package require BWidget
package require icons

#::icons::icons create \
    #-file [file join $PgAcVar(PGACCESS_HOME) lib icons1.0 tkIcons.ikons] \
	#{filenew22 fileopen22 edit22 navback22 navforward22 actreload22 fileclose22 editcopy22 editdelete22 editcut22}

::icons::icons create \
    -file [file join $PgAcVar(PGACCESS_HOME) lib widgets icons1.0 tkIcons-sample.slick] \
	{filenew-22 fileopen-22 edit-22 back-22 forward-22 reload-22 fileclose-22 editcopy-22 edittrash-22 move-22 connect_creating-22 filter1-22 cancel-22 down-22 up-22 configure-22 decrypted-22 encrypted-22 connect_no-22 exit-22 people-16 system-16 network_local-16 misc-16 thumbnail-16 txt-16 desktop_flat-16 widget_doc-16 shellscript-16 queue-16 completion-16 edit-16 1rightarrow-22 1leftarrow-22 fileprint-22 wizard-22 run-22 rever-22 filesave-22 colorize-16 view_tree-16 font_truetype-16 view_icon-16 view_text-16 xapp-16 news-16 go-16 spellcheck-16 stop-16 2rightarrow-22 2leftarrow-22 editcut-16 hotlistadd-16 hotlistdel-16 filesaveas-22 imagegallery-22 editdelete-22}

##
##  We are not including all of the BWidgets right now,
##  so we just manually load in the ones that are there
##
#set BWDIR [file join $PgAcVar(PGACCESS_HOME) lib widgets BWidget-1.4.1]
#namespace eval ::BWIDGET {variable LIBRARY; set LIBRARY $BWDIR}
#foreach p {init widget dropsite dragsite tree utils dynhelp entry arrow spinbox} {
    #source [file join $BWDIR ${p}.tcl]
#}

##
##  PGMonitor windows
##  This is a kludge...should find a better
##  way to integrate PGMonitor
##
#foreach W {query_popup sort_options pgaw:Pgmonitor} {
    #Window show .$W
    #Window hide .$W
#}

#Window show .
#Window show .pgaw:Main
vTclWindow.pgaw:Main ""

main $argc $argv

# moved this to lib/mainlib.tcl
#Pgmonitor::widget_init $argc $argv .pgaw:Pgmonitor



