#!/usr/local/bin/wish8.4
#
#    TkNetmon - main module
#
#    $Log: TkNetmon.tcl,v $
#    Revision 1.6  2006/10/26 10:04:44  vfom
#    *** empty log message ***
#
#    Revision 1.5  2006/10/26 09:39:17  vfom
#    Added code for netstate server query
#
#    Revision 1.4  2006/10/19 08:40:26  vfom
#    .
#
#    Revision 1.3  2006/10/18 05:04:02  vfom
#    Added code for including prefs and internal vars to config
#
#    Revision 1.2  2006/10/05 05:33:01  vfom
#    include libexec to PATH
#
#    Revision 1.1.1.1  2006/09/21 10:57:02  vfom
#    Loading TkNetmon to CVS
#
#
set major [lindex [split $tk_version '.' ] 0]
set minor [lindex [split $tk_version '.' ] 1]
set app_path  [ file dirname [info script ] ]
if { $major < 8 } {
    puts "Need Tcl/Tk 8.0 at least to run TkNetmon. Exiting."
    exit;
} else {
    if { $minor < 2} {
	uplevel  #0 [list source [file join $app_path lib msgcat.tcl]]
    }
}
package require msgcat 
package require BLT 
package require Tktable
#
wm geometry . +50+50
#
# Initialise Internal variables
#
set nodeIndex 0
set ifIndex 0
set srvIndex 0
set bgpIndex 0
set activeID    ""
set node2update ""
set text2update ""
set line2update ""
set minX 0
set minY 0
set activeFile "noname.conf"
set activeFileChanged "no"
set editMode "Select"
set safeExitFlag 0
#
#  Loading system wide preferences
#  
#
if  [file readable [file join $app_path ".tknetmonrc" ]]  {
    source [file join $app_path ".tknetmonrc" ]
}
#
#
#  Loading user preferences
#  
if  [ info exists ::env(HOME)] { } else { set ::env(HOME) {} } 

if {  ![ file exists [ file join $::env(HOME) ".Tknetmon"] ] } {
    file mkdir [ file join $::env(HOME) ".Tknetmon" ]
}

