# while you CAN make your site specific changes here, it is NOT
# recommended! Place any changes to these, instead, in a 
# TNOS etc/xdefaults file, and pass the name of that file to this
# script as a single parameter. If there is no parameter given,
# it will use the default of /nos/etc/xdefaults.

set NOSDIR          /nos
set CONFIGfile      etc/xdefaults
set TNOShost        fool.ampr.org
set CONVhost        localhost
set XTERM           xterm
set CONFclient      convers
set CONFlogin       fool
set CONFchannel     0
set NOSLOG          spool/log/net.log
set INITIALcmdstate withdraw
set INITIALbarstate deiconify
set HOLDMAILstate   iconify
set NEWMAILstate    deiconify
set CHATstate	    deiconify


# NOTHING past this point should be changed, at all! EVER! This means YOU!

if {$argc != 0}	{
	set USERconfig [lindex $argv 0]
} else {
	set USERconfig $NOSDIR/$CONFIGfile
}

proc start_bbs_session {} {
	global TNOShost XTERM
	exec $XTERM {-title} BBS {-e} telnet $TNOShost &
}

proc start_conf_session {} {
	global XTERM CONFlogin CONFchannel CONFclient CONVhost
	exec $XTERM {-title} "Conference at $CONVhost" {-geom} 80x50 {-e} $CONFclient {-t} $CONFlogin {-c} $CONFchannel &
}


# This initializes the status bar and displays it

proc status_init {} {
	global TNOShost INITIALbarstate
	catch {destroy .status}
	set f .status
	toplevel $f
	wm $INITIALbarstate $f
	wm geometry $f +0+0
	wm title $f "TNOS Status Bar"
	wm iconname $f StatBar
	frame $f.f

	foreach c {bbs conf ftp tut} {
		label $f.f.${c}label -text "[string toupper $c]:"
		entry $f.f.${c}button -textvariable STAT$c -relief sunken -width 6 -state disabled
		pack $f.f.${c}label $f.f.${c}button -side left
	}
	bind $f.f.bbslabel <Any-1> "finger bbs $TNOShost"
	bind $f.f.bbsbutton <Any-1> "finger bbs $TNOShost"
	bind $f.f.conflabel <Any-1> "finger conf $TNOShost"
	bind $f.f.confbutton <Any-1> "finger conf $TNOShost"

	label $f.f.fill1 -width 10
	pack $f.f.fill1 -side left
	button $f.f.trace -text "TRACE" -command "start_trace_session"
	bind $f <Control-Key-t> "start_trace_session"
	button $f.f.bbs -text "BBS" -command "start_bbs_session"
	bind $f <Control-Key-b> "start_bbs_session"
	button $f.f.conv -text "CONV" -command "start_conf_session"
	bind $f <Control-Key-c> "start_conf_session"
	button $f.f.config -text "CONFIG"
#	bind $f <Control-Key-g>
	button $f.f.finger -text "FINGER" -command "anyfinger"
	bind $f <Control-Key-f> "anyfinger"
	button $f.f.command -text "SHOW COMMAND" -command "toggle_cmd"
	bind $f <Control-Key-v> "toggle_cmd"
	pack $f.f.trace $f.f.bbs $f.f.conv $f.f.finger $f.f.config $f.f.command -side left -ipadx 4 -ipady 2 -padx 5
	label $f.f.fill2 -width 10
	pack $f.f.fill2 -side left

	button $f.f.exit -text "EXIT" -command "do_exit"
	pack $f.f.exit -side left -ipadx 4 -ipady 2 -padx 5
	pack $f.f -fill x -pady 3 -padx 5
	entry $f.msg -textvariable STATmsg -relief sunken -width 80 -state disabled -bd 3
	pack $f.msg -fill x -expand 1 -padx 5 -pady 5
	frame $f.t -relief sunken
	text $f.t.text -width 80 -height 10 -state disabled -relief sunken -bd 3
	pack $f.t.text -fill both -expand 1
	# $f.t not packed, initially, on purpose
	bind $f.msg <Any-1> {toggle_backstatus}
	bind $f.t <Any-1> {toggle_backstatus}
	bind $f.t.text <Any-1> {toggle_backstatus}
}


