#!/usr/bin/wish
## You can modify the following values :
# netwag_glo_dir_tmp :
#   description : temporary directory
#   examples : "/tmp", "$env(TEMP)", "C:/TEMP", "$env(HOME)/tmp"
# netwag_glo_file_session :
#   description : default filename containing the last session
#                 this file will be created the first time
#   examples : "/tmp/netwag.ses", "$env(HOME)/.netwag.ses",
#              "$netwag_glo_dir_tmp/netwag.ses"
# netwag_glo_bin_netwox :
#   description : path to netwox
#   examples : "netwox", "/usr/bin/netwox", "c:/netwox.exe"
set netwag_glo_dir_tmp "/tmp"
set netwag_glo_file_session "$env(HOME)/.netwag.ses"
set netwag_glo_bin_netwox "/usr/bin/netwox54"


#CHANGE NOTHING BELOW unless you know what you do
#CHANGE NOTHING BELOW unless you know what you do


# netwag_glo_bin_shell(prefer) :
#   description : preferred shell
#   examples : "sh"
# netwag_glo_bin_shell(shell_name) :
#   description : path to the given shell
#   examples : "/bin/sh", "/bin/csh"
# netwag_glo_bin_term(prefer) :
#   description : preferred terminal emulator
#   examples : "xterm", "gnome-terminal", "konsole"
# netwag_glo_bin_term(term_name) :
#   description : path to the given terminal emulator
#   examples : "/usr/bin/xterm"
set netwag_glo_bin_shell(prefer) "sh"
set netwag_glo_bin_shell(sh) "/bin/sh"
set netwag_glo_bin_shell(csh) "/bin/csh"
set netwag_glo_bin_shell(tcsh) "/bin/tcsh"
set netwag_glo_bin_shell(ksh) ""

set netwag_glo_bin_term(prefer) "xterm"
set netwag_glo_bin_term(xterm) "/usr/X11R6/bin/xterm"
set netwag_glo_bin_term(nxterm) ""
set netwag_glo_bin_term(eterm) ""
set netwag_glo_bin_term(rxvt) ""
set netwag_glo_bin_term(gnometerminal) ""
set netwag_glo_bin_term(konsole) ""
set netwag_glo_bin_term(dtterm) ""
set netwag_glo_bin_term(cmdtool) ""
set netwag_glo_versionmajor 5
set netwag_glo_versionminor 4
set netwag_glo_versionmicro 0

# color of buttons for invisible frames of notebook
set netwag_glo_notebook_button_hidden_color grey45

# color of button of the top frame of notebook
set netwag_glo_notebook_button_visible_color grey

# timeout for dynamic help in milliseconds
set netwag_glo_dynhelp_timeout 500

# background color for dynamic help
set netwag_glo_dynhelp_bgcolor "#FFFFBB"

# wrap size for dynamic help
set netwag_glo_dynhelp_wraplength 200

# size of the message listbox
set netwag_glo_msg_text_height 3

# size of the clipboard listbox
set netwag_glo_clipboard_text_height 6

# depending on system, those values will be grouped as
# netwag_glo_gui_selectcolor, and then unset
set netwag_glo_gui_selectcolor_unix black
set netwag_glo_gui_selectcolor_windows white
set netwag_glo_gui_selectcolormenu_unix black
set netwag_glo_gui_selectcolormenu_windows black

# size of the search listbox
set netwag_glo_gui_search_listbox_height 4

# size of the history listbox
set netwag_glo_gui_run_listbox_height 4

# size of the run command
set netwag_glo_gui_run_cmd_height 3

# background colors for main interface
#  listboxes
set netwag_glo_gui_bgcolor_listbox "#D0FFD0"
#  buttons
set netwag_glo_gui_bgcolor_button grey
#  background for unused zones
set netwag_glo_gui_bgcolor_unused grey
#  text which cannot be modified or selected
set netwag_glo_gui_bgcolor_text_display "#FFD0FF"
#  text which cannot be modified, but can be selected
set netwag_glo_gui_bgcolor_text_select "#D0FFFF"
#  text which can be modified and selected
set netwag_glo_gui_bgcolor_text_edit white

# messages colors
set netwag_glo_msg_color_info "#000000"
set netwag_glo_msg_color_warn "#FF00FF"
set netwag_glo_msg_color_err "#FF0000"

# color of data from stdin
set netwag_glo_run_color_stdin "#0020FF"

## CHANGE NOTHING BELOW
## CHANGE NOTHING BELOW
#################################################################
#################################################################
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_sys_platform;
global netwag_sys_os;

global netwag_sys_platform_unknown; set netwag_sys_platform_unknown 1
global netwag_sys_platform_unix; set netwag_sys_platform_unix 2
global netwag_sys_platform_windows; set netwag_sys_platform_windows 3
global netwag_sys_platform_macintosh; set netwag_sys_platform_macintosh 4

global netwag_sys_os_unknown; set netwag_sys_os_unknown 1
global netwag_sys_os_linux; set netwag_sys_os_linux 2
global netwag_sys_os_freebsd; set netwag_sys_os_freebsd 3
global netwag_sys_os_openbsd; set netwag_sys_os_openbsd 4
global netwag_sys_os_solaris; set netwag_sys_os_solaris 5
global netwag_sys_os_windows95; set netwag_sys_os_windows95 6
global netwag_sys_os_windows98; set netwag_sys_os_windows98 7
global netwag_sys_os_windowsme; set netwag_sys_os_windowsme 8
global netwag_sys_os_windowsnt4; set netwag_sys_os_windowsnt4 9
global netwag_sys_os_windows2000; set netwag_sys_os_windows2000 10
global netwag_sys_os_windowsxp; set netwag_sys_os_windowsxp 11
global netwag_sys_os_windows2003; set netwag_sys_os_windows2003 12


#################################################################
# PRIVATE FUNCTIONS
#################################################################


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Initialize global variables containing system
proc netwag_sys_init { } {
  global tcl_platform
  global netwag_sys_platform
  global netwag_sys_os
  global netwag_sys_platform_unknown
  global netwag_sys_platform_unix
  global netwag_sys_platform_windows
  global netwag_sys_platform_macintosh
  global netwag_sys_os_unknown
  global netwag_sys_os_linux
  global netwag_sys_os_freebsd
  global netwag_sys_os_openbsd
  global netwag_sys_os_solaris
  global netwag_sys_os_windows95
  global netwag_sys_os_windows98
  global netwag_sys_os_windowsme
  global netwag_sys_os_windowsnt4
  global netwag_sys_os_windows2000
  global netwag_sys_os_windowsxp
  global netwag_sys_os_windows2003

  if { $tcl_platform(platform) == "unix" } {
    set netwag_sys_platform $netwag_sys_platform_unix
  } elseif { $tcl_platform(platform) == "windows" } {
    set netwag_sys_platform $netwag_sys_platform_windows
  } elseif { $tcl_platform(platform) == "macintosh" } {
    set netwag_sys_platform $netwag_sys_platform_macintosh
  } else {
    set netwag_sys_platform $netwag_sys_platform_unknown
  }

  set osv $tcl_platform(osVersion)
  set netwag_sys_os $netwag_sys_os_unknown
  if { $tcl_platform(os) == "Linux" } {
    set netwag_sys_os $netwag_sys_os_linux
  } elseif { $tcl_platform(os) == "FreeBSD" } {
    set netwag_sys_os $netwag_sys_os_freebsd
  } elseif { $tcl_platform(os) == "OpenBSD" } {
    set netwag_sys_os $netwag_sys_os_openbsd
  } elseif { $tcl_platform(os) == "Solaris" } {
    set netwag_sys_os $netwag_sys_os_solaris
  } elseif { $tcl_platform(os) == "SunOS" } {
    set netwag_sys_os $netwag_sys_os_solaris
  } elseif { $tcl_platform(os) == "Windows 95" } {
    if { $osv == "4.0" } {
      set netwag_sys_os $netwag_sys_os_windows95
    } elseif { $osv == "4.10" } {
      set netwag_sys_os $netwag_sys_os_windows98
    } elseif { $osv == "4.90" } {
      set netwag_sys_os $netwag_sys_os_windowsme
    }
  } elseif { $tcl_platform(os) == "Windows NT" } {
    if { $osv == "4" } {
      set netwag_sys_os $netwag_sys_os_windowsnt4
    } elseif { $osv == "5.0" } {
      set netwag_sys_os $netwag_sys_os_windows2000
    } elseif { $osv == "5.1" } {
      set netwag_sys_os $netwag_sys_os_windowsxp
    } elseif { $osv == "5.2" } {
      set netwag_sys_os $netwag_sys_os_windows2003
    }
  }

  # display a warning for asking participation
  if { $netwag_sys_platform == $netwag_sys_platform_unknown ||
       $netwag_sys_os == $netwag_sys_os_unknown } {
    puts "I could not determine the platform :"
    puts "  platform : $tcl_platform(platform)"
    puts "  os : $tcl_platform(os)"
    puts "  osVersion : $tcl_platform(osVersion)"
    puts "Please contact Laurent."
  }

}


#################################################################
# INITIALIZE SYSTEM VARIABLES
#################################################################
netwag_sys_init


#################################################################
# DEFINE OF VARIABLES DEPENDING ON SYSTEM
#################################################################
if {$netwag_sys_platform == $netwag_sys_platform_unix} {
  set netwag_glo_gui_selectcolor $netwag_glo_gui_selectcolor_unix
  set netwag_glo_gui_selectcolormenu $netwag_glo_gui_selectcolormenu_unix
} elseif {$netwag_sys_platform == $netwag_sys_platform_windows} {
  set netwag_glo_gui_selectcolor $netwag_glo_gui_selectcolor_windows
  set netwag_glo_gui_selectcolormenu $netwag_glo_gui_selectcolormenu_windows
} else {
  set netwag_glo_gui_selectcolor $netwag_glo_gui_selectcolor_unix
  set netwag_glo_gui_selectcolormenu $netwag_glo_gui_selectcolormenu_unix
}
unset netwag_glo_gui_selectcolor_unix
unset netwag_glo_gui_selectcolor_windows
unset netwag_glo_gui_selectcolormenu_unix
unset netwag_glo_gui_selectcolormenu_windows


#################################################################
# CHECK TCL/TK VERSION
#################################################################
proc netwag_glo_check_version { versiontype theversion wantedmajor } {
  # theversion is w.x.y.z...
  set pospoint [string first "." $theversion]
  set versionmajor [string range $theversion 0 [expr $pospoint - 1]]
  if { $versionmajor < $wantedmajor } {
    set errms "Version of $versiontype is too old ($versionmajor<$wantedmajor)"
    puts $errms
    set winname ".errorwindow$versiontype"
    toplevel $winname
    label $winname.l -text $errms
    pack $winname.l
    tkwait visibility $winname
    after 5000
    exit
  }
}
netwag_glo_check_version "Tk" $tk_version 8
netwag_glo_check_version "Tcl" $tcl_version 8
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################


#################################################################
# PRIVATE FUNCTIONS
#################################################################
proc netwag_misc_string_replace_test { } {
  set ret [netwag_misc_string_replace "abcde" "c" "Z"]
  if { $ret != "abZde" } {
    puts "Bad output : $ret"
    exit
  }
  set ret [netwag_misc_string_replace "" "c" "Z"]
  if { $ret != "" } {
    puts "Bad output : $ret"
    exit
  }
  set ret [netwag_misc_string_replace "accde" "c" "ZY"]
  if { $ret != "aZYZYde" } {
    puts "Bad output : $ret"
    exit
  }
  set ret [netwag_misc_string_replace "ccdddc" "c" "ZY"]
  if { $ret != "ZYZYdddZY" } {
    puts "Bad output : $ret"
    exit
  }
  set ret [netwag_misc_string_replace "ccdddc" "cd" "ZY"]
  if { $ret != "cZYddc" } {
    puts "Bad output : $ret"
    exit
  }

  exit
}

proc netwag_misc_string_map_test { } {
  set ret [netwag_misc_string_map "abcde" {"c" "Z"}]
  if { $ret != "abZde" } {
    puts "Bad output : $ret"
    exit
  } else {puts "ok"}
  set ret [netwag_misc_string_map "" {"c" "Z"}]
  if { $ret != "" } {
    puts "Bad output : $ret"
    exit
  } else {puts "ok"}
  set ret [netwag_misc_string_map "accde" {"c" "ZY"}]
  if { $ret != "aZYZYde" } {
    puts "Bad output : $ret"
    exit
  } else {puts "ok"}
  set ret [netwag_misc_string_map "ccdddc" {"c" "ZY"}]
  if { $ret != "ZYZYdddZY" } {
    puts "Bad output : $ret"
    exit
  } else {puts "ok"}
  set ret [netwag_misc_string_map "ccdddc" {"cd" "ZY"}]
  if { $ret != "cZYddc" } {
    puts "Bad output : $ret"
    exit
  } else {puts "ok"}
  set ret [netwag_misc_string_map "abcdef" {"ab" "A" "de" "D"}]
  if { $ret != "AcDf" } {
    puts "Bad output : $ret"
    exit
  } else {puts "ok"}
  set ret [netwag_misc_string_map "1abcaababcabababc" {abc 1 ab 2 a 3 1 0}]
  if { $ret != "01321221" } {
    puts "Bad output : $ret"
    exit
  } else {puts "ok"}

}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Replace data in a string (needed because "string map" does not
## exists in version 8.0)
proc netwag_misc_string_replace { str strtoreplace replaceby } {

  if {![catch {string map [list "$strtoreplace" "$replaceby"] $str} newstr]} {
    return $newstr
  }

  # note : we cannot use "string first" with 5 parameters because
  # it is not supported in version 8.0
  set newstr ""
  set searchin $str
  set lengthstrtoreplace [string length $strtoreplace]
  while {1} {
    set pos [string first $strtoreplace $searchin]
    if { $pos == -1 } {
      # append end
      append newstr $searchin
      return $newstr
    }
    append newstr [string range $searchin 0 [expr $pos - 1]]
    append newstr $replaceby
    set startat [expr $pos + $lengthstrtoreplace]
    set searchin [string range $searchin $startat end]
  }

}

## Replace data in a string (needed because "string map" does not
## exists in version 8.0)
proc netwag_misc_string_map { str listab } {

  if {![catch {string map $listab $str} newstr]} {
    return $newstr
  }

  set listlength [llength $listab]
  set j 0
  for {set i 0} {$i < $listlength} {incr i} {
    set strfrom($j) [lindex $listab $i]
    incr i
    if {$i ==  $listlength} {
      # ignore error
      break;
    }
    set strto($j) [lindex $listab $i]
    incr j
  }

  set newstr ""
  set searchin $str
  set arraysize [array size strfrom]
  while {1} {

    set found 0
    for {set i 0} {$i < $arraysize} {incr i} {
      set pos [string first $strfrom($i) $searchin]
      if {$pos != -1} {
        if {!$found} {
          set found 1
          set minpos $pos
          set maxlength [string length $strfrom($i)]
          set useitem $i
        } else {
          if {$pos < $minpos} {
            set minpos $pos
            set maxlength [string length $strfrom($i)]
            set useitem $i
          } elseif {$pos == $minpos} {
            if {[string length $strfrom($i)] > $maxlength} {
              set maxlength [string length $strfrom($i)]
              set useitem $i
            }
          }
        }
      }
    }

    if { ! $found } {
      # append end
      append newstr $searchin
      return $newstr
    }
    append newstr [string range $searchin 0 [expr $minpos - 1]]
    append newstr $strto($useitem)
    set startat [expr $minpos + $maxlength]
    set searchin [string range $searchin $startat end]
  }

}

## Generate a random number used for filenames
proc netwag_misc_bigrand { } {
  set randnum [expr int(rand()*1000000000)]
  set randnum [expr $randnum - 10000000 * int($randnum/10000000)]
  return $randnum
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################


#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Display an error
proc netwag_priv_glo_errorunset { pname } {

  set msg "Variable $pname does not exist.\nSet its value, or if unsure reinstall netwag."
  set ans [tk_messageBox -message $msg -type okcancel -title "Warning" -icon warning]
  if { $ans == "cancel" } {
    exit
  }
}
proc netwag_priv_glo_errorbadval { msg } {

  set msg "$msg\nModify its value, or if unsure reinstall netwag."
  set ans [tk_messageBox -message $msg -type okcancel -title "Warning" -icon warning]
  if { $ans == "cancel" } {
    exit
  }
}

## Special check for the session file
proc netwag_priv_glo_check_file_session { pname } {
  upvar $pname name
  global $pname

  if { ! [info exists $pname] } {
    netwag_priv_glo_errorunset $pname
    set name ""
    return
  }

  set name [netwag_misc_string_replace $name "\\" "/"]

  # we do no more checks (exists, readable, writable) because this state
  # can change during execution. So, it's better to deal with
  # it in corresponding functions
}

## Special check for netwox path
proc netwag_priv_glo_check_bin_netwox { pname defaultvalue } {
  upvar $pname name
  global $pname

  if { ! [info exists $pname] }  {
    netwag_priv_glo_errorunset $pname
    set name $defaultvalue
    return
  }

}

## Check for a directory
proc netwag_priv_glo_check_directory { pname defaultvalue } {
  upvar $pname name
  global $pname

  if { ! [info exists $pname] }  {
    netwag_priv_glo_errorunset $pname
    set name $defaultvalue
    return
  }

  if { ! [file isdirectory $name] } {
    netwag_priv_glo_errorbadval "Variable $pname contains \"$name\" which is not a directory."
    set name $defaultvalue
  }
}

## Check if the file is writable
proc netwag_priv_glo_check_writable { pname defaultvalue } {
  upvar $pname name
  global $pname

  if { ! [info exists $pname] }  {
    netwag_priv_glo_errorunset $pname
    set name $defaultvalue
    return
  }

  if { ! [file readable $name] } {
    netwag_priv_glo_errorbadval "Variable $pname contains \"$name\" which is not a writable file."
    set name $defaultvalue
  }
}

## Concert backslashs
proc netwag_priv_glo_convslash { pname defaultvalue } {
  upvar $pname name
  global $pname

  if { ! [info exists $pname] }  {
    netwag_priv_glo_errorunset $pname
    set name $defaultvalue
    return
  }

  set name [netwag_misc_string_replace $name "\\" "/"]
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Check every global variable
proc netwag_glo_check { } {
  global netwag_sys_platform
  global netwag_sys_platform_unknown
  global netwag_sys_platform_unix
  global netwag_sys_platform_windows
  global env
  global netwag_glo_versionmajor
  global netwag_glo_versionminor
  global netwag_glo_versionmicro
  global netwag_glo_dir_tmp
  global netwag_glo_file_session
  global netwag_glo_bin_netwox
  global netwag_glo_notebook_button_hidden_color
  global netwag_glo_notebook_button_visible_color
  global netwag_glo_dynhelp_timeout
  global netwag_glo_dynhelp_bgcolor
  global netwag_glo_dynhelp_wraplength
  global netwag_glo_msg_color0
  global netwag_glo_msg_color1
  global netwag_glo_msg_text_height
  global netwag_glo_gui_selectcolor
  global netwag_glo_gui_selectcolormenu
  global netwag_glo_gui_search_listbox_height
  global netwag_glo_gui_run_listbox_height
  global netwag_glo_gui_run_cmd_height
  global netwag_glo_gui_bgcolor_listbox
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_text_display
  global netwag_glo_gui_bgcolor_text_select
  global netwag_glo_gui_bgcolor_text_edit
  global netwag_glo_msg_color_info
  global netwag_glo_msg_color_warn
  global netwag_glo_msg_color_err
  global netwag_glo_run_color_stdin

  # netwag_glo_dir_tmp must be a writable directory
  netwag_priv_glo_convslash netwag_glo_dir_tmp ""
  netwag_priv_glo_check_directory netwag_glo_dir_tmp ""
  if { $netwag_glo_dir_tmp != "" } {
    netwag_priv_glo_check_writable netwag_glo_dir_tmp ""
  }
  if { $netwag_glo_dir_tmp == "" } {
    if { $netwag_sys_platform == $netwag_sys_platform_windows } {
      if { [catch { set netwag_glo_dir_tmp $env(TEMP) }] } {
        if { [catch { set netwag_glo_dir_tmp $env(TMP) }] } {
          set netwag_glo_dir_tmp "."
        }
      }
    } elseif { $netwag_sys_platform == $netwag_sys_platform_unix } {
      set netwag_glo_dir_tmp "/tmp"
    } else {
      set netwag_glo_dir_tmp "."
    }
  }

  # netwag_glo_file_session should be a readable/writable file
  netwag_priv_glo_check_file_session netwag_glo_file_session

  # netwag_glo_bin_netwox
  netwag_priv_glo_convslash netwag_glo_bin_netwox "netwox"
  netwag_priv_glo_check_bin_netwox netwag_glo_bin_netwox "netwox"

  # we do not check those values, but we create the new values
  global netwag_sys_platform
  global netwag_sys_platform_unix
  if {$netwag_sys_platform == $netwag_sys_platform_unix} {
    global netwag_glo_bin_shell
    global netwag_glo_bin_shell_cmd
    global netwag_glo_bin_shell_param
    set prefer $netwag_glo_bin_shell(prefer)
    set netwag_glo_bin_shell_param $netwag_glo_bin_shell($prefer)
    set netwag_glo_bin_shell_cmd $netwag_glo_bin_shell($prefer)
    # with sh, csh, ksh and tcsh, it's always "-c"
    set netwag_glo_bin_shell_param "-c"
    global netwag_glo_bin_term
    global netwag_glo_bin_term_cmd
    global netwag_glo_bin_term_param
    set prefer $netwag_glo_bin_term(prefer)
    set netwag_glo_bin_term_cmd $netwag_glo_bin_term($prefer)
    switch -exact -- $prefer {
      "xterm" { set netwag_glo_bin_term_param "-e" }
      "nxterm" { set netwag_glo_bin_term_param "-e" }
      "eterm" { set netwag_glo_bin_term_param "-e" }
      "rxvt" { set netwag_glo_bin_term_param "-e" }
      "gnometerminal" { set netwag_glo_bin_term_param "-x" }
      "konsole" { set netwag_glo_bin_term_param "-e" }
      "dtterm" { set netwag_glo_bin_term_param "-e" }
      "cmdtool" { set netwag_glo_bin_term_param "" }
      default { set netwag_glo_bin_term_param "-e" }
    }
  }

}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

# by saving a session, we save :
#  - font (family and size)
#  - state of dynamic help (small yellow help displayed when inactive)
#  - width and height of the window
#  - the two clipboards
#  - the history of run commands

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_session_font_family
global netwag_session_font_size
global netwag_session_dynhelp_active
global netwag_session_window_width
global netwag_session_window_height
global netwag_session_clipboard_small
global netwag_session_clipboard_big
global netwag_session_run_history
global netwag_session_clipboard_text_height
global netwag_session_couldload
global netwag_sessionvars_error


#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Initialize default values for session variables
proc netwag_priv_sessionvars_initdefault { } {
  global netwag_session_font_family
  global netwag_session_font_size
  global netwag_session_dynhelp_active
  global netwag_session_window_width
  global netwag_session_window_height
  global netwag_session_clipboard_small
  global netwag_session_clipboard_big
  global netwag_session_run_history
  global netwag_session_clipboard_text_height
  global netwag_sys_platform
  global netwag_sys_platform_windows

  set netwag_session_dynhelp_active 1
  if {$netwag_sys_platform == $netwag_sys_platform_windows} {
    set netwag_session_font_family Arial
    set netwag_session_font_size 9
    set netwag_session_window_width 490
    set netwag_session_window_height 405
  } else {
    set netwag_session_font_family fixed
    set netwag_session_font_size 10
    set netwag_session_window_width 490
    set netwag_session_window_height 405
  }
  set netwag_session_clipboard_small {}
  set netwag_session_clipboard_big {}
  catch {unset netwag_session_run_history}
  set netwag_session_run_history(0) {1}
  set netwag_session_run_history(1) {2}
  set netwag_session_run_history(2) {22 "hello"}
  set netwag_session_run_history(3) {23}

  set netwag_session_clipboard_text_height 6

  return 0
}

## Initialize current values for session variables
proc netwag_priv_sessionvars_initcurrent { } {
  global netwag_session_font_family
  global netwag_session_font_size
  global netwag_session_dynhelp_active
  global netwag_session_window_width
  global netwag_session_window_height
  global netwag_session_clipboard_small
  global netwag_session_clipboard_big
  global netwag_session_run_history
  global netwag_session_clipboard_text_height

  # font_family and font_size
  # used directly

  # netwag_session_dynhelp_active
  # used directly

  # window_width and window_height
  set netwag_session_window_width [winfo width .]
  set netwag_session_window_height [winfo height .]

  # clipboard_small and big
  global netwag_gui_text_small_clipboard
  global netwag_gui_text_big_clipboard
  set netwag_session_clipboard_small [$netwag_gui_text_small_clipboard get 1.0 end]
  set netwag_session_clipboard_big [$netwag_gui_text_big_clipboard get 1.0 end]

  # run history
  global netwag_priv_runhist_lb
  set arraysize [$netwag_priv_runhist_lb size]
  catch {unset netwag_session_run_history}
  for {set i 0} {$i < $arraysize} {incr i} {
    set netwag_session_run_history($i) [$netwag_priv_runhist_lb get $i]
  }

  # netwag_glo_clipboard_text_height
  global netwag_glo_clipboard_text_height
  set netwag_session_clipboard_text_height $netwag_glo_clipboard_text_height

  return 0
}

## Applies values for the session
proc netwag_priv_sessionvars_apply { } {
  global netwag_session_font_family
  global netwag_session_font_size
  global netwag_session_dynhelp_active
  global netwag_session_window_width
  global netwag_session_window_height
  global netwag_session_clipboard_small
  global netwag_session_clipboard_big
  global netwag_session_run_history
  global netwag_session_clipboard_text_height

  # font_family and font_size
  netwag_font_change $netwag_session_font_family $netwag_session_font_size

  # dynhelp_active : nothing to do

  # window_width and window_height
  set newgeometry "$netwag_session_window_width"
  append newgeometry "x"
  append newgeometry "$netwag_session_window_height"
  set rx [winfo rootx .]
  set ry [winfo rooty .]
  if { $rx!=0 && $ry!=0 } {
    # we add them otherwise, if [wm geometry .] ends with +0+0, it
    # will be located in the corner.
    append newgeometry "+$rx+$ry"
  }
  wm geometry . "$newgeometry"

  # small clipboard
  global netwag_gui_text_small_clipboard
  $netwag_gui_text_small_clipboard delete 1.0 end
  $netwag_gui_text_small_clipboard insert end $netwag_session_clipboard_small

  # big clipboard
  global netwag_gui_text_big_clipboard
  $netwag_gui_text_big_clipboard delete 1.0 end
  $netwag_gui_text_big_clipboard insert end $netwag_session_clipboard_big

  # run history
  global netwag_priv_runhist_lb
  $netwag_priv_runhist_lb delete 0 end
  set arraysize [array size netwag_session_run_history]
  for {set i 0} {$i < $arraysize} {incr i} {
    $netwag_priv_runhist_lb insert end $netwag_session_run_history($i)
  }

  # netwag_session_clipboard_text_height
  global frame_clipboard
  global netwag_glo_clipboard_text_height
  set netwag_glo_clipboard_text_height $netwag_session_clipboard_text_height
  $frame_clipboard.text configure -height $netwag_glo_clipboard_text_height

  return 0
}

## Write session variables to a filename
proc netwag_priv_sessionvars_write { filename } {
  global netwag_varfile_error
  global netwag_sessionvars_error
  global netwag_session_font_family
  global netwag_session_font_size
  global netwag_session_dynhelp_active
  global netwag_session_window_width
  global netwag_session_window_height
  global netwag_session_clipboard_small
  global netwag_session_clipboard_big
  global netwag_session_run_history
  global netwag_session_clipboard_text_height

  set ret [netwag_varfile_write_init $filename fd]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }

  # simple variables
  set ret [netwag_varfile_write_variable $fd "font_family" $netwag_session_font_family]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }
  set ret [netwag_varfile_write_variable $fd "font_size" $netwag_session_font_size]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }
  set ret [netwag_varfile_write_variable $fd "dynhelp_active" $netwag_session_dynhelp_active]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }
  set ret [netwag_varfile_write_variable $fd "window_width" $netwag_session_window_width]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }
  set ret [netwag_varfile_write_variable $fd "window_height" $netwag_session_window_height]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }
  set ret [netwag_varfile_write_variable $fd "clipboard_small" $netwag_session_clipboard_small]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }
  set ret [netwag_varfile_write_variable $fd "clipboard_big" $netwag_session_clipboard_big]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }
  set ret [netwag_varfile_write_variable $fd "clipboard_text_height" $netwag_session_clipboard_text_height]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }

  # run history
  set ret [netwag_varfile_write_array $fd "run_history" netwag_session_run_history]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }

  set ret [netwag_varfile_write_close $fd]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }

  return 0
}