if  [file readable [file join  $::env(HOME) ".Tknetmon" ".tknetmonrc"] ]  {
	source [file join $::env(HOME) ".Tknetmon" ".tknetmonrc"]  
}
if  [file readable [file join  $::env(HOME) ".Tknetmon" ".tknetmon-options"] ]  {
	source [file join $::env(HOME) ".Tknetmon" ".tknetmon-options"]  
}
#
# Adding project executables dir to $PATH
if { $tcl_platform(platform)=="unix"} {
    set ::env(PATH) [join [list [file join  $app_path "libexec"] $::env(PATH) ] ":" ]
} elseif { $tcl_platform(platform)=="windows" } {    
    set env(Path) [join [list [file join  $app_path "libexec"] $::env(Path)] ";" ]
}
#
msgcat::mcload [file join $app_path "locale"]
#
# Open logfiles
#
close stdout
set fd stdout
if { [catch { open $myLogFile "CREAT WRONLY APPEND" 0640 } fd ] } {
    error "Can't open logfile! : $fd "
    exit    
} else {
    fconfigure stdout -buffering none
    set t [clock format [clock seconds] ]
    set u $tcl_platform(user)
    puts "$t Started by $u"
}
#
close stderr
set fd stderr
if { [catch { open $myLogFile "CREAT WRONLY APPEND" 0640 } fd ] } {
    error "Can't open errlogfile! : $fd "
    exit    
} else {
    fconfigure stderr -buffering none
}
#
# Load background image (if any)
#
image create  photo background_image -width 1 -heigh 1
background_image blank
if { [file readable $background ] } {
    if { [catch {image create  photo background_image -file $background } ] } {
	puts stderr "Can't create background image from \"$background\"!"
    }
}
#
# Loading icons
#
#
array set arIcons  [ list ]
array set arImages  [ list ]
set iconList {}
set iconDir [ file join $app_path icons ]
foreach i [ glob [file join $iconDir *.gif] ] {
    set f [lindex [split $i "/"] end ]
    set n [lindex [split $f "." ] 0]
    if ![catch { image create photo -file $i } ikn ] {
	set arIcons($n) $ikn
	set arImages($ikn) $n
	lappend iconList $n
    }
}
#
if { [catch { $arIcons($nodeIcon) cget -file } ]} {
    puts stderr "Can't find default Node Icon - $nodeIcon !"
    exit 
}
#
# Making sound list
#
array set arSounds [ list]
set soundList {}
set soundDir [ file join $app_path sounds ]
foreach i [ glob [file join $soundDir *] ] {
    set f [lindex [split $i "/"] end ]
    set n [lindex [split $f "." ] 0]

    if { ![file isdirectory $i] && [file readable $i] } {
	set arSounds($n) $i
	lappend soundList $n
    }
}
#
# loading libraries
#
foreach i [ list "Logo.tcl" "Misc.tcl" "Node.tcl" "Dialogs.tcl" \
		"fontDialog.tcl" "Text.tcl" "Monitor.tcl"  \
		"SaveFile.tcl" "LoadFile.tcl" "LoadHostsFile.tcl" \
		"Link.tcl" "Line.tcl" "Preferences.tcl" \
		"IpAddrLib.tcl" "selectTargets.tcl" "menuConfig.tcl"\
		"snmpNames.tcl" "Discovery.tcl" "EventsLog.tcl" \
		"stateSignal.tcl"  "Methods.tcl" "ifGroups.tcl" \
		"Interface.tcl" "Service.tcl" "Bgp.tcl" \
		"Variables.tcl" "Traps.tcl" "Sql.tcl" "SNMP.tcl" \
		"LoadNetStateObjs.tcl" ]  {
    uplevel #0  " [list  source [file join $app_path "lib" $i] ] "
}
#
# Pregenerate GUI
#
wm withdraw .
Logo
#
proc SaveSettings {} {
  uplevel #0 {
    if {  ![ file exists [ file join ::env(HOME) ".Tknetmon"] ] } {
	file mkdir [ file join $::env(HOME) ".Tknetmon"]
    }
    if { [ catch { open [file join $::env(HOME) ".Tknetmon" ".tknetmonrc" ] 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 "#\n#  This is user default preferences for $appName\n#"
    puts $fd "#  Created by $u at $t with $appName-$appVersion"
    puts $fd "#          on $h\n#"
    # Global settings
    puts $fd "wm geometry .     [ wm geometry . ]"
    puts $fd "set maxX          $maxX"
    puts $fd "set maxY          $maxY"
    puts $fd "set globalBG      {$globalBG}"
    puts $fd "set globalFG      {$globalFG}"
    puts $fd "set browserProg   {$browserProg}"
    puts $fd "set myLogFile     {$myLogFile}"
    puts $fd "set background     {$background}"
    puts $fd "set menuVisible   $menuVisible"
    puts $fd "set scrollVisible $scrollVisible"
    puts $fd "set statusVisible $statusVisible"
    puts $fd "set editEnable    $editEnable"
    # puts $fd "set editMode    $editMode"
    # Line settings
    puts $fd "set lineWidth     $lineWidth"
    puts $fd "set lineColor     {$lineColor}"
    # Text settings
    puts $fd "set textAnchor    $textAnchor"
    puts $fd "set textJust      $textJust"
    puts $fd "set textFont      {$textFont}"
    puts $fd "set textFontColor {$textFontColor}"
    # Link settings
    puts $fd "set linkWidth     $linkWidth"
    puts $fd "set linkColor     {$linkColor}"
    # Node settings
    puts $fd "set nodeIcon      $nodeIcon"
    puts $fd "set nodeUpSound   \"$nodeUpSound\""
    puts $fd "set nodeDownSound \"$nodeDownSound\""
    puts $fd "set nodeFont      {$nodeFont}"
    puts $fd "set nodeFontColor {$nodeFontColor}"
    puts $fd "set nodeIP        $nodeIP"
    puts $fd "set node_SrcIP    $node_SrcIP"
    puts $fd "set node_SnmpVer  $node_SnmpVer"
    puts $fd "set node_getCommunity $node_getCommunity"
    puts $fd "set node_trapCommunity $node_trapCommunity"
    puts $fd "set nodePoll      $nodePoll"
    puts $fd "set nodeRetr      $nodeRetr"
    puts $fd "set nodeTmo       $nodeTmo"
    puts $fd "set dataSaveInterval       $dataSaveInterval"
    puts $fd "set node_dblClickCmd        {$node_dblClickCmd}"
    # Nodes autoplacement step values
    puts $fd "set h_autoplacement $h_autoplacement"
    puts $fd "set w_autoplacement $w_autoplacement"    
    puts $fd "set h_align $h_align"
    puts $fd "set w_align $w_align"    
#
    puts $fd "set monitor_mode $monitor_mode"
    puts $fd "set monitor_mode disable"
    puts $fd "set rootDir             {$rootDir}" 
    puts $fd "set netStateServer      {$netStateServer}" 
    puts $fd "set netStateServerPort  {$netStateServerPort}" 
    puts $fd "set fileHistory	      {$fileHistory}"
    puts $fd "set predIncludeFile     {$predIncludeFile}"
    puts $fd "set postIncludeFile     {$postIncludeFile}"
    puts $fd "set soundPlayCmd		{$soundPlayCmd}"
    puts $fd "set daemonRestartCmd	{$daemonRestartCmd}"
    close $fd
  }
}
proc alterFileHistory { f } {
    global fileHistory

    if { [winfo exists .menu.file] } {
        foreach fileName $fileHistory {
	    .menu.file delete [ .menu.file index $fileName] 
	}
    }
    set i [ lsearch -exact $fileHistory $f]
    if { $i == -1 } {
	set fileHistory [ lrange [linsert $fileHistory 0 $f] 0 3 ]	
    } else {
	set fileHistory [ lrange [linsert [ lreplace $fileHistory $i $i ] 0 $f] 0 3 ]	
    }


    if { [winfo exists .menu.file] } {
	set mindex [ .menu.file index [msgcat::mc "Quit"]] 
	set tmpList [list]
	# reverse fileHistory list
	foreach fileName $fileHistory {
	    set tmpList [linsert $tmpList 0 $fileName ]
	}
	foreach fileName $tmpList {
	    .menu.file insert [expr $mindex-1] command -label $fileName \
		-command [ list LoadFile $fileName  ]
	}
    }
}
proc del_fromFileHistory { f } {
    global fileHistory
    set i [ lsearch -exact $fileHistory $f]
    if { $i != -1 } {
	set fileHistory [ lreplace $fileHistory $i $i ] 	
	if { [winfo exists .menu.file] } {
	    .menu.file delete [ .menu.file index $f ] 
	}
    }
}

proc NewMap {} {
    if { $::activeFileChanged !="no" } {
	if {[ tk_dialog .savedialog [msgcat::mc "Stop!"] \
		  [msgcat::mc "Current active file was changed. Save it?"] info 0 [msgcat::mc "Save"] [msgcat::mc "Cancel"] ] == 0 } {
	    if { $::activeFile !="noname.conf"} {
		SaveFile $::activeFile
	    } else {
		SaveFile [ tk_getSaveFile -title [msgcat::mc "Save As"]]
	    }
	}
    }
    set ::monitor_mode "disable"
    set ::hostName {}
    set ::hostIP   {}
    set ::hostRTT  {}
    set ::hostCNT  {}
    set ::hostLRQ  {}
    set ::hostLRP  {}
    set ::hostLCH  {}
    set c .canvas
    foreach id [ $c find all ] {
	if { $id != "" } {
	    set type [.canvas type $id]
	    switch $type {
		window {
		    set win [.canvas itemcget $id -window ]
		    $c delete $id
		    destroy $win
		}
		image {}
		default {
		    $c delete $id
		}
	    }
	}
    }
    if {[array exists ::node_name]} {
	unset ::node_name \
	      ::node_key	\
	      ::node_state	\
	      ::node_flashcnt	\
	      ::node_health	\
	      ::node_ip \
	      ::node_srcip \
	      ::node_snmpget \
	      ::node_snmptrap \
	      ::node_poll \
	      ::node_retr \
	      ::node_dataSaveInterval \
	      ::node_tmo \
	      ::node_descr \
	      ::node_datadir \
	      ::node_font \
	      ::node_fontcolor \
	      ::node_icon \
	      ::node_menu \
	      ::node_action \
	      ::node_soundup \
	      ::node_sounddown \
	      ::node_methodslist \
	      ::node_snmpver \
	      ::node_snmpvarslist \
	      ::node_snmptrapslist \
	      ::node_iflist \
	      ::node_srvlist \
	      ::node_bgplist 
    }
    if {[array exists ::if_name]} {
	unset ::if_name \
	      ::if_owner \
	      ::if_descr \
	      ::if_datadir \
	      ::if_bandwidth \
	      ::if_methodslist
    }
    if {[array exists ::srv_name]} {
	unset ::srv_name \
	      ::srv_owner \
	      ::srv_descr \
	      ::srv_datadir \
	      ::srv_methodslist \
	      ::srv_snmpvarslist 
    }
    if {[array exists ::bgp_name]} {
	unset ::bgp_name \
	      ::bgp_owner \
	      ::bgp_descr \
	      ::bgp_datadir \
	      ::bgp_methodslist \
	      ::bgp_peerslist 
    }
    if {[array exists pollMBodyArray]} { array set pollMBodyArray [list] }
    set ::pollMethods $::pollMethodsInternal    
    if {[array exists ::saveMBodyArray]} { array set ::saveMBodyArray [list] }
    set ::saveMethods $::saveMethodsInternal
    if {[array exists ::trapMBodyArray]} { array set ::trapMBodyArray [list] }
    set ::trapMethods $::trapMethodsInternal
    set ::nodeIndex 0
    set ::ifIndex   0
    set ::srvIndex  0
    set ::bgpIndex  0
    set ::activeFile "noname.conf"
    set ::activeFileChanged "no"
}

proc SafeExit { } {
    global activeFile activeFileChanged
    global safeExitFlag tcl_platform
    wm withdraw .
#    SaveSettings
    if { $activeFileChanged !="no" } {
	if {[ tk_dialog .savedialog [msgcat::mc "Stop!"] \
		  [msgcat::mc "Current active file was changed. Save it?"] info 0 [msgcat::mc "Save"] [msgcat::mc "Cancel"] ] == 0 } {
	    if { $activeFile !="noname.conf"} {
		SaveFile $activeFile
	    } else {
		SaveFile [ tk_getSaveFile -title [msgcat::mc "Save As"]]	    
	    }
	}
    }
    set t [clock format [clock seconds] ]
    set u $tcl_platform(user)
    puts "$t Stopped by $u"
    set safeExitFlag 1
    destroy .
}
#
#
#
proc showAbout {} {
    global appName appVersion
    set w .about
    set v_about ""
    if [winfo exists $w ] {
	raise $w
	return
    }
    toplevel $w -class Dialog
    wm transient $w [winfo toplevel [winfo parent $w]]
    wm title $w [msgcat::mc "TkNetmon: About"]
#
    set f $w.label
        
    frame $f
    pack $f -side top -expand on -fill both
    label $f.l1 -text "$appName"
    label $f.l2 -text "version $appVersion"
    label $f.l3 -text "Made by vfom (vfom@narod.ru)"
    label $f.l4 -text "Web Site: http://vfom.narod.ru/TkNetmon"
    pack $f.l1 $f.l2 $f.l3 $f.l4 -padx 10 -pady 10

#
    set f $w.buttons
    frame $f
    pack $f -side bottom
    button $f.ok -text "Ok" -command "set v_about ''"
    pack $f.ok -padx 10 -pady 10
#
    wm withdraw $w
    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 geom $w +$x+$y
    wm deiconify $w
    raise $w
    set oldFocus [focus]
    set oldGrab [grab current $w]
    if {[string compare $oldGrab ""]} {
	set grabStatus [grab status $oldGrab]
    }
    grab $w
    focus $w.buttons.ok

    tkwait variable v_about

    catch {focus $oldFocus}
    grab release $w
    destroy $w
    if {[string compare $oldGrab ""]} {
	if {![string compare $grabStatus "global"]} {
	    grab -global $oldGrab
	} else {
	    grab $oldGrab
	}
    }
    return 

}

#
#
#
proc mkStatusBar {} {
    global hostName hostIP hostRTT hostCNT hostLRQ hostLRP hostLCH
    if { [winfo exists .statusbar1] || [winfo exists .statusbar2]} {
	return
    } else {
	frame .statusbar1
	set s .statusbar1
	label $s.hostname -text [msgcat::mc "Description: "] 
	label $s.hostName -textvariable hostName -relief sunken -bd 1 \
	    -anchor w -width 45

	label $s.hostip   -text [msgcat::mc "IP address: "]
	label $s.hostIP   -textvariable hostIP -relief sunken -bd 1 \
	    -anchor w -width 16

	label $s.hostrtt   -text [msgcat::mc "Round trip time: "]
	label $s.hostRTT   -textvariable hostRTT -relief sunken -bd 1 \
	    -anchor w -width 16
	label $s.hostcnt   -text [msgcat::mc "Hop count: "]
	label $s.hostCNT   -textvariable hostCNT -relief sunken -bd 1 \
	    -anchor w -width 6

	pack  $s.hostname $s.hostName $s.hostip $s.hostIP\
	    $s.hostrtt $s.hostRTT $s.hostcnt $s.hostCNT\
	    -side left -padx 2 -pady 2 -fill both

	frame .statusbar2
	set s .statusbar2

	label $s.hostlrq   -text [msgcat::mc "Last request time: "] 
	label $s.hostLRQ -textvariable hostLRQ -relief sunken -bd 1 \
	    -anchor w -width 25

	label $s.hostlrp   -text [msgcat::mc "Last reply time: "] 
	label $s.hostLRP -textvariable hostLRP -relief sunken -bd 1 \
	    -anchor w -width 25
	label $s.hostlch   -text [msgcat::mc "Last change time: "]
	label $s.hostLCH -textvariable hostLCH -relief sunken -bd 1 \
	    -anchor w -width 25
    
	pack  $s.hostlrq $s.hostLRQ  $s.hostlrp $s.hostLRP $s.hostlch $s.hostLCH\
	    -side left -padx 2 -pady 2 -fill both
	pack .statusbar2 .statusbar1  -side bottom -fill both -padx 2
	update idletasks
    }
}
proc rmStatusBar { } {
    destroy .statusbar1
    destroy .statusbar2
    update idletasks
}


proc mkMainMenu {} {
    global activeFile monitor_mode editMode editEnable browserProg fileHistory docPath
    if [winfo exists .menu ] { 
	return 
    }
    menu .menu -tearoff 0
    set m .menu.file
    menu $m -tearoff 0  
    .menu add cascade -label [msgcat::mc "File"] -menu $m 
    $m add command -label [msgcat::mc "New"] -command { NewMap }
    $m add command -label [msgcat::mc "Open"] \
	-command { LoadFile [ tk_getOpenFile -title [msgcat::mc "Open file"]] }
    $m add separator
    $m add command -label [msgcat::mc "Save"] -command { SaveFile $activeFile } \
	-accelerator F2
    $m add command -label [msgcat::mc "Save As"]  \
	-command { SaveFile [ tk_getSaveFile -title [msgcat::mc "Save As"]] }
    $m add separator
    foreach fileName $fileHistory {
	$m add command -label $fileName -command [list LoadFile $fileName ]
    }
    $m add separator
    $m add command -label [msgcat::mc "Quit"] -command SafeExit 


    set m .menu.edit
    menu $m -tearoff 0
    .menu add cascade  -label [msgcat::mc "Edit"]  -menu $m
    $m add command -label [msgcat::mc "Add Line"] \
	-command {
	    set editMode "AddLine1" 
	    .canvas configure -cursor tcross
	}
    $m add command -label [msgcat::mc "Add Text"] \
	-command { 
	    set editMode "AddText1" 
	    .canvas configure -cursor tcross
	}
    $m add command -label [msgcat::mc "Add Link"] \
	-command {
	    set editMode "AddLink1" 
	    .canvas configure -cursor tcross
	}
    $m add command -label [msgcat::mc "Add Node"] \
	-command { 
	    set editMode "AddNode"
	    .canvas configure -cursor tcross
	}

    $m add command -label [msgcat::mc "Delete"] \
	-command { 
	    set editMode "DeleteObj"
	    .canvas configure -cursor pirate
	}
    $m add separator
    $m add command -label [msgcat::mc "Load 'hosts'"]  \
	-command { LoadHostsFile [ tk_getOpenFile -title [msgcat::mc "Hosts file to load"]] }
    $m add command -label [msgcat::mc "Query NetState server"]  \
	-command "LoadNetStateObjs"
    $m add command -label [msgcat::mc "Discovery"]  \
	-command "discoveryMonitor"
    $m add separator
    $m add checkbutton -label [msgcat::mc "Disable Edit"] \
	-variable editEnable -offvalue "yes" -onvalue "no" \
	-command {
	    global editEnable
	    if {$editEnable=="no"} {
		mkDisableEdit
	    } else {
		mkEnableEdit
	    }
	}
    if {$editEnable=="no"} {
	set m .menu.edit
	set ind [$m index [msgcat::mc "Add Line"]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Add Text" ]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Add Link"]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Add Node" ]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Delete" ]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Load 'hosts'" ]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Discovery" ]]
	$m entryconfigure $ind -state disabled

    } else {
	set m .menu.edit
	set ind [$m index [msgcat::mc "Add Line"]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Add Text" ]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Add Link"]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Add Node" ]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Delete" ]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Load 'hosts'" ]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Discovery" ]]
	$m entryconfigure $ind -state normal
    }


    
    set m .menu.view
    menu $m -tearoff 0
    .menu add cascade  -label [msgcat::mc "View"]  -menu $m
    $m add checkbutton -label [msgcat::mc "Main Menu"] -accelerator "Ctrl-m"\
	-variable menuVisible -onvalue "yes" -offvalue "no" \
	-command { 
	    if { $menuVisible == "no" } { rmMainMenu}
	    if { $menuVisible == "yes" } { mkMainMenu}
	}
    $m add checkbutton -label [msgcat::mc "Status Bar"] -accelerator "Ctrl-s"\
	-variable statusVisible -onvalue "yes" -offvalue "no" \
	-command { 
	    if { $statusVisible == "no" } { rmStatusBar}
	    if { $statusVisible == "yes" } { mkStatusBar}
	}
    $m add checkbutton -label [msgcat::mc "Scroll Bars"] -accelerator "Ctrl-r"\
	-variable scrollVisible -onvalue "yes" -offvalue "no" \
	-command { 
	    if { $scrollVisible == "no" } { rmScrollBars}
	    if { $scrollVisible == "yes" } { mkScrollBars}
	}
    $m add command -label [msgcat::mc "Events Log"]  -accelerator "Ctrl-l" \
	-command {
	    set ::evLog::objects_flt_flag 0
	    set ::evLog::objects_flt [list]
	    EventsLog
	}

    set m .menu.pref
    menu $m -tearoff 0
    .menu add cascade -label [msgcat::mc "Preferences"] -menu $m
    $m add command -label [msgcat::mc "Common"] \
	-command  "editPrefs"
    $m add command -label [msgcat::mc "Service Menus"]  \
	-command "editServiceMenus"
    $m add command -label [msgcat::mc "Poll Methods"]  \
	-command {ViewMethods pollMethods pollMethodsInternal pollMBodyArray [msgcat::mc "Configure Poll Methods"]}
    $m add command -label [msgcat::mc "Save Methods"]  \
	-command {ViewMethods saveMethods saveMethodsInternal saveMBodyArray [msgcat::mc "Configure Save Methods"]}
    $m add command -label [msgcat::mc "Interfaces Groups"]  \
	-command ViewIfGrp
    $m add command -label [msgcat::mc "Variables"]  \
	-command ViewVariables
    $m add command -label [msgcat::mc "Traps"]  \
	-command {ViewTraps [msgcat::mc "Configure Traps"]}
    $m add command -label [msgcat::mc "SQL database"]  \
	-command "AskForSqlDatabase"
    $m add command -label [msgcat::mc "Sound Volume"]  \
	-command "exec $::soundCtrlCmd"
    $m add separator
    $m add command -label [msgcat::mc "Save settings"] \
	-command "SaveSettings" -accelerator "Ctrl-w"

    set m .menu.monitor
    menu $m -tearoff 0
    .menu add cascade  -label [msgcat::mc "Monitor"] -menu $m
    $m add command -label [msgcat::mc "Configure"] \
	-command "monitorProperties"
    $m add separator
    $m add command -label [msgcat::mc "ReStart NETMONd"] \
	-command "Restart_netmond"
    $m add separator
    $m add checkbutton -label [msgcat::mc "Enable update"] \
	-variable monitor_mode -offvalue "disable" -onvalue "enable" \
	-command {
	    if { $monitor_mode == "enable" } {
		Start_Update 
	    } else {
		Stop_Update
	    }
	}

    set m .menu.help
    menu $m -tearoff 0 
    .menu add cascade -label [msgcat::mc "Help"] -menu $m
    $m add command -label [msgcat::mc "User Guide"] \
	-command "exec $browserProg [file join  $docPath [msgcat::mc UserGuide.html]] &"
    $m add command -label [msgcat::mc "Programmer Guide"] \
	-command "exec $browserProg [file join  $docPath [msgcat::mc ProgrammerGuide.html]] &"
    $m add separator
    $m add command -label [msgcat::mc "About"] \
	-command "showAbout"

    . configure -menu .menu
    update idletasks
}
proc rmMainMenu {} {
    . configure -menu ""
    destroy .menu
    update idletasks
}