# This initializes the command session

proc command_init {} {
	global INITIALcmdstate
	catch {destroy .command}
	set f .command
	toplevel $f
	wm $INITIALcmdstate $f
	wm geometry $f +100+100
	wm title $f "TNOS Command Session"
	wm iconname $f CmdSess
#	frame $f.f
#	button $f.f.disconnect -text "DISCONNECT" -command "toggle_cmd"
#	pack $f.f.disconnect -side right -ipadx 4 -ipady 2 -padx 5
#	pack $f.f -fill x
	frame $f.in
	text $f.in.text -width 80 -height 24 -borderwidth 2 -relief raised \
		-setgrid 1 -yscrollcommand {.command.in.scroll set}
	scrollbar $f.in.scroll -command {.command.in.text yview}
	pack $f.in.text -side left -fill both -expand 1
	pack $f.in.scroll -side right -fill y
	pack $f.in -pady 5
	frame $f.out
	text $f.out.text -width 80 -height 4 -borderwidth 2 -relief raised \
		-setgrid 1 -yscrollcommand {.command.out.scroll set}
	scrollbar $f.out.scroll -command {.command.out.text yview}
	pack $f.out.text -side left -fill both -expand 1
	pack $f.out.scroll -side right -fill y
	pack $f.out -pady 5
	bind $f <Return> {incoming "[.command.out.text get 1.0 end]" 1;.command.out.text delete 1.0 end}
	bind $f.out.text <Return> {incoming "[.command.out.text get 1.0 end]" 1;.command.out.text delete 1.0 end}
	focus $f.out.text
	bind $f <Destroy> {catch {.status.f.command config -text "SHOW COMMAND"}}
}


proc do_exit {} {
	set f .exit
	toplevel $f
	wm geometry $f +100+100
	message $f.msg -aspect 1000 -justify left -text "Exit TNOS/X?"
	label $f.b -bitmap question
	frame $f.but -relief raised
	button $f.but.cancel -text "CANCEL" -command "destroy $f;focus .status"
	button $f.but.ok -text "OK" -command "exit"
	pack $f.but.cancel $f.but.ok -side left -expand 1 -ipadx 10 -ipady 4 -padx .25i

	pack $f.but -side bottom -expand 1 -pady 10 -padx .25i
	pack $f.b $f.msg -side left -fill both -expand 1 -pady 15
#	frame $f.fill
#	pack $f.fill -pady 5
	bind $f <Return> "destroy $f;focus .status"

	wm title $f "Exiting?"
	wm iconname $f "EXIT?"
	focus $f
	grab $f
}

proc newmail {} {
	global NEWMAILstate
	set f .newmail
	catch {destroy $f}
	toplevel $f
	wm $NEWMAILstate $f
	wm geometry $f +100+100
	message $f.msg -aspect 1000 -justify left -text "You have new mail!"
	label $f.b -bitmap warning
	frame $f.but -relief raised
	button $f.but.ok -text "OK" -command {destroy .newmail;incoming "mbox mailfor alert clear" 1}
	pack $f.but.ok -side left -expand 1 -ipadx 10 -ipady 4 -padx .25i

	pack $f.but -side bottom -expand 1 -pady 10 -padx .25i
	pack $f.b $f.msg -side left -fill both -expand 1 -pady 15 -padx .5i

	wm title $f "New Mail Notification"
	wm iconname $f "NewMail"
}

