#!/usr/local/bin/wish8.4
#
package require BLT
package require Tktable
package require msgcat
#
namespace eval topNetFlows {
array set ::topNetFlows::TheColors [ list 0  red    1 blue      2 green  3 yellow 4 cyan 	\
			     5  orange 6 magenta   7 brown  8 pink   9 seagreen	\
			     10 violet  11 khaki 12 grey     ]
variable	colors_num [ array size ::topNetFlows::TheColors ] \
		active_colors_no	12	\
		other_color_idx		12
		
array set ::topNetFlows::elPos	[list]
array set ::topNetFlows::arData	[list]
variable	topNetFlows_exitFlag	0	\
		step			300	\
		depth			3	\
		scale			1	\
		scan_period		30000	\
		curr_timestamp		0	\
		last_known_tstamp	0	\
		time_window		0	\
		t_wind_size		[expr 3600*3 ]	\
		currMark		""	\
		xlabelwidth		1	\
		graphGeometry		""	\
		mode			"live"

variable	askForServer_exitFlag	0	\
		server			""	\
		port			0	\
		fd			""
				
variable	askForView_exitFlag	0	\
		view_name		"" 
		
variable	askForTimeWindow_exitFlag 0	\
		start_time		[clock scan "-1hour" ]	\
		interval		3600		

array set ::topNetFlows::tArr [list]
variable	viewFlows_exitFlag	0	\
		viewFlows_label		""	\
		viewFlows_sort_mode	"ascii"	\
		viewFlows_sort_order	"increasing"	\
		viewFlows_sort_col	0	\
		vfGeometry		""	\
		vfTableGeometry		""
variable	loadUpdate_mutex	0	\
		askServer_mutex		0
}
set ::GUI_pregenerate_list [ list ]
namespace eval ::Logo { 
variable	msg	"" 
}
#
proc Logo { } {
    set w [toplevel .logo -relief raised -borderwidth 2 ]
    wm withdraw $w
    wm overrideredirect $w 1
    
    label $w.l1 -text $::appName -font { Courier 36 bold }
    label $w.l2 -textvariable ::Logo::msg -width 40
    pack $w.l1  $w.l2 -side top  -pady 20   
    
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
    	- [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
    	- [winfo vrooty [winfo parent $w]]}]
    wm geometry $w +$x+$y
    wm deiconify $w
    raise $w
#
# Interface pregeneration function
#    
    foreach i $::GUI_pregenerate_list {
	set script [lindex $i 0]
	set ::Logo::msg [lindex $i 1 ]
	update idletasks
	eval $script	
    }    