frame .grid
set c .canvas

canvas $c  -relief sunken -bg $globalBG 

pack .grid -fill both -expand on -padx 1 -pady 1 -side top

grid rowconfig    .grid 0 -weight 1 -minsize 0 
grid columnconfig .grid 0 -weight 1 -minsize 0 

grid $c -padx 1 -in .grid  \
    -row 0 -column 0 -rowspan 1 -columnspan 1 -sticky news

set globalCursor [.canvas cget -cursor ]
$c create image 0 0 -image background_image -anchor nw -tags bgimage

#
#
# Global canvas popup menu - active while edit enabled
#
#
set m .canvas.canvas_popup
menu $m -tearoff 0 
$m add command -label [msgcat::mc "Add Node"] -command { NewNode }
$m add command -label [msgcat::mc "Add Text"] -command { 
    global editMode
    set editMode "AddText1"
    .canvas configure -cursor tcross    
}
$m add command -label [msgcat::mc "Add Line"] -command { 
    global editMode
    set editMode "AddLine1"
    .canvas configure -cursor tcross
}
$m add command -label [msgcat::mc "Add Link"] -command { 
    global editMode
    set editMode "AddLink1"
    .canvas configure -cursor tcross
}
#
# Here we creates other popups
#
makeServiceMenus
mkTextPopupMenu 
mkLinePopupMenu 
mkLinkPopupMenu 
#
bind . <Destroy> { 
    if { [string match %W "."] } {
	global safeExitFlag
	if { $safeExitFlag == 0 } { SafeExit }
    }
}
#
proc mkScrollBars {} {
    global minX maxX minY maxY
    if { [winfo exists .hscroll] || [ winfo exists .vscroll]} {
	return 
    }
    set c .canvas
    updateScrollRegion {}
    scrollbar .hscroll -orient horiz -command "$c xview"
    scrollbar .vscroll -command "$c yview"
    frame .monitor_state -borderwidth 8 -relief raised
    grid .vscroll -in .grid  \
	-row 0 -column 1 -rowspan 1 -columnspan 1 -sticky news
    grid .hscroll -in .grid  \
	-row 1 -column 0 -rowspan 1 -columnspan 1 -sticky news
    $c configure -xscrollcommand ".hscroll set" -yscrollcommand ".vscroll set" 
    grid .monitor_state -in  .grid \
	-row 1 -column 1 -rowspan 1 -columnspan 1 -sticky news
    .monitor_state configure -bg grey
    bind .monitor_state <Double-1> ShowMonitorStatus	
    update idletasks
}
proc rmScrollBars {} {
    .canvas configure -xscrollcommand "" -yscrollcommand "" 
    destroy .hscroll
    destroy .vscroll
    destroy .monitor_state
    update idletasks
}
proc updateScrollRegion  {o_list}  {
    global minX minY maxX maxY
    set c .canvas
    if { $o_list=={} } { 
	set o_list [$c find all] 
	set minX 0
	set minY 0
	set maxX 800
	set maxY 600
    }
    foreach obj $o_list {
    	set obj_tags [.canvas itemcget $obj -tags]
	# skip background image object
	if { [string match {bgimage} $obj_tags  ] } { continue } 
	set bounds [$c bbox $obj ]
	set lux [lindex $bounds 0]
	set luy [lindex $bounds 1]
	set rdx [lindex $bounds 2]
	set rdy [lindex $bounds 3]
	if { $lux < $minX } { set minX $lux } 
	if { $luy < $minY } { set minY $luy } 
	if { $rdx > $maxX } { set maxX $rdx } 
	if { $rdy > $maxY } { set maxY $rdy } 
    }
    $c configure -scrollregion  "$minX $minY $maxX $maxY" 
}
#
#
#
proc mkDisableEdit {} {
    wm title . [ msgcat::mc "TkNetmon network map" ]
    if  [winfo exists .menu ] {
	set m .menu.edit
	set ind [$m index [msgcat::mc "Add Line"]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Add Text" ]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Add Link"]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Add Node" ]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Delete" ]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Load 'hosts'" ]]
	$m entryconfigure $ind -state disabled
	set ind [$m index [msgcat::mc "Discovery" ]]
	$m entryconfigure $ind -state disabled
    }

    uplevel #0  {
    bind Label <ButtonPress-1> {
	set ID [.canvas find withtag %W.icon ]
	if {$ID != ""} { ActivateNode %W } 
    }
    bind Label <ButtonPress-2>		{}
    bind Label <B2-Motion>		{}
    bind Label <ButtonRelease-2>	{}
    bind Label <Motion>			{}

    makeServiceMenus