proc newchat {} {
	global CHATstate STATscreencaller STATscreen
	set f .chat
	catch {destroy $f}
	toplevel $f
	wm $CHATstate $f
	wm geometry $f +100+100
	message $f.msg -aspect 1000 -justify left -text "Incoming Chat request from $STATscreencaller!\nAccept it?"
	label $f.b -bitmap warning
	frame $f.but -relief raised
	button $f.but.accept -text "ACCEPT" -command {destroy .chat;incoming "chat accept" 1}
	button $f.but.deny -text "DENY" -command {destroy .chat;incoming "chat deny" 1}
	button $f.but.ignore -text "IGNORE" -command {destroy .chat}
	pack $f.but.accept $f.but.deny $f.but.ignore -side left -expand 1 -ipadx 10 -ipady 4 -padx .25i

	pack $f.but -side bottom -expand 1 -pady 10 -padx .25i
	pack $f.b $f.msg -side left -fill both -expand 1 -pady 15 -padx .5i

	wm title $f "Incoming Chat Notification"
	wm iconname $f "NewChat"
}

proc holdmail {} {
	global TNOShost HOLDMAILstate
	set f .holdmail
	catch {destroy $f}
	toplevel $f
	wm $HOLDMAILstate $f
	wm geometry $f +100+100
	message $f.msg -aspect 1000 -justify left -text "There is mail on hold on $TNOShost!"
	label $f.b -bitmap warning
	frame $f.but -relief raised
	button $f.but.ok -text "OK" -command {destroy .holdmail;incoming "mbox mailfor hold clear" 1}
	pack $f.but.ok -side left -expand 1 -ipadx 10 -ipady 4 -padx .25i

	pack $f.but -side bottom -expand 1 -pady 10 -padx .25i
	pack $f.b $f.msg -side left -fill both -expand 1 -pady 15 -padx .5i

	wm title $f "Held Mail Notification"
	wm iconname $f "HeldMail"
}

proc toggle_cmd {} {
	if {![winfo exists .command]} {
		command_init
	}
	if {[wm state .command] == "withdrawn"} {
		catch {wm deiconify .command}
		catch {.status.f.command config -text "HIDE COMMAND"}
	} else {
		catch {wm withdraw .command}
		catch {.status.f.command config -text "SHOW COMMAND"}
	}
}

proc toggle_backstatus {} {
	global backstatus NOSDIR NOSLOG
	if {$backstatus == 0} {
		incr backstatus
		pack .status.t -fill x -expand 1 -padx 5 -pady 5
		.status.t.text config -state normal
		.status.t.text delete 1.0 end
		.status.t.text insert end [exec tail $NOSDIR/$NOSLOG | tac]
		.status.t.text config -state disabled
	} else {
		incr backstatus -1
		pack forget .status.t
	}
}


proc incoming {str {andout 0}} {
	global remote firstinput
	if {$andout != 0 && [string range $str 0 1] == "ex"} {
		do_exit
		return
	}

	if {$firstinput == 0} {
		.command.in.text delete "insert -1 char"
	}
	.command.in.text insert end $str
#	.command.in.text see end
	.command.in.text yview -pickplace end
	if {$andout != 0} {
		.command.in.text insert end "\n"
		dp_send $remote $str
	}
	if {$firstinput != 0} {
		set firstinput 0
		.command.in.text insert end "txstat 1\n"
		dp_send $remote "txstat 1\n"
	}
	.command.in.text insert end "_"
}