## Read session variables from a filename
proc netwag_priv_sessionvars_read { filename } {
  global netwag_varfile_error
  global netwag_sessionvars_error
  global netwag_session_font_family
  global netwag_session_font_size
  global netwag_session_dynhelp_active
  global netwag_session_window_width
  global netwag_session_window_height
  global netwag_session_clipboard_small
  global netwag_session_clipboard_big
  global netwag_session_run_history
  global netwag_session_clipboard_text_height

  set ret [netwag_varfile_read $filename bigvar]
  if { $ret } {
    set netwag_sessionvars_error "$netwag_varfile_error"
    return -1
  }

  # reassign variables
  catch {set netwag_session_font_family $bigvar(font_family)}
  catch {set netwag_session_font_size $bigvar(font_size)}
  catch {set netwag_session_dynhelp_active $bigvar(dynhelp_active)}
  catch {set netwag_session_window_width $bigvar(window_width)}
  catch {set netwag_session_window_height $bigvar(window_height)}
  catch {set netwag_session_clipboard_small $bigvar(clipboard_small)}
  catch {set netwag_session_clipboard_big $bigvar(clipboard_big)}
  catch {set netwag_session_clipboard_text_height $bigvar(clipboard_text_height)}
  catch {unset netwag_session_run_history}
  set i 0
  while {[info exists bigvar(run_history,$i)]} {
    set netwag_session_run_history($i) $bigvar(run_history,$i)
    incr i
  }

  return 0
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Load the last session
proc netwag_session_load_vars { } {
  global netwag_glo_file_session
  global netwag_session_couldload

  netwag_priv_sessionvars_initdefault
  set ret [netwag_priv_sessionvars_read $netwag_glo_file_session]
  if { $ret } {
    set netwag_session_couldload 0
  } else {
    set netwag_session_couldload 1
  }
  return 0
}
proc netwag_session_load_apply { } {
  global netwag_glo_file_session
  global netwag_session_couldload
  global netwag_sessionvars_error

  if {!$netwag_session_couldload} {
    netwag_priv_sessionvars_initdefault
    netwag_priv_sessionvars_apply
    netwag_msg_add_err "$netwag_sessionvars_error"
    netwag_msg_add_warn "This error is normal if this is the first run of netwag"
    return -1
  }

  netwag_priv_sessionvars_apply
  return 0
}

## Create a new session
proc netwag_session_new { } {
  netwag_priv_sessionvars_initdefault
  netwag_priv_sessionvars_apply
  netwag_msg_add_info "Default session loaded"
}

## Open a session
proc netwag_session_open { } {
  global netwag_sessionvars_error
  global netwag_glo_file_session
  # note : apparently, ".ses" does not match hidden files ".netwag.ses"
  set filetypes {
    {{Session Files} {.ses} }
    {{All Files} * }
  }
  set dn [file dirname $netwag_glo_file_session]
  set filename [tk_getOpenFile -filetypes $filetypes -initialdir $dn]
  if { $filename == "" } {
    return 0
  }
  netwag_priv_sessionvars_initdefault
  set ret [netwag_priv_sessionvars_read $filename]
  if { $ret } {
    netwag_msg_add_err "$netwag_sessionvars_error"
    netwag_msg_add_warn "Could not load session from $filename"
    return -1
  }
  netwag_priv_sessionvars_apply
  netwag_msg_add_info "Session in $filename loaded"
  return 0
}

## Save the session
proc netwag_session_save { } {
  global netwag_sessionvars_error
  global netwag_glo_file_session
  netwag_priv_sessionvars_initcurrent
  set ret [netwag_priv_sessionvars_write $netwag_glo_file_session]
  if { $ret } {
    netwag_msg_add_err "$netwag_sessionvars_error"
    netwag_msg_add_warn "Could not save session to $netwag_glo_file_session"
    return -1
  }
  netwag_msg_add_info "Session saved in $netwag_glo_file_session"
  return 0
}

## Save a session
proc netwag_session_saveas { } {
  global netwag_sessionvars_error
  global netwag_glo_file_session
  set filetypes {
    {{Session Files} {.ses} }
    {{All Files} * }
  }
  set dn [file dirname $netwag_glo_file_session]
  set filename [tk_getSaveFile -filetypes $filetypes -initialdir $dn -defaultextension ".ses"]
  if { $filename == "" } {
    return
  }
  netwag_priv_sessionvars_initcurrent
  set ret [netwag_priv_sessionvars_write $filename]
  if { $ret } {
    netwag_msg_add_err "$netwag_sessionvars_error"
    netwag_msg_add_warn "Could not save session to $filename"
    return -1
  }
  netwag_msg_add_info "Session saved in $filename"
  return 0
}



#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_font_windows_name; set netwag_font_windows_name ".font_window"
global netwag_font_isfixed; set netwag_font_isfixed 1


#################################################################
# PRIVATE FUNCTIONS
#################################################################


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Create the skeleton
proc netwag_font_init { } {
  global netwag_session_font_family
  global netwag_session_font_size
  global netwag_font_isfixed

  font create myfont -family $netwag_session_font_family -size $netwag_session_font_size
  set netwag_font_isfixed [font metric myfont -fixed]
}

## Change the font
proc netwag_font_change { fam size } {
  global netwag_session_font_family
  global netwag_session_font_size
  global netwag_font_isfixed

  set netwag_session_font_family $fam
  set netwag_session_font_size $size
  font configure myfont -family $fam -size $size
  set netwag_font_isfixed [font metric myfont -fixed]
}

## Change the font opening a popup
proc netwag_font_changepopup { } {
  global netwag_session_font_family
  global netwag_session_font_size
  global netwag_font_windows_name
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_gui_bgcolor_listbox
  global netwag_glo_gui_bgcolor_unused
  global netwag_font_isfixed

  # obtain the old configuration
  set oldfam $netwag_session_font_family
  set oldsize $netwag_session_font_size

  # create window
  set fw "$netwag_font_windows_name"
  set fwc "$fw.checklists"
  set fwb "$fw.buttons"
  set fwcf "$fwc.font"
  set fwcs "$fwc.size"
  set fwbo "$fwb.ok"
  set fwbi "$fwb.ignore"

  toplevel $fw
  wm title $fw "Choose font"
  frame $fwc
  frame $fwb -bg $netwag_glo_gui_bgcolor_unused
  pack $fwc -fill both -expand 1
  pack $fwb -fill x
  frame $fwcf
  frame $fwcs
  pack $fwcf $fwcs -side left -fill both -expand 1

  # create listbox containing the families
  listbox $fwcf.box -yscrollcommand "$fwcf.scro set" -exportselection false -bg $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  scrollbar $fwcf.scro -command "$fwcf.box yview" -troughcolor $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  pack $fwcf.box -side left -fill both -expand 1
  pack $fwcf.scro -side left -fill y
  set i 0
  set isel -1
  foreach fam [lsort [font families]] {
    $fwcf.box insert end $fam
    if { $fam == $oldfam } { set isel $i }
    incr i
  }
  if { $isel != -1 } {
    $fwcf.box selection set $isel
    $fwcf.box yview $isel
  }
  bind $fwcf.box <Button-1> {
    set fam [%W get [%W nearest %y]]
    set netwag_session_font_family $fam
    font configure myfont -family $fam
    set netwag_font_isfixed [font metric myfont -fixed]
  }
  netwag_dynhelp_init $fwcf.box "Choose the font to be used."

  # create listbox containing the sizes
  listbox $fwcs.box  -yscrollcommand "$fwcs.scro set" -exportselection false -bg $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  scrollbar $fwcs.scro -command "$fwcs.box yview" -troughcolor $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  pack $fwcs.box -side left -fill both -expand 1
  pack $fwcs.scro -side left -fill y
  set imax [expr 2 * $oldsize]
  if { $imax < 30 } { set imax 30 }
  set isel -1
  for {set i 1} {$i < $imax} {incr i} {
    $fwcs.box insert end $i
    if { $i == $oldsize } { set isel $i }
  }
  if { $isel != -1 } {
    $fwcs.box selection set $isel
    $fwcs.box yview $isel
  }
  bind $fwcs.box <Button-1> {
    set size [%W get [%W nearest %y]]
    set netwag_session_font_size $size
    font configure myfont -size $size
  }
  netwag_dynhelp_init $fwcs.box "Choose the size for the font."

  # create buttons
  eval "button $fwb.bi -text Ignore -command { netwag_font_change \"$oldfam\" $oldsize ; destroy $fw } -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0"
  eval "button $fwb.bo -text OK -command { destroy $fw } -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0"
  pack $fwb.bi $fwb.bo -side left -expand 1
  netwag_dynhelp_init $fwb.bi "Revert to the old font."
  netwag_dynhelp_init $fwb.bo "Choose the current font."

}

#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_cursor_default_cursor;
set netwag_cursor_default_cursor [. cget -cursor]

#################################################################
# PRIVATE FUNCTIONS
#################################################################


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Set waiting cursor
proc netwag_cursor_wait { } {
  . configure -cursor watch
  update idletasks
}

## Set default cursor
proc netwag_cursor_default { } {
  global netwag_cursor_default_cursor;
  . configure -cursor $netwag_cursor_default_cursor
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_help_about_winname ; set netwag_help_about_winname ".helpabout_window"
global netwag_help_doc_winname ; set netwag_help_doc_winname ".helpdoc_window"


#################################################################
# PRIVATE FUNCTIONS
#################################################################


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## About
proc netwag_help_about_popup { } {
  global netwag_help_about_winname
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_versionmajor
  global netwag_glo_versionminor
  global netwag_glo_versionmicro

  # create window
  set hw $netwag_help_about_winname
  toplevel $hw
  wm title $hw "About netwag"

  # set content
  set msg "netwag $netwag_glo_versionmajor.$netwag_glo_versionminor.$netwag_glo_versionmicro\n"
  append msg "Copyright Laurent Constantin\n"
  label $hw.l1 -font myfont -bg $netwag_glo_gui_bgcolor_unused -text $msg
  pack $hw.l1 -fill both

  set msg "http://www.laurentconstantin.com/\n"
  append msg "http://go.to/laurentconstantin/\n"
  append msg "http://laurentconstantin.est-la.com/\n"
  append msg "http://laurentconstantin.free.fr/\n"
  append msg "http://membres.lycos.fr/lauconstantin/\n"
  label $hw.l2 -font myfont -bg $netwag_glo_gui_bgcolor_unused -text $msg -justify left
  pack $hw.l2 -fill both -expand 1

  # set button
  frame $hw.f -bg $netwag_glo_gui_bgcolor_unused
  pack $hw.f -fill x
  eval "button $hw.f.b -text OK -command { destroy $hw } -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0 -font myfont"
  pack $hw.f.b

}

## Documentation
proc netwag_help_doc_popup { } {
  global netwag_help_doc_winname
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_dynhelp_timeout

  # create window
  set hw $netwag_help_doc_winname
  toplevel $hw
  set msg "netwag 's documentation"
  wm title $hw $msg

  # set content
  frame $hw.f1 -bg $netwag_glo_gui_bgcolor_unused
  pack $hw.f1 -fill both
  set msg "This documentation is very short.\n"
  append msg "\n"
  append msg "To obtain help :\n"
  append msg " - activate \"Dynamic Help\" (in menu Help)\n"
  append msg " - put the mouse on top of an item\n"
  append msg " - do not move during $netwag_glo_dynhelp_timeout milliseconds\n"
  append msg " - then, a small yellow help window displays\n"
  append msg "\n"
  append msg "Note about background colors :"
  label $hw.f1.l1 -font myfont -bg $netwag_glo_gui_bgcolor_unused -text $msg -justify left
  pack $hw.f1.l1 -anchor w

  global netwag_glo_gui_bgcolor_listbox
  frame $hw.f2 -bg $netwag_glo_gui_bgcolor_listbox
  pack $hw.f2 -fill both
  set msg " - This color is used for listboxes"
  label $hw.f2.c1 -font myfont -bg $netwag_glo_gui_bgcolor_listbox -text $msg
  pack $hw.f2.c1 -anchor w

  global netwag_glo_gui_bgcolor_text_edit
  frame $hw.f3 -bg $netwag_glo_gui_bgcolor_text_edit
  pack $hw.f3 -fill both
  set msg " - This color is used for editable text"
  label $hw.f3.c2 -font myfont -bg $netwag_glo_gui_bgcolor_text_edit -text $msg
  pack $hw.f3.c2 -anchor w

  global netwag_glo_gui_bgcolor_text_select
  frame $hw.f4 -bg $netwag_glo_gui_bgcolor_text_select
  pack $hw.f4 -fill both
  set msg " - This color is used for selectable only text"
  label $hw.f4.c3 -font myfont -bg $netwag_glo_gui_bgcolor_text_select -text $msg
  pack $hw.f4.c3 -anchor w

  frame $hw.f5 -bg $netwag_glo_gui_bgcolor_unused
  pack $hw.f5 -fill both -expand 1
  set msg "\n"
  label $hw.f5.l2 -font myfont -bg $netwag_glo_gui_bgcolor_unused -text $msg -justify left
  pack $hw.f5.l2 -fill both

  # set button
  frame $hw.f6 -bg $netwag_glo_gui_bgcolor_unused
  pack $hw.f6 -fill x
  eval "button $hw.f6.b -text OK -command { destroy $hw } -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0 -font myfont"
  pack $hw.f6.b

}


#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_menu_fileexit_try ; set netwag_menu_fileexit_try 0

#################################################################
# PRIVATE FUNCTIONS
#################################################################


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Menu File - Exit
proc netwag_menu_fileexit { } {
  global netwag_menu_fileexit_try

  if {$netwag_menu_fileexit_try} {
    # direct exit, otherwise on error could not exit
    exit
  }
  set netwag_menu_fileexit_try 1

  netwag_run_button_int 0
  netwag_session_save
  exit
}

## Menu Edit - Cut
proc netwag_menu_editcut { } {
  event generate [focus] <Control-Key-x>
}

## Menu Edit - Copy
proc netwag_menu_editcopy { } {
  event generate [focus] <Control-Key-c>
}

## Menu Edit - Paste
proc netwag_menu_editpaste { } {
  event generate [focus] <Control-Key-v>
}

## Menu Session - New
proc netwag_menu_sessnew { } {
  netwag_session_new
}

## Menu Session - Open
proc netwag_menu_sessopen { } {
  netwag_session_open
}

## Menu Session - Save
proc netwag_menu_sesssave { } {
  netwag_session_save
}

## Menu Session - SaveAs
proc netwag_menu_sesssaveas { } {
  netwag_session_saveas
}

## Menu Option - Font
proc netwag_menu_optfont { } {
  global netwag_font_windows_name
  if { [winfo exists $netwag_font_windows_name] } {
    raise $netwag_font_windows_name
  } else {
    netwag_font_changepopup
  }
}

## Menu Help - Documentation
proc netwag_menu_helpdoc { } {
  global netwag_help_doc_winname
  if { [winfo exists $netwag_help_doc_winname] } {
    raise $netwag_help_doc_winname
  } else {
    netwag_help_doc_popup
  }
}

## Menu Help - About
proc netwag_menu_helpabout { } {
  global netwag_help_about_winname
  if { [winfo exists $netwag_help_about_winname] } {
    raise $netwag_help_about_winname
  } else {
    netwag_help_about_popup
  }
}

#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_notebook_tabs
global netwag_priv_notebook_numtab
global netwag_priv_notebook_butnum_pressed

#################################################################
# PRIVATE FUNCTIONS
#################################################################
## Resize the frame
proc netwag_priv_notebook_resize { mainframe } {
  global netwag_priv_notebook_numtab
  set numtab $netwag_priv_notebook_numtab($mainframe)

  set w [winfo width $mainframe.body]
  set h [winfo height $mainframe.body]
  # puts "res $w $h"
  for {set i 0} {$i < $numtab } {incr i} {
    $mainframe.body.pf$i.top.c configure -width $w
    $mainframe.body.pf$i.bot.left.c configure -height $h
  }
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Create the notebook
proc netwag_notebook_init { mainframe tabs presscb } {
  global netwag_priv_notebook_tabs
  global netwag_priv_notebook_numtab
  global netwag_glo_gui_bgcolor_unused

  # set all callbacks
  set numtab 0
  foreach cb $presscb {
    set netwag_priv_notebook_presscb($mainframe,$numtab) $cb
    incr numtab
  }

  frame $mainframe
  frame $mainframe.head -bg $netwag_glo_gui_bgcolor_unused
  frame $mainframe.body -bg $netwag_glo_gui_bgcolor_unused
  set numtab 0
  foreach ong $tabs {
    set netwag_priv_notebook_tabs($mainframe,$numtab) $ong
    button $mainframe.head.b$numtab -text "$ong" -font myfont -highlightthickness 0
    pack $mainframe.head.b$numtab -side left -padx 1
    incr numtab
  }
  set netwag_priv_notebook_numtab($mainframe) $numtab
  pack $mainframe.head -anchor w -fill x
  pack $mainframe.body -anchor w -expand 1 -fill both

  for {set i 0} {$i < $numtab} {incr i} {
    # create the place frame
    frame $mainframe.body.pf$i
    place $mainframe.body.pf$i -x 0 -y 0
    # create the frames inside
    frame $mainframe.body.pf$i.top
    frame $mainframe.body.pf$i.bot
    frame $mainframe.body.pf$i.bot.left
    frame $mainframe.body.pf$i.bot.right
    pack $mainframe.body.pf$i.top
    pack $mainframe.body.pf$i.bot -expand 1 -fill both
    pack $mainframe.body.pf$i.bot.left -side left
    pack $mainframe.body.pf$i.bot.right -expand 1 -fill both -side left
    # create the canvas used to force respect of sizes
    canvas $mainframe.body.pf$i.top.c -width 1 -height 1 -bg white -highlightthickness 0
    pack $mainframe.body.pf$i.top.c
    canvas $mainframe.body.pf$i.bot.left.c -width 1 -height 1 -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0
    pack $mainframe.body.pf$i.bot.left.c
    # bind the buttons
    set presscb "netwag_notebook_button_press $mainframe $i"
    if {[ info exist netwag_priv_notebook_presscb($mainframe,$i)]} {
      append presscb " ; "
      append presscb $netwag_priv_notebook_presscb($mainframe,$i)
    }
    eval "bind $mainframe.head.b$i <Button-1> { $presscb }"
  }

  eval "bind $mainframe.body <Configure> {netwag_priv_notebook_resize $mainframe }"

  return $mainframe
}

## Simulate the press of a button
proc netwag_notebook_button_press { mainframe butnum } {
  global netwag_priv_notebook_numtab
  global netwag_glo_notebook_button_visible_color
  global netwag_glo_notebook_button_hidden_color
  global netwag_priv_notebook_butnum_pressed

  set numtab $netwag_priv_notebook_numtab($mainframe)
  if { $butnum >= $numtab } {
    error "netwag_notebook_button_press: butnum > numtab"
  }
  set netwag_priv_notebook_butnum_pressed($mainframe) $butnum

  raise $mainframe.body.pf$butnum

  for {set i 0} {$i < $numtab} {incr i} {
    if {$i == $butnum} {
     $mainframe.head.b$i configure -bg $netwag_glo_notebook_button_visible_color
    } else {
      $mainframe.head.b$i configure -bg $netwag_glo_notebook_button_hidden_color
    }
  }
}

## Get the frame associated to a button number
proc netwag_notebook_frame_get { mainframe butnum } {
  global netwag_priv_notebook_numtab
  set numtab $netwag_priv_notebook_numtab($mainframe)
  if { $butnum >= $numtab } {
    error "netwag_notebook_frame_get: butnum > numtab"
  }
  return $mainframe.body.pf$butnum.bot.right
}

## Get the button associated to a button number
proc netwag_notebook_button_get { mainframe butnum } {
  global netwag_priv_notebook_numtab
  set numtab $netwag_priv_notebook_numtab($mainframe)
  if { $butnum >= $numtab } {
    error "netwag_notebook_frame_get: butnum > numtab"
  }
  return $mainframe.head.b$butnum
}

## Get the button number currently pressed
proc netwag_notebook_butnum_get { mainframe } {
  global netwag_priv_notebook_butnum_pressed
  return $netwag_priv_notebook_butnum_pressed($mainframe)
}

#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_dynhelp_afterid
global netwag_priv_dynhelp_msg
global netwag_priv_dynhelp_name ; set netwag_priv_dynhelp_name ".netwag_priv_dynhelp_w"


#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Event handlers
bind netwag_priv_dynhelp_evt <Enter> {
  global netwag_priv_dynhelp_afterid
  global netwag_glo_dynhelp_timeout
  global netwag_session_dynhelp_active
  if { $netwag_session_dynhelp_active == 0 } {continue}
  set netwag_priv_dynhelp_afterid [after $netwag_glo_dynhelp_timeout {netwag_priv_dynhelp_display %W %X %Y}]
}
bind netwag_priv_dynhelp_evt <Motion> {
  global netwag_priv_dynhelp_afterid
  global netwag_glo_dynhelp_timeout
  global netwag_session_dynhelp_active
  if { $netwag_session_dynhelp_active == 0 } {continue}
  after cancel $netwag_priv_dynhelp_afterid
  if {[winfo exists .netwag_priv_dynhelp] != 1} {
    set netwag_priv_dynhelp_afterid [after $netwag_glo_dynhelp_timeout {netwag_priv_dynhelp_display %W %X %Y}]
  }
}
bind netwag_priv_dynhelp_evt <Leave> {
  global netwag_session_dynhelp_active
  if { $netwag_session_dynhelp_active == 0 } {continue}
  netwag_priv_dynhelp_destroy
}
bind netwag_priv_dynhelp_evt <Button> {
  global netwag_session_dynhelp_active
  if { $netwag_session_dynhelp_active == 0 } {continue}
  netwag_priv_dynhelp_destroy
}

## Display a small window
proc netwag_priv_dynhelp_display {w x y} {
  global netwag_priv_dynhelp_msg
  global netwag_priv_dynhelp_name
  global netwag_glo_dynhelp_bgcolor
  global netwag_glo_dynhelp_wraplength
  global netwag_session_dynhelp_active

  if { $netwag_session_dynhelp_active == 0 } {return}
  if [catch {toplevel $netwag_priv_dynhelp_name} res] {
    # simply ignore the error, and do not create a new window
    return
  }
  wm overrideredirect $netwag_priv_dynhelp_name 1
  set x [expr $x + 0]
  set y [expr $y + 15]
  wm geometry $netwag_priv_dynhelp_name +$x+$y

  frame $netwag_priv_dynhelp_name.f -relief flat -bd 1 -bg black
  label $netwag_priv_dynhelp_name.f.l -anchor e -text $netwag_priv_dynhelp_msg($w) -bg $netwag_glo_dynhelp_bgcolor -wraplength $netwag_glo_dynhelp_wraplength -font myfont -justify left
  pack $netwag_priv_dynhelp_name.f.l -anchor nw
  pack $netwag_priv_dynhelp_name.f
}

## Destroy the window
proc netwag_priv_dynhelp_destroy {} {
  global netwag_priv_dynhelp_afterid
  global netwag_priv_dynhelp_name
  global netwag_session_dynhelp_active

  if { $netwag_session_dynhelp_active == 0 } {return}
  after cancel $netwag_priv_dynhelp_afterid
  if {[winfo exists $netwag_priv_dynhelp_name] == 1} {
    destroy $netwag_priv_dynhelp_name
  }
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Initialize the message for an object
proc netwag_dynhelp_init {w message} {
  global netwag_priv_dynhelp_msg

  set netwag_priv_dynhelp_msg($w) $message
  bindtags $w "[bindtags $w] netwag_priv_dynhelp_evt"
}

## Change the message of an object
proc netwag_dynhelp_change {w message} {
  global netwag_priv_dynhelp_msg

  set netwag_priv_dynhelp_msg($w) $message
}

## Remove the message for an object
proc netwag_dynhelp_close {w} {
  set tmptags [bindtags $w]
  set posdebut [string first "netwag_priv_dynhelp_evt" $tmptags]
  set posfin [expr $posdebut + [string length "netwag_priv_dynhelp_evt"]]
  set posdebut [expr $posdebut - 1]
  set newtags [string range $tmptags 1 $posdebut]
  append newtags [string range $tmptags $posfin end]
  bindtags $w $newtags
}

## Activate/desactivate the dynhelp
proc netwag_dynhelp_activate { activate } {
  global netwag_priv_dynhelp_afterid
  global netwag_priv_dynhelp_name
  global netwag_session_dynhelp_active
  set netwag_session_dynhelp_active $activate
  if { !$activate } {
    catch {after cancel $netwag_priv_dynhelp_afterid}
    if {[winfo exists $netwag_priv_dynhelp_name] == 1} {
      destroy $netwag_priv_dynhelp_name
    }
  }
}

#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_msg_textframe
global netwag_priv_msg_nummsg

#################################################################
# PRIVATE FUNCTIONS
#################################################################
## Add a message and a newline
proc netwag_priv_msg_add { msg {errorlevel 0} } {
  global netwag_priv_msg_textframe
  global netwag_glo_gui_run_cmd_height
  global netwag_priv_msg_nummsg

  $netwag_priv_msg_textframe configure -state normal
  if { $errorlevel == 0 } {
    $netwag_priv_msg_textframe insert end "$msg\n" netwag_priv_msg_info
  } elseif { $errorlevel == 1 } {
    $netwag_priv_msg_textframe insert end "$msg\n" netwag_priv_msg_warn
  } else {
    $netwag_priv_msg_textframe insert end "$msg\n" netwag_priv_msg_err
  }
  $netwag_priv_msg_textframe configure -state disabled

#  $netwag_priv_msg_textframe yview moveto 1
  incr netwag_priv_msg_nummsg
  if { $netwag_priv_msg_nummsg <= $netwag_glo_gui_run_cmd_height } {
    $netwag_priv_msg_textframe see 1.0
  } else {
    set tmpvar [expr $netwag_glo_gui_run_cmd_height - 1]
    set tmpvar "-$tmpvar"
    append tmpvar "lines"
    $netwag_priv_msg_textframe see "end $tmpvar"
  }
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Set the global variable indicating where is the message zone
proc netwag_msg_init { textframe } {
  global netwag_priv_msg_textframe
  global netwag_glo_msg_color_info
  global netwag_glo_msg_color_warn
  global netwag_glo_msg_color_err
  global netwag_priv_msg_nummsg

  set netwag_priv_msg_nummsg 0

  set netwag_priv_msg_textframe $textframe
  $netwag_priv_msg_textframe configure -state disabled

  $netwag_priv_msg_textframe tag configure netwag_priv_msg_info -foreground $netwag_glo_msg_color_info
  $netwag_priv_msg_textframe tag configure netwag_priv_msg_warn -foreground $netwag_glo_msg_color_warn
  $netwag_priv_msg_textframe tag configure netwag_priv_msg_err -foreground $netwag_glo_msg_color_err
}

## Empty the message box
proc netwag_msg_purge { } {
  global netwag_priv_msg_textframe
  global netwag_priv_msg_nummsg

  $netwag_priv_msg_textframe configure -state normal
  $netwag_priv_msg_textframe delete 1.0 end
  $netwag_priv_msg_textframe configure -state disabled

  set netwag_priv_msg_nummsg 0
}

## Add a message and a newline
proc netwag_msg_add_info { msg } {
  netwag_priv_msg_add $msg 0
}
proc netwag_msg_add_warn { msg } {
  netwag_priv_msg_add $msg 1
}
proc netwag_msg_add_err { msg } {
  netwag_priv_msg_add $msg 2
}







#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################


#################################################################
# PRIVATE FUNCTIONS
#################################################################
# Most of this code is taken from the Tk library.

## Used for Entry
proc netwag_priv_clip_tkEntryGetSelection {w} {
  set posstart [$w index sel.first]
  set posend [expr [$w index sel.last] - 1]
  set entryString [string range [$w get] $posstart $posend]
  if {[$w cget -show] != ""} {
    # a password
    regsub -all . $entryString [string index [$w cget -show] 0] entryString
  }
  return $entryString
}
proc netwag_priv_clip_tkEntrySeeInsert w {
  set c [$w index insert]
  set left [$w index @0]
  if {$left > $c} {
    $w xview $c
    return
  }
  set x [winfo width $w]
  if {$c > [$w index @[winfo width $w]]} {
    $w xview insert
  }
}

# on Text widget, cut
proc netwag_priv_clip_text_cut {w} {
  #puts mytextcut
  if {![catch {set data [$w get sel.first sel.last]}]} {
    clipboard clear -displayof $w
    clipboard append -displayof $w $data
    $w delete sel.first sel.last
  }
}

# on Entry widget, cut
proc netwag_priv_clip_entry_cut {w} {
  #puts myentrycut
  if {![catch {netwag_priv_clip_tkEntryGetSelection $w} data]} {
    clipboard clear -displayof $w
    clipboard append -displayof $w $data
    $w delete sel.first sel.last
  }
}

# on Text widget, copy
proc netwag_priv_clip_text_copy {w} {
  #puts mytextcopy
  if {![catch {set data [$w get sel.first sel.last]}]} {
    clipboard clear -displayof $w
    clipboard append -displayof $w $data
  }
}

# on Entry widget, copy
proc netwag_priv_clip_entry_copy {w} {
  #puts myentrycopy
  if {![catch {netwag_priv_clip_tkEntryGetSelection $w} data]} {
    clipboard clear -displayof $w
    clipboard append -displayof $w $data
  }
}

# on Text widget, paste
proc netwag_priv_clip_text_paste {w} {
  #puts mytextpaste
  catch {$w delete sel.first sel.last}
  if {[catch {selection get -displayof $w -selection CLIPBOARD} inclip]} {
    # ignore error
    return
  }
  $w insert insert $inclip
}

# on Entry widget, paste
proc netwag_priv_clip_entry_paste {w} {
  #puts myentrypaste
  catch {$w delete sel.first sel.last}
  if {[catch {selection get -displayof $w -selection CLIPBOARD} inclip]} {
    # ignore error
    return
  }
  $w insert insert $inclip
  netwag_priv_clip_tkEntrySeeInsert $w
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Initialize the clipboard
proc netwag_clip_init {} {
  global netwag_sys_platform
  global netwag_sys_platform_unix

  # add events to Text
  bind Text <Control-Key-x> { netwag_priv_clip_text_cut %W }
  bind Text <Control-Key-c> { netwag_priv_clip_text_copy %W }
  bind Text <Control-Key-v> { netwag_priv_clip_text_paste %W }
  bind Text <Shift-Key-Delete> { netwag_priv_clip_text_cut %W }
  bind Text <Control-Key-Insert> { netwag_priv_clip_text_copy %W }
  bind Text <Shift-Key-Insert> { netwag_priv_clip_text_paste %W }
  if {$netwag_sys_platform == $netwag_sys_platform_unix} {
    bind Text <Key-F20> { netwag_priv_clip_text_cut %W }
    bind Text <Key-F16> { netwag_priv_clip_text_copy %W }
    bind Text <Key-F18> { netwag_priv_clip_text_paste %W }
  }

  # add events to Entry
  bind Entry <Control-Key-x> { netwag_priv_clip_entry_cut %W }
  bind Entry <Control-Key-c> { netwag_priv_clip_entry_copy %W }
  bind Entry <Control-Key-v> { netwag_priv_clip_entry_paste %W }
  bind Entry <Shift-Key-Delete> { netwag_priv_clip_entry_cut %W }
  bind Entry <Control-Key-Insert> { netwag_priv_clip_entry_copy %W }
  bind Entry <Shift-Key-Insert> { netwag_priv_clip_entry_paste %W }
  if {$netwag_sys_platform == $netwag_sys_platform_unix} {
    bind Entry <Key-F20> { netwag_priv_clip_entry_cut %W }
    bind Entry <Key-F16> { netwag_priv_clip_entry_copy %W }
    bind Entry <Key-F18> { netwag_priv_clip_entry_paste %W }
  }

}

## Buttons pressed to resize the height
proc netwag_clip_height_callback_less { } {
  global frame_clipboard
  global netwag_glo_clipboard_text_height

  # suppose 5 is the min, even if it's currently set to 6
  if { $netwag_glo_clipboard_text_height < 5 } {
    netwag_msg_add_warn "Cannot shrink more"
    return
  }

  incr netwag_glo_clipboard_text_height -1
  $frame_clipboard.text configure -height $netwag_glo_clipboard_text_height
}
proc netwag_clip_height_callback_more { } {
  global frame_clipboard
  global netwag_glo_clipboard_text_height

  incr netwag_glo_clipboard_text_height
  $frame_clipboard.text configure -height $netwag_glo_clipboard_text_height
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_gui_text_big_clipboard
global netwag_gui_text_small_clipboard

#################################################################
# PRIVATE FUNCTIONS
#################################################################


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Create the skeleton
proc netwag_gui_skeleton { pframe_notebook pframe_clipboard pframe_message } {
  upvar $pframe_notebook frame_notebook
  upvar $pframe_clipboard frame_clipboard
  upvar $pframe_message frame_message
  global netwag_session_window_width
  global netwag_session_window_height

  wm title . "netwag"
  set newgeometry "$netwag_session_window_width"
  append newgeometry "x"
  append newgeometry "$netwag_session_window_height"
  wm geometry . "$newgeometry"
  wm protocol . WM_DELETE_WINDOW { netwag_menu_fileexit }

  set frame_notebook ".fn"
  set frame_clipboard ".fc"
  set frame_message ".fm"

  netwag_notebook_init $frame_notebook {"Search" "Run" "Run output" "Local info" "Remote info" "Clipboard"} { {netwag_search_eventuallyinit} {netwag_runhf_display} {} {netwag_infol_eventuallyinit}}
  netwag_notebook_button_press $frame_notebook 1

  frame $frame_clipboard

  frame $frame_message

  pack $frame_notebook -expand yes -fill both
  pack $frame_clipboard -fill x
  pack $frame_message -fill x

}

## Create the first notebook
proc netwag_gui_notebook0 { frame_notebook } {
  global netwag_glo_gui_selectcolor
  global netwag_glo_gui_search_listbox_height
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_listbox
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_gui_bgcolor_text_select
  global netwag_glo_gui_bgcolor_text_edit
  set cf [netwag_notebook_frame_get $frame_notebook 0]

  # create the radios, search, infos and buttons frames
  set cfr "$cf.radios"
  frame $cfr -bg $netwag_glo_gui_bgcolor_unused
  set cfs "$cf.search"
  frame $cfs -bg $netwag_glo_gui_bgcolor_unused
  set cfi "$cf.infos"
  frame $cfi -bg $netwag_glo_gui_bgcolor_unused
  set cfb "$cf.buttons"
  frame $cfb -bg $netwag_glo_gui_bgcolor_unused
  pack $cfr -fill x
  pack $cfs -expand 1 -fill both
  pack $cfi $cfb -fill x

  # create the radios frame
  global netwag_priv_search_type_sort
  global netwag_priv_search_type_tree
  frame $cfr.a
  radiobutton $cfr.a.sort -text "sort" -variable netwag_priv_search_type -command netwag_priv_search_radiobutton_callback -value $netwag_priv_search_type_sort -selectcolor $netwag_glo_gui_selectcolor -font myfont -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0
  radiobutton $cfr.a.tree -text "tree" -variable netwag_priv_search_type -command netwag_priv_search_radiobutton_callback -value $netwag_priv_search_type_tree -selectcolor $netwag_glo_gui_selectcolor -font myfont -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0
  $cfr.a.sort select
  pack $cfr.a.sort $cfr.a.tree -side left
  pack $cfr.a -side left
  netwag_dynhelp_init $cfr.a.sort "Show tools sorted by number."
  netwag_dynhelp_init $cfr.a.tree "Show tools in a tree."

  frame $cfr.c
  radiobutton $cfr.c.all -text "show all" -variable netwag_priv_search_showsearch -command netwag_priv_search_radiobutton_callback -value "1" -selectcolor $netwag_glo_gui_selectcolor -font myfont -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0
  radiobutton $cfr.c.search -text "search" -variable netwag_priv_search_showsearch -command netwag_priv_search_radiobutton_callback -value "2" -selectcolor $netwag_glo_gui_selectcolor -font myfont -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0
  set cfrbe $cfr.c.entry
  global netwag_priv_search_searchentry ; set netwag_priv_search_searchentry $cfrbe
  entry $cfrbe -textvariable netwag_priv_search_searchvar -width 20 -font myfont -bg $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  pack $cfr.c.all $cfr.c.search $cfr.c.entry -side left
  pack $cfr.c -side right
  $cfr.c.all select
  netwag_dynhelp_init $cfr.c.all "Show all tools in the listbox below."
  netwag_dynhelp_init $cfr.c.search "Search among the tools in the listbox below."
  netwag_dynhelp_init $cfr.c.entry "This is the searched text."

  # create the search frame containing the listbox
  frame $cfs.top
  set cfsb "$cfs.top.box"
  global netwag_priv_search_lb ; set netwag_priv_search_lb $cfsb
  listbox $cfsb -yscrollcommand "$cfs.top.scro set" -xscrollcommand "$cfs.scro set" -height $netwag_glo_gui_search_listbox_height -font myfont -bg $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  scrollbar $cfs.top.scro -command "$cfsb yview" -troughcolor $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  pack $cfs.top -expand 1 -fill both
  pack $cfsb -side left -expand 1 -fill both
  pack $cfs.top.scro -side left -fill y
  scrollbar $cfs.scro -command "$cfsb xview" -orient horizontal -troughcolor $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  pack $cfs.scro -fill x
  netwag_dynhelp_init $cfsb "This listbox contains the title of tools. If \"Show all\" is checked this list contains every tool. If \"Search\" is checked, this list contains the result of the search."

  set cb [netwag_notebook_button_get $frame_notebook 0]
  netwag_dynhelp_init $cb "Search a tool."
}

## Create the second notebook
proc netwag_gui_notebook1_bm_down { bm } {
  global netwag_glo_gui_bgcolor_button
  global netwag_gui_notebook1_bm_down_init
  set netwag_gui_notebook1_bm_down_init 0

  if {! $netwag_gui_notebook1_bm_down_init} {
    # to create this, use Unix "bitmap", save file, and paste contents
    set bm_down {
      #define i_width 15
      #define i_height 15
      static unsigned char i_bits[] = {
        0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01,
        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xf8, 0x0f, 0xf0, 0x07,
        0xe0, 0x03, 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00};
    }
    image create bitmap netwag_gui_notebook1_bm_down_bm -data $bm_down
    set netwag_gui_notebook1_bm_down_init 1
  }

  button $bm -image netwag_gui_notebook1_bm_down_bm -bd 0 -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0 -activebackground $netwag_glo_gui_bgcolor_button
  netwag_dynhelp_init $bm "This icon indicates that, when button is pressed, data goes from top window to bottom window."
}
proc netwag_gui_notebook1_bm_up { bm } {
  global netwag_glo_gui_bgcolor_button
  global netwag_gui_notebook1_bm_up_init
  set netwag_gui_notebook1_bm_up_init 0

  if {! $netwag_gui_notebook1_bm_up_init} {
    set bm_up {
      #define i_width 15
      #define i_height 15
      static unsigned char i_bits[] = {
        0x80, 0x00, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf8, 0x0f, 0x80, 0x00,
        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07,
        0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0x00, 0x00};
    }
    image create bitmap netwag_gui_notebook1_bm_up_bm -data $bm_up
    set netwag_gui_notebook1_bm_up_init 1
  }

  button $bm -image netwag_gui_notebook1_bm_up_bm -bd 0 -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0 -activebackground $netwag_glo_gui_bgcolor_button
  netwag_dynhelp_init $bm "This icon indicates that, when button is pressed, data goes from bottom window to top window."
}
proc netwag_gui_notebook1_bm_top { bm } {
  global netwag_glo_gui_bgcolor_button
  global netwag_gui_notebook1_bm_top_init
  set netwag_gui_notebook1_bm_top_init 0

  if {! $netwag_gui_notebook1_bm_top_init} {
    set bm_top {
      #define i_width 15
      #define i_height 15
      static unsigned char i_bits[] = {
        0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    }
    image create bitmap netwag_gui_notebook1_bm_top_bm -data $bm_top
    set netwag_gui_notebook1_bm_top_init 1
  }

  button $bm -image netwag_gui_notebook1_bm_top_bm -bd 0 -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0 -activebackground $netwag_glo_gui_bgcolor_button
  netwag_dynhelp_init $bm "This icon indicates button work on above window."
}

proc netwag_gui_notebook1 { frame_notebook } {
  global netwag_glo_gui_run_listbox_height
  global netwag_glo_gui_run_cmd_height
  global netwag_glo_gui_selectcolor
  global netwag_glo_gui_bgcolor_listbox
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_text_select
  global netwag_glo_gui_bgcolor_text_edit
  set cf [netwag_notebook_frame_get $frame_notebook 1]

  # create notebook and run frames
  set cfn "$cf.nb"
  global netwag_priv_run_nb ; set netwag_priv_run_nb $cfn
  netwag_notebook_init $cfn {"History" "Help" "Form"} { {} {netwag_runhf_display}}
  set cfr "$cf.run"
  frame $cfr
  pack $cfn -expand 1 -fill both
  pack $cfr -side left -expand 1 -fill x

  # history notebook
  set cfh [netwag_notebook_frame_get $cfn 0]
  frame $cfh.top
  frame $cfh.scro
  frame $cfh.bot -bg $netwag_glo_gui_bgcolor_unused
  pack $cfh.top -side top -expand 1 -fill both
  pack $cfh.scro -side top -fill x
  pack $cfh.bot -side top -fill x
  set cfhb "$cfh.top.box"
  global netwag_priv_runhist_lb ; set netwag_priv_runhist_lb $cfhb
  listbox $cfhb -yscrollcommand "$cfh.top.scro set" -xscrollcommand "$cfh.scro.scro set" -height $netwag_glo_gui_run_listbox_height -font myfont -bg $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  scrollbar $cfh.top.scro -command "$cfhb yview" -troughcolor $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  pack $cfhb -side left -expand 1 -fill both
  pack $cfh.top.scro -side left -fill y
  scrollbar $cfh.scro.scro -command "$cfhb xview" -orient horizontal -troughcolor $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
  pack $cfh.scro.scro -fill x
  frame $cfh.bot.l -bg $netwag_glo_gui_bgcolor_unused
  frame $cfh.bot.c -bg $netwag_glo_gui_bgcolor_unused
  frame $cfh.bot.c.c -bg $netwag_glo_gui_bgcolor_unused
  frame $cfh.bot.r -bg $netwag_glo_gui_bgcolor_unused
  pack $cfh.bot.l $cfh.bot.c $cfh.bot.r -side left -expand 1 -fill x
  netwag_gui_notebook1_bm_down $cfh.bot.l.copybm
  button $cfh.bot.l.copy -text "Copy line" -command netwag_runhist_button_copy -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  button $cfh.bot.l.runit -text "Run it" -command {netwag_runhist_button_copy ; netwag_run_button_run} -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  netwag_gui_notebook1_bm_down $cfh.bot.l.copybm2
  pack $cfh.bot.l.copybm $cfh.bot.l.copy $cfh.bot.l.runit $cfh.bot.l.copybm2 -side left
  netwag_gui_notebook1_bm_top $cfh.bot.c.c.delbm
  button $cfh.bot.c.c.del -text "Delete line" -command netwag_runhist_button_del -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  netwag_gui_notebook1_bm_top $cfh.bot.c.c.delbm2
  pack $cfh.bot.c.c -side top
  pack $cfh.bot.c.c.delbm $cfh.bot.c.c.del $cfh.bot.c.c.delbm2 -side left
  netwag_gui_notebook1_bm_up $cfh.bot.r.addbm
  button $cfh.bot.r.add -text "Add current" -command netwag_runhist_button_add -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  netwag_gui_notebook1_bm_up $cfh.bot.r.addbm2
  pack $cfh.bot.r.addbm $cfh.bot.r.add $cfh.bot.r.addbm2 -side right
  netwag_dynhelp_init $cfhb "History of tools. When a tool is run, it is automatically added here."
  netwag_dynhelp_init $cfh.bot.l.copy "Copy selected tool below."
  netwag_dynhelp_init $cfh.bot.l.runit "Copy selected tool below, and run it."
  netwag_dynhelp_init $cfh.bot.c.c.del "Delete the selected tool from history."
  netwag_dynhelp_init $cfh.bot.r.add "Add the current command line in the history, without running it."
  netwag_notebook_button_press $cfn 0
  set cb [netwag_notebook_button_get $cfn 0]
  netwag_dynhelp_init $cb "History of run tools."

  # help notebook
  set cfi [netwag_notebook_frame_get $cfn 1]
  frame $cfi.top
  frame $cfi.bot -bg $netwag_glo_gui_bgcolor_unused
  pack $cfi.top -side top -expand 1 -fill both
  pack $cfi.bot -side top -fill x
  set cfit "$cfi.top.text"
  global netwag_priv_runhelp_text ; set netwag_priv_runhelp_text $cfit
  text $cfit -height 1 -width 1 -font myfont -bg $netwag_glo_gui_bgcolor_text_select -highlightthickness 0 -yscrollcommand "$cfi.top.scro set"
  scrollbar $cfi.top.scro -command "$cfit yview" -troughcolor $netwag_glo_gui_bgcolor_text_select -highlightthickness 0
  pack $cfit -side left -expand 1 -fill both
  pack $cfi.top.scro -side left -fill y
  eval "bind $cfit <Button-1> { focus $cfit }"
  frame $cfi.bot.l -bg $netwag_glo_gui_bgcolor_unused
  frame $cfi.bot.r -bg $netwag_glo_gui_bgcolor_unused
  pack $cfi.bot.l $cfi.bot.r -side left -expand 1 -fill x
  netwag_gui_notebook1_bm_down $cfi.bot.l.copybm
  button $cfi.bot.l.copyex -text "Copy example" -command netwag_runhelp_button_copyex -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  button $cfi.bot.l.copyus -text "Copy usage" -command netwag_runhelp_button_copyus -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  button $cfi.bot.l.runit -text "Run it" -command {netwag_runhelp_button_copyex ; netwag_run_button_run} -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  netwag_gui_notebook1_bm_down $cfi.bot.l.copybm2
  pack $cfi.bot.l.copybm $cfi.bot.l.copyex $cfi.bot.l.copyus $cfi.bot.l.runit $cfi.bot.l.copybm2 -side left
  netwag_gui_notebook1_bm_up $cfi.bot.r.chbm
  button $cfi.bot.r.ch -text "Change tool" -command netwag_runhf_button_change -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  netwag_gui_notebook1_bm_up $cfi.bot.r.chbm2
  pack $cfi.bot.r.chbm $cfi.bot.r.ch $cfi.bot.r.chbm2 -side right
  netwag_dynhelp_init $cfit "This zone contains help of tool selected in Search notebook."
  netwag_dynhelp_init $cfi.bot.l.copyex "Copy above example below."
  netwag_dynhelp_init $cfi.bot.l.copyus "Copy above usage below."
  netwag_dynhelp_init $cfi.bot.l.runit "Copy above example below, and run it."
  netwag_dynhelp_init $cfi.bot.r.ch "Obtain help about current number in the run command below."
  set cb [netwag_notebook_button_get $cfn 1]
  netwag_dynhelp_init $cb "Help of selected tool."

  # form notebook
  set cff [netwag_notebook_frame_get $cfn 2]
  frame $cff.top
  frame $cff.bot -bg $netwag_glo_gui_bgcolor_unused
  pack $cff.top -side top -expand 1 -fill both
  pack $cff.bot -side top -fill x
  set cffc "$cff.top.c"
  global netwag_priv_runform_cv ; set netwag_priv_runform_cv $cffc
  canvas $cffc -yscrollcommand "$cff.top.scro set" -width 1 -height 1 -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0
  scrollbar $cff.top.scro -command "$cffc yview" -troughcolor $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  pack $cffc -side left -expand 1 -fill both
  pack $cff.top.scro -side left -fill y
  frame $cff.bot.l -bg $netwag_glo_gui_bgcolor_unused
  frame $cff.bot.c -bg $netwag_glo_gui_bgcolor_unused
  frame $cff.bot.c.c -bg $netwag_glo_gui_bgcolor_unused
  frame $cff.bot.r -bg $netwag_glo_gui_bgcolor_unused
  pack $cff.bot.l $cff.bot.c $cff.bot.r -side left -expand 1 -fill x
  netwag_gui_notebook1_bm_down $cff.bot.l.genbm
  button $cff.bot.l.gen -text "Generate" -command netwag_runform_button_gen -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  button $cff.bot.l.runit -text "Run it" -command {netwag_runform_button_gen ; netwag_run_button_run} -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  netwag_gui_notebook1_bm_down $cff.bot.l.genbm2
  pack $cff.bot.l.genbm $cff.bot.l.gen $cff.bot.l.runit $cff.bot.l.genbm2 -side left
  netwag_gui_notebook1_bm_top $cff.bot.c.c.rstbm
  button $cff.bot.c.c.rst -text "Reset" -command netwag_runform_button_rst -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  netwag_gui_notebook1_bm_top $cff.bot.c.c.rstbm2
  pack $cff.bot.c.c -side top
  pack $cff.bot.c.c.rstbm $cff.bot.c.c.rst $cff.bot.c.c.rstbm2 -side left
  netwag_gui_notebook1_bm_up $cff.bot.r.chbm
  button $cff.bot.r.ch -text "Change tool" -command netwag_runhf_button_change -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  netwag_gui_notebook1_bm_up $cff.bot.r.chbm2
  pack $cff.bot.r.chbm $cff.bot.r.ch $cff.bot.r.chbm2 -side right
  netwag_dynhelp_init $cff.bot.l.gen "Generate command line. The check button on the left indicates if the corresponding option has to be generated."
  netwag_dynhelp_init $cff.bot.l.runit "Generate command line, and run it."
  netwag_dynhelp_init $cff.bot.c.c.rst "Reset form."
  netwag_dynhelp_init $cff.bot.r.ch "Obtain form about current number in the run command below."
  set cb [netwag_notebook_button_get $cfn 2]
  netwag_dynhelp_init $cb "Easy selection of tool parameters."

  # create the run frame containing the command parameters
  frame $cfr.left
  frame $cfr.right -bg $netwag_glo_gui_bgcolor_unused
  pack $cfr.left -side left -expand 1 -fill both
  pack $cfr.right -side left -fill y
  set cfrt "$cfr.left.text"
  global netwag_priv_run_text_cmd ; set netwag_priv_run_text_cmd $cfrt
  text $cfrt -yscrollcommand "$cfr.left.scro set" -width 2 -height $netwag_glo_gui_run_cmd_height -font myfont -bg $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  scrollbar $cfr.left.scro -command "$cfrt yview" -troughcolor $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  pack $cfrt -side left -expand 1 -fill both
  pack $cfr.left.scro -side left -fill y
  button $cfr.right.run -text "Run" -command netwag_run_button_run -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  checkbutton $cfr.right.runnw -text "NW" -variable netwag_priv_run_checkbutton_nw -font myfont -selectcolor $netwag_glo_gui_selectcolor -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0
  pack $cfr.right.run $cfr.right.runnw -fill x
  netwag_dynhelp_init $cfrt "Tool to run. For example :\n1\n3 1.2.3.4\nThose are equivalent to \"netwox 1\" and \"netwox 3 1.2.3.4\""
  netwag_dynhelp_init $cfr.right.run "Run the current command and add it in the history."
  netwag_dynhelp_init $cfr.right.runnw "If checked, run the tool in a New Window.\nElse, display its output in the \"Run output\" notebook."

  set cb [netwag_notebook_button_get $frame_notebook 1]
  netwag_dynhelp_init $cb "Run a tool."
}

## Create the third notebook
proc netwag_gui_notebook2 { frame_notebook } {
  global netwag_glo_gui_bgcolor_text_select
  global netwag_glo_gui_bgcolor_text_edit
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_gui_selectcolor
  global netwag_priv_run_text_send

  set cf [netwag_notebook_frame_get $frame_notebook 2]
  frame $cf.top -bg $netwag_glo_gui_bgcolor_unused
  frame $cf.middle
  frame $cf.bottom
  pack $cf.top -fill x
  pack $cf.middle -expand 1 -fill both
  pack $cf.bottom -fill x

  entry $cf.top.sendtext -textvariable netwag_priv_run_text_send -width 10 -font myfont -bg $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  checkbutton $cf.top.echo -variable netwag_priv_run_text_echo -font myfont -selectcolor $netwag_glo_gui_selectcolor -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0
  button $cf.top.sendbut -text "Send" -command netwag_run_button_send -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  global netwag_priv_run_button_pause ;set netwag_priv_run_button_pause "$cf.top.pause"
  button $netwag_priv_run_button_pause -text "Pause" -command netwag_run_button_pause -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  button $cf.top.int -text "Interrupt" -command netwag_run_button_int -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  pack $cf.top.sendtext -side left -expand 1 -fill x
  pack $cf.top.echo $cf.top.sendbut $cf.top.pause $cf.top.int -side left
  netwag_dynhelp_init $cf.top.sendtext "Text to send to tool. Note : \"\\n\" indicates a new line."
  netwag_dynhelp_init $cf.top.echo "Send text is/isn't echoed."
  netwag_dynhelp_init $cf.top.sendbut "Send the text at the left to tool."
  netwag_dynhelp_init $netwag_priv_run_button_pause "To pause (or continue) the display of a tool."
  netwag_dynhelp_init $cf.top.int "To interrupt a running tool."

  set cftt "$cf.middle.text"
  global netwag_priv_run_text_output ; set netwag_priv_run_text_output $cftt
  text $cftt -yscrollcommand "$cf.middle.scro set" -xscrollcommand "$cf.bottom.scro set" -width 2 -height 2 -font myfont -bg $netwag_glo_gui_bgcolor_text_select -wrap none -highlightthickness 0
  scrollbar $cf.middle.scro -command "$cftt yview" -troughcolor $netwag_glo_gui_bgcolor_text_select -highlightthickness 0
  pack $cf.middle.scro -side right -fill y
  pack $cftt -expand 1 -fill both
  scrollbar $cf.bottom.scro -command "$cftt xview" -orient horizontal -troughcolor $netwag_glo_gui_bgcolor_text_select -highlightthickness 0
  pack $cf.bottom.scro -expand 1 -fill x
  eval "bind $cftt <Button-1> { focus $cftt }"
  netwag_dynhelp_init $cftt "Output (stdout) of a tool, if the checkbox NW was not checked."

  set cb [netwag_notebook_button_get $frame_notebook 2]
  netwag_dynhelp_init $cb "Output of a tool, if the checkbox NW was not checked. Otherwise, the tool is run in a New Window."
}

## Create the fourth notebook
proc netwag_gui_notebook3 { frame_notebook } {
  global netwag_glo_gui_bgcolor_text_select
  global netwag_glo_gui_bgcolor_text_edit
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_gui_selectcolor

  set cf [netwag_notebook_frame_get $frame_notebook 3]
  frame $cf.top -bg $netwag_glo_gui_bgcolor_unused
  frame $cf.middle
  frame $cf.bottom
  pack $cf.top -fill x
  pack $cf.middle -expand 1 -fill both
  pack $cf.bottom -fill x

  global netwag_glo_notebook_button_hidden_color
  button $cf.top.butupdate -text "Update" -command netwag_infol_button_update -font myfont -bg $netwag_glo_notebook_button_hidden_color -highlightthickness 0
  global netwag_priv_infol_buttons ; set netwag_priv_infol_buttons $cf.top
  button $cf.top.butdevices -text "Devices" -command {netwag_infol_button_press 1} -font myfont -bg $netwag_glo_notebook_button_hidden_color -highlightthickness 0
  button $cf.top.butip -text "Ip" -command {netwag_infol_button_press 2} -font myfont -bg $netwag_glo_notebook_button_hidden_color -highlightthickness 0
  button $cf.top.butarp -text "Arp cache" -command {netwag_infol_button_press 3} -font myfont -bg $netwag_glo_notebook_button_hidden_color -highlightthickness 0
  button $cf.top.butroutes -text "Routes" -command {netwag_infol_button_press 4} -font myfont -bg $netwag_glo_notebook_button_hidden_color -highlightthickness 0
  pack $cf.top.butupdate $cf.top.butdevices $cf.top.butip -side left -padx 1
  pack $cf.top.butarp $cf.top.butroutes -side left -padx 1
  netwag_dynhelp_init $cf.top.butupdate "Update configuration."
  netwag_dynhelp_init $cf.top.butdevices "Display devices."
  netwag_dynhelp_init $cf.top.butip "Display ip."
  netwag_dynhelp_init $cf.top.butarp "Display arp cache."
  netwag_dynhelp_init $cf.top.butroutes "Display routes."

  set cftt "$cf.middle.text"
  global netwag_priv_infol_text_output ; set netwag_priv_infol_text_output $cftt
  text $cftt -yscrollcommand "$cf.middle.scro set" -xscrollcommand "$cf.bottom.scro set" -width 2 -height 2 -font myfont -bg $netwag_glo_gui_bgcolor_text_select -wrap none -highlightthickness 0
  scrollbar $cf.middle.scro -command "$cftt yview" -troughcolor $netwag_glo_gui_bgcolor_text_select -highlightthickness 0
  pack $cf.middle.scro -side right -fill y
  pack $cftt -expand 1 -fill both
  scrollbar $cf.bottom.scro -command "$cftt xview" -orient horizontal -troughcolor $netwag_glo_gui_bgcolor_text_select -highlightthickness 0
  pack $cf.bottom.scro -expand 1 -fill x
  eval "bind $cftt <Button-1> { focus $cftt }"
  netwag_dynhelp_init $cftt "Local information depending of pressed button."

  set cb [netwag_notebook_button_get $frame_notebook 3]
  netwag_dynhelp_init $cb "Display network configuration of the local computer."
}

## Create the fifth notebook
proc netwag_gui_notebook4 { frame_notebook } {
  global netwag_glo_gui_bgcolor_text_select
  global netwag_glo_gui_bgcolor_text_edit
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_gui_selectcolor

  set cf [netwag_notebook_frame_get $frame_notebook 4]
  frame $cf.top -bg $netwag_glo_gui_bgcolor_unused
  frame $cf.middle
  frame $cf.bottom
  pack $cf.top -fill x
  pack $cf.middle -expand 1 -fill both
  pack $cf.bottom -fill x

  entry $cf.top.addr -textvariable netwag_priv_infor_text_input -width 10 -font myfont -bg $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  button $cf.top.butquery -text "Query" -command netwag_infor_button_query -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  pack $cf.top.addr -side left -expand 1 -fill x
  pack $cf.top.butquery -side left
  netwag_dynhelp_init $cf.top.addr "Contain the hostname, IP address or Ethernet address to query."
  netwag_dynhelp_init $cf.top.butquery "Query configuration and display the results."

  set cftt "$cf.middle.text"
  global netwag_priv_infor_text_output ; set netwag_priv_infor_text_output $cftt
  text $cftt -yscrollcommand "$cf.middle.scro set" -xscrollcommand "$cf.bottom.scro set" -width 2 -height 2 -font myfont -bg $netwag_glo_gui_bgcolor_text_select -wrap none -highlightthickness 0
  scrollbar $cf.middle.scro -command "$cftt yview" -troughcolor $netwag_glo_gui_bgcolor_text_select -highlightthickness 0
  pack $cf.middle.scro -side right -fill y
  pack $cftt -expand 1 -fill both
  scrollbar $cf.bottom.scro -command "$cftt xview" -orient horizontal -troughcolor $netwag_glo_gui_bgcolor_text_select -highlightthickness 0
  pack $cf.bottom.scro -expand 1 -fill x
  eval "bind $cftt <Button-1> { focus $cftt }"
  netwag_dynhelp_init $cftt "Local information depending of pressed button."

  set cb [netwag_notebook_button_get $frame_notebook 4]
  netwag_dynhelp_init $cb "Display network configuration of a remote computer."
}

## Create the sixth notebook
proc netwag_gui_notebook5 { frame_notebook } {
  global netwag_glo_gui_bgcolor_text_edit
  global netwag_gui_text_big_clipboard

  set cf [netwag_notebook_frame_get $frame_notebook 5]
  frame $cf.top
  frame $cf.bottom
  pack $cf.top -expand 1 -fill both
  pack $cf.bottom -fill x
  set netwag_gui_text_big_clipboard $cf.top.text
  text $cf.top.text -yscrollcommand "$cf.top.scro set" -xscrollcommand "$cf.bottom.scro set" -width 2 -height 2 -font myfont -bg $netwag_glo_gui_bgcolor_text_edit -wrap none -highlightthickness 0
  scrollbar $cf.top.scro -command "$cf.top.text yview" -troughcolor $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  pack $cf.top.scro -side right -fill y
  pack $cf.top.text -expand 1 -fill both
  scrollbar $cf.bottom.scro -command "$cf.top.text xview" -orient horizontal -troughcolor $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  pack $cf.bottom.scro -expand 1 -fill x

  netwag_dynhelp_init $cf.top.text "This big clipboard is useful to manage a lot of data."

  set cb [netwag_notebook_button_get $frame_notebook 5]
  netwag_dynhelp_init $cb "This big clipboard is useful to manage a lot of data."
}

## Create the clipboard
proc netwag_gui_clipboard { frame_clipboard } {
  global netwag_glo_gui_bgcolor_text_edit
  global netwag_gui_text_small_clipboard
  global netwag_glo_gui_bgcolor_button
  global netwag_glo_clipboard_text_height

  set netwag_gui_text_small_clipboard $frame_clipboard.text
  text $frame_clipboard.text -height $netwag_glo_clipboard_text_height -yscrollcommand "$frame_clipboard.scro.s set" -font myfont -bg $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  frame $frame_clipboard.scro
  scrollbar $frame_clipboard.scro.s -command "$frame_clipboard.text yview" -troughcolor $netwag_glo_gui_bgcolor_text_edit -highlightthickness 0
  # we do not use buttons because they are too big under Windows
  label $frame_clipboard.scro.more -relief raised -text "+" -pady 0 -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  bind $frame_clipboard.scro.more <Button-1> netwag_clip_height_callback_more
  label $frame_clipboard.scro.less -relief raised -text "-" -pady 0 -font myfont -bg $netwag_glo_gui_bgcolor_button -highlightthickness 0
  bind $frame_clipboard.scro.less <Button-1> netwag_clip_height_callback_less
  pack $frame_clipboard.scro.s -expand yes -fill y
  pack $frame_clipboard.scro.more -fill x
  pack $frame_clipboard.scro.less -fill x
  pack $frame_clipboard.scro -side right -fill y
  pack $frame_clipboard.text -expand yes -fill both

  netwag_dynhelp_init $frame_clipboard.text "This clipboard is shared between the six notebooks."
  netwag_dynhelp_init $frame_clipboard.scro.more "Enlarge the clipboard."
  netwag_dynhelp_init $frame_clipboard.scro.less "Shrink the clipboard."
}

## Create the message
proc netwag_gui_message { frame_message } {
  global netwag_glo_msg_text_height
  global netwag_glo_gui_bgcolor_text_select

  text $frame_message.text -height $netwag_glo_msg_text_height -yscrollcommand "$frame_message.scro set" -font myfont -bg $netwag_glo_gui_bgcolor_text_select -highlightthickness 0
  scrollbar $frame_message.scro -command "$frame_message.text yview" -troughcolor $netwag_glo_gui_bgcolor_text_select -highlightthickness 0
  pack $frame_message.scro -side right -fill y
  pack $frame_message.text -expand yes -fill both
  eval "bind $frame_message.text <Button-1> { focus $frame_message.text }"

  netwag_msg_init $frame_message.text

  netwag_dynhelp_init $frame_message.text "This zone contains info, warning and error messages."
}

## Create the menu
proc netwag_gui_menu { } {
  global netwag_session_helpdyn_active
  global netwag_glo_gui_selectcolormenu

  set topmenu ".m"
  set topmenufile "$topmenu.file"
  set topmenuedit "$topmenu.edit"
  set topmenusess "$topmenu.sess"
  set topmenuopt  "$topmenu.opt"
  set topmenuhelp "$topmenu.help"

  menu $topmenu -font myfont
  $topmenu add cascade -label "File" -menu $topmenufile -underline 0
  $topmenu add cascade -label "Edit" -menu $topmenuedit -underline 0
  $topmenu add cascade -label "Session" -menu $topmenusess -underline 0
  $topmenu add cascade -label "Options" -menu $topmenuopt -underline 0
  $topmenu add cascade -label "Help" -menu $topmenuhelp -underline 0
  . configure -menu $topmenu

  menu $topmenufile -tearoff 0 -font myfont
  $topmenufile add command -label "Exit" -command netwag_menu_fileexit -underline 1 -accelerator "Ctrl-Q"
  bind . <Control-q> netwag_menu_fileexit

  menu $topmenuedit -tearoff 0 -font myfont
  $topmenuedit add command -label "Cut" -command netwag_menu_editcut -underline 2 -accelerator "Ctrl-X"
  $topmenuedit add command -label "Copy" -command netwag_menu_editcopy -underline 0 -accelerator "Ctrl-C"
  $topmenuedit add command -label "Paste" -command netwag_menu_editpaste -underline 0 -accelerator "Ctrl-V"

  menu $topmenusess -tearoff 0 -font myfont
  $topmenusess add command -label "New" -command netwag_menu_sessnew -underline 0 -accelerator "Ctrl-N"
  bind . <Control-n> netwag_menu_sessnew
  $topmenusess add separator
  $topmenusess add command -label "Open" -command netwag_menu_sessopen -underline 0 -accelerator "Ctrl-O"
  bind . <Control-o> netwag_menu_sessopen
  $topmenusess add separator
  $topmenusess add command -label "Save" -command netwag_menu_sesssave -underline 0 -accelerator "Ctrl-S"
  bind . <Control-s> netwag_menu_sesssave
  $topmenusess add command -label "Save As..." -command netwag_menu_sesssaveas -underline 0

  menu $topmenuopt -tearoff 0 -font myfont
  $topmenuopt add command -label "Font..." -command netwag_menu_optfont -underline 0 -accelerator "Ctrl-F"
  bind . <Control-f> netwag_menu_optfont
  $topmenuopt add checkbutton -label "Dynamic help" -variable netwag_session_dynhelp_active -selectcolor $netwag_glo_gui_selectcolormenu -underline 0

  menu $topmenuhelp -tearoff 0 -font myfont
  $topmenuhelp add checkbutton -label "Dynamic help" -variable netwag_session_dynhelp_active -selectcolor $netwag_glo_gui_selectcolormenu -underline 0
  $topmenuhelp add command -label "Documentation" -command netwag_menu_helpdoc -underline 1
  $topmenuhelp add command -label "About netwag..." -command netwag_menu_helpabout -underline 0

}

#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_tmpfile_root ; set netwag_tmpfile_root ""


#################################################################
# PRIVATE FUNCTIONS
#################################################################


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Create a temporary file
# usage :
#set f [netwag_tmpfile_open filename]
#puts "$filename open"
#puts $f "blabla"
#close $f
proc netwag_tmpfile_open { {pfilename ""} } {
  global netwag_glo_dir_tmp
  global netwag_tmpfile_root

  if { $netwag_tmpfile_root == "" } {
    set netwag_tmpfile_root $netwag_glo_dir_tmp
    append netwag_tmpfile_root "/netwag."
  }

  set fn $netwag_tmpfile_root

  if {"$pfilename" != ""} {
    upvar $pfilename filename
  }

  while {1} {
    set randnum [netwag_misc_bigrand]
    set filename $fn$randnum
    set ret [catch {open $filename {WRONLY EXCL CREAT} 0600} fd]
    if { ! $ret } {
      return $fd
    }
  }
  return -1
}

## Delete the temporary file
proc netwag_tmpfile_del { filename {warnifabsent 1} } {
  global netwag_tmpfile_root

  if { $netwag_tmpfile_root == "" } {
    netwag_msg_add_err "netwag_tmpfile_del called to delete $filename, but netwag_tmpfile_root is unset"
    return
  }

  if { ! [regexp "^$netwag_tmpfile_root\[0-9\]*$" $filename] } {
    netwag_msg_add_err "netwag_tmpfile_del called to delete $filename, which was not created by netwag_tmpfile_open"
    return
  }

  file delete -- $filename
}

#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_search_lb
global netwag_priv_search_lb_type

global netwag_priv_search_type
global netwag_priv_search_type_sort ; set netwag_priv_search_type_sort 1
global netwag_priv_search_type_tree; set netwag_priv_search_type_tree 2

global netwag_priv_search_showsearch
global netwag_priv_search_searchentry
global netwag_priv_search_searchvar

global netwag_priv_search_tools_max

global netwag_priv_search_tools_sort_max
global netwag_priv_search_tools_sort_lbline

global netwag_priv_search_tools_tree_expand
global netwag_priv_search_tools_tree_nodes
global netwag_priv_search_tools_tree_text
global netwag_priv_search_tools_tree_toolstart
global netwag_priv_search_tools_tree_branch
global netwag_priv_search_tools_tree_max
global netwag_priv_search_tools_tree_lbline


#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Obtain current selected line number
proc netwag_priv_search_selnum_init_cursel {} {
  global netwag_priv_search_lb

  set sellist [$netwag_priv_search_lb curselection]
  if { ! [llength $sellist] } {
    return -1
  }

  return [lindex $sellist 0]
}

## Select last line
proc netwag_priv_search_lb_select_end { } {
  global netwag_priv_search_lb
  $netwag_priv_search_lb activate end
  $netwag_priv_search_lb selection set end
}

## See current entry
proc netwag_priv_search_lb_see_active { } {
  global netwag_priv_search_lb
  $netwag_priv_search_lb see active
}

## Display all tools in the listbox
proc netwag_priv_search_lb_all_sort { } {
  global netwag_priv_search_lb
  global netwag_priv_search_lb_type
  global netwag_priv_search_type_sort
  global netwag_priv_search_tools_sort_max
  global netwag_priv_search_tools_sort_lbline

  set entrytoselect [netwag_search_toolnum_init_cursel]
  $netwag_priv_search_lb delete 0 end
  for {set i 1} {$i<=$netwag_priv_search_tools_sort_max} {incr i} {
    $netwag_priv_search_lb insert end $netwag_priv_search_tools_sort_lbline($i)
    if { $i == $entrytoselect } {
      netwag_priv_search_lb_select_end
    }
  }
  set netwag_priv_search_lb_type $netwag_priv_search_type_sort
}

## Display searched tools in the listbox (sorted view)
proc netwag_priv_search_lb_search_sort { } {
  global netwag_priv_search_searchvar
  global netwag_priv_search_lb
  global netwag_priv_search_lb_type
  global netwag_priv_search_type_sort
  global netwag_priv_search_tools_sort_max
  global netwag_priv_search_tools_sort_lbline

  # we use "string tolower" instead of "string match -nocase"
  # because it does not exists in version 8.0
  set entrytoselect [netwag_search_toolnum_init_cursel]
  $netwag_priv_search_lb delete 0 end
  set searchedstr [string tolower $netwag_priv_search_searchvar]
  for {set i 1} {$i<=$netwag_priv_search_tools_sort_max} {incr i} {
    set lbline [string tolower $netwag_priv_search_tools_sort_lbline($i)]
    if { [string match "*$searchedstr*" $lbline] } {
      $netwag_priv_search_lb insert end $netwag_priv_search_tools_sort_lbline($i)
      if { $i == $entrytoselect } {
        netwag_priv_search_lb_select_end
      }
    }
  }
  set netwag_priv_search_lb_type $netwag_priv_search_type_sort
}

## Display searched tools in the listbox (tree view)
proc netwag_priv_search_lb_search_tree_rec_insert { subnode selnode repplus } {
  global netwag_priv_search_lb
  global netwag_priv_search_tools_tree_max
  global netwag_priv_search_tools_tree_lbline
  global netwag_priv_search_tools_tree_text

  set netwag_priv_search_tools_tree_lbline($netwag_priv_search_tools_tree_max) $subnode
  incr netwag_priv_search_tools_tree_max
  set lbline $netwag_priv_search_tools_tree_text($subnode)
  if {$repplus} {
    set lbline [netwag_misc_string_replace $lbline "+" "-"]
  }
  $netwag_priv_search_lb insert end $lbline
  if {$subnode == $selnode} {
    netwag_priv_search_lb_select_end
  }
}
proc netwag_priv_search_lb_search_tree_rec { curnode searchedstr selnode } {
  global netwag_priv_search_tools_tree_nodes
  global netwag_priv_search_tools_tree_text
  global netwag_priv_search_tools_tree_expand
  global netwag_priv_search_tools_tree_toolstart

  foreach subnode $netwag_priv_search_tools_tree_nodes($curnode) {
    if {$subnode < $netwag_priv_search_tools_tree_toolstart} {
      if {$netwag_priv_search_tools_tree_expand($subnode)} {
        netwag_priv_search_lb_search_tree_rec_insert $subnode $selnode 1
        netwag_priv_search_lb_search_tree_rec $subnode $searchedstr $selnode
      } else {
        netwag_priv_search_lb_search_tree_rec_insert $subnode $selnode 0
      }
    } else {
      if {$searchedstr == {}} {
        netwag_priv_search_lb_search_tree_rec_insert $subnode $selnode 0
      } else {
        set lbline [string tolower $netwag_priv_search_tools_tree_text($subnode)]
        if { [string match "*$searchedstr*" $lbline] } {
          netwag_priv_search_lb_search_tree_rec_insert $subnode $selnode 0
        }
      }
    }
  }
}
proc netwag_priv_search_lb_search_tree { } {
  global netwag_priv_search_lb
  global netwag_priv_search_lb_type
  global netwag_priv_search_type_tree
  global netwag_priv_search_showsearch
  global netwag_priv_search_searchvar
  global netwag_priv_search_tools_tree_branch
  global netwag_priv_search_tools_tree_max
  global netwag_priv_search_tools_tree_lbline
  global netwag_priv_search_tools_tree_toolstart
  global netwag_priv_search_tools_tree_expand

  # searched string
  if { $netwag_priv_search_showsearch == 1 } {
    set searchedstr {}
  } else {
    set searchedstr [string tolower $netwag_priv_search_searchvar]
  }

  # selected entry
  set selnode [netwag_search_node_init_cursel]
  if {$netwag_priv_search_lb_type != $netwag_priv_search_type_tree} {
    # ensure tool is visible
    if {$selnode > $netwag_priv_search_tools_tree_toolstart} {
      foreach expandnode $netwag_priv_search_tools_tree_branch($selnode) {
        set netwag_priv_search_tools_tree_expand($expandnode) 1
      }
    }
  }

  # clean
  set netwag_priv_search_tools_tree_max 0
  catch { unset netwag_priv_search_tools_tree_lbline }
  $netwag_priv_search_lb delete 0 end

  # main
  netwag_priv_search_lb_search_tree_rec 1 $searchedstr $selnode
  set netwag_priv_search_lb_type $netwag_priv_search_type_tree
}

## Called when the radio button is changed (or to update lb data)
proc netwag_priv_search_radiobutton_callback { } {
  global netwag_priv_search_type
  global netwag_priv_search_type_sort
  global netwag_priv_search_type_tree
  global netwag_priv_search_showsearch
  global netwag_priv_search_searchvar

  if { $netwag_priv_search_showsearch == 1 } {
    if {$netwag_priv_search_type == $netwag_priv_search_type_sort} {
      netwag_priv_search_lb_all_sort
    } elseif {$netwag_priv_search_type == $netwag_priv_search_type_tree} {
      netwag_priv_search_lb_search_tree
    }
  } elseif { $netwag_priv_search_showsearch == 2 } {
    if {$netwag_priv_search_type == $netwag_priv_search_type_sort} {
      netwag_priv_search_lb_search_sort
    } elseif {$netwag_priv_search_type == $netwag_priv_search_type_tree} {
      netwag_priv_search_lb_search_tree
    }
  } else {
    netwag_msg_add_err "netwag_priv_search_showsearch should be 1 or 2"
  }

  netwag_priv_search_lb_see_active
}

## Called to toggle tree
proc netwag_priv_search_tree_toggle {} {
  global netwag_priv_search_type
  global netwag_priv_search_type_tree
  global netwag_priv_search_tools_tree_toolstart
  global netwag_priv_search_tools_tree_expand

  if {$netwag_priv_search_type != $netwag_priv_search_type_tree} {
    return 0
  }

  set selnode [netwag_search_node_init_cursel]
  if {$selnode == -1 || $selnode >= $netwag_priv_search_tools_tree_toolstart} {
    return 0
  }

  if {$netwag_priv_search_tools_tree_expand($selnode)} {
    set netwag_priv_search_tools_tree_expand($selnode) 0
  } else {
    set netwag_priv_search_tools_tree_expand($selnode) 1
  }

  netwag_priv_search_radiobutton_callback
}

#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Obtain the current selected tool number
proc netwag_search_toolnum_init_cursel {} {
  global netwag_priv_search_lb
  global netwag_priv_search_tools_tree_toolstart
  global netwag_priv_search_tools_tree_lbline
  global netwag_priv_search_tools_tree_text
  global netwag_priv_search_lb_type
  global netwag_priv_search_type_sort

  set selnum [netwag_priv_search_selnum_init_cursel]
  if { $selnum == -1 } {
    return -1
  }

  if {$netwag_priv_search_lb_type == $netwag_priv_search_type_sort} {
    set seltext [$netwag_priv_search_lb get $selnum]
    if { $seltext == {} } {
      return -1
    }
    set poscolon [expr [string first ":" $seltext] - 1]
    set toolnumtext [string range $seltext 0 $poscolon]
    set toolnum [expr $toolnumtext + 0]
  } else {
    set selnode $netwag_priv_search_tools_tree_lbline($selnum)
    if {$selnode < $netwag_priv_search_tools_tree_toolstart} {
      return -1
    } else {
      set seltext $netwag_priv_search_tools_tree_text($selnode)
      set poscolon [expr [string first ":" $seltext] - 1]
      set toolnumtext [string range $seltext 0 $poscolon]
      set toolnum [expr $toolnumtext + 0]
    }
  }

  return $toolnum
}

## Obtain the current selected node
proc netwag_search_node_init_cursel {} {
  global netwag_priv_search_lb_type
  global netwag_priv_search_type_tree
  global netwag_priv_search_tools_tree_lbline
  global netwag_priv_search_tools_tree_toolstart

  set selnode -1
  if {$netwag_priv_search_lb_type == $netwag_priv_search_type_tree} {
    set selnum [netwag_priv_search_selnum_init_cursel]
    if { $selnum != -1 } {
      set selnode $netwag_priv_search_tools_tree_lbline($selnum)
    }
  } else {
    set seltoolnum [netwag_search_toolnum_init_cursel]
    if { $seltoolnum != -1 } {
      set selnode [expr $netwag_priv_search_tools_tree_toolstart + $seltoolnum]
    }
  }

  return $selnode
}

## Initialize the search function
proc netwag_search_init { } {
  global netwag_priv_search_lb
  global netwag_priv_search_searchentry
  global netwag_priv_search_searchvar
  global netwag_priv_search_showsearch
  global netwag_priv_runhf_wanttoolnum

  # associate events
  bind $netwag_priv_search_searchentry <KeyRelease> {
    netwag_priv_search_radiobutton_callback
  }
  bind $netwag_priv_search_searchentry <Button-1> {
    set netwag_priv_search_showsearch 2
    netwag_priv_search_radiobutton_callback
  }
  bind $netwag_priv_search_lb <Button-1> {
    focus $netwag_priv_search_lb
  }
  bind $netwag_priv_search_lb <ButtonRelease-1> {
    # Note : this is a bit tricky here...
    # We have "search_lb <ButtonRelease-1> netwag_priv_search_tree_toggle".
    # On the system there is (/usr/lib/tk/listbox.tcl) "Listbox <ButRelease-1>
    # %W activate @%x,%y".
    # And bindtag is "search_lb Listbox . all"
    # So, in tree mode, when we release button, we do :
    #   search_lb activate end (this is correct)
    #   Listbox activate @%x,%y (this activates the current location
    # of the mouse, which might be incorrect because we've redrawed
    # the listbox)
    # So we use a small delay to ensure "Listbox <ButRelease-1>" is finished
    # BEFORE netwag_priv_search_tree_toggle
    after 1 netwag_priv_search_tree_toggle
    # set wanted num for help and form
    set wanttoolnum [netwag_search_toolnum_init_cursel]
    if {$wanttoolnum != -1} {
      set netwag_priv_runhf_wanttoolnum $wanttoolnum
    }
  }
  bind $netwag_priv_search_lb <Key-Return> {
    netwag_priv_search_tree_toggle
  }
#  bind $netwag_priv_search_lb <ButtonRelease-1> {
#  }

  # initialize tool information
  global netwag_priv_search_tools_max
  global netwag_priv_search_tools_sort_max
  global netwag_priv_search_tools_tree_max
  set netwag_priv_search_tools_max 0
  set netwag_priv_search_tools_sort_max 0
  set netwag_priv_search_tools_tree_max 0

  # set search type
  global netwag_priv_search_type
  global netwag_priv_search_type_sort
  set netwag_priv_search_type $netwag_priv_search_type_sort
}

## Load tool definitions
global netwag_search_eventuallyinit_done
set netwag_search_eventuallyinit_done 0
proc netwag_search_eventuallyinit { } {
  global netwag_search_eventuallyinit_done
  if {$netwag_search_eventuallyinit_done} {
    return 0
  }

  # obtain list
  global netwag_glo_bin_netwox
  global netwag_popen_error
  netwag_cursor_wait
  set ret [netwag_popen "$netwag_glo_bin_netwox 0 --tools" outmsg errcode]
  netwag_cursor_default
  if { $ret } {
    netwag_msg_add_err "Cannot obtain the list of tools ($netwag_popen_error)"
    return $ret
  }
  if { $errcode } {
    netwag_msg_add_err "Tool list might be incomplete (retgets=$errcode)"
  }

  # set
  global netwag_priv_search_tools_max
  global netwag_priv_search_tools_sort_max
  global netwag_priv_search_tools_sort_lbline
  global netwag_priv_search_tools_tree_expand
  global netwag_priv_search_tools_tree_nodes
  global netwag_priv_search_tools_tree_branch
  global netwag_priv_search_tools_tree_text
  global netwag_priv_search_tools_tree_toolstart
  netwag_cursor_wait
  catch {eval $outmsg}

  # init display
  netwag_priv_search_radiobutton_callback
  netwag_cursor_default

  # just indicate the number of tools
  global netwag_priv_search_tools_max
  netwag_msg_add_info "This version contains $netwag_priv_search_tools_max tools"

  set netwag_search_eventuallyinit_done 1
  return 0
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_popen_error
global netwag_priv_popen_fdcmd


#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Set error messages
proc netwag_popen_error_set { msg } {
  global netwag_popen_error
  set netwag_popen_error $msg
}

## Initialize a popen
proc netwag_priv_popen_init_rw { cmd isread iswrite pfd } {
  global netwag_priv_popen_fdcmd

  upvar $pfd fd

  if { $isread && $iswrite } {
    set acc "r+"
  } elseif { $isread } {
    set acc "r"
  } elseif { $iswrite } {
    set acc "w"
  } else {
    return -1
  }

  if { [catch { set fd [open "| $cmd" $acc] }] } {
    netwag_popen_error_set "Cannot run $cmd"
    return -1
  }

  if { $fd == -1 } {
    netwag_popen_error_set "Cannot run $cmd"
    return -1
  }

  set netwag_priv_popen_fdcmd($fd) $cmd
  return 0
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Initialize a popen
proc netwag_popen_init_read { cmd pfd } {
  upvar $pfd fd
  return [netwag_priv_popen_init_rw $cmd 1 0 fd]
}
proc netwag_popen_init_write { cmd pfd } {
  upvar $pfd fd
  return [netwag_priv_popen_init_rw $cmd 0 1 fd]
}
proc netwag_popen_init_readwrite { cmd pfd } {
  upvar $pfd fd
  return [netwag_priv_popen_init_rw $cmd 1 1 fd]
}

## Configure popen to be unblocking
proc netwag_popen_conf_block { fd block } {

  if { $block } {
    fconfigure $fd -blocking 1 -buffering line
  } else  {
    fconfigure $fd -blocking 0 -buffering none
  }

  return 0
}

## Get the next line
proc netwag_popen_read_line { fd {pline ""} } {
  global netwag_priv_popen_fdcmd

  if {"$pline" != ""} {
    upvar $pline line
  }

  set ret [gets $fd line]

  if { $ret == -1 } {
    set cmd $netwag_priv_popen_fdcmd($fd)
    netwag_popen_error_set "Cannot get next line of command $cmd"
    return -1
  }

  return 0
}

## Get the next data
proc netwag_popen_read_data { fd {pdata ""} } {
  global netwag_priv_popen_fdcmd

  if {"$pdata" != ""} {
    upvar $pdata data
  }

  if [eof $fd] {
    return -1
  }

  set data [read $fd 16383]

  if { [string length $data] == 0 && [eof $fd] } {
    return -1
  }

  return 0
}

## Write a line
proc netwag_popen_write_line { fd line } {
  puts $fd $line
}

## Write data
proc netwag_popen_write_data { fd data } {
  puts -nonewline $fd $data
}

## Close
proc netwag_popen_close { fd {perrcode ""} } {
  global errorCode
  global netwag_priv_popen_fdcmd

  if {"$perrcode" != ""} {
    upvar $perrcode errcode
  }

  if { [catch { close $fd }] } {
    set cmd $netwag_priv_popen_fdcmd($fd)
    set errlist [split $errorCode]
    set errtype [lindex $errlist 0]
    if { $errtype == "CHILDSTATUS" } {
      set errcode [lindex $errlist 2]
      return 0
    } else {
      netwag_popen_error_set "The command $cmd exited with error $errlist"
      return -1
    }
  }

  set errcode 0
  return 0
}

## Interrupt
proc netwag_popen_interrupt { fd } {
  global errorCode
  global netwag_priv_popen_fdcmd

  if { [catch { close $fd }] } {
    set cmd $netwag_priv_popen_fdcmd($fd)
    set errlist [split $errorCode]
    set errtype [lindex $errlist 0]
    if { $errtype == "CHILDKILLED" } {
      return 0
    } elseif { $errtype == "CHILDSTATUS" } {
      return 0
    } else {
      netwag_popen_error_set "The command $cmd exited with error $errlist"
      return -1
    }
  }

  return 0
}

## Complete popen
# Example :
#   set ret [netwag_popen "/bin/ls" outmsg errcode]
#   if { $ret } {
#     puts "$netwag_popen_error"
#     exit
#   } elseif { $errcode } {
#     puts "err : $errcode"
#     exit
#   }
#   puts $outmsg
proc netwag_popen { cmd {poutmsg ""} {perrcode ""} } {
  if {"$poutmsg" != ""} {
    upvar $poutmsg outmsg
  }
  if {"$perrcode" != ""} {
    upvar $perrcode errcode
  }

  set outmsg ""
  set ret [netwag_popen_init_read $cmd fd]
  if { $ret } {
    return $ret
  }

  while {1} {
    set data [read $fd 16383]
    if { [string length $data] == 0 && [eof $fd] } {
      break
    }
    append outmsg "$data"
  }

  set ret [netwag_popen_close $fd errcode]
  return $ret
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_run_text_cmd
global netwag_priv_run_text_output
global netwag_priv_run_text_send
global netwag_priv_run_text_echo
global netwag_priv_run_text_paused
global netwag_priv_run_checkbutton_nw
global netwag_priv_run_button_pause
global netwag_priv_run_current_fd
global netwag_priv_run_current_state
global netwag_priv_run_nb


#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Convert data to hexa printable
proc netwag_priv_run_debug_hexa { data } {
  set result ""
  set resulth ""
  set resultc ""
  set strlendata [string length $data]
  for {set i 0} {$i < $strlendata} {} {
    set c [string index $data $i]
    # create hexa string
    scan $c "%c" cb
    append resulth [format "%02X " $cb]
    # create char string
    if {$cb >= 32 && $cb <= 127} {
      append resultc $c
    } else {
      append resultc "."
    }
    # concatene
    incr i
    if {!($i % 16)} {
      append result "$resulth    $resultc\n"
      set resulth ""
      set resultc ""
    }
  }
  set leftsize [expr $strlendata % 16]
  if {$leftsize} {
    append result "$resulth    "
    set leftsize [expr 16 - $leftsize]
    for {set i 0} {$i < $leftsize} {incr i} {
      append result "   "
    }
    append result "$resultc\n"
  }
  return $result
}

## Create the temporary file containing the command
proc netwag_priv_run_cmdfile_init { cmd ptmpfile } {
  upvar $ptmpfile filename

  set fd [netwag_tmpfile_open filename]
  puts $fd "$cmd\n"
  close $fd
}

## Close the temporary file
proc netwag_priv_run_cmdfile_del { tmpfilename } {
  netwag_tmpfile_del $tmpfilename 0
}

## Toggle the state of running tool
proc netwag_priv_run_state { thestate } {
  global netwag_priv_run_current_state

  set netwag_priv_run_current_state $thestate
#  if { $thestate == 1 } {
#    set netwag_priv_run_label_state "Tool is running..."
#  } elseif { $thestate == 2 } {
#    set netwag_priv_run_label_state "..tool is paused.."
#  } else {
#    set netwag_priv_run_label_state "No tool is running"
#  }
}

## Append data in the text [color0:black 1:stdin 2:end]
proc netwag_priv_run_text_output_append { thedata {colortype 0} } {
  global netwag_priv_run_text_output
  $netwag_priv_run_text_output configure -state normal
  if {$colortype == 0} {
    $netwag_priv_run_text_output insert end "$thedata"
  } elseif {$colortype == 1} {
    $netwag_priv_run_text_output insert end "$thedata" netwag_priv_run_color_stdin
  } elseif {$colortype == 2} {
    $netwag_priv_run_text_output insert end "__END_OF_PROGRAM__" netwag_priv_run_color_end
  } else {
    netwag_msg_add_err "colortype $colortype unknown"

  }
  $netwag_priv_run_text_output configure -state disabled
}

## Get the error message associated to a number
proc netwag_priv_run_errmsg { errnum } {
  global netwag_glo_bin_netwox

  set ret [netwag_popen "$netwag_glo_bin_netwox 0 -e -u $errnum" outmsg errcode]
  if { $ret || $errcode} {
    return "could not obtain the error message"
  }
  set msg $outmsg

  return $msg
}

## Check the command
proc netwag_priv_run_cmd_check { pcmd ptoolnum } {
  upvar $pcmd cmd
  upvar $ptoolnum toolnum
  global netwag_priv_run_text_cmd

  set cmd [$netwag_priv_run_text_cmd get 1.0 end]
  set cmd [netwag_misc_string_map $cmd {"\r" " " "\n" " "}]
  set cmd [string trim $cmd]

  if { $cmd == "" } {
    netwag_msg_add_warn "Command \"$cmd\" too short"
    return -1
  }
  set cmdlist [split $cmd]

  set toolnum [lindex $cmdlist 0]
  if { [regexp {[^0-9]} $toolnum] } {
    netwag_msg_add_warn "The first parameter (\"$toolnum\") must be a number"
    return -1
  }

  return 0
}

## Check if the command is empty
proc netwag_priv_run_cmd_empty { } {
  global netwag_priv_run_text_cmd

  set cmd [$netwag_priv_run_text_cmd get 1.0 end]
  set cmd [netwag_misc_string_map $cmd {"\r" " " "\n" " "}]
  set cmd [string trim $cmd]

  if { $cmd == "" } {
    return -1
  }

  return 0
}

## Called when data is available
proc netwag_priv_run_text_event { } {
  global netwag_priv_run_current_fd
  global netwag_priv_run_text_paused
  global netwag_priv_run_current_state

  set fd $netwag_priv_run_current_fd
  set ret [netwag_popen_read_data $fd data]

  if { $ret == 0 } {
    # suppress \r
    set data [netwag_misc_string_replace $data "\r" ""]
    # ok
    if { $netwag_priv_run_current_state == 1 } {
      netwag_priv_run_text_output_append "$data"
    } else {
      append netwag_priv_run_text_paused "$data"
    }
    return 0
  }

  netwag_priv_run_state 0

  set ret [netwag_popen_close $fd errcode]
  if { $ret } {
    netwag_msg_add_err "Error when closing \"$cmd\""
    return $ret
  }

  if { $errcode } {
    set msg "The process returned $errcode"
    set msgerr [netwag_priv_run_errmsg $errcode]
    if { $msgerr != "" } {
      append msg " ($msgerr)"
    }
    netwag_msg_add_err $msg
  } else {
    netwag_msg_add_info "The process returned OK"
  }
  netwag_priv_run_text_output_append "" 2

  return 0
}

#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Run a command and put result in a text
proc netwag_run_text { cmd } {
  global netwag_glo_bin_netwox
  global netwag_priv_run_current_fd

  netwag_priv_run_cmdfile_init $cmd tmpfilename

  set ret [netwag_popen_init_readwrite "$netwag_glo_bin_netwox 0 -r -b $tmpfilename" fd]
  if { $ret } {
    netwag_msg_add_err "Cannot run \"$cmd\""
    netwag_priv_run_cmdfile_del $tmpfilename
    return $ret
  } else {
    netwag_msg_add_info "Running \"$cmd\""
  }

  netwag_priv_run_state 1
  set netwag_priv_run_current_fd $fd
  netwag_popen_conf_block $fd 0

  fconfigure $fd -translation {binary binary}

  global netwag_priv_run_text_output
  $netwag_priv_run_text_output configure -state normal
  $netwag_priv_run_text_output delete 1.0 end
  $netwag_priv_run_text_output configure -state disabled

  fileevent $fd readable { netwag_priv_run_text_event }

  return 0
}

## Run a command in a new window
proc netwag_run_nw { cmd } {
  global netwag_glo_bin_netwox
  global netwag_sys_platform
  global netwag_sys_platform_unix
  global netwag_sys_platform_windows
  global netwag_glo_bin_shell_cmd
  global netwag_glo_bin_shell_param
  global netwag_glo_bin_term_cmd
  global netwag_glo_bin_term_param
  global env
  global netwag_sys_os;
  global netwag_sys_os_windows95
  global netwag_sys_os_windows98
  global netwag_sys_os_windowsme

  netwag_priv_run_cmdfile_init $cmd tmpfilename

  if {$netwag_sys_platform == $netwag_sys_platform_unix} {
    # we use "sh -c" in case netwox is not in the path
    exec $netwag_glo_bin_term_cmd $netwag_glo_bin_term_param $netwag_glo_bin_shell_cmd $netwag_glo_bin_shell_param "$netwag_glo_bin_netwox 0 -R -b $tmpfilename" &
  } elseif {$netwag_sys_platform == $netwag_sys_platform_windows} {
    # we use "$env(COMSPEC) /c" in case netwox is not in the path
    if { $netwag_sys_os==$netwag_sys_os_windows95 || $netwag_sys_os==$netwag_sys_os_windows98 || $netwag_sys_os==$netwag_sys_os_windowsme } {
      exec start $env(COMSPEC) /c $netwag_glo_bin_netwox 0 -R -b $tmpfilename &
    } else {
      # because start is not an external command
      exec $env(COMSPEC) /c start $env(COMSPEC) /c $netwag_glo_bin_netwox 0 -R -b $tmpfilename &
    }
  } else {
    netwag_msg_add_err "I don't know how to run a command on this platform"
  }

  # eventually remove command filename
  after 5000 "netwag_priv_run_cmdfile_del $tmpfilename"

  return 0
}

## Press Run button
proc netwag_run_button_run { } {
  global netwag_priv_run_checkbutton_nw
  global netwag_priv_run_current_state
  global netwag_priv_run_nb
  global frame_notebook

  if { [netwag_priv_run_cmd_empty] } {
    netwag_msg_add_warn "Command is empty. Will try to automatically press on first button."
    set butnum [netwag_notebook_butnum_get $netwag_priv_run_nb]
    if {$butnum == 0} {
      netwag_runhist_button_copy
    } elseif {$butnum == 1} {
      netwag_runhelp_button_copyex
    } elseif {$butnum == 2} {
      netwag_runform_button_gen
    } else {
      netwag_msg_add_err "Butnum $butnum is not implemented."
      return
    }
    if { ! [netwag_priv_run_cmd_empty] } {
      netwag_msg_add_info "If you agree with this command, press Run again."
    }
    return
  }
  if { [netwag_priv_run_cmd_check cmd toolnum] } {
    return
  }
  netwag_runhist_add "$cmd"

  if { $netwag_priv_run_checkbutton_nw } {
    netwag_msg_add_info "Running \"$cmd\""
    netwag_msg_add_info "We cannot check its return value because tool is run in a New Window"
    netwag_run_nw $cmd
  } else {
    if { $netwag_priv_run_current_state } {
      netwag_msg_add_warn "A tool is currently running"
    } else {
      netwag_notebook_button_press $frame_notebook 2
      netwag_run_text $cmd
    }
  }
}

## Press Interrupt button
proc netwag_run_button_int { {warnifnorun 1} } {
  global netwag_priv_run_current_fd
  global netwag_priv_run_current_state
  global netwag_glo_bin_netwox

  if {![info exists netwag_priv_run_current_state]} {
    set netwag_priv_run_current_state 0
  }

  if { ! $netwag_priv_run_current_state } {
    if {$warnifnorun} {
      netwag_msg_add_warn "There is no tool currently running"
    }
    return 0
  }

  # we kill the child in 500 ms if it doesn't close itself
  set thepid [pid $netwag_priv_run_current_fd]
  exec $netwag_glo_bin_netwox 0 -k -u $thepid -b 500 &

  set ret [netwag_popen_interrupt $netwag_priv_run_current_fd]
  if { $ret == 0 } {
    netwag_msg_add_info "Tool interrupted successfully"
    netwag_priv_run_text_output_append "" 2
  }
  netwag_priv_run_state 0
  return $ret
}

## Press Send button
proc netwag_run_button_send { } {
  global netwag_priv_run_current_fd
  global netwag_priv_run_current_state
  global netwag_priv_run_text_send
  global netwag_priv_run_text_echo

  if { ! $netwag_priv_run_current_state } {
    netwag_msg_add_warn "There is no tool currently running"
    return 0
  }

  set sendtext [netwag_misc_string_map $netwag_priv_run_text_send {"\\\\" "\\" "\\0" "\0" "\\r" "\r" "\\n" "\n"}]
  if {$netwag_priv_run_text_echo} {
    netwag_priv_run_text_output_append $sendtext 1
  }
  netwag_popen_write_data $netwag_priv_run_current_fd $sendtext
  return 0
}

## Press Pause button
proc netwag_run_button_pause { } {
  global netwag_priv_run_current_fd
  global netwag_priv_run_current_state
  global netwag_priv_run_text_paused
  global netwag_priv_run_button_pause

  if { ! $netwag_priv_run_current_state } {
    netwag_msg_add_warn "There is no tool currently running"
    return 0
  }

  if { $netwag_priv_run_current_state == 1 } {
    netwag_priv_run_state 2
    netwag_dynhelp_change $netwag_priv_run_button_pause "To continue the display of a tool."
    $netwag_priv_run_button_pause configure -text "Continue"
  } else {
    netwag_priv_run_state 1
    netwag_priv_run_text_output_append $netwag_priv_run_text_paused
    netwag_dynhelp_change $netwag_priv_run_button_pause "To pause the display of a tool."
    $netwag_priv_run_button_pause configure -text "Pause"
  }
  set netwag_priv_run_text_paused ""

  return 0
}

## Check netwox and its version
proc netwag_run_checknetwox { } {
  global netwag_glo_versionmajor
  global netwag_glo_versionminor
  global netwag_glo_bin_netwox
  global netwag_popen_error

  set errmsg1 "We cannot run $netwag_glo_bin_netwox"
  set errmsg2 "Variable netwag_glo_bin_netwox($netwag_glo_bin_netwox) might not contain a valid path to netwox."
  set ret [netwag_popen "$netwag_glo_bin_netwox 0" outmsg errcode]
  if { $ret } {
    netwag_msg_add_err "$errmsg1 ($netwag_popen_error)"
    netwag_priv_glo_errorbadval "$errmsg1 ($netwag_popen_error).\n$errmsg2"
    return -1
  } elseif { $errcode } {
    netwag_msg_add_err "$errmsg1 (errcode=$errcode)"
    netwag_priv_glo_errorbadval "$errmsg1 (errcode=$errcode).\n$errmsg2"
    return -1
  }
  # puts $outmsg

  return 0
}

## Initialize run
proc netwag_run_init { } {
  global netwag_priv_run_text_send
  global netwag_priv_run_checkbutton_nw
  global netwag_priv_run_text_echo

  set netwag_priv_run_text_send "\\n"
  set netwag_priv_run_checkbutton_nw 0
  set netwag_priv_run_text_echo 1
  netwag_priv_run_state 0

  global netwag_priv_run_text_output
  global netwag_glo_run_color_stdin
  $netwag_priv_run_text_output tag configure netwag_priv_run_color_stdin -foreground $netwag_glo_run_color_stdin
  $netwag_priv_run_text_output tag configure netwag_priv_run_color_end -foreground "#66CC66"
  $netwag_priv_run_text_output configure -state disabled

  return 0
}

## Initialize the command
proc netwag_run_cmd_init { cmd } {
  global netwag_priv_run_text_cmd
  $netwag_priv_run_text_cmd delete 1.0 end
  $netwag_priv_run_text_cmd insert end $cmd
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_runhist_lb

#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Obtain the current selected command
proc netwag_priv_runhist_cmd_init_cursel {} {
  global netwag_priv_runhist_lb

  set sellist [$netwag_priv_runhist_lb curselection]
  if { ! [llength $sellist] } {
    return ""
  }

  set selnum [lindex $sellist 0]
  set cmd [netwag_priv_runhist_cmd_init_selnum $selnum]

  return $cmd
}

## Obtain the command at a given position
proc netwag_priv_runhist_cmd_init_selnum { selnum } {
  global netwag_priv_runhist_lb

  set seltext [$netwag_priv_runhist_lb get $selnum]

  return $seltext
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Called when the "Copy" button is changed
proc netwag_runhist_button_copy { } {
  set cmd [netwag_priv_runhist_cmd_init_cursel]
  if { $cmd == "" } {
    netwag_msg_add_warn "No history line is selected"
    return
  }
  netwag_run_cmd_init $cmd
}

## Called when the "Del" button is changed
proc netwag_runhist_button_del { } {
  global netwag_priv_runhist_lb

  set sellist [$netwag_priv_runhist_lb curselection]
  if { ! [llength $sellist] } {
    netwag_msg_add_warn "No history line is selected"
    return
  }

  $netwag_priv_runhist_lb del $sellist

  set selsize [$netwag_priv_runhist_lb size]
  if { $selsize } {
    set toselect [lindex $sellist 0]
    if { $toselect < $selsize } {
      $netwag_priv_runhist_lb selection set $toselect
    } else {
      $netwag_priv_runhist_lb selection set end
    }
  }
}

## To add a command in the history
proc netwag_runhist_add { cmd } {
  global netwag_priv_runhist_lb

  # add at end
  $netwag_priv_runhist_lb insert end "$cmd"
  $netwag_priv_runhist_lb see end

  # now eventually remove it from previous history
  set arraysize [$netwag_priv_runhist_lb size]
  for {set i 0} {$i < [expr $arraysize - 1]} {incr i} {
    set cmdi [$netwag_priv_runhist_lb get $i]
    if {$cmdi == $cmd} {
      # must be done now, because after the del, it will be unset
      set sellist [$netwag_priv_runhist_lb curselection]
      # remove the old entry
      $netwag_priv_runhist_lb del $i
      # eventually reselect the item
      if { [llength $sellist] } {
        set cursel [lindex $sellist 0]
        if {$i == $cursel} {
          $netwag_priv_runhist_lb selection set end
        }
      }
      # exit now because it should only be once
      return
      # note : if we decide to not return, do not forget "set i [expr $i - 1]"
    }
  }

}

## Called when the "Add" button is changed
proc netwag_runhist_button_add { } {

  if { [netwag_priv_run_cmd_check cmd toolnum] } {
    return
  }
  netwag_runhist_add "$cmd"
}

## Initialize the hist function
proc netwag_runhist_init { } {
  global netwag_priv_runhist_lb

  # associate events
  bind $netwag_priv_runhist_lb <Button-1> {
    focus $netwag_priv_runhist_lb
  }
  bind $netwag_priv_runhist_lb <Key-Return> {
    netwag_runhist_button_copy
  }
  bind $netwag_priv_runhist_lb <Key-Delete> {
    netwag_runhist_button_del
  }
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_runhelp_text

global netwag_priv_runhelp_help
global netwag_priv_runhelp_example
global netwag_priv_runhelp_usage


#################################################################
# PRIVATE FUNCTIONS
#################################################################


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Display the description of a tool
proc netwag_runhelp_display { toolnum } {
  global netwag_priv_runhelp_text
  global netwag_priv_runhelp_help

  $netwag_priv_runhelp_text configure -state normal
  $netwag_priv_runhelp_text delete 1.0 end
  $netwag_priv_runhelp_text insert end $netwag_priv_runhelp_help($toolnum)
  $netwag_priv_runhelp_text configure -state disabled
}

## Called when Copy example is pressed
proc netwag_runhelp_button_copyex {} {
  global netwag_priv_runhf_curtoolnum
  global netwag_priv_runhelp_example

  if {$netwag_priv_runhf_curtoolnum == -1} {
    netwag_msg_add_err "No tool is selected"
    return
  }

  netwag_run_cmd_init $netwag_priv_runhelp_example($netwag_priv_runhf_curtoolnum)
}

## Called when Copy usage is pressed
proc netwag_runhelp_button_copyus {} {
  global netwag_priv_runhf_curtoolnum
  global netwag_priv_runhelp_usage

  if {$netwag_priv_runhf_curtoolnum == -1} {
    netwag_msg_add_err "No tool is selected"
    return
  }

  netwag_run_cmd_init $netwag_priv_runhelp_usage($netwag_priv_runhf_curtoolnum)
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_runform_cv

global netwag_priv_runform_numobj ; set netwag_priv_runform_numobj 0
global netwag_priv_runform_objects
global netwag_priv_runform_info

global netwag_priv_runform_nexty

#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Generate a button
proc netwag_runform_add_button { isreq key title defaultval } {
  global netwag_priv_runform_cv
  global netwag_priv_runform_info
  global netwag_glo_gui_selectcolor
  global netwag_glo_gui_bgcolor_unused

  # create item
  global netwag_priv_runform_numobj ; set numobj $netwag_priv_runform_numobj
  global netwag_priv_runform_objects
  set f $netwag_priv_runform_cv.fb($numobj)
  # 65 is for the size of "space entry -t entry" on left
  set freespace [expr [winfo width $netwag_priv_runform_cv] - 65]
  if {![winfo exist $f.b]} {
    frame $f
    checkbutton $f.r -text "-$key" -variable netwag_priv_runform_info($numobj,isset) -font myfont -selectcolor $netwag_glo_gui_selectcolor -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0 -justify left
    checkbutton $f.b -text $title -variable netwag_priv_runform_info($numobj,var) -font myfont -selectcolor $netwag_glo_gui_selectcolor -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0 -wraplen $freespace -justify left -command "set netwag_priv_runform_info($numobj,isset) 1"
    pack $f.r $f.b -side left -expand 1 -fill y
  } else {
    $f.r configure -text "-$key"
    $f.b configure -text $title -wraplen $freespace
  }
  set netwag_priv_runform_info($numobj,isset) $isreq
  set netwag_priv_runform_info($numobj,var) $defaultval

  # create window
  global netwag_priv_runform_nexty
  set netwag_priv_runform_objects($numobj) [$netwag_priv_runform_cv create window 5 $netwag_priv_runform_nexty -window $f -anchor nw -tags item]
  incr netwag_priv_runform_nexty [winfo reqheight $f.b]
  # +2 for a small space
  incr netwag_priv_runform_nexty 2

  # save info
  set netwag_priv_runform_info($numobj,type) "button"
  # netwag_priv_runform_info($numobj,isset) set above
  # netwag_priv_runform_info($numobj,var) set above
  set netwag_priv_runform_info($numobj,isreq) $isreq
  set netwag_priv_runform_info($numobj,key) $key
  set netwag_priv_runform_info($numobj,defaultval) $defaultval

  # ready for next
  incr netwag_priv_runform_numobj
}
proc netwag_runform_gene_button { numobj } {
  global netwag_priv_runform_info
  if {!$netwag_priv_runform_info($numobj,isset)} {
    return ""
  }
  set key $netwag_priv_runform_info($numobj,key)
  if {$netwag_priv_runform_info($numobj,var)} {
    return " -$key"
  }
  return " +$key"
}
proc netwag_runform_rst_button { numobj } {
  global netwag_priv_runform_info
  set netwag_priv_runform_info($numobj,isset) $netwag_priv_runform_info($numobj,isreq)
  set netwag_priv_runform_info($numobj,var) $netwag_priv_runform_info($numobj,defaultval)
}

## Generate an entry
proc netwag_runform_add_entry { isreq key title defaultval } {
  global netwag_priv_runform_cv
  global netwag_priv_runform_info
  global netwag_glo_gui_selectcolor
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_text_edit

  # create item
  global netwag_priv_runform_numobj ; set numobj $netwag_priv_runform_numobj
  global netwag_priv_runform_objects
  set f $netwag_priv_runform_cv.fe($numobj)
  # 65 is for the size of "space button -t frame [entry] frame" on left
  set freespace [expr [winfo width $netwag_priv_runform_cv] - 65]
  # substract entry size
  set freespace [expr $freespace - 20 * [font measure myfont "w"]]
  if {![winfo exist $f.e]} {
    frame $f -bg $netwag_glo_gui_bgcolor_unused
    checkbutton $f.r -text "-$key" -variable netwag_priv_runform_info($numobj,isset) -font myfont -selectcolor $netwag_glo_gui_selectcolor -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0 -justify left
    entry $f.e -textvariable netwag_priv_runform_info($numobj,var) -font myfont -highlightthickness 0 -width 20 -bg $netwag_glo_gui_bgcolor_text_edit
    bind $f.e <Button-1> "set netwag_priv_runform_info($numobj,isset) 1"
    label $f.l -text $title -font myfont -highlightthickness 0 -wraplen $freespace -justify left -bg $netwag_glo_gui_bgcolor_unused
    bind $f.l <Button-1> "set netwag_priv_runform_info($numobj,isset) 1"
    pack $f.r -side left -expand 1 -fill y
    pack $f.e -side left
    pack $f.l -side left -expand 1 -fill y
  } else {
    $f.r configure -text "-$key"
    $f.l configure -text $title -wraplen $freespace
  }
  set netwag_priv_runform_info($numobj,isset) $isreq
  set netwag_priv_runform_info($numobj,var) $defaultval

  # create window
  global netwag_priv_runform_nexty
  set netwag_priv_runform_objects($numobj) [$netwag_priv_runform_cv create window 5 $netwag_priv_runform_nexty -window $f -anchor nw -tags item]
  incr netwag_priv_runform_nexty [winfo reqheight $f.l]
  # +2 for a small space
  incr netwag_priv_runform_nexty 2

  # save info
  set netwag_priv_runform_info($numobj,type) "entry"
  # netwag_priv_runform_info($numobj,isset) set above
  # netwag_priv_runform_info($numobj,var) set above
  set netwag_priv_runform_info($numobj,isreq) $isreq
  set netwag_priv_runform_info($numobj,key) $key
  set netwag_priv_runform_info($numobj,defaultval) $defaultval

  # ready for next
  incr netwag_priv_runform_numobj
}
proc netwag_runform_gene_entry { numobj } {
  global netwag_priv_runform_info
  if {!$netwag_priv_runform_info($numobj,isset)} {
    return ""
  }
  set key $netwag_priv_runform_info($numobj,key)
  set val [netwag_misc_string_replace $netwag_priv_runform_info($numobj,var) "\"" "\\\""]
  return " -$key \"$val\""
}
proc netwag_runform_rst_entry { numobj } {
  global netwag_priv_runform_info
  set netwag_priv_runform_info($numobj,isset) $netwag_priv_runform_info($numobj,isreq)
  set netwag_priv_runform_info($numobj,var) $netwag_priv_runform_info($numobj,defaultval)
}

## Generate a listbox
proc netwag_runform_add_listbox { isreq key title listval defaultval } {
  global netwag_priv_runform_cv
  global netwag_priv_runform_info
  global netwag_glo_gui_selectcolor
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_listbox

  # obtain listbox height/width
  set listboxwidth [string length $defaultval]
  set listboxheight 0
  set listboxscrol 0
  set defaultfound 0
  foreach val $listval {
    set len [string length $val]
    if {$len > $listboxwidth} { set listboxwidth $len }
    if {$val == $defaultval} { set defaultfound 1 }
    incr listboxheight
  }
  if {!$defaultfound && $defaultval != ""} { incr listboxheight }
  if {$listboxheight > 6} { set listboxscrol 1 ; set listboxheight 6 }
  # create item
  global netwag_priv_runform_numobj ; set numobj $netwag_priv_runform_numobj
  global netwag_priv_runform_objects
  set f $netwag_priv_runform_cv.fl($numobj)
  # 65 is for the size of "space button -t frame [listbox] frame" on left
  set freespace [expr [winfo width $netwag_priv_runform_cv] - 65]
  # substract listbox size
  set freespace [expr $freespace - $listboxwidth * [font measure myfont "w"]]
  if {$listboxscrol} {
    incr freespace -10
  }
  # create
  if {![winfo exist $f.f]} {
    frame $f -bg $netwag_glo_gui_bgcolor_unused
    checkbutton $f.r -text "-$key" -variable netwag_priv_runform_info($numobj,isset) -font myfont -selectcolor $netwag_glo_gui_selectcolor -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0 -justify left
    frame $f.f -bg $netwag_glo_gui_bgcolor_unused
    listbox $f.f.l -yscrollcommand "$f.f.s set" -font myfont -bg $netwag_glo_gui_bgcolor_listbox -highlightthickness 0 -height $listboxheight -exportselection false -width $listboxwidth
    scrollbar $f.f.s -command "$f.f.l yview" -troughcolor $netwag_glo_gui_bgcolor_listbox -highlightthickness 0
    pack $f.f.l -side left -expand 1 -fill y
    bind $f.f.l <Button-1> "focus $f.f.l ; set netwag_priv_runform_info($numobj,isset) 1"
    label $f.l -text $title -font myfont -highlightthickness 0 -wraplen $freespace -justify left -bg $netwag_glo_gui_bgcolor_unused
    bind $f.l <Button-1> "set netwag_priv_runform_info($numobj,isset) 1"
    pack $f.r $f.f $f.l -side left -expand 1 -fill y
  } else {
    $f.r configure -text "-$key"
    $f.l configure -text $title -wraplen $freespace
  }
  if {$listboxscrol} {
    pack $f.f.s -side left -expand 1 -fill y
  } else {
    pack forget $f.f.s
  }
  set netwag_priv_runform_info($numobj,isset) $isreq

  # create window
  global netwag_priv_runform_nexty
  set netwag_priv_runform_objects($numobj) [$netwag_priv_runform_cv create window 5 $netwag_priv_runform_nexty -window $f -anchor nw -tags item]
  if {[winfo reqheight $f.l] > [winfo reqheight $f.f.l]} {
    incr netwag_priv_runform_nexty [winfo reqheight $f.l]
  } else {
    incr netwag_priv_runform_nexty [winfo reqheight $f.f.l]
  }
  # +2 for a small space
  incr netwag_priv_runform_nexty 2

  # save info
  set netwag_priv_runform_info($numobj,type) "listbox"
  set netwag_priv_runform_info($numobj,lb) $f.f.l
  # netwag_priv_runform_info($numobj,isset) set above
  set netwag_priv_runform_info($numobj,isreq) $isreq
  set netwag_priv_runform_info($numobj,key) $key
  set netwag_priv_runform_info($numobj,listval) $listval
  set netwag_priv_runform_info($numobj,defaultval) $defaultval

  # display entries
  netwag_runform_rst_listbox $numobj

  # ready for next
  incr netwag_priv_runform_numobj
}
proc netwag_runform_gene_listbox { numobj } {
  global netwag_priv_runform_info
  if {!$netwag_priv_runform_info($numobj,isset)} {
    return ""
  }
  set key $netwag_priv_runform_info($numobj,key)
  set i [lindex [$netwag_priv_runform_info($numobj,lb) curselection] 0]
  set val [$netwag_priv_runform_info($numobj,lb) get $i]
  set val [netwag_misc_string_replace $val "\"" "\\\""]
  return " -$key \"$val\""
}
proc netwag_runform_rst_listbox { numobj } {
  global netwag_priv_runform_info

  set netwag_priv_runform_info($numobj,isset) $netwag_priv_runform_info($numobj,isreq)

  $netwag_priv_runform_info($numobj,lb) delete 0 end
  set defaultfound 0
  if {$netwag_priv_runform_info($numobj,defaultval) == ""} {
    set defaultfound 1
  }
  foreach val $netwag_priv_runform_info($numobj,listval) {
    $netwag_priv_runform_info($numobj,lb) insert end $val
    if {!$defaultfound && $val==$netwag_priv_runform_info($numobj,defaultval)} {
      $netwag_priv_runform_info($numobj,lb) activate end
      set defaultfound 1
    }
  }
  if {!$defaultfound} {
    $netwag_priv_runform_info($numobj,lb) insert end $netwag_priv_runform_info($numobj,defaultval)
    $netwag_priv_runform_info($numobj,lb) activate end
  }
  $netwag_priv_runform_info($numobj,lb) selection set active
  $netwag_priv_runform_info($numobj,lb) see active
}

## Generate a more
proc netwag_runform_add_more { title defaultval } {
  global netwag_priv_runform_cv
  global netwag_priv_runform_info
  global netwag_glo_gui_selectcolor
  global netwag_glo_gui_bgcolor_unused
  global netwag_glo_gui_bgcolor_text_edit

  # create item
  global netwag_priv_runform_numobj ; set numobj $netwag_priv_runform_numobj
  global netwag_priv_runform_objects
  set f $netwag_priv_runform_cv.fm($numobj)
  # 65 is for the size of "space button -t frame [more] frame" on left
  set freespace [expr [winfo width $netwag_priv_runform_cv] - 65]
  # substract more size
  set freespace [expr $freespace - 20 * [font measure myfont "w"]]
  if {![winfo exist $f.e]} {
    frame $f -bg $netwag_glo_gui_bgcolor_unused
    checkbutton $f.r -text "  " -variable netwag_priv_runform_info($numobj,isset) -font myfont -selectcolor $netwag_glo_gui_selectcolor -bg $netwag_glo_gui_bgcolor_unused -highlightthickness 0 -justify left
    entry $f.e -textvariable netwag_priv_runform_info($numobj,var) -font myfont -highlightthickness 0 -width 20 -bg $netwag_glo_gui_bgcolor_text_edit
    bind $f.e <Button-1> "set netwag_priv_runform_info($numobj,isset) 1"
    label $f.l -text $title -font myfont -highlightthickness 0 -wraplen $freespace -justify left -bg $netwag_glo_gui_bgcolor_unused
    bind $f.l <Button-1> "set netwag_priv_runform_info($numobj,isset) 1"
    pack $f.r -side left -expand 1 -fill y
    pack $f.e -side left
    pack $f.l -side left -expand 1 -fill y
  } else {
    $f.l configure -text $title -wraplen $freespace
  }
  set netwag_priv_runform_info($numobj,isset) 0
  set netwag_priv_runform_info($numobj,var) $defaultval

  # create window
  global netwag_priv_runform_nexty
  set netwag_priv_runform_objects($numobj) [$netwag_priv_runform_cv create window 5 $netwag_priv_runform_nexty -window $f -anchor nw -tags item]
  incr netwag_priv_runform_nexty [winfo reqheight $f.l]
  # +2 for a small space
  incr netwag_priv_runform_nexty 2

  # save info
  set netwag_priv_runform_info($numobj,type) "more"
  # netwag_priv_runform_info($numobj,isset) set above
  # netwag_priv_runform_info($numobj,var) set above
  set netwag_priv_runform_info($numobj,isreq) 0
  set netwag_priv_runform_info($numobj,defaultval) $defaultval

  # ready for next
  incr netwag_priv_runform_numobj
}
proc netwag_runform_gene_more { numobj } {
  global netwag_priv_runform_info
  if {!$netwag_priv_runform_info($numobj,isset)} {
    return ""
  }
  set val [netwag_misc_string_replace $netwag_priv_runform_info($numobj,var) "\"" "\\\""]
  if {$val == ""} {
    return ""
  }
  return " \"$val\""
}
proc netwag_runform_rst_more { numobj } {
  global netwag_priv_runform_info
  set netwag_priv_runform_info($numobj,isset) $netwag_priv_runform_info($numobj,isreq)
  set netwag_priv_runform_info($numobj,var) $netwag_priv_runform_info($numobj,defaultval)
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Display the description of a tool
proc netwag_runform_display { toolnum } {
  global netwag_priv_runform_cv
  global netwag_priv_runform_numobj
  global netwag_priv_runform_objects
  global netwag_priv_runform_nexty

  set c $netwag_priv_runform_cv

  # delete previous
  for {set i 0} {$i < $netwag_priv_runform_numobj} {incr i} {
    $c delete $netwag_priv_runform_objects($i)
  }
  set netwag_priv_runform_numobj 0
  set netwag_priv_runform_nexty 5

  # create new ones
  eval "netwag_runform_display_func$toolnum"

  if {$netwag_priv_runform_numobj == 0} {
    $c create text 5 10 -text "This tool does not need parameters" -anchor w -font myfont
  }

  # end
  eval "$c configure -scrollregion {0 0 0 $netwag_priv_runform_nexty}"
  update idletasks
}

## Called when Generate is pressed
proc netwag_runform_button_gen {} {
  global netwag_priv_runform_numobj
  global netwag_priv_runform_info
  global netwag_priv_runhf_curtoolnum

  set cmd $netwag_priv_runhf_curtoolnum

  for {set i 0} {$i < $netwag_priv_runform_numobj} {incr i} {
    if {$netwag_priv_runform_info($i,type) =="button"} {
      append cmd [netwag_runform_gene_button $i]
    } elseif {$netwag_priv_runform_info($i,type) =="entry"} {
      append cmd [netwag_runform_gene_entry $i]
    } elseif {$netwag_priv_runform_info($i,type) =="listbox"} {
      append cmd [netwag_runform_gene_listbox $i]
    } elseif {$netwag_priv_runform_info($i,type) =="more"} {
      append cmd [netwag_runform_gene_more $i]
    } else {
      set type netwag_priv_runform_info($i,type)
      netwag_msg_add_warn "Cannot generate this type($type) of form"
    }
  }

  netwag_run_cmd_init $cmd
}

## Called when Reset is pressed
proc netwag_runform_button_rst {} {
  global netwag_priv_runform_numobj
  global netwag_priv_runform_info

  for {set i 0} {$i < $netwag_priv_runform_numobj} {incr i} {
    if {$netwag_priv_runform_info($i,type) =="button"} {
      netwag_runform_rst_button $i
    } elseif {$netwag_priv_runform_info($i,type) =="entry"} {
      netwag_runform_rst_entry $i
    } elseif {$netwag_priv_runform_info($i,type) =="listbox"} {
      netwag_runform_rst_listbox $i
    } elseif {$netwag_priv_runform_info($i,type) =="more"} {
      netwag_runform_rst_more $i
    } else {
      set type netwag_priv_runform_info($i,type)
      netwag_msg_add_warn "Cannot reset this type($type) of form"
    }
  }
}

#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
# used for help and form
global netwag_priv_runhf_curtoolnum ; set netwag_priv_runhf_curtoolnum -1
global netwag_priv_runhf_wanttoolnum ; set netwag_priv_runhf_wanttoolnum -2


#################################################################
# PRIVATE FUNCTIONS
#################################################################

proc netwag_priv_runhf_init { toolnum } {
  global netwag_priv_runhelp_help
  global netwag_priv_runhelp_example
  global netwag_priv_runhelp_usage
  global netwag_glo_bin_netwox
  global netwag_popen_error

  if {![info exist netwag_priv_runhelp_help($toolnum)]} {
    netwag_cursor_wait
    set ret [netwag_popen "$netwag_glo_bin_netwox 0 -h -u $toolnum" outmsg errcode]
    netwag_cursor_default
    if { $ret } {
      netwag_msg_add_err "Cannot obtain the help for $toolnum ($netwag_popen_error)"
      return $ret
    }
    if { $errcode } {
      netwag_msg_add_err "Help for $toolnum might be incomplete (retgets=$errcode)"
    }
    eval $outmsg
  }
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Display the description of a tool
proc netwag_runhf_display { } {
  global netwag_priv_runhelp_text
  global netwag_priv_runhf_curtoolnum
  global netwag_priv_runhf_wanttoolnum

  if {$netwag_priv_runhf_wanttoolnum == $netwag_priv_runhf_curtoolnum} {
    return
  }

  if {$netwag_priv_runhf_wanttoolnum < 0} {
    $netwag_priv_runhelp_text configure -state normal
    $netwag_priv_runhelp_text delete 1.0 end
    $netwag_priv_runhelp_text insert end "No tool is selected. You have two choices to obtain help :\n - select a tool in Search notebook\n - enter a command (in front of Run button) and press Change tool button\n"
    $netwag_priv_runhelp_text configure -state disabled
    return
  }

  netwag_priv_runhf_init $netwag_priv_runhf_wanttoolnum
  netwag_runhelp_display $netwag_priv_runhf_wanttoolnum
  netwag_runform_display $netwag_priv_runhf_wanttoolnum
  set netwag_priv_runhf_curtoolnum $netwag_priv_runhf_wanttoolnum
}

## Called when Change tool is pressed
proc netwag_runhf_button_change {} {

  if { [netwag_priv_run_cmd_check cmd toolnum] } {
    return
  }

  global netwag_priv_runhf_wanttoolnum
  set netwag_priv_runhf_wanttoolnum $toolnum

  netwag_runhf_display
}

#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_varfile_error


#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Set error messages
proc netwag_varfile_error_set { msg } {
  global netwag_varfile_error
  set netwag_varfile_error $msg
}

## Write variable value
proc netwag_priv_varfile_write_val { fd val } {
  set strlenval [string length $val]

  puts $fd $strlenval

  set chunksize 60
  set startpos 0
  while { $startpos < $strlenval } {
    set endpos [expr $startpos + $chunksize - 1]
    if { $endpos < $strlenval } {
      set trueline [string range $val $startpos $endpos]
    } else {
      set trueline [string range $val $startpos end]
    }
    set line [netwag_misc_string_replace $trueline "\\" "\\\\"]
    set line [netwag_misc_string_replace $line "\0" "\\0"]
    set line [netwag_misc_string_replace $line "\r" "\\r"]
    set line [netwag_misc_string_replace $line "\n" "\\n"]
    puts $fd $line
    set startpos [expr $endpos + 1]
  }

}

## Read variable value
proc netwag_priv_varfile_read_val { filename valname fd pval } {
  upvar $pval val

  # first, there is the size of the variable
  set ret [gets $fd line]
  if { $ret == -1 } {
    netwag_varfile_error_set "Could not read variable size for $valname from $filename"
    return -1
  }
  set varsize $line

  # special case of empty line
  if { $varsize == 0 } {
    # no data to read
    set val ""
    return 0
  }

  # now, read the value
  set val ""
  while {![eof $fd]} {
    set ret [gets $fd line]
    if { $ret == -1 } {
      netwag_varfile_error_set "Error when trying to read value for $valname from $filename"
      return -1
    }
    set line [netwag_misc_string_map $line {"\\\\" "\\" "\\0" "\0" "\\r" "\r" "\\n" "\n"}]
    append val $line
    set readsize [string length $val]
    if { $readsize == $varsize } {
      return 0
    } elseif { $readsize > $varsize } {
      netwag_varfile_error_set "Value contain too much data ($readsize>$varsize) for $valname from $filename"
      return -1
    }
  }
  return 0
}

## Read the varfile
proc netwag_priv_varfile_read_variable { filename fd pvarfilestruct } {
  upvar $pvarfilestruct varfilestruct

  # first, there is the name of the variable
  set ret [gets $fd line]
  if { $ret == -1 } {
    netwag_varfile_error_set "Could not read variable name from $filename"
    return -1
  }
  set varname $line

  # now, read the value
  set ret [netwag_priv_varfile_read_val $filename $varname $fd varval]
  if { $ret } {
    return -1
  }

  set varfilestruct($varname) $varval
  return 0
}

## Read the varfile
proc netwag_priv_varfile_read_array { filename fd pvarfilestruct } {
  upvar $pvarfilestruct varfilestruct

  # first, there is the name of the array
  set ret [gets $fd line]
  if { $ret == -1 } {
    netwag_varfile_error_set "Could not read array name from $filename"
    return -1
  }
  set arrayname $line

  # then, read the array size
  set ret [gets $fd line]
  if { $ret == -1 } {
    netwag_varfile_error_set "Could not read array size for $arrayname from $filename"
    return -1
  }
  set arraysize $line

  # now, read the values
  for {set i 0} {$i < $arraysize} {incr i} {
    set varname "$arrayname\($i\)"
    set ret [netwag_priv_varfile_read_val $filename $varname $fd varval]
    if { $ret } {
      return -1
    }
    set varfilestruct($arrayname,$i) $varval
  }
  return 0
}


#################################################################
# PUBLIC WRITING FUNCTIONS
#################################################################

## Initialize the varfile
proc netwag_varfile_write_init { filename pfd } {
  upvar $pfd fd

  if {[file exists $filename]} {
    if  {[catch {file delete -- $filename}]} {
      netwag_varfile_error_set "Could not modify file $filename"
      return -1
    }
  }

  if  {[catch {open $filename {WRONLY EXCL CREAT} 0600} fd]} {
    netwag_varfile_error_set "Could not open $filename"
    return -1
  }
  # 1 is the current version of varfile syntax
  puts $fd "1"
  puts $fd "# This is a session file for netwag. You should not edit it."
  puts $fd ""
  return 0
}

## Close the varfile
proc netwag_varfile_write_close { fd } {
  close $fd
  return 0
}

## Write variable
proc netwag_varfile_write_variable { fd var val } {
  puts $fd "VARIABLE"
  puts $fd "$var"
  netwag_priv_varfile_write_val $fd $val
  puts $fd ""
  return 0
}

## Write array
proc netwag_varfile_write_array { fd var parray } {
  upvar $parray thearray
  puts $fd "ARRAY"
  puts $fd "$var"
  set arraysize [array size thearray]
  puts $fd $arraysize
  for {set i 0} {$i<$arraysize} {incr i} {
    netwag_priv_varfile_write_val $fd $thearray($i)
  }
  puts $fd ""
  return 0
}

## Just for test
proc netwag_varfile_write_test {} {
  global netwag_varfile_error
  for {set i 0} {$i<30} {incr i} {
    set thearr($i) "aa $i bb"
  }
  set ret [netwag_varfile_write_init "/tmp/ses" fd]
  if { $ret } {
    puts "Error $netwag_varfile_error"
  }

  netwag_varfile_write_variable $fd "toto1" "blabla"
  netwag_varfile_write_variable $fd "toto2" "bl\nabla"
  netwag_varfile_write_variable $fd "toto3" "bl\0abla"
  netwag_varfile_write_variable $fd "toto4" 1
  netwag_varfile_write_variable $fd "toto5" ""
  netwag_varfile_write_array $fd "thearr" thearr
  netwag_varfile_write_close $fd
}


#################################################################
# PUBLIC READING FUNCTIONS
#################################################################

## Read the varfile
proc netwag_varfile_read { filename pvarfilestruct } {

  if  {[catch {set fd [open $filename "r"]}]} {
    netwag_varfile_error_set "Could not read $filename"
    return -1
  }

  # read the version
  set ret [gets $fd line]
  if { $ret == -1 } {
    netwag_varfile_error_set "Could not read version from $filename"
    close $fd
    return -1
  }
  set theversion $line
  if { $theversion != 1 } {
    netwag_varfile_error_set "This program is too old to recognize sessions format $theversion (from $filename)"
    close $fd
    return -1
  }

  upvar $pvarfilestruct varfilestruct
  while {![eof $fd]} {
    # get a line
    set ret [gets $fd line]
    if { $ret == -1 } {
      if {[eof $fd]} { break; }
      netwag_varfile_error_set "Could not read line from $filename"
      close $fd
      return -1
    }
    # ignore empty lines
    if { [regexp "^\s*$" $line] } { continue; }
    # ignore commented lines
    if { [regexp "^\s*#" $line] } { continue; }
    # check known parameters
    if { $line == "VARIABLE" } {
      set ret [netwag_priv_varfile_read_variable $filename $fd varfilestruct]
    } elseif { $line == "ARRAY" } {
      set ret [netwag_priv_varfile_read_array $filename $fd varfilestruct]
    } else {
      netwag_varfile_error_set "Parameter $line unrecognized in file $filename"
      set ret -1
    }
    if { $ret } {
      if {[eof $fd]} {
        netwag_varfile_error_set "Premature end of file $filename"
      }
      close $fd
      return -1
    }
  }

  if { [catch { close $fd }] } {
    netwag_varfile_error_set "Could not close $filename"
    return -1
  }
  return 0
}

## Just for test
proc netwag_varfile_read_test {} {
  global netwag_varfile_error
  set ret [netwag_varfile_read "/tmp/ses" titi]
  if { $ret } {
     puts "err $netwag_varfile_error"
     return
  }
  puts $titi(toto1)
  puts $titi(toto2)
  puts $titi(toto3)
  puts $titi(toto4)
  puts $titi(toto5)
  puts $titi(thearr,12)

}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_infol_text_output
global netwag_priv_infol_out_devices
global netwag_priv_infol_out_ip
global netwag_priv_infol_out_arp
global netwag_priv_infol_out_routes
global netwag_priv_infol_out_current


#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Append data in the text
proc netwag_priv_infol_text_output_set { thedata } {
  global netwag_priv_infol_text_output

  $netwag_priv_infol_text_output configure -state normal
  $netwag_priv_infol_text_output delete 1.0 end
  $netwag_priv_infol_text_output insert end "$thedata"
  $netwag_priv_infol_text_output configure -state disabled
}

## Get configuration
proc netwag_priv_infol_run { infotype } {
  global netwag_glo_bin_netwox
  global netwag_popen_error

  set ret [netwag_popen "$netwag_glo_bin_netwox 0 -c -u $infotype" outmsg errcode]
  if { $ret } {
    set msg "could not obtain the configuration ($netwag_popen_error)"
  } elseif { $errcode } {
    set msg "could not obtain the configuration (errcode=$errcode)"
  } else {
    set msg $outmsg
  }

  return $msg
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Initialize local information
proc netwag_infol_init { } {
  global netwag_priv_infol_out_current
  set netwag_priv_infol_out_current 1

  return 0
}

## Called when a button is pressed
proc netwag_infol_button_press { butnum } {
  global netwag_priv_infol_out_devices
  global netwag_priv_infol_out_ip
  global netwag_priv_infol_out_arp
  global netwag_priv_infol_out_routes
  global netwag_priv_infol_out_current
  global netwag_glo_notebook_button_hidden_color
  global netwag_glo_notebook_button_visible_color
  global netwag_priv_infol_buttons

  if {$butnum == 1} {
    netwag_priv_infol_text_output_set $netwag_priv_infol_out_devices
    $netwag_priv_infol_buttons.butdevices configure -bg $netwag_glo_notebook_button_visible_color
  } else {
    $netwag_priv_infol_buttons.butdevices configure -bg $netwag_glo_notebook_button_hidden_color
  }

  if {$butnum == 2} {
    netwag_priv_infol_text_output_set $netwag_priv_infol_out_ip
    $netwag_priv_infol_buttons.butip configure -bg $netwag_glo_notebook_button_visible_color
  } else {
    $netwag_priv_infol_buttons.butip configure -bg $netwag_glo_notebook_button_hidden_color
  }

  if {$butnum == 3} {
    netwag_priv_infol_text_output_set $netwag_priv_infol_out_arp
    $netwag_priv_infol_buttons.butarp configure -bg $netwag_glo_notebook_button_visible_color
  } else {
    $netwag_priv_infol_buttons.butarp configure -bg $netwag_glo_notebook_button_hidden_color
  }

  if {$butnum == 4} {
    netwag_priv_infol_text_output_set $netwag_priv_infol_out_routes
    $netwag_priv_infol_buttons.butroutes configure -bg $netwag_glo_notebook_button_visible_color
  } else {
    $netwag_priv_infol_buttons.butroutes configure -bg $netwag_glo_notebook_button_hidden_color
  }

  set netwag_priv_infol_out_current $butnum
}

## Called when Update button is pressed
proc netwag_infol_button_update { } {
  global netwag_priv_infol_out_devices
  global netwag_priv_infol_out_ip
  global netwag_priv_infol_out_arp
  global netwag_priv_infol_out_routes

  netwag_cursor_wait
  set netwag_priv_infol_out_devices [netwag_priv_infol_run 1]
  set netwag_priv_infol_out_ip [netwag_priv_infol_run 2]
  set netwag_priv_infol_out_arp [netwag_priv_infol_run 3]
  set netwag_priv_infol_out_routes [netwag_priv_infol_run 4]
  netwag_cursor_default

  netwag_priv_infol_text_output_set $netwag_priv_infol_out_devices

  global netwag_priv_infol_out_current
  netwag_infol_button_press $netwag_priv_infol_out_current
  return 0
}

## To initialize
global netwag_infol_eventuallyinit_done
set netwag_infol_eventuallyinit_done 0
proc netwag_infol_eventuallyinit { } {
  global netwag_infol_eventuallyinit_done
  if {$netwag_infol_eventuallyinit_done} {
    return 0
  }
  netwag_infol_button_update
  set netwag_infol_eventuallyinit_done 1
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# GLOBAL VARIABLES
#################################################################
global netwag_priv_infor_text_output
global netwag_priv_infor_text_input


#################################################################
# PRIVATE FUNCTIONS
#################################################################

## Append data in the text
proc netwag_priv_infor_text_output_set { thedata } {
  global netwag_priv_infor_text_output

  $netwag_priv_infor_text_output configure -state normal
  $netwag_priv_infor_text_output delete 1.0 end
  $netwag_priv_infor_text_output insert end "$thedata"
  $netwag_priv_infor_text_output configure -state disabled
}

## Get configuration
proc netwag_priv_infor_run { thequery } {
  global netwag_glo_bin_netwox
  global netwag_popen_error

  set ret [netwag_popen "$netwag_glo_bin_netwox 3 -a $thequery" outmsg errcode]
  if { $ret } {
    set msg "could not obtain the configuration ($netwag_popen_error)"
  } elseif { $errcode } {
    set msg "An error occured (errcode=$errcode) :\n"
    append msg $outmsg
  } else {
    set msg $outmsg
  }

  return $msg
}


#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Initialize local information
proc netwag_infor_init { } {

  set msg "Enter an IP address or a Hostname and press on Query button"
  netwag_priv_infor_text_output_set $msg

  return 0
}

## Called when Query button is pressed
proc netwag_infor_button_query { } {
  global netwag_priv_infor_text_input

  set thequery $netwag_priv_infor_text_input
  if { $thequery == "" } {
    netwag_msg_add_warn "Query \"\" too short"
    return -1
  }

  netwag_priv_infor_text_output_set [netwag_priv_infor_run $thequery]
  return 0
}
#################################################################
#                             NETWAG                            #
#                        Network toolbox                        #
#           Copyright(c) 1999-2003 Laurent Constantin           #
#                             -----                             #
#  Main server    : http://www.laurentconstantin.com/           #
#  Backup servers : http://go.to/laurentconstantin/             #
#                   http://laurentconstantin.est-la.com/        #
#                   http://laurentconstantin.free.fr/           #
#                   http://membres.lycos.fr/lauconstantin/      #
#  [my current email address is on the web servers]             #
#                             -----                             #
#  This file is part of Netwag.                                 #
#  Netwag is free software; you can redistribute it and/or      #
#  modify it under the terms of the GNU General Public License  #
#  version 2 as published by the Free Software Foundation.      #
#  Netwag is distributed in the hope that it will be useful,    #
#  but WITHOUT ANY WARRANTY; without even the implied warranty  #
#  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See  #
#  the GNU General Public License for more details.             #
#################################################################

#################################################################
# PUBLIC FUNCTIONS
#################################################################

## Time profiling
proc netwag_prof_init {} {
  global netwag_prof_init_lastime
  global netwag_prof_init_msg
  set netwag_prof_init_lastime [clock clicks]
  set netwag_prof_init_msg {}
}
proc netwag_prof_diff { msg } {
  global netwag_prof_init_lastime
  global netwag_prof_init_msg
  append netwag_prof_init_msg [expr [clock clicks] - $netwag_prof_init_lastime]
  append netwag_prof_init_msg "\t($msg)\n"
  set netwag_prof_init_lastime [clock clicks]
}
proc netwag_prof_report {} {
  global netwag_prof_init_lastime
  global netwag_prof_init_msg
  append netwag_prof_init_msg [expr [clock clicks] - $netwag_prof_init_lastime]
  append netwag_prof_init_msg "\t(end)"
  puts $netwag_prof_init_msg
}

## Create a fake widget using a font. Indeed, font computation is
## very slow when there is not yet any window
proc netwag_main_fake_widget {} {
  label .fake_widget -font myfont
}

## Main
proc netwag_main {} {
  global frame_notebook
  global frame_clipboard
  global frame_message
  global netwag_glo_versionmajor
  global netwag_glo_versionminor
  global netwag_glo_versionmicro

  # check global variables
  netwag_glo_check
  #netwag_prof_diff "after glo_check"

  # load the last session
  netwag_session_load_vars
  #netwag_prof_diff "after load_vars"

  # initialize font
  netwag_font_init
  #netwag_prof_diff "after font_init"

  # create a fake widget to speed startup
  netwag_main_fake_widget
  #netwag_prof_diff "after fake_widget"

  # initialize the clipboard
  netwag_clip_init
  #netwag_prof_diff "after clip_init"

  # initialize widgets
  netwag_gui_skeleton frame_notebook frame_clipboard frame_message
  netwag_gui_notebook0 $frame_notebook
  netwag_gui_notebook1 $frame_notebook
  netwag_gui_notebook2 $frame_notebook
  netwag_gui_notebook3 $frame_notebook
  netwag_gui_notebook4 $frame_notebook
  netwag_gui_notebook5 $frame_notebook
  netwag_gui_clipboard $frame_clipboard
  netwag_gui_message $frame_message
  netwag_gui_menu
  #netwag_prof_diff "after gui"

  # display first message
  netwag_msg_add_info "netwag version $netwag_glo_versionmajor.$netwag_glo_versionminor.$netwag_glo_versionmicro"

  # check netwox and its version
  set ret [netwag_run_checknetwox]
  if { $ret == -1 } { return $ret }
  #netwag_prof_diff "after run"

  # initialize search functions
  netwag_search_init
  #netwag_prof_diff "after search"

  # initialize run functions
  netwag_run_init
  #netwag_prof_diff "after run_init"

  # initialize history
  netwag_runhist_init
  #netwag_prof_diff "after runhist_init"

  # initialize information
  netwag_infol_init
  netwag_infor_init
  #netwag_prof_diff "after info_init"

  # apply the last session
  netwag_session_load_apply
  #netwag_prof_diff "after load_apply"

  return 0
}


#################################################################
# MAIN
#################################################################
#netwag_prof_init
netwag_main

# used with "time netwag" to obtain startup time
#tkwait visibility $netwag_priv_search_lb
#netwag_prof_diff "after visibility"
#netwag_prof_report
#exit