#    bind Label <Button-3> {
#	global activeID
#	set activeID [ .canvas find withtag %W.icon ]
#	if { $activeID != "" } { tk_popup .canvas.label_popup_noedit %X %Y  }
#    }
    bind Label <Control-ButtonPress-3>	{}
    bind Label <Control-B3-Motion>	{}
    bind Label <Control-ButtonRelease-3> {}
#
    set c .canvas
    bind $c <ButtonPress-1>		{}
    bind $c <ButtonPress-2>		{}
    bind $c <B2-Motion>			{}
    bind $c <ButtonRelease-2>		{}
    bind $c <Motion>			{}
    bind $c <Button-3>			{}
    bind $c <Control-ButtonPress-3>	{}
    bind $c <Control-B3-Motion>		{}
    bind $c <Control-ButtonRelease-3>	{}
    update idletasks
    }
}
#
#
#
proc mkEnableEdit {} {
    global editMode
    wm title . [ msgcat::mc "TkNetmon network map: edit mode" ]
    if  [winfo exists .menu ] {
	set m .menu.edit
	set ind [$m index [msgcat::mc "Add Line"]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Add Text" ]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Add Link"]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Add Node" ]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Delete" ]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Load 'hosts'" ]]
	$m entryconfigure $ind -state normal
	set ind [$m index [msgcat::mc "Discovery" ]]
	$m entryconfigure $ind -state normal
    }

    uplevel #0  {
    bind Label <ButtonPress-1> {
	global startX startY globalXpos globalYpos editMode activeID  \
	    globalCursor  linkColor globalFG activeFileChanged node_key
	set ID [.canvas find withtag %W.icon ]
	if {$ID != ""} { 
	    switch $editMode {
                Moving { }
		Select { 
		    ActivateNode %W
		} 
		AddLink1 {
		    set startX [ lindex [ .canvas coords $ID ] 0 ]
		    set startY [ lindex [ .canvas coords $ID ] 1 ]
		    set activeID [.canvas create line $startX $startY $startX $startY \
			      -fill $globalFG -tags $node_name(%W) ]
		    set editMode "AddLink2"
		}
		AddLink2 {
		    
		    set stopX [ lindex [ .canvas coords $ID ] 0 ]
		    set stopY [ lindex [ .canvas coords $ID ] 1 ]
		    .canvas coords $activeID $startX $startY $stopX $stopY 
		    .canvas itemconfigure $activeID -fill $linkColor  \
			-tags [list [.canvas itemcget $activeID -tags ] $node_name(%W) ]
		    set activeFileChanged "yes"
		    set activeID ""
		    set editMode "Select"
		    .canvas configure -cursor $globalCursor
		    #set globalHint "Adding link done."
		}
		DeleteObj {
		    NodeDelete %W
		    set activeID ""
		    set editMode "Select"
		    set activeFileChanged "yes"
		    .canvas configure -cursor $globalCursor
		}
	    }
	}
    }
    #
    bind Label <ButtonPress-2> {
	global globalXpos globalYpos oldXpos oldYpos activeID globalFG editMode
	if { [string equal $editMode Select] } {
	    set ID [ .canvas find withtag %W.icon ]	
	    if { $ID != "" } {	
		set activeID $ID
		set globalXpos [ lindex [ .canvas coords $ID ] 0 ]
		set globalYpos [ lindex [ .canvas coords $ID ] 1 ]
		set oldXpos %X
		set oldYpos %Y
		set i_n [%W cget -image ]
		set i_hc [expr [image height $i_n]/2 +4 ]
		set i_wc [expr [image width $i_n]/2 +4 ]
		.canvas create rectangle [expr $globalXpos -$i_wc] [expr $globalYpos -$i_hc] \
		    [expr $globalXpos +$i_wc] [expr $globalYpos +$i_hc] -outline $globalFG \
		    -tags tempFrame
		set editMode "Moving"
	    }
	}
    }
    bind Label <B2-Motion> {
	global globalXpos globalYpos oldXpos oldYpos activeID minX minY maxX maxY
	if { [string equal $editMode Moving] } {
	    set deltaX [expr %X - $oldXpos ]
	    set deltaY [expr %Y - $oldYpos ]
	    set oldXpos %X
	    set oldYpos %Y
	    set globalXpos [expr $globalXpos + $deltaX]
	    set globalYpos [expr $globalYpos + $deltaY]
	    if { $activeID != "" } {
		set ID [ .canvas find withtag "tempFrame" ]
		if {$ID !="" } {
		    .canvas move $ID $deltaX $deltaY
		}
	    }
	}
    }
    bind Label <ButtonRelease-2> {
	global  activeID globalCursor editMode
	if { [string equal $editMode Moving ] } {
	    if {  $activeID != "" } { 
		set ID    [.canvas find withtag "tempFrame"] 
		if {$ID != ""} {
		    set newXY [.canvas coords $ID ]
		    set newX  [expr ([lindex $newXY 2]+[lindex $newXY 0])/2]
		    set newX  [expr int($newX/$::w_align) * $::w_align ]
		    set newY  [expr ([lindex $newXY 3]+[lindex $newXY 1])/2]
		    set newY  [expr int($newY/$::h_align) * $::h_align ]
		    .canvas delete $ID
		    NodeMove $activeID $newX  $newY
		}
	    set editMode "Select"
	    .canvas configure -cursor $globalCursor
	    }
	}
    }