proc get_remote {mode fid} {
	# Check if remote connection was closed on us
	global input leftovers oldnews STAThold STATalert STATscreen
	if [catch {dp_receive $fid} input] {
		puts stdout "Connection closed by foreign host."
		exit
	}
	if {$leftovers != 0} {
		set input "${oldnews}${input}"
#		puts "combined packets into: $input"
	}

	while {[set place [string first "~tk~" $input]] != -1} {
		global theend
		if {$place != 0}	{
			# send beginning stuff along
			set partial "[string range $input 0 [expr $place - 1]]"
			incoming $partial
			set input "[string range $input [expr $place + 4] end]"
		} else {
			set input "[string range $input 4 end]"
		}
		set theend [string first "~" $input]
		if {$theend == -1} {
			# message must be spanning into next buffer
			set leftovers 1
			set oldnews "~tk~[set input]"
			return
		}
		incr theend -1
		set oldhold [set STAThold]
		set oldalert [set STATalert]
		set oldscreen [set STATscreen]
		uplevel #0 eval {[string range $input 0 $theend]}
		if {$oldhold != $STAThold}	{
			if {$STAThold == 0} {
				catch {destroy .holdmail}
			} else {
				holdmail
			}
		}
		if {$oldalert != $STATalert}	{
			if {$STATalert == 0} {
				catch {destroy .newmail}
			} else {
				newmail
			}
		}
		if {$oldscreen != $STATscreen}	{
			if {$STATscreen != -1} {
				catch {destroy .chat}
			} else {
				newchat
			}
		}
		# move past the "~\n"
		set input "[string range $input [expr $theend + 3] end]"
	}

	if {[string length $input] < 4 && [string range $input 0 0] == "~"} {
		set leftovers 1
		set oldnews "[set input]"
		return
	}
	if {[string length $input] != 0} {
		incoming $input
	}
	set leftovers 0
}


proc get_remote_finger {name server mode fid} {
	# Check if remote connection was closed on us
	set infinger1 [dp_receive $fid]
	if {$infinger1 == ""} {
		wm title .$name "Finger $name@$server Complete..."
		return
	}

	regsub -all "\r" $infinger1 "" infinger

	catch {.$name.text config -state normal}
	catch {.$name.text insert end $infinger}
	catch {.$name.text config -state disabled}
#	.$name.text see end
	update idletasks
}


proc finger {name server} {
#	catch {destroy .$name}
	set f .$name
	if {![winfo exists $f]}	{
		toplevel .$f
		wm geometry $f +100+100
		text $f.text -width 80 -height 24 -borderwidth 2 -relief raised \
			-setgrid 1 -yscrollcommand "$f.scroll set" -state disabled
		scrollbar $f.scroll -command "$f.text yview"
		button $f.ok -text "OK" -command "destroy $f"
		pack $f.ok -side bottom -expand 1 -ipadx 10 -ipady 4 -pady 5
		pack $f.text -side left -fill both -expand 1
		pack $f.scroll -side right -fill y
#		bind $f <Return> "destroy $f"
	} else	{
		$f.text delete 1.0 end
	}
	wm title $f "Finger $name@$server (in progress)..."
	wm iconname $f $name
#	focus $f
	global $f.remote
	set $f.remote [lindex [dp_connect $server 79] 0]
	dp_send [set $f.remote] "$name\n"
	dp_filehandler [set $f.remote] r "get_remote_finger $name $server"
	update idletasks
}


proc anyfinger {} {
	global TNOShost thename sitename
	catch {destroy .finger}
	set f .finger
	toplevel $f
	wm geometry $f +100+100
	wm title $f "Finger"
	wm iconname $f "Finger"
	frame $f.site
	label $f.site.lab -text "Site Name:" -width 13
	bind $f.site.lab <Any-1> "set sitename $TNOShost"
	entry $f.site.ent -width 40 -textvariable sitename -relief sunken
	if {$sitename == ""}	{
		set sitename $TNOShost
	}
	pack $f.site.lab $f.site.ent -side left

	frame $f.name -relief raised
	label $f.name.lab -text "Finger Name:" -width 13
	entry $f.name.ent -width 40 -textvariable thename -relief sunken
	pack $f.name.lab $f.name.ent -side left

	pack $f.site $f.name -padx 1i -pady 15

	frame $f.but
	button $f.but.cancel -text "CANCEL" -command "destroy .finger"
	button $f.but.ok  -text "OK" -command {destroy .finger;catch {finger $thename $sitename}}
	pack $f.but.cancel $f.but.ok -side left -expand 1 -ipadx 10 -ipady 4 -padx 10 -pady 10

	pack $f.but

	bind $f.site.ent <Tab> "focus $f.name.ent"
	bind $f.site.ent <Return> {destroy .finger;catch {finger $thename $sitename}}
	bind $f.name.ent <Tab> "focus $f.site.ent"
	bind $f.name.ent <Return> {destroy .finger;catch {finger $thename $sitename}}
	bind $f <Destroy> "focus .status"
	focus $f.name.ent
}