# 
    destroy $w   
}
#
proc Help_GUIconstructor {} {
    set w .help
    if [ winfo exists $w ]  { 
	raise $w
	return
    }
    toplevel $w -relief raised -borderwidth 2  -class Dialog
    wm withdraw $w
    wm overrideredirect $w 1
    
    label $w.l1 -text "Hot keys"
    label $w.l2 -justify left -font {Arial 12} -text {
	F1 - This text.
	F2 - Save current configuration to file.
	F3 - Save graph to .GIF file.
	F4 - Save graph to .EPS file.
	F5 - Time window dialog ( for History mode )
	F7 - Server parameters dialog
	F8 - View selection dialog
	F10, Control-x, Alt-F4  - exit 
	F12 - refresh graph
	Alt-e  - load configuration from file
    }
    pack $w.l1  $w.l2 -side top  -pady 10   
    button $w.ok -text "Ok" -command "wm withdraw $w"
    pack $w.ok -side bottom -padx 10 -pady 10
    bind $w <Escape> "wm withdraw $w"    
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
    	- [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
    	- [winfo vrooty [winfo parent $w]]}]
    wm geometry $w +$x+$y
}	 
#
lappend ::GUI_pregenerate_list [list {Help_GUIconstructor} {Loading...} ]
#
proc Help {} {
    set w .help
    if { ![ winfo exists $w ] }  { 
	Help_GUIconstructor
    }
    wm deiconify $w
    raise $w
    focus $w.ok
    update idletasks
}
#
proc MapYGrid { } {
    set w .topNF
    set g $w.graph 
    if [ info exists ::topNetFlows::bandwidth ] {
	$g yaxis configure -min 0.0 -rotate 90  \
	     -title "% bandwidth [expr $::topNetFlows::bandwidth/1024] Kbit/sec" \
	    -command fkBand
	set band8 [expr double(($::topNetFlows::bandwidth*$::topNetFlows::step)/8) ] 
	set ::topNetFlows::prs50  [expr double($band8/2) ] 
	set ::topNetFlows::prs20  [expr double($band8/5) ] 
	set ::topNetFlows::prs10  [expr double($band8/10) ] 
	set ::topNetFlows::prs5   [expr double($band8/20) ]
	set ::topNetFlows::prs2   [expr double($band8/50) ]
	set ::topNetFlows::prs1   [expr double($band8/100) ]
	set ::topNetFlows::prs01  [expr double($band8/1000) ]
	set ::topNetFlows::ticks100 [ list \
	    [expr double(2 * $::topNetFlows::prs10) ] \
	    [expr double(4 * $::topNetFlows::prs10) ] \
	    [expr double(6 * $::topNetFlows::prs10) ] \
	    [expr double(8 * $::topNetFlows::prs10) ] \
	                     $band8 ]
	set ::topNetFlows::ticks50 [ list \
	    [expr double(    $::topNetFlows::prs10) ] \
	    [expr double(2 * $::topNetFlows::prs10) ] \
	    [expr double(3 * $::topNetFlows::prs10) ] \
	    [expr double(4 * $::topNetFlows::prs10) ] \
	                     $::topNetFlows::prs50  ]

	set ::topNetFlows::ticks20 [ list \
	    [expr double(4 * $::topNetFlows::prs1) ] \
	    [expr double(8 * $::topNetFlows::prs1) ] \
	    [expr double(12* $::topNetFlows::prs1) ] \
	    [expr double(16* $::topNetFlows::prs1) ] \
	                     $::topNetFlows::prs20 ]	                     
	set ::topNetFlows::ticks10 [ list \
	    [expr double(2 * $::topNetFlows::prs1) ] \
	    [expr double(4 * $::topNetFlows::prs1) ] \
	    [expr double(6 * $::topNetFlows::prs1) ] \
	    [expr double(8 * $::topNetFlows::prs1) ] \
	                     $::topNetFlows::prs10  ]
	set ::topNetFlows::ticks5 [ list \
	    [expr double(    $::topNetFlows::prs1) ] \
	    [expr double(2 * $::topNetFlows::prs1) ] \
	    [expr double(3 * $::topNetFlows::prs1) ] \
	    [expr double(4 * $::topNetFlows::prs1) ] \
	                     $::topNetFlows::prs5  ]
	set ::topNetFlows::ticks2 [ list \
	    [expr double(4 * $::topNetFlows::prs01) ] \
	    [expr double(8 * $::topNetFlows::prs01) ] \
	    [expr double(12* $::topNetFlows::prs01) ] \
	    [expr double(16* $::topNetFlows::prs01) ] \
	                     $::topNetFlows::prs2  ]
	set ::topNetFlows::ticks1 [ list \
	    [expr double(2 * $::topNetFlows::prs01) ] \
	    [expr double(4 * $::topNetFlows::prs01) ] \
	    [expr double(6 * $::topNetFlows::prs01) ] \
	    [expr double(8 * $::topNetFlows::prs01) ] \
	                     $::topNetFlows::prs1  ]	    
    } else {
	$g yaxis configure -min 0.0 -rotate 90   -title "Bytes/sec" -command fkBytes
    }
}
#
proc topNetFlows_GUIconstructor {} {
    set w .topNF
    set g $w.graph 

    toplevel $w 
    wm withdraw $w 

    blt::vector create ::topNetFlows::timeVector     
    blt::barchart $g -width 1024 
#
    $g element bind ChangeBase <ButtonRelease-1> {
	%W element closest %x %y ::topNetFlows::elPos    
	if { $::topNetFlows::elPos(name) != "" } {
	    set ::topNetFlows::curr_timestamp [expr int($::topNetFlows::elPos(x)) ]
	    ReColorBy $::topNetFlows::curr_timestamp
	    .topNF.graph marker configure $::topNetFlows::currMark -coords "$::topNetFlows::curr_timestamp 0" 
	}    
    }
#
    $g legend bind ShowDetails <ButtonPress-1> {
	set el [ %W legend get @%x,%y ]
	set lab [ %W element cget $el -label ]
	ViewFlows .topNF $::topNetFlows::view_name $lab $::topNetFlows::curr_timestamp
    }
#
    $g configure -barmode stacked
    $g configure -barwidth $::topNetFlows::step
    $g xaxis configure -command fTime -stepsize $::topNetFlows::step
    MapYGrid
    $g legend configure -position top -font fixed -anchor sw \
	-activebackground white 
#
    foreach c [lsort -integer -decreasing [ array names ::topNetFlows::TheColors ]] {
	blt::vector create "::$::topNetFlows::TheColors($c)Vector"     
	$g element create X$::topNetFlows::TheColors($c) -xdata ::topNetFlows::timeVector -ydata ::$::topNetFlows::TheColors($c)Vector \
	    -borderwidth 1 -fg $::topNetFlows::TheColors($c) -relief raised -bg white -label "" -bindtags "ChangeBase ShowDetails"
    }    
#    
    pack $g -fill both -expand on -padx 5

    set ::topNetFlows::xlabelwidth [ font measure [ $g axis cget x -tickfont ] "00:00:00" ]

    set ::topNetFlows::currMark [ $g marker create text -text "X" -coords "0 0" ]

    blt::ZoomStack .topNF.graph
    Blt_Crosshairs .topNF.graph

    if { $::topNetFlows::graphGeometry != "" } {
	wm geometry .topNF $::topNetFlows::graphGeometry
    }
    
    bind $w <F1> { 	Help     }
    bind $g <F1> { 	Help     }
    bind $w <Alt-F4> "destroy $w"
    bind $w <F2> {
	set f [ tk_getSaveFile -title "Save configuration to file" -defaultextension .cfg  ]
	if { $f != "" } { 
	    if [ catch { open $f "w" } fd ] {
		error $fd    
	    }
	    set t [clock format [clock seconds]]
	    set u $tcl_platform(user)
	    if { $tcl_platform(platform) =="unix" } {
    		set uname [open "|uname -mnrs" r]
    		set h [read -nonewline $uname] ; close $uname
	    } else {
		set h "localhost"
	    }
	    puts $fd "#  This is configuration file for $::myName"
	    puts $fd "#  Created by $u at $t with $::myName-$::appVersion"
	    puts $fd "#          on $h\n#"
	    puts $fd "set ::topNetFlows::server	$::topNetFlows::server"
	    puts $fd "set ::topNetFlows::port	$::topNetFlows::port"
	    puts $fd "set ::topNetFlows::view_name $::topNetFlows::view_name"	
	    if { [ string match $::topNetFlows::mode "history" ] } {
		puts $fd "set ::topNetFlows::start_time $::topNetFlows::start_time"
		puts $fd "set ::topNetFlows::interval  $::topNetFlows::interval" 	    
	    } 
#	    puts $fd "set ::topNetFlows::step $::topNetFlows::step"
#	    puts $fd "set ::topNetFlows::t_wind_size $::topNetFlows::t_wind_size \n#\n#\n#"
	    if [ info exists ::topNetFlows::bandwidth ] {
		puts $fd "set ::topNetFlows::bandwidth $::topNetFlows::bandwidth \n#"
	    }
	    puts $fd "set ::topNetFlows::viewFlows_sort_order $::topNetFlows::viewFlows_sort_order"
	    puts $fd "set ::topNetFlows::viewFlows_sort_mode $::topNetFlows::viewFlows_sort_mode"
	    puts $fd "set ::topNetFlows::viewFlows_sort_col $::topNetFlows::viewFlows_sort_col \n#\n#\n#"
	    puts $fd "set ::topNetFlows::graphGeometry [ wm geometry .topNF ]"
	    #
	    if [ winfo exists .topNF.vf.t.tx ]  {
		puts $fd "set ::topNetFlows::vfGeometry [ wm geometry .topNF.vf ]"
		puts $fd "set ::topNetFlows::vfTableGeometry \{[ .topNF.vf.t.tx width ]\}"
	    } else {
		puts $fd "set ::topNetFlows::vfGeometry $::topNetFlows::vfGeometry"
		puts $fd "set ::topNetFlows::vfTableGeometry  \{$::topNetFlows::vfTableGeometry\}\n#\n"
	    }
	    close $fd
	}
    }
    bind $w <Alt-e> {
	set f [ tk_getOpenFile -title "Open configuration file" -defaultextension .cfg  ]
	if { $f != "" } { 
	    source $f
	}    
	if { $::topNetFlows::graphGeometry != "" } {
	    wm geometry .topNF $::topNetFlows::graphGeometry
	}
	if { [ winfo exists .topNF.vf ]  && $::topNetFlows::vfGeometry != "" } {
	    wm geometry .topNF.vf $::topNetFlows::vfGeometry
	    if { [info exists ::topNetFlows::vfTableGeometry]  && $::topNetFlows::vfTableGeometry != 0 } {
		eval .topNF.vf.t.tx width [join $::topNetFlows::vfTableGeometry]
	    }
	}
	.topNF.graph configure -barwidth $::topNetFlows::step
	MapYGrid
	set p %W
	array unset ::topNetFlows::arData
	set ::topNetFlows::last_known_tstamp 0
	after cancel [ after info ]

	if [ string match $::topNetFlows::mode "history" ] {
	    wm title .topNF [join [list "HISTORY" [ AskServer "DESCRIBE VIEW \"$::topNetFlows::view_name\"" ] ] ]
	    after 100 AskForTimeWindow $p
	} else {
	    wm title .topNF [join [ AskServer "DESCRIBE VIEW \"$::topNetFlows::view_name\"" ] ]
	    if { $::topNetFlows::loadUpdate_mutex == 0 } { after 100 loadUpdate }
	}	
    }
    bind $w <F3> { 
	set f [ tk_getSaveFile -title "Save Graph to GIF file" -defaultextension .gif  ]
	if { $f != "" } { 
	    image create photo .photo_graph
	    .topNF.graph snap .photo_graph
	    .photo_graph write $f -format gif 
	    image delete .photo_graph
	}
    }
    bind $w <F5> "AskForTimeWindow $w"

    bind $w <F4> {
	set f [ tk_getSaveFile -title "Encap PostScript output file" -defaultextension .ps ]
	if { $f != "" } { .topNF.graph postscript output $f }
    }
    bind $w <F7>  "AskForServer $w"
    bind $w <F8>  "AskForView $w"
    bind $w <F10> "destroy $w"
    bind $w <Configure> {
	set times [list]
	foreach x [eval array names ::topNetFlows::arData {*,$::topNetFlows::TheColors(0),*} ] {
	    lappend times [join [ lindex [split [lindex $x 0] "," ] 0 ] ]
	}
	if { $times !="" } { 
    	    set times [lsort -integer -unique $times]
    	    set ntimes [llength $times]
    	    set nlabels  [expr [ winfo width .topNF.graph  ]/$::topNetFlows::xlabelwidth/2 ]
    	    if { $nlabels < 3 } { set nlabels 3 }
    	    set interval [expr ([lindex $times end] - [lindex $times 0])/$nlabels ]
    	    set subdiv   [expr $ntimes/$nlabels + 1  ]
    	    .topNF.graph xaxis configure -stepsize $interval  -subdivisions $subdiv  
	}
    }
    bind $w <F12> {
	set p %W
	array unset ::topNetFlows::arData
	set ::topNetFlows::last_known_tstamp 0
	after cancel [ after info ]

	if [ string match $::topNetFlows::mode "history" ] {
	    wm title .topNF [join [list "HISTORY" [ AskServer "DESCRIBE VIEW \"$::topNetFlows::view_name\"" ] ] ]
	    after 100 AskForTimeWindow $p
	} else {
	    wm title .topNF [join [ AskServer "DESCRIBE VIEW \"$::topNetFlows::view_name\"" ] ]
	    if { $::topNetFlows::loadUpdate_mutex == 0 } { after 100 loadUpdate }
	}
    }
}
lappend ::GUI_pregenerate_list [list {topNetFlows_GUIconstructor} {Loading...} ]
#
proc topNetFlows { } {
    set w .topNF
    
    if { ![ winfo exists $w ] } {
	topNetFlows_GUIconstructor
    }
    MapYGrid
    update idletasks
    if { [string equal [wm state $w] withdrawn ] } {
        wm deiconify $w
        raise $w
    } else {
        raise $w
    }    
}
#
proc fTime { w val } {
    return [ clock format [expr int($val) ] -format "%H:%M:%S" ]
}
#
proc fkBytes { w val } {
    return [ expr double($val/$::topNetFlows::step/$::topNetFlows::scale) ]
}
#
proc fkBand { w val } {
    return [ expr int(double(800*$val/$::topNetFlows::step/$::topNetFlows::bandwidth)) ]
}
#
proc ReColorBy { t } {
    set g .topNF.graph
    set t [ expr int($t) ]
    ::topNetFlows::timeVector	set {}
    for { set c 0} { $c<$::topNetFlows::active_colors_no} { incr c }   {
	set $::topNetFlows::TheColors($c)_mask [join [ lindex [split [lindex [ array names ::topNetFlows::arData $t,$::topNetFlows::TheColors($c),* ] 0] "," ] 2 ] ]
	if { ! [ eval string match $$::topNetFlows::TheColors($c)_mask "other"] } {
	    eval $g element configure X$::topNetFlows::TheColors($c) -label $$::topNetFlows::TheColors($c)_mask
	    ::$::topNetFlows::TheColors($c)Vector	set {}
	}
    }
    eval $g element configure X$::topNetFlows::TheColors($::topNetFlows::other_color_idx) -label "other"
    ::$::topNetFlows::TheColors($::topNetFlows::other_color_idx)Vector	set {}

    set times [list]
    foreach x [eval array names ::topNetFlows::arData {*,$::topNetFlows::TheColors(0),*} ] {
	lappend times [join [ lindex [split [lindex $x 0] "," ] 0 ] ]
    }
    set times [lsort -integer -unique $times]
    if { $times=="" } { return }
    set nlabels  [expr [ winfo  width $g  ]/$::topNetFlows::xlabelwidth/2 ]
    if { $nlabels < 3 } { set nlabels 3 }
    set interval [ expr ([lindex $times end] - [lindex $times 0])/$nlabels ]
    set ntimes   [ llength $times]
    set subdiv   [ expr ($ntimes/$nlabels) + 1  ]
    $g xaxis configure -stepsize $interval  -subdivisions $subdiv  
        
    set max_octets 0
    # итерация по известным отсчетам
    foreach tt $times { 
	if { $tt < $::topNetFlows::time_window } { 
	    # удалить устаревшие отсчеты
	    array unset ::topNetFlows::arData "$tt,*"
	    continue
	}	
	::topNetFlows::timeVector append $tt
	set total_octets 0
	set masks [list]
	foreach x [array names ::topNetFlows::arData "$tt,*" ] {            
	    set v $::topNetFlows::arData($x)                                
	    set total_octets [ expr $total_octets + $v ]
	    set m [join [ lindex [split $x  "," ] 2 ]]
	    if { ![string match $m "other"] } {
		lappend masks $m
	    }
	} 
	# подсчитали общее число байт  в данном отсчете
	if {$total_octets > $max_octets} {                     
	    set max_octets $total_octets
	} 
	# проверили на верхнюю планку
	for { set c 0} { $c<$::topNetFlows::active_colors_no} { incr c }   {
	    if { [ eval lsearch {$masks} $$::topNetFlows::TheColors($c)_mask ] >=0 } {	
		set val [lindex [eval array get ::topNetFlows::arData "$tt,*,{$$::topNetFlows::TheColors($c)_mask}" ] 1]	
		set total_octets [ expr $total_octets - $val ]
		::$::topNetFlows::TheColors($c)Vector append $val	
	    } else {
		::$::topNetFlows::TheColors($c)Vector append 0
	    }
	}
	::$::topNetFlows::TheColors($::topNetFlows::other_color_idx)Vector append $total_octets
    }
    # разметим шкалу Y
    if [info exists ::topNetFlows::bandwidth  ] {
	if { $max_octets > $::topNetFlows::prs50 } {
	    $g yaxis configure -majorticks $::topNetFlows::ticks100
	} elseif { $max_octets > $::topNetFlows::prs20 } {
	    $g yaxis configure -majorticks $::topNetFlows::ticks50
	} elseif { $max_octets > $::topNetFlows::prs10 } {
	    $g yaxis configure -majorticks $::topNetFlows::ticks20
	} elseif { $max_octets > $::topNetFlows::prs5 } {
	    $g yaxis configure -majorticks $::topNetFlows::ticks10
	} elseif { $max_octets > $::topNetFlows::prs2 } {
	    $g yaxis configure -majorticks $::topNetFlows::ticks5
	} elseif { $max_octets > $::topNetFlows::prs1 } {
	    $g yaxis configure -majorticks $::topNetFlows::ticks2
	} else {
	    $g yaxis configure -majorticks $::topNetFlows::ticks1
	}	
    } else { 
	set speed  [expr double($max_octets/$::topNetFlows::step) ]
	if { $speed < 2000 } {
	    set ::topNetFlows::scale 1    
	    $g yaxis  configure -title "Bytes/sec"
	} elseif { $speed < 2000000 } {
	    set ::topNetFlows::scale 1024    
	    $g yaxis  configure -title "Kbytes/sec"
	} else {
	    set ::topNetFlows::scale 1048576    
	    $g yaxis  configure -title "Mbytes/sec"
	}
	set mltpl [ expr double($::topNetFlows::scale * $::topNetFlows::step) ]	
	set mmx  [ expr double($max_octets/$mltpl) ]
	if { $mmx > 1000 } {
	    set	ticks [ list \
		[ expr double(400*$mltpl )  ]  \
		[ expr double(800*$mltpl )  ]  \
		[ expr double(1200*$mltpl )  ]  \
		[ expr double(1600*$mltpl )  ]  \
		[ expr double(2000*$mltpl )  ]  ]		
	} elseif { $mmx > 500 } {
	    set	ticks [ list \
		[ expr double(200*$mltpl )  ]  \
		[ expr double(400*$mltpl )  ]  \
		[ expr double(600*$mltpl )  ]  \
		[ expr double(800*$mltpl )  ]  \
		[ expr double(1000*$mltpl )  ]  ]		
	} elseif { $mmx > 200 } {
	    set	ticks [ list \
		[ expr double(100*$mltpl )  ]  \
		[ expr double(200*$mltpl )  ]  \
		[ expr double(300*$mltpl )  ]  \
		[ expr double(400*$mltpl )  ]  \
		[ expr double(500*$mltpl )  ]  ]		
	} elseif { $mmx > 100 } {
	    set	ticks [ list \
		[ expr double(40*$mltpl )  ]  \
		[ expr double(80*$mltpl )  ]  \
		[ expr double(120*$mltpl )  ]  \
		[ expr double(160*$mltpl )  ]  \
		[ expr double(200*$mltpl )  ]  ]		
	} elseif { $mmx > 50 } {
	    set	ticks [ list \
		[ expr double(20*$mltpl )  ]  \
		[ expr double(40*$mltpl )  ]  \
		[ expr double(60*$mltpl )  ]  \
		[ expr double(80*$mltpl )  ]  \
		[ expr double(100*$mltpl )  ]  ]		
	} elseif { $mmx > 20 } {
	    set	ticks [ list \
		[ expr double(10*$mltpl )  ]  \
		[ expr double(20*$mltpl )  ]  \
		[ expr double(30*$mltpl )  ]  \
		[ expr double(40*$mltpl )  ]  \
		[ expr double(50*$mltpl )  ]  ]		
	} elseif { $mmx > 5 } {
	    set	ticks [ list \
		[ expr double(2*$mltpl )  ]  \
		[ expr double(4*$mltpl )  ]  \
		[ expr double(6*$mltpl )  ]  \
		[ expr double(8*$mltpl )  ]  \
		[ expr double(10*$mltpl )  ]  ]		
	} elseif { $mmx > 2 } {
	    set	ticks [ list \
		[ expr double(1*$mltpl )  ]  \
		[ expr double(2*$mltpl )  ]  \
		[ expr double(3*$mltpl )  ]  \
		[ expr double(4*$mltpl )  ]  \
		[ expr double(5*$mltpl )  ]  ]		
	} elseif { $mmx > 1 } {
	    set	ticks [ list \
		[ expr double(0.4*$mltpl )  ]  \
		[ expr double(0.8*$mltpl )  ]  \
		[ expr double(1.2*$mltpl )  ]  \
		[ expr double(1.6*$mltpl )  ]  \
		[ expr double(2  *$mltpl )  ]  ]		
	} else {
	    set	ticks [ list \
		[ expr double(0.2*$mltpl )  ]  \
		[ expr double(0.3*$mltpl )  ]  \
		[ expr double(0.6*$mltpl )  ]  \
		[ expr double(0.7*$mltpl )  ]  \
		[ expr double(    $mltpl )  ]  ]		
	}
	#puts "Max= $max_octets $mmx $mltpl $speed \n $ticks"
	$g yaxis configure -majorticks $ticks		
    }
    $g configure  -title "Selection: [clock format $t ]"    
    set ::topNetFlows::curr_timestamp $t
}
#
#------------------------------------------------------------------------
proc  AskServer { q } {
    if { $::topNetFlows::askServer_mutex > 0 } { return "" }
    incr ::topNetFlows::askServer_mutex
    set p .topNF
    set g $p.graph
    if { [ catch { fconfigure $::topNetFlows::fd -peername } rez ] } {   
	catch { close $::topNetFlows::fd }
	if { [ catch { socket $::topNetFlows::server $::topNetFlows::port } ::topNetFlows::fd ] } {
	    puts "error $::topNetFlows::fd"
	    AskForServer .topNF
	    set ::topNetFlows::askServer_mutex 0
	    return ""
        }
	if { [string match $::topNetFlows::mode "history" ]} {
	        puts  $::topNetFlows::fd "HISTORY MODE\n\n"
		flush $::topNetFlows::fd
		gets $::topNetFlows::fd
		gets $::topNetFlows::fd
	}
    }
    set g_cursor [ $g cget -cursor]
    set p_cursor [ $p cget -cursor]
    $g configure -cursor watch
    $p configure -cursor watch
    update idletasks    
    puts  $::topNetFlows::fd "$q\n\n"
    flush $::topNetFlows::fd
    set rez ""
    set str ""
    while (1) {
	gets $::topNetFlows::fd str
	if { [string match $str "" ] } { break }
	lappend rez $str	
    }
    $g configure -cursor $g_cursor
    $p configure -cursor $p_cursor
    set ::topNetFlows::askServer_mutex 0
    return $rez
}
#
proc loadUpdate {} {
    if { $::topNetFlows::loadUpdate_mutex > 0 } { return }
    incr ::topNetFlows::loadUpdate_mutex 
    set str ""    
    set prev_last_known_tstamp $::topNetFlows::last_known_tstamp
    if { $::topNetFlows::last_known_tstamp > 0 } {
	set  t_update [ expr $::topNetFlows::last_known_tstamp - $::topNetFlows::step * $::topNetFlows::depth ]
    } else {
	set  t_update $::topNetFlows::last_known_tstamp
    }
    foreach str [ AskServer "UPDATE \"$::topNetFlows::view_name\" $t_update" ]  {
        set n_flows 0
	set tstamp [lindex $str 0]
	set ::topNetFlows::last_known_tstamp $tstamp
	set pair_list   [lindex $str 1]
	set pair_no     [llength $pair_list] 
	for { set i 0 } { $i<$pair_no } { set i [expr $i + 2] } {
	    set the_pair [ lrange $pair_list $i [expr $i + 1]  ] 
	    set k [lindex $the_pair 0 ]
	    set v [lindex $the_pair 1 ]
	    if { [string match $k "other" ] } {
		set ::topNetFlows::arData($tstamp,$::topNetFlows::TheColors($::topNetFlows::other_color_idx),{$k}) $v 
	    } else {
		set ::topNetFlows::arData($tstamp,$::topNetFlows::TheColors($n_flows),{$k}) $v 
		incr n_flows  
	    }		
	}  	
	while { $n_flows < $::topNetFlows::active_colors_no } {
	    set ::topNetFlows::arData($tstamp,$::topNetFlows::TheColors($n_flows),{}) 0
	    incr n_flows
	}    
    }
    if { $str != "" } {
	set ::topNetFlows::time_window [expr $::topNetFlows::last_known_tstamp - $::topNetFlows::t_wind_size ]
	if { $::topNetFlows::curr_timestamp == $prev_last_known_tstamp } {
		set recolor_timestamp $::topNetFlows::last_known_tstamp
	} else {
	    if { $::topNetFlows::time_window <= $::topNetFlows::curr_timestamp } {
		set recolor_timestamp $::topNetFlows::curr_timestamp	
	    } else {
		set recolor_timestamp $::topNetFlows::last_known_tstamp
	    }
	}
	ReColorBy $recolor_timestamp
	.topNF.graph marker configure $::topNetFlows::currMark -coords "$::topNetFlows::curr_timestamp 0" 
    }
#    after $::topNetFlows::scan_period loadUpdate
    set x [expr abs( 2 * $::topNetFlows::step + 5 + ($::topNetFlows::last_known_tstamp - [clock seconds] ) ) * 1000 ]
    after $x  loadUpdate
    set  ::topNetFlows::loadUpdate_mutex 0
}
#
proc loadHistory { } {
    array unset ::topNetFlows::arData
    set str ""    
    foreach str [ AskServer "HISTORY \"$::topNetFlows::view_name\" $::topNetFlows::start_time $::topNetFlows::interval" ]  {
        set n_flows 0
	set tstamp [lindex $str 0]
	set ::topNetFlows::last_known_tstamp $tstamp
	set pair_list   [lindex $str 1]
	set pair_no     [llength $pair_list] 
	for { set i 0 } { $i<$pair_no } { set i [expr $i + 2] } {
	    set the_pair [ lrange $pair_list $i [expr $i + 1]  ] 
	    set k [lindex $the_pair 0 ]
	    set v [lindex $the_pair 1 ]
	    if { [string match $k "other" ] } {
		set ::topNetFlows::arData($tstamp,$::topNetFlows::TheColors($::topNetFlows::other_color_idx),{$k}) $v 
	    } else {
		set ::topNetFlows::arData($tstamp,$::topNetFlows::TheColors($n_flows),{$k}) $v 
		incr n_flows  
	    }		
	}  	
	while { $n_flows < $::topNetFlows::active_colors_no } {
	    set ::topNetFlows::arData($tstamp,$::topNetFlows::TheColors($n_flows),{}) 0
	    incr n_flows
	}    
    }
    if { $str != "" } {
	ReColorBy $::topNetFlows::last_known_tstamp
	.topNF.graph marker configure $::topNetFlows::currMark -coords "$::topNetFlows::curr_timestamp 0" 
    }
}
#
#------------------------------------------------------------------------
#
proc ReSortTable { } {
    set tx .topNF.vf.t.tx 
    if { $::topNetFlows::viewFlows_sort_col < 0 } { return }
    $tx configure -state normal
    set dlist [list]
    set nrows [ $tx cget -rows ]
    set ncols [ $tx cget -cols ]
    for { set i 1 } { $i <$nrows} { incr i } {
	set str [list]
	for  { set j 0 } { $j <$ncols } { incr j } {	
	    if [ info exists ::topNetFlows::tArr($i,$j) ] {
		lappend str $::topNetFlows::tArr($i,$j)
	    }
	}
	lappend dlist $str
    }        
    if  ![ catch { lsort -index $::topNetFlows::viewFlows_sort_col -$::topNetFlows::viewFlows_sort_order -$::topNetFlows::viewFlows_sort_mode $dlist  } dlist ] {
        set i 1
	foreach s $dlist  {
	    set j 0
	    foreach token  $s  {
		set ::topNetFlows::tArr($i,$j) $token
		incr j
	    }
	    incr i
        }
    }
    $tx configure -state disabled
    set ::topNetFlows::viewFlows_label "SORTED by column '$::topNetFlows::tArr(0,$::topNetFlows::viewFlows_sort_col)', interpreted as '$::topNetFlows::viewFlows_sort_mode', order: '$::topNetFlows::viewFlows_sort_order'"
}
#
proc ViewFlows_GUIconstructor {  } {
    set p .topNF
    set w $p.vf
    set t $w.t
    set b $w.b

    toplevel $w -class Dialog
    wm withdraw $w
#
    grid rowconfig    $w 0 -weight 1 -minsize 0 
    grid columnconfig $w 0 -weight 1 -minsize 0 
    frame $t
    grid $t -in $w \
	-row 0 -column 0 -columnspan 1 -rowspan 1 -sticky news
    grid rowconfig    $t 0 -weight 1 -minsize 0 
    grid columnconfig $t 0 -weight 1 -minsize 0 
    table $t.tx -rows 1 -cols 1 \
	-variable ::topNetFlows::tArr	\
	-titlerows 1 -titlecols 0 \
	-xscrollcommand "$t.sx set" \
	-yscrollcommand "$t.sy set" \
	-maxwidth 300 -maxheight 400 \
	-bg white \
	-fg black \
	-selectmode single \
	-selecttype row \
	-rowstretch none -colstretch last \
	-drawmode single \
	-resizeborders both \
	-flashmode 0 \
	-state disabled \
	-borderwidth 1 \
	-anchor nw
    $t.tx tag config title -bg #0000bf00ff00 -relief groove
    $t.tx tag config sel  -bg #f700f700f700 -fg #48003d008b00
	
    grid $t.tx -in $t \
	-row 0 -column 0 -columnspan 1 -rowspan 1 -sticky news
    scrollbar $t.sy -command "$t.tx yview"
    grid $t.sy -in $t \
	-row 0 -column 1 -columnspan 1 -rowspan 1 -sticky news
    scrollbar $t.sx -command "$t.tx xview" -orient horiz
    grid $t.sx -in $t \
	-row 1 -column 0 -columnspan 1 -rowspan 1 -sticky news	
#    
    frame $b

    grid $b -in $w \
	-row 1 -column 0 -columnspan 1 -rowspan 1 -sticky news
    button $b.ok -text [msgcat::mc "Ok"]  -command "wm withdraw $w"
    pack $b.ok -side right
    label $b.lb -textvariable ::topNetFlows::viewFlows_label
    pack $b.lb -side left
    
    update idletasks
    if { [info exists ::topNetFlows::vfGeometry] } {
	wm geom $w $::topNetFlows::vfGeometry	
    } else {
	set x [expr {[winfo screenwidth $w] - [winfo reqwidth $w] \
    	    - [winfo vrootx [winfo parent $w]]}]
        set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]
	wm geom $w +$x+$y
    }
    if { [info exists ::topNetFlows::vfTableGeometry] } {
	eval $t.tx width [join $::topNetFlows::vfTableGeometry]
    }
    #	    
    bind $w <Control-o> {
	if { [string match $::topNetFlows::viewFlows_sort_order "increasing" ] } { 
	    set ::topNetFlows::viewFlows_sort_order "decreasing"
	} else {
	    set ::topNetFlows::viewFlows_sort_order "increasing"
	}
	ReSortTable
    }
    #
    bind $w <Control-m> {
	if { [string match $::topNetFlows::viewFlows_sort_mode "ascii" ] } { 
	    set ::topNetFlows::viewFlows_sort_mode "integer"
	} else {
	    set ::topNetFlows::viewFlows_sort_mode "ascii"
	}
	ReSortTable
    }
    #
    bind $w <F2> {
        set f [ tk_getSaveFile -title "View Flows output file"  ]
        if { $f != "" } {
	    if [ catch { open $f "w" } fd ] {
		error $fd    
	    }
	    set t [clock format [clock seconds]]
	    set u $tcl_platform(user)
	    if { $tcl_platform(platform) =="unix" } {
    		set uname [open "|uname -mnrs" r]
    		set h [read -nonewline $uname] ; close $uname
	    } else {
	    set h "localhost"
	    }
	    puts $fd "#  Created by $u at $t with $::myName-$::appVersion"
	    puts $fd "#          on $h"
	    puts $fd "# This is flows in [wm title .topNF.vf]"
	    puts $fd "# $::topNetFlows::viewFlows_label "
	    set x ""
	    foreach s [ array names ::topNetFlows::tArr "0,*" ] {
		lappend x $::topNetFlows::tArr($s)
	    }
	    puts $fd "#[join $x ";" ]"
	    set max_i [ .topNF.vf.t.tx cget -rows ]
	    set max_j [ .topNF.vf.t.tx cget -cols ]
	    for { set i 1 } { $i < $max_i } { incr i } {
		set x ""
		for { set j 0 } { $j < $max_j } { incr j } {
		    lappend x $::topNetFlows::tArr($i,$j)
		}
		puts $fd "[join $x ";" ]"
	    }	    
	    close $fd
	}
    }
    #
    bind $t.tx <Double-1> {
	if [ %W tag includes title @%x,%y ] {
	    set ::topNetFlows::viewFlows_sort_col [ %W index @%x,%y col ]
	    ReSortTable
	}
    }
    #
    bind $w <Destroy> { 
#    	if { [string match %W .topNF.vf.t.tx  ] } {
#	    set ::topNetFlows::vfTableGeometry "\{[ .topNF.vf.t.tx width ] \}"
#	}
	if { [string match %W .topNF.vf ] } {
	    set ::topNetFlows::vfGeometry [ wm geom .topNF.vf ] 
	}
    }
}
lappend ::GUI_pregenerate_list [list {ViewFlows_GUIconstructor} {Loading...} ]
#
proc ViewFlows { p v c tm } {
    set w $p.vf
    set t $w.t
    set b $w.b
    set g .topNF.graph

    if { ![winfo exists $w] } {
    	ViewFlows_GUIconstructor 
    }
    set ttm [ clock format $tm -format "%H:%M:%S" ]
    wm title $w "VIEW:  '$v'  CLASS  '$c'  AT $ttm"

    $t.tx configure -state normal
    array set ::topNetFlows::tArr [list]
#
    set t_cursor [$t.tx cget -cursor]
    $t.tx configure -cursor watch
    update idletasks    
#
    set dlist [ AskServer "GET FLOWS \"$v\" \"$c\" $tm" ]
    #puts "-$dlist-"
    if { $::topNetFlows::viewFlows_sort_col >=0 } {
	if  ![ catch { lsort -index $::topNetFlows::viewFlows_sort_col \
		-$::topNetFlows::viewFlows_sort_order \
		-$::topNetFlows::viewFlows_sort_mode $dlist  } rlist ] {
	    set dlist $rlist
	}
    }
#
    set i 1    
    set max_col 0
    foreach s  $dlist {
	set j 0
	foreach token  $s  {
	    set ::topNetFlows::tArr($i,$j) $token
	    incr j
	}
	if { $j >$max_col } {
	    set max_col $j
	}
	incr i
    }
#
    
    set dlist [join [ AskServer "GET FLOWS LEGEND \"$v\"" ] ]
    #puts "--$dlist--"
    if { $dlist !={} } {
	set j 0
	foreach s $dlist  {
	    set ::topNetFlows::tArr(0,$j) $s 
	    if { $j >$max_col } {
		set max_col $j
	    }
	    incr j
	}
    }
    $t.tx configure -rows $i -cols $max_col
#
    $t.tx configure -cursor $t_cursor
    $t.tx configure -state disabled
    if { $::topNetFlows::viewFlows_sort_col >=0 } {
	set ::topNetFlows::viewFlows_label "SORTED by column '$::topNetFlows::tArr(0,$::topNetFlows::viewFlows_sort_col)', interpreted as '$::topNetFlows::viewFlows_sort_mode', order: '$::topNetFlows::viewFlows_sort_order'"
    } else {
	set ::topNetFlows::viewFlows_label "SORTED:   none"
    }

    if { [string equal [wm state $w] withdrawn ] } {
        wm deiconify $w
    } else {
        raise $w
    }    
    focus $b.ok
}
#------------------------------------------------------------------------
proc AskForServer_GUIconstructor {  } {
    set p .topNF
    set w $p.askForServer

    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w "Host and port"
    wm withdraw $w

    set we $w.entryFrame
    frame $we -relief sunken -border 2
    pack $we -side top -padx 10 -pady 10 -ipadx 5 -ipady 5
    label $we.lhost -text "Host:" 	
    grid $we.lhost -in $we -column 0 -row 0 -sticky e
    entry $we.ehost -width 16
    grid $we.ehost -in $we -column 1 -row 0 -sticky w
    label $we.lport -text "Port:"
    grid $we.lport -in $we -column 0 -row 1 -sticky e
    entry $we.eport -width 16
    grid $we.eport -in $we -column 1 -row 1 -sticky w
    
#    pack $we.lhost $we.ehost $we.lport $we.eport -padx 5 -pady 5
         	
#    label $we.lstep -text "Step:"
#    grid $we.lstep -in $we -column 0 -row 2 -sticky e
#    entry $we.estep -width 16
#    grid $we.estep -in $we -column 1 -row 2 -sticky w
#    label $we.ltwind -text "Time_Window:"
#    grid $we.ltwind -in $we -column 0 -row 3 -sticky e
#    entry $we.etwind -width 16
#    grid $we.etwind -in $we -column 1 -row 3 -sticky w

#    pack $we.lstep $we.estep $we.ltwind $we.etwind -padx 5 -pady 5

    set wb $w.buttonFrame
    frame $wb
    pack $wb -side bottom
    button $wb.ok -text "Ok" -command "set ::topNetFlows::askForServer_exitFlag 1"
    button $wb.cancel -text "Cancel" -command "set ::topNetFlows::askForServer_exitFlag 2"
    pack $wb.cancel $wb.ok -side right -padx 5 -pady 5
    bind $w <Return> "$wb.ok invoke"
    
    update idletasks
    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]

    wm geometry  $w  +$x+$y
    bind $w <Escape> "set ::topNetFlows::askForServer_exitFlag 2"
    bind $w <Destroy> "set ::topNetFlows::askForServer_exitFlag 2"
}
lappend ::GUI_pregenerate_list [list {AskForServer_GUIconstructor} {Loading...} ]
#
proc AskForServer { p } {
    set w $p.askForServer
    set we $w.entryFrame
    set wb $w.buttonFrame
    
    if {![ winfo exists $w ]} {
	AskForServer_GUIconstructor 
    }
    $we.ehost delete 0 end	
    $we.ehost insert 0 $::topNetFlows::server
    $we.eport delete 0 end	
    $we.eport insert 0 $::topNetFlows::port

    focus $we.ehost
    
    update idletasks

    if { [string equal [wm state $w] withdrawn ] } {
        wm deiconify $w
        raise $w
    } else {
        raise $w
    }    

    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w

    tkwait variable ::topNetFlows::askForServer_exitFlag

    catch {focus $oldFocus}
    if { $::topNetFlows::askForServer_exitFlag==1 } {
	set ::topNetFlows::server [string trim [ $we.ehost get ] ]
	set ::topNetFlows::port   [string trim [ $we.eport get ] ]
	set params  [join [ AskServer "GET PARAMS" ] ]
	if { $params !=  "" } {
	    set ::topNetFlows::server_version  [ lindex $params 0 ]
	    set ::topNetFlows::step         [ lindex $params 1 ]
	    set ::topNetFlows::t_wind_size  [lindex $params 2 ]
	}
	MapYGrid
	.topNF.graph configure -barwidth $::topNetFlows::step
	AskForView  $p
    }    
    if { [winfo exists $w ] } { 
	grab release $w
	wm withdraw  $w
	$we.ehost delete 0 end	
	$we.eport delete 0 end	
    }
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
    focus $oldFocus
}
#------------------------------------------------------------------------
proc AskForView_GUIconstructor {  } {
    set p .topNF
    set w $p.askForView

    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w "Select VIEW"
    wm withdraw $w

    set f $w.entryFrame
    frame $f
    pack $f -side top -padx 5 -pady 5 -expand on -fill both
    grid rowconfig	$f 0 -weight 1 -minsize 0
    grid columnconfig   $f 0 -weight 1 -minsize 0
	
    listbox $f.sl -width 32 -height 16 -selectmode single \
	-yscrollcommand "$f.sy set"
    scrollbar $f.sy -command "$f.sl yview"
    grid $f.sl -in $f -row 0 -column 0 -sticky news
    grid $f.sy -in $f -row 0 -column 1 -sticky news         
    set wb $w.buttonFrame
    frame $wb
    pack $wb -side bottom
    button $wb.ok -text "Ok" -command "set ::topNetFlows::askForView_exitFlag 1"
    button $wb.cancel -text "Cancel" -command "set ::topNetFlows::askForView_exitFlag 2"
    pack $wb.cancel $wb.ok -side right -padx 5 -pady 5
    bind $w <Return> "$wb.ok invoke"

    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]

    wm geometry  $w  +$x+$y
    
    bind $w <Escape> "set ::topNetFlows::askForView_exitFlag 2"
    bind $w <Destroy> "set ::topNetFlows::askForView_exitFlag 2"
}
lappend ::GUI_pregenerate_list [list {AskForView_GUIconstructor} {Loading...} ]
#
proc AskForView { p } {
    set $p .topNF
    set w $p.askForView
    set f $w.entryFrame
    set wb $w.buttonFrame
    
    if { ![ winfo exists $w ] } {
	AskForView_GUIconstructor 
    }
    
    set v_list [join [ AskServer "GET VIEWS" ]]
    foreach i $v_list { $f.sl insert end $i }
    set idx [ lsearch -exact $v_list $::topNetFlows::view_name ]
    if { $idx >= 0 } {
	$f.sl selection clear 0 end    
	$f.sl selection set $idx
	$f.sl activate $idx
    }	
    
    focus $f.sl
    
    update idletasks
    if { [string equal [wm state $w] withdrawn ] } {
        wm deiconify $w
        raise $w
    } else {
        raise $w
    }    

    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w

    tkwait variable ::topNetFlows::askForView_exitFlag
    catch {focus $oldFocus}

    if { $::topNetFlows::askForView_exitFlag==1} {
	set ind [ $f.sl curselection ] 
	if { $ind !="" } { 
	    array unset ::topNetFlows::arData
	    set ::topNetFlows::view_name [$f.sl get [ $f.sl curselection ] ]
	    set ::topNetFlows::last_known_tstamp 0
	    after cancel [after info]
	    if { [string match $::topNetFlows::mode "history" ] } {
	    	wm title $p [join [list HISTORY [ AskServer "DESCRIBE VIEW \"$::topNetFlows::view_name\"" ] ] ]
		after 100 AskForTimeWindow $p
	    } else {
	    	wm title $p [join [ AskServer "DESCRIBE VIEW \"$::topNetFlows::view_name\"" ] ]
		if { $::topNetFlows::loadUpdate_mutex == 0 } { after 100 loadUpdate }
	    }
	}
    }

    if { [winfo exists $w ] } {
	grab release $w
	wm withdraw  $w
	$f.sl delete 0 end
    }	
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
}
#------------------------------------------------
proc AskForTimeWindow_GUIconstructor {  } {
    set p .topNF
    set w $p.askForTimeWindow

    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w "History Time Window"
    wm withdraw $w

    set we $w.entryFrame
    frame $we
    pack $we -side top
    label $we.lst -text "Start time:" 
    entry $we.est -width 24 -validate focusout \
	-invalidcommand { 
	    bell 
	    focus %W
	} \
	-vcmd { 
	    if { [ catch { clock scan [ %W get ] } x ] } { return 0 }
	    return 1
	}
    label $we.lint -text "Interval:"
    entry $we.eint -width 24 -validate focusout \
	-invalidcommand {
	    bell 
	    focus %W
	} \
	-vcmd { return [string is digit [%W get] ] }

    pack $we.lst $we.est $we.lint $we.eint -padx 5 -pady 5
         	
    set wb $w.buttonFrame
    frame $wb
    pack $wb -side bottom
    button $wb.ok -text "Ok" -command "set ::topNetFlows::askForTimeWindow_exitFlag 1"
    button $wb.cancel -text "Cancel" -command "set ::topNetFlows::askForTimeWindow_exitFlag 2"
    pack $wb.cancel $wb.ok -side right -padx 5 -pady 5
    bind $w <Return> "$wb.ok invoke"

    set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
	    - [winfo vrootx [winfo parent $w]]}]
    set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
	    - [winfo vrooty [winfo parent $w]]}]

    wm geometry  $w  +$x+$y

    bind $w <Escape> "set ::topNetFlows::askForTimeWindow_exitFlag 2"    
    bind $w <Destroy> "set ::topNetFlows::askForTimeWindow_exitFlag 2"    
}
lappend ::GUI_pregenerate_list [list {AskForTimeWindow_GUIconstructor} {Loading...} ]
#
proc AskForTimeWindow { p } {
    set p .topNF
    set w $p.askForTimeWindow
    set we $w.entryFrame
    set wb $w.buttonFrame

    if { ![ winfo exists $w ] }  {
	AskForTimeWindow_GUIconstructor 
    }
    $we.est  insert 0 [clock format $::topNetFlows::start_time -format "%Y-%m-%d %H:%M:%S"]
    $we.eint insert 0  $::topNetFlows::interval    
            
    update idletasks
    if { [string equal [wm state $w] withdrawn ] } {
        wm deiconify $w
        raise $w
    } else {
        raise $w
    }    

    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w
    focus $wb.ok

    tkwait variable ::topNetFlows::askForTimeWindow_exitFlag

    catch {focus $oldFocus}
    if { $::topNetFlows::askForTimeWindow_exitFlag == 1 } {
	set ::topNetFlows::start_time [clock scan [ $we.est get ] ]
	set ::topNetFlows::interval [string trim [ $we.eint get ] ]	
	after 100 loadHistory
    }
    if { [winfo exists $w ] } {
	grab release $w    
	wm withdraw $w
	$we.est  delete 0 end
        $we.eint delete 0 end
    }

    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
}
#------------------------------------------------------------------------
proc blt::ZoomStack { graph {start "Control-1"} {reset "ButtonPress-3"} } {
    global zoomInfo zoomMod
    
    blt::InitStack $graph
    
    if { [info exists zoomMod] } {
	set modifier $zoomMod
    } else {
	set modifier ""
    }
    bind bltZoomGraph <${modifier}${start}> { blt::SetZoomPoint %W %x %y }
    bind bltZoomGraph <${modifier}${reset}> { 
	if { [%W inside %x %y] } { 
	    blt::ResetZoom %W 
	}
    }
    blt::AddBindTag $graph bltZoomGraph 
}
proc blt::InitStack { graph } {
    global zoomInfo
    set zoomInfo($graph,interval) 100
    set zoomInfo($graph,afterId) 0
    set zoomInfo($graph,A,x) {}
    set zoomInfo($graph,A,y) {}
    set zoomInfo($graph,B,x) {}
    set zoomInfo($graph,B,y) {}
    set zoomInfo($graph,stack) {}
    set zoomInfo($graph,corner) A
}
proc blt::AddBindTag { graph name } {
    set oldtags [bindtags $graph]
    if { [lsearch $oldtags $name] < 0 } {
	bindtags $graph [concat $name $oldtags]
    }
}
#------------------------------------------------------------------------
# Wheel mouse support ( from "Bruce Stephens" <bruce@cenderis.demon.co.uk> )
#
proc mscroll { bindtag } {
     bind $bindtag <Button-5> [list %W yview scroll 1 units]
     bind $bindtag <Button-4> [list %W yview scroll -1 units]
     bind $bindtag <Shift-Button-5> [list %W yview scroll 5 units]
     bind $bindtag <Shift-Button-4> [list %W yview scroll -5 units]
     bind $bindtag <Control-Button-5> [list %W yview scroll 1 pages]
     bind $bindtag <Control-Button-4> [list %W yview scroll -1 pages]
}
#
proc mscroll_scrollbar { bindtag } {
     bind $bindtag <Button-5> {
	set cmd [%W cget -command]
	if [ string equal $cmd "" ] { return }
	uplevel #0 $cmd scroll 1 units
     }
     bind $bindtag <Button-4> {
	set cmd [%W cget -command]
	if [ string equal $cmd "" ] { return }
	uplevel #0 $cmd scroll -1 units
     }
     bind $bindtag <Shift-Button-5> {
	set cmd [%W cget -command]
	if [ string equal $cmd "" ] { return }
	uplevel #0 $cmd scroll 5 units
     }
     bind $bindtag <Shift-Button-4> {
	set cmd [%W cget -command]
	if [ string equal $cmd "" ] { return }
	uplevel #0 $cmd scroll -5 units
     }
     bind $bindtag <Control-Button-5> {
	set cmd [%W cget -command]
	if [ string equal $cmd "" ] { return }
	uplevel #0 $cmd scroll 1 pages
     }
     bind $bindtag <Control-Button-4> {
	set cmd [%W cget -command]
	if [ string equal $cmd "" ] { return }
	uplevel #0 $cmd scroll -1 pages
     }
}
#
mscroll Canvas
mscroll Table
mscroll Text						 
mscroll Listbox
mscroll_scrollbar Scrollbar
#