#----------
    #
    bind Label <Control-ButtonPress-3> {
	global globalXpos globalYpos oldXpos oldYpos activeID globalFG editMode
	if { [string equal $editMode Select] } {
	    set ID [ .canvas find withtag %W.icon ]	
	    if { $ID != "" } {	
		set activeID $ID
		set globalXpos [ lindex [ .canvas coords $ID ] 0 ]
	        set globalYpos [ lindex [ .canvas coords $ID ] 1 ]
		set oldXpos %X
		set oldYpos %Y
		set i_n [%W cget -image ]
		set i_hc [expr [image height $i_n]/2 +4 ]
		set i_wc [expr [image width $i_n]/2 +4 ]
		.canvas create rectangle [expr $globalXpos -$i_wc] [expr $globalYpos -$i_hc] \
		    [expr $globalXpos +$i_wc] [expr $globalYpos +$i_hc] -outline $globalFG \
		    -tags tempFrame
		set editMode "Moving"
	    }
	}
    }
    bind Label <Control-B3-Motion> {
	global globalXpos globalYpos oldXpos oldYpos activeID minX minY maxX maxY
	if { [string equal $editMode Moving] } {
	    set deltaX [expr %X - $oldXpos ]
	    set deltaY [expr %Y - $oldYpos ]
	    set oldXpos %X
	    set oldYpos %Y
	    set globalXpos [expr $globalXpos + $deltaX]
	    set globalYpos [expr $globalYpos + $deltaY]
	    if { $activeID != "" } {
		set ID [ .canvas find withtag "tempFrame" ]
		if {$ID !="" } {
		    .canvas move $ID $deltaX $deltaY
		}
	    }
	}    
    }
    bind Label <Control-ButtonRelease-3> {
	global  activeID globalCursor editMode
	if { [string equal $editMode Moving] } {
	    if {  $activeID != "" } { 
		set ID    [.canvas find withtag "tempFrame"] 
		if {$ID != ""} {
		    set newXY [.canvas coords $ID ]
		    set newX  [expr ([lindex $newXY 2]+[lindex $newXY 0])/2]
		    set newY  [expr ([lindex $newXY 3]+[lindex $newXY 1])/2]
		    .canvas delete $ID
		    NodeMove $activeID $newX  $newY
		}
	    set editMode "Select"
	    .canvas configure -cursor $globalCursor
	    }
	}
    }
    bind Label <ButtonRelease-3> {
	global  activeID globalCursor editMode
	if { [string equal $editMode Select] || [string equal $editMode Moving] } {
	    if {  $activeID != "" } { 
		set ID    [.canvas find withtag "tempFrame"] 
		if {$ID != ""} {
		    .canvas delete $ID
		}
	    set editMode "Select"
	    .canvas configure -cursor $globalCursor
	    }
	}
    }