proc get_remote_trace {iface ifacemode mode fid} {
	global TNOShost
	# Check if remote connection was closed on us
	set intrace1 [dp_receive $fid]
	if {$intrace1 == ""} {
		wm title .$name "Trace of $iface:$ifacemode @$TNOShost Complete..."
		return
	}

	regsub -all "\r" $intrace1 "" intrace

	catch {.trace$iface.text config -state normal}
	catch {.trace$iface.text insert end $intrace}
	catch {.trace$iface.text config -state disabled}
#	.trace$iface.text see end
	update idletasks
}


proc trace {iface mode} {
	global TNOShost
#	catch {destroy .trace$iface}
	set f .trace$iface
	if {![winfo exists $f]}	{
		toplevel .$f
		wm geometry $f +100+100
		text $f.text -width 80 -height 24 -borderwidth 2 -relief raised \
			-setgrid 1 -yscrollcommand "$f.scroll set" -state disabled
		scrollbar $f.scroll -command "$f.text yview"
		button $f.ok -text "OK" -command "destroy $f"
		pack $f.ok -side bottom -expand 1 -ipadx 10 -ipady 4 -pady 5
		pack $f.text -side left -fill both -expand 1
		pack $f.scroll -side right -fill y
#		bind $f <Return> "destroy $f"
	} else	{
		$f.text delete 1.0 end
	}
	wm title $f "Trace of $iface:$mode @$TNOShost (in progress)..."
	wm iconname $f "Trace $iface"
#	focus $f
	global $f.remote
	set $f.remote [lindex [dp_connect $TNOShost 1236] 0]
	dp_send [set $f.remote] "trace $iface $mode !\n"
	dp_filehandler [set $f.remote] r "get_remote_trace $iface $mode"
	update idletasks
}

proc start_trace_session {} {
	global TNOShost ifacemode interface
	catch {destroy .trace}
	set f .trace
	toplevel $f
	wm geometry $f +100+100
	wm title $f "Trace"
	wm iconname $f "Trace"
	frame $f.iface
	label $f.iface.lab -text "Interface Name:" -width 13
	entry $f.iface.ent -width 40 -textvariable interface -relief sunken
	pack $f.iface.lab $f.iface.ent -side left

	frame $f.mode -relief raised
	label $f.mode.lab -text "Mode Value:" -width 13
	entry $f.mode.ent -width 40 -textvariable ifacemode -relief sunken
	pack $f.mode.lab $f.mode.ent -side left

	pack $f.iface $f.mode -padx 1i -pady 15

	frame $f.but
	button $f.but.cancel -text "CANCEL" -command "destroy .trace"
	button $f.but.ok  -text "OK" -command {destroy .trace;catch {trace $interface $ifacemode}}
	pack $f.but.cancel $f.but.ok -side left -expand 1 -ipadx 10 -ipady 4 -padx 10 -pady 10

	pack $f.but

	bind $f.iface.ent <Tab> "focus $f.mode.ent"
	bind $f.iface.ent <Return> {destroy .trace;catch {trace $interface $ifacemode}}
	bind $f.mode.ent <Tab> "focus $f.iface.ent"
	bind $f.mode.ent <Return> {destroy .trace;catch {trace $interface $ifacemode}}
	bind $f <Destroy> "focus .status"
	focus $f.iface.ent
}


set TNOSport	7388
set firstinput  1
set backstatus  0
set leftovers	0


set STAThold 	0
set STATalert	0
set STATscreen  0
set STATscreencaller ""


catch {source $USERconfig}

wm withdraw .
status_init
command_init

set remote [lindex [dp_connect $TNOShost $TNOSport] 0]
dp_socketOption $remote noblock yes
dp_filehandler $remote r get_remote
#incoming "txstat 1" 1