#-----------
#-----------

    bind Label <Motion> {
	global globalXpos globalYpos activeID editMode globalCursor \
	    startX startY globalHint
	set ID [.canvas find withtag %W.icon]
	if { $ID != "" } {
	    set bounds [ .canvas bbox $ID]
	    set lux [lindex $bounds 0]
	    set luy [lindex $bounds 1]
	    
	    set globalXpos [expr $lux+%x]
	    set globalYpos [expr $luy+%y]
	    switch $editMode {
		AddLine2 {
		    .canvas coords $activeID $startX $startY $globalXpos $globalYpos
		}
		AddLink2 {
		    .canvas coords $activeID $startX $startY $globalXpos $globalYpos
		}
	    }
	}
    }
    makeServiceMenus
    #
    #  Canvas bindings
    #
    bind $c <ButtonPress-1> {
	global activeID editMode globalXpos globalYpos globalCursor \
	    activeID startX startY textFont textFontColor textAnchor \
	    textJust globalFG activeFileChanged
	switch $editMode {
	    Moving { }
	    Select { }
	    AddNode  {
		NewNode
		set editMode "Select"
		.canvas configure -cursor $globalCursor
		#    set globalHint "Adding new node done."
	    }
	    AddLine1 {
		set startX $globalXpos
		set startY $globalYpos
		set activeID [ .canvas create line $startX $startY $globalXpos $globalYpos -fill $::globalFG ]
		set editMode "AddLine2"
		#   set globalHint "Select location and click left mouse button to place a line."
	    }
	    AddLine2 {
		.canvas coords $activeID $startX $startY $globalXpos $globalYpos
		.canvas itemconfigure $activeID -fill $::lineColor
		set editMode "Select"
		set activeFileChanged "yes"
		.canvas configure -cursor $globalCursor
		#  set globalHint "Adding new line done."
	    }
	    AddText1 {
		set activeID [.canvas create text $globalXpos $globalYpos -text "bla-bla" \
				  -font $::textFont -fill $::textFontColor \
				  -anchor $::textAnchor -justify $::textJust ]
		TextProperties $activeID
		set editMode "Select"
		.canvas configure -cursor $globalCursor
	    }
	    AddLink1 {
		set editMode "Select"
		.canvas configure -cursor $globalCursor
	    }
	    AddLink2 {
		.canvas delete $activeID
		set editMode "Select"
		.canvas configure -cursor $globalCursor
	    }
	    DeleteObj {
		set ID [.canvas find withtag "current" ]
		if { $ID != "" } {
		    set type [ .canvas type $ID ]
		    switch $type {
			line {	
			    .canvas delete $ID
			}
			text {
			    set tags [.canvas itemcget $ID -tags]
			    if {$tags=={current}} {
				.canvas delete $ID
			    }

			}
		    }
		}
				.canvas delete [.canvas find withtag tempFrame]
		set activeFileChanged "yes"
		set editMode "Select"
		.canvas configure -cursor $globalCursor
	    }
	}
    }
    #
    bind $c <ButtonPress-2> {
	global globalXpos globalYpos activeID editMode globalCursor globalHint\
	    lineMoveMode startX startY globalFG
	set globalXpos [ %W canvasx %x 1 ]
	set globalYpos [ %W canvasy %y 1 ]
	if { $editMode == "Select" } {
	    #set IDs [.canvas find closest $globalXpos $globalYpos 5 5 ]
	    #set ID  [lindex $IDs 0]
	    set ID [ .canvas find withtag "current"]
	    if { $ID != "" } {
		set type [ .canvas type $ID ]
		switch $type {
		    line {
			set tags [.canvas itemcget $ID -tags]
			if {$tags=={current}} {
			    set activeID $ID
			    set lXY [.canvas coords $ID ]
			    set uplX  [lindex $lXY 0]
			    set uplY  [lindex $lXY 1]
			    set dnrX  [lindex $lXY 2]
			    set dnrY  [lindex $lXY 3]
			    # arrow points close to line-start
			    if [expr  [expr abs($globalXpos-$uplX)<5]  && \
				    [expr abs($globalYpos-$uplY)<5 ]]  {  
				.canvas create rectangle [expr $uplX -5] [expr $uplY -5]\
				    [expr $uplX+5] [expr $uplY+5] -outline $globalFG \
				    -tags "tempFrame"
				set lineMoveMode "first"
				set editMode "Moving"
				# arrow points close to line-start
			    } elseif [expr [expr abs($globalXpos-$dnrX)<5]  && \
					  [expr abs($globalYpos-$dnrY)<5] ] {
				.canvas create rectangle [expr $dnrX -5] [expr $dnrY -5]\
				    [expr $dnrX+5] [expr $dnrY+5] -outline $globalFG \
				    -tags "tempFrame"
				set startX [lindex $lXY 0]
				set lineMoveMode "last"
				set editMode "Moving"
				# arrow points at the middle of line
			    } else {
				set id [.canvas create rectangle $uplX $uplY $dnrX $dnrY \
					    -outline $globalFG -tags "tempFrame" ]
				set lXY [.canvas coords $id ]
				set startX [lindex $lXY 0]
				set startY [lindex $lXY 1]
				set lineMoveMode "middle"
				set editMode "Moving"
			    }	     
			}
		    }
		    text {
			set tags [.canvas itemcget $ID -tags ]
			if {$tags=={current}} {
			    # This is simple text 
			    set activeID $ID
			    set bounds [.canvas bbox $ID ]
			    set lXY   [.canvas coords $ID ]
			    set uplX  [lindex $bounds 0]
			    set uplY  [lindex $bounds 1]
			    set dnrX  [lindex $bounds 2]
			    set dnrY  [lindex $bounds 3]
			    .canvas  create rect $uplX $uplY $dnrX $dnrY \
				-outline $globalFG -tags "tempFrame"
			    set startX $uplX
			    set startY $uplY
			    set editMode "Moving"
			}
		    } 
		    window {}
		    image {}
		}
	    }
	}
    }
    #
    bind $c <B2-Motion> {
	global globalXpos globalYpos activeID editMode globalCursor
	set lXpos [ %W canvasx %x 1 ]
	set lYpos [ %W canvasy %y 1 ]
	set f [.canvas find withtag "tempFrame" ]
	if { $f != "" } {
	    .canvas move $f [expr $lXpos -$globalXpos] [expr $lYpos -$globalYpos]
	}
	set globalXpos [ %W canvasx %x 1 ]
	set globalYpos [ %W canvasy %y 1 ]
    }
    #
    bind $c <ButtonRelease-2> { 
	global globalXpos globalYpos activeID editMode globalCursor \
	    lineMoveMode startX startY editMode activeFileChanged
	set f [.canvas find withtag "tempFrame" ]
	if { $f != "" & $activeID!=""  } {
	    # old coordinates
	    set lXY [.canvas coords $activeID ]  
	    set uplX  [lindex $lXY 0]
	    set uplY  [lindex $lXY 1]
	    # new coordinates
	    set fXY [.canvas coords $f ]  
	    set fX  [lindex $fXY 0]
	    set fY  [lindex $fXY 1]
	    switch [.canvas type $activeID] {
		text {
		    .canvas move $activeID [expr $fX-$startX] [expr $fY-$startY]
		    set activeFileChanged "yes"
		}
		line {
		    set dnrX  [lindex $lXY 2]
		    set dnrY  [lindex $lXY 3]
		    set activeFileChanged "yes"
		    switch $lineMoveMode {
			first {		
			    .canvas coords $activeID [expr $fX+5] [expr $fY+5] $dnrX $dnrY
			}
			last {
			    .canvas coords $activeID $uplX $uplY [expr $fX+5] [expr $fY+5]
			}
			middle {
			    .canvas move $activeID [expr $fX-$startX ] [expr $fY-$startY]
			}
		    }
		}
	    }
	    .canvas delete $f
	    updateScrollRegion $activeID
	    set activeID ""
	    set lineMoveMode ""
	}
	set editMode "Select"
      }

#
#-------------------------------
    bind $c <Control-ButtonPress-3> {
	global globalXpos globalYpos activeID editMode globalCursor globalHint\
	    lineMoveMode startX startY globalFG
	set globalXpos [ %W canvasx %x 1 ]
	set globalYpos [ %W canvasy %y 1 ]
	if { $editMode == "Select" } {
	    #set IDs [.canvas find closest $globalXpos $globalYpos 5 5 ]
	    #set ID  [lindex $IDs 0]
	    set ID [ .canvas find withtag "current"]
	    if { $ID != "" } {
		set type [ .canvas type $ID ]
		switch $type {
		    line {
			set tags [.canvas itemcget $ID -tags]
			if {$tags=={current}} {
			    set activeID $ID
			    set lXY [.canvas coords $ID ]
			    set uplX  [lindex $lXY 0]
			    set uplY  [lindex $lXY 1]
			    set dnrX  [lindex $lXY 2]
			    set dnrY  [lindex $lXY 3]
			    # arrow points close to line-start
			    if [expr  [expr abs($globalXpos-$uplX)<5]  && \
				    [expr abs($globalYpos-$uplY)<5 ]]  {  
				.canvas create rectangle [expr $uplX -5] [expr $uplY -5]\
				    [expr $uplX+5] [expr $uplY+5] -outline $globalFG \
				    -tags "tempFrame"
				set lineMoveMode "first"
				set editMode "Moving"
				# arrow points close to line-start
			    } elseif [expr [expr abs($globalXpos-$dnrX)<5]  && \
					  [expr abs($globalYpos-$dnrY)<5] ] {
				.canvas create rectangle [expr $dnrX -5] [expr $dnrY -5]\
				    [expr $dnrX+5] [expr $dnrY+5] -outline $globalFG \
				    -tags "tempFrame"
				set startX [lindex $lXY 0]
				set lineMoveMode "last"
				set editMode "Moving"
				# arrow points at the middle of line
			    } else {
				set id [.canvas create rectangle $uplX $uplY $dnrX $dnrY \
					    -outline $globalFG -tags "tempFrame" ]
				set lXY [.canvas coords $id ]
				set startX [lindex $lXY 0]
				set startY [lindex $lXY 1]
				set lineMoveMode "middle"
				set ::editMode "Moving"
			    }	     
			}
		    }
		    text {
			set tags [.canvas itemcget $ID -tags ]
			if {$tags=={current}} {
			    # This is simple text 
			    set activeID $ID
			    set bounds [.canvas bbox $ID ]
			    set lXY   [.canvas coords $ID ]
			    set uplX  [lindex $bounds 0]
			    set uplY  [lindex $bounds 1]
			    set dnrX  [lindex $bounds 2]
			    set dnrY  [lindex $bounds 3]
			    .canvas  create rect $uplX $uplY $dnrX $dnrY \
				-outline $globalFG -tags "tempFrame"
			    set startX $uplX
			    set startY $uplY
			    set ::editMode "Moving"
			}
		    } 
		    window {}
		    image {}
		}
	    }
	}
    }
    #
    bind $c <Control-B3-Motion> {
	global globalXpos globalYpos activeID editMode globalCursor
	if { [string equal $::editMode Moving] } {
	    set lXpos [ %W canvasx %x 1 ]
	    set lYpos [ %W canvasy %y 1 ]
	    set f [.canvas find withtag "tempFrame" ]
	    if { $f != "" } {
		.canvas move $f [expr $lXpos -$globalXpos] [expr $lYpos -$globalYpos]
	    }
	    set globalXpos [ %W canvasx %x 1 ]
	    set globalYpos [ %W canvasy %y 1 ]
	}
    }
    #
    bind $c <Control-ButtonRelease-3> { 
	global globalXpos globalYpos activeID editMode globalCursor \
	    lineMoveMode startX startY editMode activeFileChanged
	if { [string equal $::editMode Moving] } {
	    set f [.canvas find withtag "tempFrame" ]
	    if { $f != "" & $activeID!=""  } {
		# old coordinates
		set lXY [.canvas coords $activeID ]  
		set uplX  [lindex $lXY 0]
		set uplY  [lindex $lXY 1]
		# new coordinates
		set fXY [.canvas coords $f ]  
		set fX  [lindex $fXY 0]
		set fY  [lindex $fXY 1]
		switch [.canvas type $activeID] {
		    text {
			.canvas move $activeID [expr $fX-$startX] [expr $fY-$startY]
			set activeFileChanged "yes"
		    }
		    line {
			set dnrX  [lindex $lXY 2]
			set dnrY  [lindex $lXY 3]
			set activeFileChanged "yes"
			switch $lineMoveMode {
			    first {		
				.canvas coords $activeID [expr $fX+5] [expr $fY+5] $dnrX $dnrY
			    }
			    last {
				.canvas coords $activeID $uplX $uplY [expr $fX+5] [expr $fY+5]
			    }
			    middle {
				.canvas move $activeID [expr $fX-$startX ] [expr $fY-$startY]
			    }
			}
		    }
		}
		.canvas delete $f
		updateScrollRegion $activeID
		set activeID ""
		set lineMoveMode ""
	    }
	    set editMode "Select"
	}
    }
    bind $c <ButtonRelease-3> {
	global  activeID globalCursor editMode
	if {  $activeID != "" } { 
	    set ID    [.canvas find withtag "tempFrame"] 
	    if {$ID != ""} {
		.canvas delete $ID
	    }
	set editMode "Select"
	.canvas configure -cursor $globalCursor
	}
    }

#-------------------------------

    bind $c <Motion> {
	global globalXpos globalYpos activeID editMode globalCursor \
	    startX startY globalHint
	set globalXpos [ %W canvasx %x 1 ]
	set globalYpos [ %W canvasy %y 1 ]
	switch $editMode {
	    AddLine2 {
		.canvas coords $activeID $startX $startY $globalXpos $globalYpos
	    }
	    AddLink2 {
		.canvas coords $activeID $startX $startY $globalXpos $globalYpos
	    }
	}
    } 
    #
    bind .canvas <Button-3> {
	global globalXpos globalYpos activeID editMode
	set activeID [ .canvas find withtag "current"]
	if { $activeID!=""  & $editMode!="Moving" } {
	    set bounds [.canvas bbox $activeID ]
	    set type [.canvas type $activeID ]
	    set tags [.canvas itemcget $activeID -tags]
	    #
	    # Only free text, bgimage or line have no tags unless "current"
	    # 
	    if { $tags =="current" } {
		switch $type {
		    line {
			.canvas create rectangle [lindex $bounds 0] [lindex $bounds 1] \
			    [lindex $bounds 2] [lindex $bounds 3] -outline $globalFG -tags tempFrame
			tk_popup .canvas.canvas_line_popup %X %Y 
		    }
		    text {
			.canvas create rectangle [lindex $bounds 0] [lindex $bounds 1] \
			    [lindex $bounds 2] [lindex $bounds 3] -outline $globalFG -tags tempFrame
			tk_popup .canvas.canvas_text_popup %X %Y 
		    }
		    image {
			tk_popup .canvas.canvas_popup %X %Y 
		    }
		}
	    } else {
		switch $type {
		    line {
			# This is link
			.canvas create rectangle [lindex $bounds 0] [lindex $bounds 1] \
			    [lindex $bounds 2] [lindex $bounds 3] \
			    -outline $globalFG -tags tempFrame
			tk_popup .canvas.canvas_link_popup %X %Y 
		    }
		    image {
			tk_popup .canvas.canvas_popup %X %Y 
		    }	
		}
	    }
	} else {
	    tk_popup .canvas.canvas_popup %X %Y 
	}
    }
    bind .canvas <ButtonRelease-3> { 
	.canvas delete [ .canvas find withtag "tempFrame" ]
    }
    update idletasks
  }
}
#
# Global bindings
#
bind Label <Double-1> {
    global activeID
    set ID [.canvas find withtag %W.icon]
    if { $ID != "" } {
        set activeID $ID
        NodeAction
    }
}
#    
bind $c <Escape> {
    global editMode globalCursor
    set editMode "Select"
   .canvas configure -cursor $globalCursor
}

bind . <Control-m> {
    global menuVisible
    if [winfo exists .menu ] {
	rmMainMenu
	set menuVisible "no"
    } else {
	mkMainMenu
	set menuVisible "yes"
    }
}
bind . <Control-s> {
    global statusVisible
    if [winfo exists .statusbar1 ] {
	rmStatusBar
	set statusVisible "no"
    } else {
	mkStatusBar	
	set statusVisible "yes"
    }
}
bind . <Control-r> {
    global scrollVisible
    if [winfo exists .hscroll ] {
	rmScrollBars
	set scrollVisible "no"
    } else {
	mkScrollBars
	set scrollVisible "yes"
    }
}
bind . <Control-l> { 
    set ::evLog::objects_flt_flag 0
    set ::evLog::objects_flt [list]
    EventsLog
}
bind . <Control-u> {
    if { $::monitor_mode == "enable" } {
	Stop_Update 
    } else {
	Start_Update
    }
}
bind . <Control-w> { SaveSettings }
bind . <F2> "SaveFile $activeFile"
#
# 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
#
#
#
if {$statusVisible=="yes"} { mkStatusBar  }
if {$menuVisible=="yes"  } { mkMainMenu   }
if {$scrollVisible=="yes"} { mkScrollBars } 
if {$editEnable=="yes"   } { mkEnableEdit } else { mkDisableEdit }
#
foreach f $argv {
    global activeFile
    if [file readable $f] {
	LoadFile $f
	set activeFile $f
    }
}
#
if { $monitor_mode != "disable"} {
	uplevel #0 "after $dataReloadPeriod { ReloadStatus cycle }"
	uplevel #0 "after 500 FlashJustChange"
}

wm deiconify .
#