#!/usr/local/bin/wish -f
#
# Directory Utility with Cluster support
# (For later Extension with AFS support)
#
# Programmer: Rainer Kowallik
#
set Version    1.1.5
#

set UNAME [exec uname]
set User [exec whoami]
set Domain "ifh.de"
set LS1cmd "/bin/ls -la"
set LS2cmd "/bin/ls -lag"
set LScmd $LS1cmd
set CPcmd "cp -r"
set MVcmd "mv"
set RCPcmd "rcp -r"
set LNcmd "ln -sf"
set RMcmd "rm -rf"
set RSHcmd "rsh 2>/dev/null"
if {([file exists "/usr/bin/remsh"]) || ($UNAME == "HP-UX")} {
   set RSHcmd "remsh 2>/dev/null"
}
set DIFFcmd "tkdiff"
set MKDIRcmd "mkdir"
set CHMODcmd "chmod"
set CHOWNcmd "chown"
set CHGRPcmd "chgrp"
set XMOREcmd "tke"
set EDITcmd "tkedit"
set VIEWcmd "tkedit -ro"
set PSVIEWcmd "ghostview"
set GIFVIEWcmd "xv"
set DVIVIEWcmd "xdvi"
set IFFVIEWcmd "xv"
set HTMLVIEWcmd "xmosaic"

set TempName "/tmp/tkdir.[exec whoami]"

set TARXcmd "gtar xf"
set TARXZcmd "gtar xZf"
set TARXGZcmd "gtar xzf"
set TARTcmd "gtar tf"
set TARTZcmd "gtar tZf"
set TARTGZcmd "gtar tzf"
set TARCcmd "gtar cf"
set FileSelect "tkdir -fs"

set FileTypes ".tar tar .tar.Z tarz .tar.gz targz \
               .gif gif .ps ps .ps.Z psz .ps.gz psgz \
               .dvi dvi .iff iff .html html \
               .o obj .so obj .a lib"

set FontName "-Adobe-Courier-Medium-R-Normal"
set FontSize "120"

set SortMode "none"

set FileModesLYN 1
set FileDatesLYN 0
set FileSizeLYN 1
set FileUIDLYN 0
set FileGIDLYN 0
set FileLinkLYN 0

set FileModesRYN 0
set FileDatesRYN 0
set FileSizeRYN 0
set FileUIDRYN 0
set FileGIDRYN 0
set FileLinkRYN 0

set ClusterModeYN 0
set BW_ModeYN 0

set Ready 1
set CmdPtr 0
set CmdAct -1

set HotListOn 0
set HotList ""

set XPrefEntFont "8x13bold"

proc GetColorSelect {var val} {
   global TempName
   
   set rgb [eval "exec ColorSelect 2>/dev/null $val"]
   return $rgb
}

proc SetRGB var {
   upvar $var x
   set rgb [GetColorSelect $var $x]
   if {[string index $rgb 0] != "#"} return
   set x $rgb
   UpdateRGB
}

proc SetRGBX {var rgb} {

   if {[string index $rgb 0] != "#"} return
   upvar $var x
   set x $rgb
   UpdateRGB
   SetCLR
   update
}

proc UpdateRGB { } {
   global ViewBGColor ViewFGColor XPrefMainBack XPrefMenuBack \
          XPrefEntBack XPrefButtonBack XPrefMatchRGB \
          FromBGColor FromFGColor ToBGColor ToFGColor FFileSelectBGColor \
          FFileSelectFGColor TFileSelectBGColor TFileSelectFGColor \
          FDirBlankBGColor FDirSelectBGColor FDirBlankFGColor \
          FDirSelectFGColor TDirBlankBGColor  TDirBlankFGColor \
          TDirSelectFGColor TDirSelectBGColor FLinkBlankBGColor \
          FLinkBlankFGColor FLinkSelectBGColor  FLinkSelectFGColor \
          TLinkBlankBGColor TLinkSelectBGColor TLinkBlankFGColor \
          TLinkSelectFGColor ViewBGColor ViewFGColor tk_version

DoCfg 1 "configure -background $FromBGColor -foreground $FromFGColor"
DoCfg 2 "configure -background $ToBGColor -foreground $ToFGColor"
DoCfg 1 "tag configure f -back $FFileSelectBGColor  -fore $FFileSelectFGColor"
DoCfg 2 "tag configure f -back $TFileSelectBGColor -fore $TFileSelectFGColor"
DoCfg 1 "tag configure dir -back $FDirBlankBGColor -fore $FDirBlankFGColor"
DoCfg 1 "tag configure d -back $FDirSelectBGColor -fore $FDirSelectFGColor"
DoCfg 2 "tag configure dir -back $TDirBlankBGColor -fore $TDirBlankFGColor"
DoCfg 2 "tag configure d -back $TDirSelectBGColor -fore $TDirSelectFGColor"
DoCfg 1 "tag configure link -back $FLinkBlankBGColor -fore $FLinkBlankFGColor"
DoCfg 1 "tag configure l -back $FLinkSelectBGColor -fore $FLinkSelectFGColor"
DoCfg 2 "tag configure link -back $TLinkBlankBGColor -fore $TLinkBlankFGColor"
DoCfg 2 "tag configure l -back $TLinkSelectBGColor -fore $TLinkSelectFGColor"
catch {.help.win configure -bg $ViewBGColor -fg $ViewFGColor}
foreach x [info commands .mBar*] {$x configure -background $XPrefMenuBack}
foreach x "[info commands .c*] .public .size1 .size2" \
         {$x configure -background $XPrefMainBack}
if {$tk_version < 4.0} {
foreach x ".scroll1 .scroll2 .dirscr1 .dirscr2" \
      {$x configure -fg $XPrefButtonBack  -bg $XPrefEntBack}
}
foreach x ".ws1 .ws2 .dirname1 .dirname2 .input .comment .patt1 .patt2" \
      {$x configure -background $XPrefEntBack}
foreach x "[info commands .b*] .parent1 .parent2 .home1 .home2 .root1 .root2" \
      {$x configure -background $XPrefButtonBack}
update
}

proc DefaultColor x {
   global XPrefMainBack XPrefMenuBack XPrefEntBack XPrefButtonBack \
          XPrefBorderW FromBGColor FromFGColor ToBGColor ToFGColor \
          FDirBlankBGColor FDirSelectBGColor FDirBlankFGColor \
          FDirSelectFGColor TDirBlankBGColor TDirSelectBGColor \
          TDirBlankFGColor TDirSelectFGColor FFileSelectBGColor \
          FFileSelectFGColor TFileSelectBGColor TFileSelectFGColor \
          FLinkBlankBGColor FLinkSelectBGColor FLinkBlankFGColor \
          FLinkSelectFGColor TLinkBlankBGColor TLinkSelectBGColor \
          TLinkBlankFGColor TLinkSelectFGColor ClusterBGColor ClusterFGColor \
          ClusterSelBGColor ClusterSelFGColor ViewBGColor ViewFGColor

   set FromBGColor "#ffffff"
   set FromFGColor "#000000"
   set ToBGColor   "#d0d0d0"
   set ToFGColor   "#000000"
   
   set FDirBlankBGColor    "#ffffff"
   set FDirSelectBGColor   "#d0a0a0"
   set FDirBlankFGColor    "#ff0000"
   set FDirSelectFGColor   "#00ffff"
   
   set TDirBlankBGColor    "#d0d0d0"
   set TDirSelectBGColor   "#d0a0a0"
   set TDirBlankFGColor    "#ff0000"
   set TDirSelectFGColor   "#00ffff"
   
   set FFileSelectBGColor  "#a0d0a0"
   set FFileSelectFGColor  "#ff00ff"
   
   set TFileSelectBGColor  "#a0d0a0"
   set TFileSelectFGColor  "#ff00ff"
   
   set FLinkBlankBGColor    "#ffffff"
   set FLinkSelectBGColor   "#a0a0d0"
   set FLinkBlankFGColor    "#0000ff"
   set FLinkSelectFGColor   "#ffff00"
   
   set TLinkBlankBGColor    "#d0d0d0"
   set TLinkSelectBGColor   "#a0a0d0"
   set TLinkBlankFGColor    "#0000ff"
   set TLinkSelectFGColor   "#ffff00"
   
   set ClusterBGColor      "#c0b090"
   set ClusterFGColor      "#000000"
   set ClusterSelBGColor   "#b0b0ff"
   set ClusterSelFGColor   "#000000"
   
   set ViewBGColor         "#f1f1f1"
   set ViewFGColor         "#000000"

   switch $x {
      1 {
         set XPrefMainBack "#c0c0c0"
         set XPrefMenuBack "#d0d0d0"
         set XPrefEntBack "#f5d5ff"
         set XPrefButtonBack "#c1c8e9"
         set XPrefBorderW 1
      }
      2 {
         set XPrefMainBack "#c2e3d5"
         set XPrefMenuBack "#d9e7e1"
         set XPrefEntBack "#d9e3df"
         set XPrefButtonBack "#97e2d6"
         set XPrefBorderW 1
      }
      3 {
         set XPrefMainBack "#f9e6c7"
         set XPrefMenuBack "#f9e6c7"
         set XPrefEntBack "#f9e6c7"
         set XPrefButtonBack "#f9e6c7"
         set XPrefBorderW 1
      }
   }
}

DefaultColor 1

#
# Now read Configuration ".tkdir"
#
if {[file exists "~/.tkdir"]} {
   source "~/.tkdir"
}
set FontString "${FontName}--*-${FontSize}-*-*-*-*-iso8859-*"


frame .mBar -relief raised -bd 2 -bg $XPrefMenuBack
pack .mBar -side top -fill x

frame .c00 -background $XPrefMainBack
frame .c01 -background $XPrefMainBack
frame .c02 -background $XPrefMainBack
frame .c03 -background $XPrefMainBack
frame .c04 -background $XPrefMainBack
frame .public -background $XPrefMainBack

frame .c10 -background $XPrefMainBack
frame .c11 -background $XPrefMainBack
frame .c12 -background $XPrefMainBack
frame .c13 -background $XPrefMainBack

frame .c20 -background $XPrefMainBack
frame .c21 -background $XPrefMainBack
frame .c22 -background $XPrefMainBack
frame .c23 -background $XPrefMainBack

pack .c00 -side top -expand 1 -fill both
pack .c01 -side top -after .c00 -expand 0 -fill both
pack .c02 -side top -after .c01 -expand 0 -fill both
pack .c03 -side top -after .c02 -expand 0 -fill both
pack .public -side top -after .c03 -expand 0 -fill both
pack .c04 -side top -after .public -expand 0 -fill both

pack .c10 -side left -in .c00 -expand 1 -fill both
pack .c20 -side left -in .c00 -after .c10 -expand 1 -fill both

pack .c11 -side top -in .c10 -expand 0 -fill both
pack .c12 -side top -after .c11 -in .c10 -expand 1 -fill both
pack .c13 -side top -after .c12 -in .c10  -expand 0 -fill both

pack .c21 -side top -in .c20 -expand 0 -fill both
pack .c22 -side top -after .c21 -in .c20 -expand 1 -fill both
pack .c23 -side top -after .c22 -in .c20 -expand 0 -fill both

frame .c131 -background $XPrefMainBack
frame .c132 -background $XPrefMainBack
frame .c133 -background $XPrefMainBack
pack .c131 -in .c13 -side left -expand 0 -fill x
pack .c132 -in .c13 -side left -after .c131 -expand 1 -fill both
pack .c133 -in .c13 -side left -after .c132 -expand 0 -fill x

frame .c231 -background $XPrefMainBack
frame .c232 -background $XPrefMainBack
frame .c233 -background $XPrefMainBack
pack .c231 -in .c23 -side left -expand 0 -fill x
pack .c232 -in .c23 -side left -after .c231 -expand 1 -fill both
pack .c233 -in .c23 -side left -after .c232 -expand 0 -fill x

#
# Build up Menu Bar
#
#
# File Menu
#
menubutton .mBar.file -text File -menu .mBar.file.m  -background $XPrefMenuBack
menu .mBar.file.m -background $XPrefMenuBack
.mBar.file.m add command -label "Save Preferences" -command {SavePrefs}
.mBar.file.m add command -label "Save Cluster" -command {SaveCluster}
.mBar.file.m add command -label "Load Cluster" -command {LoadCluster}
.mBar.file.m add command -label "Exit" -command {exit}
#
# ftp Menu
#

# menubutton .mBar.ftp -text FTP -menu .mBar.ftp.m -background $XPrefMenuBack
# menu .mBar.ftp.m -background $XPrefMenuBack
# .mBar.ftp.m add command -label "Open ftp Session" -command {OpenFTP}


#
# Preferences Menu
#
menubutton .mBar.prefs -text Preferences -menu .mBar.prefs.m -bg $XPrefMenuBack
menu .mBar.prefs.m -bg $XPrefMenuBack
.mBar.prefs.m add command -label "Save Preferences" -command {SavePrefs}
.mBar.prefs.m add cascade -label "cmds (ls,ln)" \
                -menu .mBar.prefs.m.cmds
.mBar.prefs.m add cascade -label "Font Type" \
                -menu .mBar.prefs.m.font
.mBar.prefs.m add cascade -label "Font Size" \
                -menu .mBar.prefs.m.size
.mBar.prefs.m add checkbutton -label "BW-Monitor" \
                -variable BW_ModeYN -command {SwitchBW}

.mBar.prefs.m add cascade -label "Color Left Window" \
                -menu .mBar.prefs.m.left
.mBar.prefs.m add cascade -label "Color Right Window" \
                -menu .mBar.prefs.m.right
.mBar.prefs.m add cascade -label "Color Cluster" \
                -menu .mBar.prefs.m.cluster
.mBar.prefs.m add cascade -label "Other Colors" \
                -menu .mBar.prefs.m.other
.mBar.prefs.m add cascade -label "Default Colors" \
                -menu .mBar.prefs.m.defcolor

menu .mBar.prefs.m.cmds -bg $XPrefMenuBack
   .mBar.prefs.m.cmds add command -label "1. ls: $LS1cmd" \
                -command {SetLS LS1cmd}
   .mBar.prefs.m.cmds add command -label "2. ls: $LS2cmd" \
                -command {SetLS LS2cmd}
   .mBar.prefs.m.cmds add command -label "use ls: $LScmd" \
                -command {SetLS LScmd}
   .mBar.prefs.m.cmds add command -label "ln: $LNcmd" \
                -command {SetLS LNcmd}

menu .mBar.prefs.m.left -bg $XPrefMenuBack
.mBar.prefs.m.left add cascade -label "Background" \
                -menu .mBar.prefs.m.left.back
.mBar.prefs.m.left add cascade -label "Foreground" \
                -menu .mBar.prefs.m.left.fore

menu .mBar.prefs.m.left.back -bg $XPrefMenuBack
.mBar.prefs.m.left.back add command -label "Left BG Color" \
                -command {SetRGB FromBGColor}
.mBar.prefs.m.left.back add command -label "Left Select BG Color" \
                -command {SetRGB FFileSelectBGColor}
.mBar.prefs.m.left.back add command -label "Left Dir BG Color" \
                -command {SetRGB FDirBlankBGColor}
.mBar.prefs.m.left.back add command -label "Left Dir Select BG Color" \
                -command {SetRGB FDirSelectBGColor}
.mBar.prefs.m.left.back add command -label "Left Link BG Color" \
                -command {SetRGB FLinkBlankBGColor}
.mBar.prefs.m.left.back add command -label "Left Link Select BG Color" \
                -command {SetRGB FLinkSelectBGColor}

menu .mBar.prefs.m.left.fore -bg $XPrefMenuBack
.mBar.prefs.m.left.fore add command -label "Left FG Color" \
                -command {SetRGB FromFGColor}
.mBar.prefs.m.left.fore add command -label "Left Select FG Color" \
                -command {SetRGB FFileSelectFGColor}
.mBar.prefs.m.left.fore add command -label "Left Dir FG Color" \
                -command {SetRGB FDirBlankFGColor}
.mBar.prefs.m.left.fore add command -label "Left Dir Select FG Color" \
                -command {SetRGB FDirSelectFGColor}
.mBar.prefs.m.left.fore add command -label "Left Link FG Color" \
                -command {SetRGB FLinkBlankFGColor}
.mBar.prefs.m.left.fore add command -label "Left Link Select FG Color" \
                -command {SetRGB FLinkSelectFGColor}

menu .mBar.prefs.m.right -bg $XPrefMenuBack
.mBar.prefs.m.right add cascade -label "Background" \
                -menu .mBar.prefs.m.right.back
.mBar.prefs.m.right add cascade -label "Foreground" \
                -menu .mBar.prefs.m.right.fore

menu .mBar.prefs.m.right.back -bg $XPrefMenuBack
.mBar.prefs.m.right.back add command -label "Right BG Color" \
                -command {SetRGB ToBGColor}
.mBar.prefs.m.right.back add command -label "Right Select BG Color" \
                -command {SetRGB TFileSelectBGColor}
.mBar.prefs.m.right.back add command -label "Right Dir BG Color" \
                -command {SetRGB TDirBlankBGColor}
.mBar.prefs.m.right.back add command -label "Right Dir Select BG Color" \
                -command {SetRGB TDirSelectBGColor}
.mBar.prefs.m.right.back add command -label "Right Link BG Color" \
                -command {SetRGB TLinkBlankBGColor}
.mBar.prefs.m.right.back add command -label "Right Link Select BG Color" \
                -command {SetRGB TLinkSelectBGColor}

menu .mBar.prefs.m.right.fore -bg $XPrefMenuBack
.mBar.prefs.m.right.fore add command -label "Right FG Color" \
                -command {SetRGB ToFGColor}
.mBar.prefs.m.right.fore add command -label "Right Select FG Color" \
                -command {SetRGB TFileSelectFGColor}
.mBar.prefs.m.right.fore add command -label "Right Dir FG Color" \
                -command {SetRGB TDirBlankFGColor}
.mBar.prefs.m.right.fore add command -label "Right Dir Select FG Color" \
                -command {SetRGB TDirSelectFGColor}
.mBar.prefs.m.right.fore add command -label "Right Link FG Color" \
                -command {SetRGB TLinkBlankFGColor}
.mBar.prefs.m.right.fore add command -label "Right Link Select FG Color" \
                -command {SetRGB TLinkSelectFGColor}
                
menu .mBar.prefs.m.cluster -bg $XPrefMenuBack
.mBar.prefs.m.cluster add command -label "Cluster BG Color" \
                -command {SetRGB ClusterBGColor}
.mBar.prefs.m.cluster add command -label "Cluster FG Color" \
                -command {SetRGB ClusterFGColor}
.mBar.prefs.m.cluster add command -label "Select BG Color" \
                -command {SetRGB ClusterSelBGColor}
.mBar.prefs.m.cluster add command -label "Select FG Color" \
                -command {SetRGB ClusterSelFGColor}

menu .mBar.prefs.m.other -background $XPrefMenuBack -bg $XPrefMenuBack
.mBar.prefs.m.other add command -label "View BG Color" \
                -command {SetRGB ViewBGColor}
.mBar.prefs.m.other add command -label "View FG Color" \
                -command {SetRGB ViewFGColor}
.mBar.prefs.m.other add command -label "Button Color" \
                -command {SetRGB XPrefButtonBack}
.mBar.prefs.m.other add command -label "Entry Color" \
                -command {SetRGB XPrefEntBack}
#
menu .mBar.prefs.m.defcolor -background $XPrefMenuBack -bg $XPrefMenuBack
.mBar.prefs.m.defcolor add command -label "grey/blue/violett" \
                -command {DefaultColor 1 ; UpdateRGB}
.mBar.prefs.m.defcolor add command -label "Green" \
                -command {DefaultColor 2 ; UpdateRGB}
.mBar.prefs.m.defcolor add command -label "Original" \
                -command {DefaultColor 3 ; UpdateRGB}
#
menu .mBar.prefs.m.font -background $XPrefMenuBack -bg $XPrefMenuBack
.mBar.prefs.m.font add command -label "Helvetica Medium" \
                -command {SetFont -Adobe-Helvetica-Medium-R-Normal}
.mBar.prefs.m.font add command -label "Courier Medium" \
                -command {SetFont -Adobe-Courier-Medium-R-Normal}
.mBar.prefs.m.font add command -label "Times Medium" \
                -command {SetFont -Adobe-Times-Medium-R-Normal}
.mBar.prefs.m.font add command -label "Fixed Medium" \
                -command {SetFont -Misc-Fixed-Medium-R-Normal}
#
menu .mBar.prefs.m.size -bg $XPrefMenuBack
.mBar.prefs.m.size add command -label "80" -command {NewFontSize 80}
.mBar.prefs.m.size add command -label "90" -command {NewFontSize 90}
.mBar.prefs.m.size add command -label "100" -command {NewFontSize 100}
.mBar.prefs.m.size add command -label "120" -command {NewFontSize 120}
.mBar.prefs.m.size add command -label "140" -command {NewFontSize 140}
.mBar.prefs.m.size add command -label "180" -command {NewFontSize 180}
.mBar.prefs.m.size add command -label "240" -command {NewFontSize 240}
#
# "Sort by" Menu
#
menubutton .mBar.sort -text "Sort by" -menu .mBar.sort.m -bg $XPrefMenuBack
menu .mBar.sort.m -bg $XPrefMenuBack
.mBar.sort.m add radiobutton -label "Name"\
                -value "name" -variable SortMode -command {ReadDirs}
.mBar.sort.m add radiobutton -label "Size"\
                -value "size" -variable SortMode -command {ReadDirs}
.mBar.sort.m add radiobutton -label "Date"\
                -value "date" -variable SortMode -command {ReadDirs}
.mBar.sort.m add radiobutton -label "User"\
                -value "user" -variable SortMode -command {ReadDirs}
.mBar.sort.m add radiobutton -label "Group"\
                -value "group" -variable SortMode -command {ReadDirs}
.mBar.sort.m add radiobutton -label "None"\
                -value "none" -variable SortMode -command {ReadDirs}
#
# View Left Menu
#
menubutton .mBar.viewl -text "View Left" -menu .mBar.viewl.m -bg $XPrefMenuBack
menu .mBar.viewl.m -bg $XPrefMenuBack
.mBar.viewl.m add checkbutton -label "File modes" \
                -variable FileModesLYN -command {RebuildWin}
.mBar.viewl.m add checkbutton -label "File dates" \
                -variable FileDatesLYN -command {RebuildWin}
.mBar.viewl.m add checkbutton -label "File size" \
                -variable FileSizeLYN -command {RebuildWin}
.mBar.viewl.m add checkbutton -label "File UID" \
                -variable FileUIDLYN -command {RebuildWin}
.mBar.viewl.m add checkbutton -label "File GID" \
                -variable FileGIDLYN -command {RebuildWin}
.mBar.viewl.m add checkbutton -label "File Link To" \
                -variable FileLinkLYN -command {RebuildWin}
#
# View Right Menu
#
menubutton .mBar.viewr -text "View Right" -menu .mBar.viewr.m -bg $XPrefMenuBack
menu .mBar.viewr.m -bg $XPrefMenuBack
.mBar.viewr.m add checkbutton -label "File modes" \
                -variable FileModesRYN -command {RebuildWin}
.mBar.viewr.m add checkbutton -label "File dates" \
                -variable FileDatesRYN -command {RebuildWin}
.mBar.viewr.m add checkbutton -label "File size" \
                -variable FileSizeRYN -command {RebuildWin}
.mBar.viewr.m add checkbutton -label "File UID" \
                -variable FileUIDRYN -command {RebuildWin}
.mBar.viewr.m add checkbutton -label "File GID" \
                -variable FileGIDRYN -command {RebuildWin}
.mBar.viewr.m add checkbutton -label "File Link To" \
                -variable FileLinkRYN -command {RebuildWin}

#
# Cluster Menu
#
menubutton .mBar.cluster -text "Cluster" -menu .mBar.cluster.m \
         -bg $XPrefMenuBack
menu .mBar.cluster.m -bg $XPrefMenuBack
.mBar.cluster.m add checkbutton -label "Cluster Mode" \
               -variable ClusterModeYN -command {RebuildWin}
.mBar.cluster.m add command -label "Add machine \[ctrl-a\]" -underline 0 \
      -command {ClusterAdd [AskUser "Please Enter Name:" ""]}
bind Frame <Control-a> {ClusterAdd [AskUser "Please Enter Name:" ""]}
.mBar.cluster.m add command -label "Delete machine" \
      -command {ClusterDelete [GetCluster]}
.mBar.cluster.m add command -label "From netgroup" \
      -command {ClusterNetGroup}
.mBar.cluster.m add command -label "Select All" \
      -command {ClusterSelectAll}
.mBar.cluster.m add command -label "Deselect All" \
      -command {ClusterSelectNone}
#
# Hotlist Menu
#
menubutton .mBar.hot -text "Hotlist" -menu .mBar.hot.m -bg $XPrefMenuBack
menu .mBar.hot.m -bg $XPrefMenuBack
.mBar.hot.m add command -label "Show Hotlist" -command {ShowHotlist}
.mBar.hot.m add command -label "Add Left" -command {AddHot 1 0}
.mBar.hot.m add command -label "Add Left + host" -command {AddHot 1 1}
.mBar.hot.m add command -label "Add Right" -command {AddHot 2 0}
.mBar.hot.m add command -label "Add Right + host" -command {AddHot 2 1}
#
# Help Menu
#
menubutton .mBar.help -text "Help" -menu .mBar.help.m -bg $XPrefMenuBack
menu .mBar.help.m -bg $XPrefMenuBack
.mBar.help.m add command -label "Version $Version" -command {Commercial}
.mBar.help.m add command -label "Rainer Kowallik" -command {Commercial}
.mBar.help.m add command -label "kowallik@ifh.de" -command {Commercial}
.mBar.help.m add command -label "Read Documentation" -command {LoadDoc}
#
# Activate Menu Bar
#
pack .mBar.file .mBar.prefs .mBar.sort .mBar.viewl .mBar.viewr .mBar.cluster \
     .mBar.hot .mBar.help -side left -expand 1
tk_menuBar .mBar .mBar.file .mBar.prefs .mBar.sort .mBar.viewl .mBar.viewr \
     .mBar.cluster .mBar.hot .mBar.help
#
# "Quit" Button
#
button .quit -text "QUIT" -background green -borderwidth $XPrefBorderW \
        -padx 0 -pady 0 -command {exit} 
pack .quit -side left -in .c11 -anchor w -expand 0
#
# left box
#
label .size1 -text "----/--------" -bd 2 -relief ridge -bg $XPrefMainBack
label .fromlabel -text "From" -background green -borderwidth $XPrefBorderW
button .parent1 -text "Parent" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
        -padx 0 -pady 0 -command { UpDir 1 }
button .home1 -text "Home" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
        -padx 0 -pady 0 -command { set DirName1 "~" ; ReadDir 1}
button .root1 -text "Root" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
        -padx 0 -pady 0 -command { set DirName1 "/" ; ReadDir 1}
entry .patt1 -width 5 -relief sunken -bd 2 -borderwidth $XPrefBorderW \
         -bg $XPrefEntBack -font $XPrefEntFont -textvariable Patt1
pack .patt1 .parent1 .home1 .root1 .fromlabel .size1\
         -side right -in .c11 -padx 1m -pady 1m -fill x

text .filebox1 -wrap none -wrap none -relief raised -borderwidth $XPrefBorderW \
		-yscrollcommand ".scroll1 set" \
		-setgrid 1 -width 30 -height 15 \
                -font $FontString \
                -background $FromBGColor \
                -foreground $FromFGColor

text .modebox1 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 10 -height 15 \
                -font $FontString \
                -background $FromBGColor \
                -foreground $FromFGColor
                
text .uidbox1 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 10 -height 15 \
                -font $FontString \
                -background $FromBGColor \
                -foreground $FromFGColor

text .gidbox1 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 10 -height 15 \
                -font $FontString \
                -background $FromBGColor \
                -foreground $FromFGColor

text .flenbox1 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 10 -height 15 \
                -font $FontString \
                -background $FromBGColor \
                -foreground $FromFGColor

text .datebox1 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 12 -height 15 \
                -font $FontString \
                -background $FromBGColor \
                -foreground $FromFGColor

text .linkbox1 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 30 -height 15 \
                -font $FontString \
                -background $FromBGColor \
                -foreground $FromFGColor


pack .filebox1 -in .c12 -side left -expand 1 -fill both
scrollbar .scroll1 -command "DoScroll_1" -borderwidth $XPrefBorderW 
pack .scroll1 -in .c12 -side left -after .filebox1 -fill y

entry .ws1 -width 10 -relief sunken -borderwidth $XPrefBorderW \
      -textvariable WorkStation1 -font $XPrefEntFont -bg $XPrefEntBack
entry .dirname1 -width 28 -relief sunken -borderwidth $XPrefBorderW \
      -textvariable DirName1 -font $XPrefEntFont -bg $XPrefEntBack
button .dirup1 -text "^" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command "DirUp 1"
button .dirdown1 -text "v" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command "DirDown 1"
button .dircp12 -text ">" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command "DirCp 1 2"
button .direxc -text "<>" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command "DirExc"

scrollbar .dirscr1 -command ".dirname1 view" -borderwidth $XPrefBorderW \
      -orient horizontal -width 18

pack .dirup1 .dirdown1 .ws1 -side left -in .c131 -fill both -expand 1
pack .dirname1 -in .c132 -side left -expand 1 -fill both -padx 1m
pack .dirscr1 -in .c132 -side left -expand 0
pack .dircp12 .direxc -side left -in .c133

bind .dirname1 <Return> {ReadDir 1}
bind .dirname1 <Left> {EntryCursor .dirname1 -1}
bind .dirname1 <Right> {EntryCursor .dirname1 1}

bind .ws1 <Return> {ReadDir 1}
bind .ws1 <Left> {EntryCursor .ws1 -1}
bind .ws1 <Right> {EntryCursor .ws1 1}

bind .patt1 <Return> {ReadDir 1}

foreach w { \
   .filebox1 .modebox1 .uidbox1 .gidbox1 .flenbox1 .datebox1 .linkbox1} {
   $w tag configure f \
         -foreground $FFileSelectFGColor -background $FFileSelectBGColor
   $w tag configure d \
         -foreground $FDirSelectFGColor -background $FDirSelectBGColor
   $w tag configure dir \
         -foreground $FDirBlankFGColor -background $FDirBlankBGColor
   $w tag configure l \
         -foreground $FLinkSelectFGColor -background $FLinkSelectBGColor
   $w tag configure link \
         -foreground $FLinkBlankFGColor -background $FLinkBlankBGColor
   $w tag configure warn \
         -foreground "#000000" -background "#ff0000"
   }

#
# right box
#
label .size2 -text "----/-------" -bd 2 -relief ridge -bg $XPrefMainBack
label .tolabel -text "To" -background red
button .parent2 -text "Parent" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command { UpDir 2}
button .home2 -text "Home" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command {set DirName2 "~" ; ReadDir 2}
button .root2 -text "Root" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command {set DirName2 "/" ; ReadDir 2}
entry .patt2 -width 5 -relief sunken -bd 2 -borderwidth $XPrefBorderW \
         -bg $XPrefEntBack -font $XPrefEntFont -textvariable Patt2
pack .patt2 .parent2 .home2 .root2 .tolabel .size2\
         -side right -in .c21 -padx 1m -pady 1m -fill x

text .filebox2 -wrap none -relief raised -borderwidth $XPrefBorderW \
		-yscrollcommand ".scroll2 set" \
		-width 30 -height 15 \
                -setgrid 1 \
                -font $FontString \
                -background $ToBGColor \
                -foreground $ToFGColor

text .modebox2 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 10 -height 15 \
                -font $FontString \
                -background $ToBGColor \
                -foreground $ToFGColor

text .uidbox2 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 10 -height 15 \
                -font $FontString \
                -background $ToBGColor \
                -foreground $ToFGColor

text .gidbox2 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 10 -height 15 \
                -font $FontString \
                -background $ToBGColor \
                -foreground $ToFGColor

text .flenbox2 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 10 -height 15 \
                -font $FontString \
                -background $ToBGColor \
                -foreground $ToFGColor

text .datebox2 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 12 -height 15 \
                -font $FontString \
                -background $ToBGColor \
                -foreground $ToFGColor

text .linkbox2 -wrap none -relief raised -borderwidth $XPrefBorderW \
                -setgrid 1 -width 30 -height 15 \
                -font $FontString \
                -background $ToBGColor \
                -foreground $ToFGColor


pack .filebox2 -in .c22 -side left -expand 1 -fill both
scrollbar .scroll2 -command "DoScroll_2" -borderwidth $XPrefBorderW 
pack .scroll2 -in .c22 -side left -after .filebox2 -fill y

entry .ws2 -width 10 -relief sunken -textvariable WorkStation2 \
      -borderwidth $XPrefBorderW -font $XPrefEntFont -bg $XPrefEntBack
entry .dirname2 -width 28 -relief sunken -textvariable DirName2 \
      -borderwidth $XPrefBorderW -font $XPrefEntFont -bg $XPrefEntBack
button .dirup2 -text "^" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command "DirUp 2"
button .dirdown2 -text "v" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command "DirDown 2"
button .dircp21 -text "<" -borderwidth $XPrefBorderW -bg $XPrefButtonBack \
      -padx 0 -pady 0 -command "DirCp 2 1"

scrollbar .dirscr2 -command ".dirname2 view" -borderwidth $XPrefBorderW \
      -orient horizontal -width 18

if {$tk_version >= 4.0} {
   .dirscr1 configure -command ".dirname1 xview"
   .dirscr2 configure -command ".dirname2 xview"
   .dirname1 configure -xscrollcommand ".dirscr1 set"
   .dirname2 configure -xscrollcommand ".dirscr2 set"
} else {
   .scroll1 configure -fg $XPrefButtonBack -bg $XPrefEntBack
   .scroll2 configure -fg $XPrefButtonBack -bg $XPrefEntBack
   .dirscr1 configure -fg $XPrefButtonBack -bg $XPrefEntBack
   .dirscr2 configure -fg $XPrefButtonBack -bg $XPrefEntBack
   .dirname1 configure -scrollcommand ".dirscr1 set"
   .dirname2 configure -scrollcommand ".dirscr2 set"
}

pack .dircp21 .ws2 -side left -in .c231 -fill both -expand 1
pack .dirname2 -side left -in .c232 -expand 1 -fill both -padx 1m
pack .dirscr2 -in .c232 -side left -expand 0
pack .dirup2 .dirdown2 -side left -in .c233

bind .dirname2 <Return> {ReadDir 2}
bind .dirname2 <Left> {EntryCursor .dirname2 -1}
bind .dirname2 <Right> {EntryCursor .dirname2 1}

bind .ws2 <Return> {ReadDir 2}
bind .ws2 <Left> {EntryCursor .ws2 -1}
bind .ws2 <Right> {EntryCursor .ws2 1}

bind .patt2 <Return> {ReadDir 2}

foreach w { \
   .filebox2 .modebox2 .uidbox2 .gidbox2 .flenbox2 .datebox2 .linkbox2} {
   $w tag configure f \
         -foreground $TFileSelectFGColor -background $TFileSelectBGColor
   $w tag configure d \
         -foreground $TDirSelectFGColor -background $TDirSelectBGColor
   $w tag configure dir \
         -foreground $TDirBlankFGColor -background $TDirBlankBGColor
   $w tag configure l \
         -foreground $TLinkSelectFGColor -background $TLinkSelectBGColor
   $w tag configure link \
         -foreground $TLinkBlankFGColor -background $TLinkBlankBGColor
   $w tag configure warn \
         -foreground "#000000" -background "#ff0000"
   }
   
#
# Bindings for Text widget
#

bind Text <1> {DoSelect 1 %W @%x,%y}
bind Text <2> {UnSelect 1 %W @%x,%y}
bind Text <3> {UnSelect 1 %W @%x,%y}
bind Text <B1-Motion> {DoSelect 0 %W @%x,%y}
bind Text <B2-Motion> {UnSelect 0 %W @%x,%y}
bind Text <B3-Motion> {UnSelect 0 %W @%x,%y}
bind Text <Double-1> {DoExecute %W @%x,%y}

#
# Bindings for Entry widgets
#

bind Entry <2> {%W insert insert "[GetXSelect]"}
bind Entry <Control-k> {%W delete 0 end}
bind Entry <Left> {EntryCursor %W -1}
bind Entry <Right> {EntryCursor %W 1}

#
# Cluster definition box
#
text .clusterbox -wrap none -relief raised -borderwidth $XPrefBorderW \
		-yscrollcommand ".scrollc set" \
                -setgrid 1 -width 10 -height 15 \
                -font $FontString \
                -background $ClusterBGColor \
                -foreground $ClusterFGColor


scrollbar .scrollc -command ".clusterbox yview" -borderwidth $XPrefBorderW
bind .clusterbox <Double-1> {
   set WorkStation2 [.clusterbox get "@%x,%y linestart" "@%x,%y lineend"]
   ReadDir 2
}
.clusterbox tag configure x -background $ClusterSelBGColor \
                            -foreground $ClusterSelFGColor
#
#
#

proc SetLS var {
global LS1cmd LS2cmd LScmd LNcmd
   
   .mBar.prefs.m.cmds delete "1. ls: $LS1cmd"
   .mBar.prefs.m.cmds delete "2. ls: $LS2cmd"
   .mBar.prefs.m.cmds delete "use ls: $LScmd"
   .mBar.prefs.m.cmds delete "ln: $LNcmd"
   set x "set $var \[AskUser \"Set cmd\" \$$var\]"
   eval "$x"
   .mBar.prefs.m.cmds add command -label "1. ls: $LS1cmd" \
                -command {SetLS LS1cmd}
   .mBar.prefs.m.cmds add command -label "2. ls: $LS2cmd" \
                -command {SetLS LS2cmd}
   .mBar.prefs.m.cmds add command -label "use ls: $LScmd" \
                -command {SetLS LScmd}
   .mBar.prefs.m.cmds add command -label "ln: $LNcmd" \
                -command {SetLS LNcmd}
}

proc OpenFTP { } {
global User Domain FTPin FTPout

   set passwd "$User@$Domain"
   set host [AskUser "Host name or IP address" "ftp.ifh.de"]
   set user [AskUser "user name" "ftp"]
   set passwd [AskUser "password" "$passwd"]
   exec mkfifo /tmp/ftp.in
   exec mkfifo /tmp/ftp.out
   exec eval "ftp $host </tmp/ftp.in >tmp/ftp.out &"
   set FTPin [open /tmp/ftp.in w]
   set FTPout [open /tmp/ftp.out r]
   puts $FTPin $user
   puts $FTPin $passwd
   puts $FTPin "ls -l"
   gets $FTPout s
   puts stdout $s
}

proc RebuildWin { } {
global FileModesLYN FileDatesLYN FileSizeLYN FileUIDLYN FileGIDLYN FileLinkLYN \
       FileModesRYN FileDatesRYN FileSizeRYN FileUIDRYN FileGIDRYN FileLinkRYN \
       ClusterModeYN
          
   pack forget .modebox1
   pack forget .modebox2
   pack forget .uidbox1
   pack forget .uidbox2
   pack forget .gidbox1
   pack forget .gidbox2
   pack forget .flenbox1
   pack forget .flenbox2
   pack forget .datebox1
   pack forget .datebox2
   pack forget .linkbox1
   pack forget .linkbox2
   
   pack forget .clusterbox
   pack forget .scrollc
   
if {$FileModesLYN} {pack .modebox1 -in .c12 -side left -after .filebox1 -fill y}
if {$FileDatesLYN} {pack .datebox1 -in .c12 -side left -after .filebox1 -fill y}
if {$FileSizeLYN} {pack .flenbox1 -in .c12 -side left -after .filebox1 -fill y}
if {$FileUIDLYN} {pack .uidbox1 -in .c12 -side left -after .filebox1 -fill y}
if {$FileGIDLYN} {pack .gidbox1 -in .c12 -side left -after .filebox1 -fill y}
if {$FileLinkLYN} {pack .linkbox1 -in .c12 -side left -after .filebox1 -fill y}

if {$FileModesRYN} {pack .modebox2 -in .c22 -side left -after .filebox2 -fill y}
if {$FileDatesRYN} {pack .datebox2 -in .c22 -side left -after .filebox2 -fill y}
if {$FileSizeRYN} {pack .flenbox2 -in .c22 -side left -after .filebox2 -fill y}
if {$FileUIDRYN} {pack .uidbox2 -in .c22 -side left -after .filebox2 -fill y}
if {$FileGIDRYN} {pack .gidbox2 -in .c22 -side left -after .filebox2 -fill y}
if {$FileLinkRYN} {pack .linkbox2 -in .c22 -side left -after .filebox2 -fill y}

   if {$ClusterModeYN} {
      pack .clusterbox -in .c22 -side right -fill y
      pack .scrollc -in .c22 -side right -before .clusterbox -fill y
   }

   update
}


#
#
#

set width 10

button .b01 -text "All"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "SelAll"
button .b02 -text "None" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "SelNone"
button .b03 -text "Intersect"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "SelIntersect"
button .b04 -text "NOT in TO"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "SelNotInTo"
button .b05 -text "Diff Len"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "SelDiffLen"
button .b06 -text "pattern" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "SelPattern"
button .b07 -text "Reselect" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "ReSelect"
button .b08 -text "Force Read" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command {ForceRead 1; ForceRead 2}
button .b09 -text "X11-Select" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command {DoX11Select}


pack .b01 .b02 .b03 .b04 .b05 .b06 .b07 .b08 .b09 -in .c01 -side left

button .b11 -text "Copy"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoCopy"
button .b12 -text "Delete" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoDelete"
button .b13 -text "Move"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoMove"
button .b14 -text "Rename"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoRename"
button .b15 -text "Link"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoLink"
button .b16 -text "TkDiff" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoCompare"
button .b17 -text "MakeDir" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoMakeDir"
button .b18 -text "Chmod"  -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoChmod"
button .b19 -text "Chgrp"  -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoChgrp"
button .b20 -text "Chown"  -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoChown"

pack .b11 .b12 .b13 .b14 .b15 .b16 .b17 .b18 .b19 .b20 -in .c02 -side left

button .b21 -text "Edit"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoEdit"
button .b22 -text "View"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoView"
button .b23 -text "tar extr." -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoTarX"
button .b24 -text "tar crea." -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoTarC"
button .b25 -text "tar list"  -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoTarT"
button .b26 -text "configure" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoConfig"
button .b27 -text "xmkmf"   -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoXmkmf"
button .b28 -text "make"    -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoMake"
button .b29 -text "Command" -width $width -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command "DoCommand"

pack .b21 .b22 .b23 .b24 .b25 .b26 .b27 .b28 .b29 -in .c03 -side left

entry .comment -width 30 -relief sunken -bd 2 -borderwidth $XPrefBorderW \
      -bg $XPrefEntBack -font $XPrefEntFont -textvariable Comment
entry .input -width 30 -relief sunken -bd 2 -borderwidth $XPrefBorderW \
      -bg $XPrefEntBack -font $XPrefEntFont -textvariable Input

button .getfsel -text "Select" -borderwidth $XPrefBorderW \
      -padx 0 -pady 0 -bg $XPrefButtonBack  -command {
            set Input "[string trim [eval "exec $FileSelect"]]"
      }

pack .comment .input -in .c04 -side left -expand 1 -fill both -padx 2m -pady 1m
pack .getfsel -side right -in .c04
bind .input <Return> {HandleInput}
bind .input <Up> {CmdUp}
bind .input <Down> {CmdDown}

RebuildWin

proc EntryCursor {w dir} {
   set x [$w index insert]
   set x [expr $x + $dir]
   $w icursor $x
}

proc GetXSelect { } {

   set s ""   
   catch {set s [selection get STRING]}
   return "$s"
}

proc DoScroll_1 {args} {
   eval .filebox1 yview $args
   eval .modebox1 yview $args
   eval .uidbox1 yview $args
   eval .gidbox1 yview $args
   eval .flenbox1 yview $args
   eval .datebox1 yview $args
   eval .linkbox1 yview $args
}
proc DoScroll_2 {args} {
   eval .filebox2 yview $args
   eval .modebox2 yview $args
   eval .uidbox2 yview $args
   eval .gidbox2 yview $args
   eval .flenbox2 yview $args
   eval .datebox2 yview $args
   eval .linkbox2 yview $args
}

proc ReadDirs { } {
   ReadDir 1
   ReadDir 2
}

proc ForceRead {box} {
   global ClusterModeYN WorkStation1 WorkStation2 DirName1 DirName2 LS
   
   switch $box {
      1 {unset LS($WorkStation1,$DirName1) ; ReadDir 1 }
      2 {
         unset LS($WorkStation2,$DirName2)
         if $ClusterModeYN {
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               catch {unset LS($i,$DirName2)}
            }
         }
         ReadDir 2
        }
   }
}

proc ReadDir {box} {
   global ThisHostName SortMode RSHcmd LScmd LS1cmd LS2cmd Comment Input LS
   
   switch $box  {
      1 {
         upvar #0 WorkStation1 WS DirName1 DirName Patt1 Patt \
                  Dirs1 Dirs Links1 Links Warn1 Warn Tagged1 Tagged

         set files ".filebox1"
         set modes ".modebox1"
         set uids ".uidbox1"
         set gids ".gidbox1"
         set flens ".flenbox1"
         set dates ".datebox1"
         set links ".linkbox1"
         set size ".size1"
        }
      2 {
         upvar #0 WorkStation2 WS DirName2 DirName Patt2 Patt \
                  Dirs2 Dirs Links2 Links Warn2 Warn Tagged2 Tagged

         set files ".filebox2"
         set modes ".modebox2"
         set uids ".uidbox2"
         set gids ".gidbox2"
         set flens ".flenbox2"
         set dates ".datebox2"
         set links ".linkbox2"
         set size ".size2"
        }
   }

    $files delete 1.0 end
    $modes delete 1.0 end
    $uids  delete 1.0 end   
    $gids  delete 1.0 end
    $flens delete 1.0 end
    $dates delete 1.0 end
    $links delete 1.0 end

    catch {unset Tagged}
    catch {unset Dirs}
    catch {unset Links}
    catch {unset Warn}

    update
    
    if {![info exists LS($WS,$DirName)]} {
       set Dir [GetGlobName $DirName]
       set Comment "Reading Directory $box"
       update
       if {$WS == $ThisHostName} {
         set cmd "exec $LScmd $Dir"
       } else {
          set cmd "exec $RSHcmd $WS $LScmd $Dir"
       }
      set allfiles [split [eval $cmd] \n]
      StackUp $box $WS $DirName
    } else {
      set allfiles "$LS($WS,$DirName)"
    }
    
    set Input ""
    foreach i "$allfiles" {
      if {[llength $i] < 8} continue
      set mode [lindex "$i" 0]
      set m [string index $mode 0]
      if {$m == "-"} {
         if {[llength $i] == 8} {
            if {$LScmd == $LS1cmd} {set LScmd $LS2cmd} else {set LScmd $LS1cmd}
            set Input "changing LS mode to $LScmd"
            update
            ReadDir $box
            return
         }
         break
      }
    }

    set nfiles 0
    set nbytes 0
   
    if {$SortMode != "none"} {
       set Comment "Sorting Directory $box"
       update
       set allfiles [lsort -command DirSort "$allfiles"]
    }
    set LS($WS,$DirName) "$allfiles"
    set Comment ""
    update

    foreach i "$allfiles" {
      if {[llength $i] < 8} continue
      set mode [lindex "$i" 0]
      set m [string index $mode 0]
      if {($m == "c") || ($m == "b") || ($m == "p")} {
         set fsize 0
         set fnam [lindex "$i" 9]
         set date [lrange "$i" 6 8]
         set link [lrange "$i" 4 5]
      } else {
         set fnam [lindex "$i" 8]
         set fsize [lindex "$i" 4]
         set date [lrange "$i" 5 7]
         set link [lindex "$i" 10]
      }
      if {[string match $Patt $fnam]} {
         set uid [lindex "$i" 2]
         set gid [lindex "$i" 3]
         incr nfiles
#          if {($fnam != ".") && ($fnam != "..")} {
            catch {set nbytes [expr $nbytes + $fsize]}
#          }
         $files insert $nfiles.0 "$fnam\n"
         if {$m == "d"} {
            set Dirs($nfiles) 1
         } else {
            set Dirs($nfiles) 0
         }
         if {$m == "l"} {
            set Links($nfiles) 1
         } else {
            set Links($nfiles) 0
         }
         if {[string index $mode 3] == "s"} {
            set Warn($nfiles) 1
         } else {
            set Warn($nfiles) 0
         }
         set Tagged($nfiles) 0
         $modes insert $nfiles.0 "$mode\n"
         $uids insert $nfiles.0 "$uid\n"
         $gids insert $nfiles.0 "$gid\n"
         $flens insert $nfiles.0 "$fsize\n"
         $dates insert $nfiles.0 "$date\n"
         $links insert $nfiles.0 "$link\n"
      }
    }
    $size configure -text "$nfiles / $nbytes"
    for {set i 1} {$i <= $nfiles} {incr i} {
      if $Dirs($i) {
         $files tag add dir $i.0 "$i.0 lineend + 1c"
         $modes tag add dir $i.0 "$i.0 lineend + 1c"
         $uids tag add dir $i.0 "$i.0 lineend + 1c"
         $gids tag add dir $i.0 "$i.0 lineend + 1c"
         $dates tag add dir $i.0 "$i.0 lineend + 1c"
         $flens tag add dir $i.0 "$i.0 lineend + 1c"
         $links tag add dir $i.0 "$i.0 lineend + 1c"
      }
      if $Links($i) {
         $files tag add link $i.0 "$i.0 lineend + 1c"
         $modes tag add link $i.0 "$i.0 lineend + 1c"
         $uids tag add link $i.0 "$i.0 lineend + 1c"
         $gids tag add link $i.0 "$i.0 lineend + 1c"
         $dates tag add link $i.0 "$i.0 lineend + 1c"
         $flens tag add link $i.0 "$i.0 lineend + 1c"
         $links tag add link $i.0 "$i.0 lineend + 1c"
      }
      if $Warn($i) {
         $files tag add warn $i.0 "$i.0 lineend + 1c"
         $modes tag add warn $i.0 "$i.0 lineend + 1c"
         $uids tag add warn $i.0 "$i.0 lineend + 1c"
         $gids tag add warn $i.0 "$i.0 lineend + 1c"
         $dates tag add warn $i.0 "$i.0 lineend + 1c"
         $flens tag add warn $i.0 "$i.0 lineend + 1c"
         $links tag add warn $i.0 "$i.0 lineend + 1c"
      }
    }
}

proc DirSort {a b} {
   global SortMode
   
   set d1 [string index $a 0]
   set d2 [string index $b 0]
   if {($d1 == "d") && ($d2 != "d")} {return -1}
   if {($d1 != "d") && ($d2 == "d")} {return 1}
   
   switch $SortMode {
         "name" { set n1 [lindex "$a" 8]
                  set n2 [lindex "$b" 8]
                  return [string compare "$n1" "$n2"]
                }
         "user" { set n1 [lindex "$a" 2]
                  set n2 [lindex "$b" 2]
                  if {$n1 != $n2} {return [string compare "$n1" "$n2"]}
                  set n1 [lindex "$a" 8]
                  set n2 [lindex "$b" 8]
                  return [string compare "$n1" "$n2"]
                }
        "group" { set n1 [lindex "$a" 3]
                  set n2 [lindex "$b" 3]
                  if {$n1 != $n2} {return [string compare "$n1" "$n2"]}
                  set n1 [lindex "$a" 8]
                  set n2 [lindex "$b" 8]
                  return [string compare "$n1" "$n2"]
                }
         "size" { set n1 [lindex "$a" 4]
                  set n2 [lindex "$b" 4]
                  if {$n1 > $n2} {return 1}
                  if {$n1 < $n2} {return -1}
                  set n1 [lindex "$a" 8]
                  set n2 [lindex "$b" 8]
                  return [string compare "$n1" "$n2"]
                }
         "date" { set m1 [Month [lindex "$a" 5]]
                  set m2 [Month [lindex "$b" 5]]
                  set d1 [lindex "$a" 6]
                  set d2 [lindex "$b" 6]
                  set x1 [lindex "$a" 7]
                  set x2 [lindex "$b" 7]
                  set y1 10000
                  set y2 10000
                  set t1 0
                  set t2 0
                  if {[string index $x1 2] == ":"} {
set t1 [expr ([string range $x1 0 1] * 60) + ([string range $x1 3 4])]
                  } else { set y1 $x1 }
                  if {[string index $x2 2] == ":"} {
set t2 [expr ([string range $x2 0 1] * 60) + ([string range $x2 3 4])]
                  } else { set y2 $x2 }
                  if {$y1 > $y2} {return 1}
                  if {$y1 < $y2} {return -1}
                  if {$m1 > $m2} {return 1}
                  if {$m1 < $m2} {return -1}
                  if {$d1 > $d2} {return 1}
                  if {$d1 < $d2} {return -1}
                  if {$t1 > $t2} {return 1}
                  if {$t1 < $t2} {return -1}
                  return 0
                }
   }
}

proc Month {s} {
   switch $s {
      Jan {return 1}
      Feb {return 2}
      Mar {return 3}
      Apr {return 4}
      May {return 5}
      Jun {return 6}
      Jul {return 7}
      Aug {return 8}
      Sep {return 9}
      Oct {return 10}
      Nov {return 11}
      Dec {return 12}
      default {puts stdout "You should NEVER use localization ($s) !"}
   }
}

proc StackUpCmd {cmd} {
   global CmdStack CmdPtr CmdAct

   catch {if {$CmdStack($CmdAct) == $cmd} return}
   set CmdStack($CmdPtr) $cmd 
   set CmdAct $CmdPtr
   incr CmdPtr
}

proc CmdUp { } {
   global CmdStack CmdPtr CmdAct Input
   if {$CmdAct < 0} return
   set Input "$CmdStack($CmdAct)"
   set CmdAct [expr $CmdAct - 1]
}

proc CmdDown { } {
   global CmdStack CmdPtr CmdAct Input
   incr CmdAct
   if {$CmdAct >= $CmdPtr} {set CmdAct [expr $CmdPtr - 1] ; return}
   set Input "$CmdStack($CmdAct)"
}

proc HandleInput { } {
   global Comment Input Ready
   if {$Ready == 0} {
      set Ready 1
   } else {
      Do_Command $Input
   }
}

proc AskUser {str try} {
   global Comment Input Ready
   
   set Comment $str
   set Input $try
   set Ready 0
   focus .input
   
   while {!$Ready} {
      update
      after 200
   }
   set Comment ""
   set x $Input
   set Input ""
   focus .c00
   
   return $x
}

#
# Cluster File I/O
#
proc LoadCluster { } {
   global Taggedx
   set fnam [AskUser "Filename to Load" "~/.default_cluster"]
   if {$fnam == ""} return
   Load_Cluster $fnam
}
proc Load_Cluster fnam {
   global Taggedx
   .clusterbox delete 0.0 end
   set fp [open $fnam]
   while {![eof $fp]} {
      set s [string trim [gets $fp]]
      if {[string length $s] > 0} {ClusterAdd "$s"}
   }
   close $fp
}


proc SaveCluster { } {
   set fnam [AskUser "Filename to Save" "~/.default_cluster"]
   if {$fnam == ""} return
   ClusterSelectAll
   set Cluster "[GetCluster]"
   set fp [open $fnam w]
   foreach i "$Cluster" {
      puts $fp $i
   }
   close $fp
}

proc ClusterNetGroup { } {
   set group [AskUser "Please Enter group name" ""]
   if {$group == ""} return
   .clusterbox delete 1.0 end
   set x [eval exec ypcat -k netgroup.byhost | grep $group]
   set y [split "$x" "\n"]
   foreach i "$y" {
      set n [lindex [split "$i" " "] 0]
      set j [expr [string first "." $n] -1]
      if {$j >0} {set n [string range "$n" 0 $j]}
      if {![info exists seen($n)]} {
         ClusterAdd $n
         set seen($n) 1
      }
   }   
}

proc ClusterAdd node {
   global Taggedx
   scan [.clusterbox index end] "%d.%d" l n
   .clusterbox insert end "$node\n"
   set Taggedx($l) 0
   update
}
proc ClusterDelete {nodes} {
   global Taggedx
   scan [.clusterbox index end] "%d.%d" l n
   foreach i "$nodes" {
      for {set j 0} {$j <= $l} {incr j} {
         set s [.clusterbox get $l.0 "$l.0 lineend"]
         if {$s == $i} {
            .clusterbox delete $l.0 "$l.0 lineend +1c"
         }
      }
   }
   ClusterSelectNone
}
proc ClusterSelectAll { } {
   global Taggedx
   scan [.clusterbox index end] "%d.%d" l n
   for {set i 1} {$i <= $l} {incr i} {
      if {[string length [.clusterbox get $i.0 "$i.0 lineend"]] > 0} {
         set Taggedx($i) 1
         .clusterbox tag add x $i.0 "$i.0 lineend + 1c"
      }
   }
   update
}
proc ClusterSelectNone { } {
   global Taggedx
   scan [.clusterbox index end] "%d.%d" l n
   for {set i 1} {$i <= $l} {incr i} {
      set Taggedx($i) 0
      .clusterbox tag remove x $i.0 "$i.0 lineend + 1c"
   }
   update
}


#
# Saving Preferences
#
proc SavePrefs { } {
   global HotList
 
   set cwd [pwd] ; cd
   set f [open ".tkdir" w]
   
   foreach Var { \
            FontName FontSize FromBGColor FromFGColor ToBGColor ToFGColor \
            FDirBlankBGColor FDirSelectBGColor FDirBlankFGColor \
            FDirSelectFGColor TDirBlankBGColor TDirSelectBGColor \
            TDirBlankFGColor TDirSelectFGColor FFileSelectBGColor \
            FFileSelectFGColor TFileSelectBGColor TFileSelectFGColor SortMode \
            FileModesLYN FileDatesLYN FileSizeLYN FileUIDLYN FileGIDLYN \
            FileLinkLYN FileModesRYN FileDatesRYN FileSizeRYN FileUIDRYN \
            FileGIDRYN FileLinkRYN ClusterModeYN FLinkBlankBGColor \
            FLinkSelectBGColor FLinkBlankFGColor FLinkSelectFGColor \
            TLinkBlankBGColor TLinkSelectBGColor TLinkBlankFGColor \
            TLinkSelectFGColor ClusterBGColor ClusterFGColor \
            ClusterSelBGColor ClusterSelFGColor ViewBGColor ViewFGColor \
            BW_ModeYN LS1cmd LS2cmd LScmd LNcmd} {

      upvar $Var tmp
      puts $f "set $Var \"$tmp\""
   }
   foreach Var  [info globals "XPref*"] {
      upvar $Var tmp
      puts $f "set $Var \"$tmp\""
   }
   foreach i "$HotList" {
      puts $f "set HotList \"\$HotList $i\""
   }
   close $f
   
   set f [open ".default_cluster" w]
   scan [.clusterbox index end] "%d.%d" l n
   set erg ""
   for {set j 1} {$j < $l} {incr j} {
      set s [.clusterbox get $j.0 "$j.0 lineend"]
      puts $f "$s"
   }

   close $f
   cd $cwd
}

proc SetCLR { } {
global FontString BW_ModeYN FFileSelectFGColor FFileSelectBGColor \
       FDirSelectFGColor FDirSelectBGColor FDirBlankFGColor FDirBlankBGColor \
       FLinkSelectFGColor FLinkSelectBGColor FLinkBlankFGColor \
       FLinkBlankBGColor TFileSelectFGColor TFileSelectBGColor \
       TDirSelectFGColor TDirSelectBGColor TDirBlankFGColor TDirBlankBGColor \
       TLinkSelectFGColor TLinkSelectBGColor TLinkBlankFGColor \
       TLinkBlankBGColor FromBGColor FromFGColor ToBGColor ToFGColor \
       XPrefButtonBack XPrefEntBack

foreach w { \
   .filebox1 .modebox1 .uidbox1 .gidbox1 .flenbox1 .datebox1 .linkbox1} {
   $w configure -font $FontString \
         -background $FromBGColor -foreground $FromFGColor
   $w tag configure f -font $FontString \
         -foreground $FFileSelectFGColor -background $FFileSelectBGColor
   $w tag configure d -font $FontString \
         -foreground $FDirSelectFGColor -background $FDirSelectBGColor
   $w tag configure dir -font $FontString \
         -foreground $FDirBlankFGColor -background $FDirBlankBGColor
   $w tag configure l -font $FontString \
         -foreground $FLinkSelectFGColor -background $FLinkSelectBGColor
   $w tag configure link -font $FontString \
         -foreground $FLinkBlankFGColor -background $FLinkBlankBGColor
   $w tag configure warn -font $FontString \
         -foreground "#000000" -background "#ff0000"
   }

foreach w { \
   .filebox2 .modebox2 .uidbox2 .gidbox2 .flenbox2 .datebox2 .linkbox2} {
   $w configure -font $FontString \
         -background $ToBGColor -foreground $ToFGColor
   $w tag configure f -font $FontString \
         -foreground $TFileSelectFGColor -background $TFileSelectBGColor
   $w tag configure d -font $FontString \
         -foreground $TDirSelectFGColor -background $TDirSelectBGColor
   $w tag configure dir -font $FontString \
         -foreground $TDirBlankFGColor -background $TDirBlankBGColor
   $w tag configure l -font $FontString \
         -foreground $TLinkSelectFGColor -background $TLinkSelectBGColor
   $w tag configure link -font $FontString \
         -foreground $TLinkBlankFGColor -background $TLinkBlankBGColor
   $w tag configure warn -font $FontString \
         -foreground "#000000" -background "#ff0000"
   }
   foreach b [info commands .b*] {$b configure -bg $XPrefButtonBack}
   foreach e ".patt1 .patt2 .ws1 .ws2 .dirname1 .dirname2 .input" {
                           $e configure -bg $XPrefEntBack}
}

proc SetBW { } {
global FontString BW_ModeYN

regsub "Medium" $FontString "Bold" BFont
if {$BW_ModeYN == 1} {
   foreach i {filebox1 modebox1 uidbox1 gidbox1 flenbox1 datebox1 linkbox1 \
              filebox2 modebox2 uidbox2 gidbox2 flenbox2 datebox2 linkbox2 } {

      .$i configure -background white  -foreground black
      .$i tag configure f -background grey  -foreground black
      .$i tag configure dir -background white -foreground black -font $BFont
      .$i tag configure d -background grey -foreground black -font $BFont
      .$i tag configure link -background white -foreground grey
      .$i tag configure l -background grey -foreground white
      .$i tag configure warn -background black -foreground white -font $BFont
   }
   foreach b [info commands .b*] {$b configure -bg white}
   foreach e ".patt1 .patt2 .ws1 .ws2 .dirname1 .dirname2 .input" {
                           $e configure -bg LightGrey}
}
}

proc SwitchBW { } {
   global BW_ModeYN
   if {$BW_ModeYN == 1} {
      SetBW
   } else {
      SetCLR
   }
}


proc DoCfg {lr str} {
   foreach i {.filebox .modebox .uidbox .gidbox .flenbox .datebox .linkbox} {
      set w "$i$lr"
      eval "$w $str"
   }
}

proc SetFont font {
   global FontSize FontName FontString

   set FontName $font
   set FontString "${FontName}--*-${FontSize}-*-*-*-*-iso8859-*"
   foreach i {filebox1 modebox1 uidbox1 gidbox1 flenbox1 datebox1 linkbox1 \
              filebox2 modebox2 uidbox2 gidbox2 flenbox2 datebox2 linkbox2 } {
      .$i configure -font "$FontString"
   }
   SetBW
}

proc NewFontSize size {
   global FontSize FontName FontString

   set FontSize $size
   set FontString "${FontName}--*-${FontSize}-*-*-*-*-iso8859-*"
   foreach i {filebox1 modebox1 uidbox1 gidbox1 flenbox1 datebox1 linkbox1 \
              filebox2 modebox2 uidbox2 gidbox2 flenbox2 datebox2 linkbox2 } {
      .$i configure -font "$FontString"
   }
   SetBW
}

#
# Selecting and deselecting (First Function Row)
#

proc DoSelect {flg win index} {
   global LastIndex

   set lr [string index $win [expr [string length $win] - 1]]
   set line [$win index "$index linestart"]

   scan $line %d l
   if $flg {
      SelectLine $lr $l
   } else {
      for {set i [expr $LastIndex + 1]} {$i <= $l} {incr i} {
         SelectLine $lr $i
      }
   }
   set LastIndex $l
}

proc SelectLine {lr l} {

   switch $lr  {
      1 {upvar #0 Tagged1 Tagged Dirs1 Dirs Links1 Links}
      2 {upvar #0 Tagged2 Tagged Dirs2 Dirs Links2 Links}
      x {upvar #0 Taggedx Tagged
         .clusterbox tag add x $l.0 "$l.0 lineend + 1c"
         set Tagged($l) 1
         return
        }
   }

   set s [.filebox$lr get $l.0 "$l.0 lineend"]
   if {($s == ".")||($s == "..")} return
   if {![info exists Dirs($l)]} return
   set Tagged($l) 1
   foreach i {.filebox .modebox .uidbox .gidbox .flenbox .datebox .linkbox} {
      set w "$i$lr"
      if {$Dirs($l)} {
         $w tag remove dir $l.0 "$l.0 lineend + 1c"
         $w tag add d $l.0 "$l.0 lineend + 1c"
      } else {
         if {$Links($l)} {
            $w tag remove link $l.0 "$l.0 lineend + 1c"
            $w tag add l $l.0 "$l.0 lineend + 1c"
         } else {
            $w tag remove warn $l.0 "$l.0 lineend + 1c"
            $w tag add f $l.0 "$l.0 lineend + 1c"
         }
      }
   }
}

proc UnSelect {flg win index} {
   global LastIndex

   selection clear .
   set lr [string index $win [expr [string length $win] - 1]]
   set line [$win index "$index linestart"]

   scan $line %d l
   if $flg {
      UnSelectLine $lr $l
   } else {
      for {set i [expr $LastIndex + 1]} {$i <= $l} {incr i} {
         UnSelectLine $lr $i
      }
   }
   set LastIndex $l
}

proc UnSelectLine {lr l} {

   switch $lr  {
      1 {upvar #0 Tagged1 Tagged Dirs1 Dirs Links1 Links}
      2 {upvar #0 Tagged2 Tagged Dirs2 Dirs Links2 Links}
      x {upvar #0 Taggedx Tagged
         .clusterbox tag remove x $l.0 "$l.0 lineend + 1c"
         set Tagged($l) 0
         return
        }
   }

   if {![info exists Dirs($l)]} return
   set Tagged($l) 0
   foreach i {.filebox .modebox .uidbox .gidbox .flenbox .datebox .linkbox} {
      set w "$i$lr"
      if {$Dirs($l)} {
         $w tag remove d $l.0 "$l.0 lineend + 1c"
         $w tag add dir $l.0 "$l.0 lineend + 1c"
      } else {
         if {$Links($l)} {
            $w tag remove l $l.0 "$l.0 lineend + 1c"
            $w tag add link $l.0 "$l.0 lineend + 1c"
         } else {
            $w tag remove f $l.0 "$l.0 lineend + 1c"
         }
      }
   }
}

proc SelNone { } {
   global LastTagged1 LastTagged2 Tagged1 Tagged2
   
   aset LastTagged1 Tagged1
   aset LastTagged2 Tagged2
   
   foreach i [array names Tagged1] {UnSelectLine 1 $i}
   foreach i [array names Tagged2] {UnSelectLine 2 $i}
}

proc SelAll { } {
   global Tagged1
   
   foreach i [array names Tagged1] {SelectLine 1 $i}
}

proc ReSelect { } {
   global LastTagged1 LastTagged2 Tagged1 Tagged2
      
   foreach i [array names Tagged1] {
      if $LastTagged1($i) {SelectLine 1 $i}
   }
   foreach i [array names Tagged2] {
      if $LastTagged2($i) {SelectLine 2 $i}
   }
}

proc SelIntersect { } {
   global Tagged1 Tagged2
   
   SelNone
   foreach i [array names Tagged1] {
      set s [.filebox1 get $i.0 "$i.0 lineend"]
      if {($s == ".") || ($s == "..")} continue
      foreach j [array names Tagged2] {
         set z [.filebox2 get $j.0 "$j.0 lineend"]
         if {$s == $z} {SelectLine 1 $i ; break}
      }
   }
}

proc SelNotInTo { } {
   global Tagged1 Tagged2
   
   SelNone
   foreach i [array names Tagged1] {
      set s [.filebox1 get $i.0 "$i.0 lineend"]
      set flag 1
      foreach j [array names Tagged2] {
         set z [.filebox2 get $j.0 "$j.0 lineend"]
         if {$s == $z} {set flag 0 ; break}
      }
      if {$flag == 1} {SelectLine 1 $i}
   }
}

proc SelPattern { } {
   global Tagged1
   
   set Patt [AskUser "glob style Pattern" "*"]
   
   foreach i [array names Tagged1] {
      set s [.filebox1 get $i.0 "$i.0 lineend"]
      if {[string match $Patt $s]} {SelectLine 1 $i}
   }
}

proc SelDiffLen { } {
   global Tagged1 Tagged2
   
   SelNone
   foreach i [array names Tagged1] {
      set s [.filebox1 get $i.0 "$i.0 lineend"]
      if {($s == ".") || ($s == "..")} continue
      set l [.flenbox1 get $i.0 "$i.0 lineend"]
      foreach j [array names Tagged2] {
         set z [.filebox2 get $j.0 "$j.0 lineend"]
         if {$s == $z} {
            set x [.flenbox2 get $j.0 "$j.0 lineend"]
            if {$l != $x} {
               SelectLine 1 $i
               break
            }
         }
      }
   }
}

proc aset {dest src} {

   upvar $dest b $src a
   
   catch {unset b}
   foreach i [array names a] {
      set b($i) $a($i)
   }
}

#
# Support functions for Elementary Functions
#

proc GetCluster { } {
   global ClusterModeYN DirName2 WorkStation2 Taggedx

   if $ClusterModeYN {
      scan [.clusterbox index end] "%d.%d" l n
      set erg ""
      for {set j 1} {$j <= $l} {incr j} {
         if {$Taggedx($j) == 1} {
            set s [.clusterbox get $j.0 "$j.0 lineend"]
            set erg "$erg $s"
         }
      }
      if {$erg == ""} {
         tk_dialog .err "Error:" "No nodes selected" warning -1 OK
      }
   } else {
      set erg $WorkStation2
   }
   return "$erg"
}

proc OperationMode { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 ThisHostName
# L=Local, R=Remote, C=Cluster
   set erg "LL"
   if $ClusterModeYN {
      if {$WorkStation1 == $ThisHostName} {
         set erg "LC"
      } else {
         set erg "RC"
      }
   } else {
      if {$WorkStation1 == $ThisHostName} {
         if {$WorkStation2 != $ThisHostName} {
            set erg "LR"
         } else {
            set erg "LL"
         }
      } else {
         if {$WorkStation2 == $ThisHostName} {
            set erg "RL"
         } else {
            set erg "RR"
         }
      }
   }
   return "$erg"
}

#
# Elementary Functions (Second row)
#

proc DoCopy { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName CPcmd RCPcmd 
   
   set op [OperationMode]
   switch $op {
      LL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoCopy1 "$CPcmd" "$s1" "[GlobDir2]" $DirName1 $DirName2
            DoCopy1 "$CPcmd" "$s2" "[GlobDir1]" $DirName2 $DirName1
         }
      LR {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 1]
            DoCopy1 "$RCPcmd" "$s1" "$WorkStation2:$DirName2" \
               $WorkStation1 $WorkStation2
            DoCopy1 "$RCPcmd" "$s2" "[GlobDir1]" $WorkStation2 $WorkStation1
         }
      LC {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 1]
            set Cluster [GetCluster]
            foreach i "$Cluster" {
   if {($i == $ThisHostName) && ($DirName1 == $DirName2)} continue
               DoCopy1 "$RCPcmd" "$s1" "$i:$DirName2 &" "" "$i"
            }
            DoCopy1 "$RCPcmd" "$s2" "[GlobDir1]" "" $WorkStation1
         }
      RL {
            set s1 [GetSelect 1 1]
            set s2 [GetSelect 2 0]
            DoCopy1 "$RCPcmd" "$s1" "[GlobDir2]" "" $WorkStation2
            DoCopy1 "$RCPcmd" "$s2" "[GlobDir1]" "" $WorkStation1
         }
      RR {
            set s1 [GetSelect 1 1]
            set s2 [GetSelect 2 1]
            DoCopy1 "$RCPcmd" "$s1" "$WorkStation2:$DirName2" \
               $WorkStation1  $WorkStation2
            DoCopy1 "$RCPcmd" "$s2" "$WorkStation1:$DirName1" \
               $WorkStation2  $WorkStation1
         }
      RC {
            set s1 [GetSelect 1 1]
            set s2 [GetSelect 2 1]
            set Cluster [GetCluster]
            foreach i "$Cluster" {
      if {($i == $WorkStation1) && ($DirName1 == $DirName2)} continue
               DoCopy1 "$RCPcmd" "$s1" "$i:[GlobDir2] &" "" "$i"
            }
            DoCopy1 "$RCPcmd" "$s2" "$WorkStation1:[GlobDir1]" \
               $WorkStation2  $WorkStation1
         }
   }
   set Comment "" ; update
   SelNone
   ForceRead 1
   ForceRead 2
}

proc DoCopy1 {cpcmd file1 file2 src dest} {
   global Comment
   if {($file1 == "") || ($file2 == "")} return
   set cmd "$cpcmd $file1 $file2"
   set Comment "Copying $src to $dest" ; update
   eval "exec $cmd"
}

proc DoDelete { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName RSHcmd RMcmd 
   
   set op [OperationMode]
   switch $op {
      LL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoDelete1 "$RMcmd" "$s1" "Local $DirName1"
            DoDelete1 "$RMcmd" "$s2" "Local $DirName2"
         }
      LR {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoDelete1 "$RMcmd" "$s1" "Local $DirName1"
            DoDelete1 "$RSHcmd $WorkStation2 $RMcmd" "$s2" \
               "$WorkStation2 $DirName2"
         }
      LC {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoDelete1 "$RMcmd" "$s1" "Local $DirName1"
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               DoDelete1 "$RSHcmd $i $RMcmd" "$s2" "$i $DirName2"
            }
         }
      RL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoDelete1 "$RSHcmd $WorkStation1 $RMcmd" "$s1" \
               "$WorkStation1 $DirName1"
            DoDelete1 "$RMcmd" "$s2" "Local $DirName2"
         }
      RR {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoDelete1 "$RSHcmd $WorkStation1 $RMcmd" "$s1" \
                     "$WorkStation1 $DirName1"
            DoDelete1 "$RSHcmd $WorkStation2 $RMcmd" "$s2" \
                     "$WorkStation2:$DirName2"
         }
      RC {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoDelete1 "$RSHcmd $WorkStation1 $RMcmd" "$s1" \
                 "$WorkStation1 $DirName1"
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               DoDelete1 "$RSHcmd $i $RMcmd" "$s2" "$i $DirName2"
            }
         }
   }
   set Comment "" ; update
   SelNone
   ForceRead 1
   ForceRead 2
}

proc DoDelete1 {rmcmd files dest} {
   global Comment
   if {$files == ""} return
   set cmd "$rmcmd $files"
   set Comment "Removing from $dest" ; update
   eval "exec $cmd"
}

proc DoMove { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName MVcmd RMcmd CPcmd RCPcmd 
   
   set op [OperationMode]
   switch $op {
      LL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            set cmd "$MVcmd $s1 [GlobDir2]"
            set Comment "Moving to $DirName2" ; update
            if {$s1 != ""} {eval "exec $cmd"}
            set cmd "$MVcmd $s2 [GlobDir1]"
            set Comment "Moving from $DirName2" ; update
            if {$s2 != ""} {eval "exec $cmd"}
         }
 default {
tk_dialog .err "Error:" "You are trying to move files\n \
between Workstations. I am not shure\n \
If this makes any sense" warning -1 OK
         }
   }
   set Comment "" ; update
   SelNone
   ForceRead 1
   ForceRead 2
}

proc DoRename { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName MVcmd RMcmd RSHcmd

   set s1 [GetSelect 1 0]
   set s2 [GetSelect 2 0]
 
   set op [OperationMode]
   foreach i "$s1" {
      set new [AskUser "Rename" "$i"]
      DoRename1 $i $new $op
   }
   foreach i "$s2" {
      set new [AskUser "Rename" "$i"]
      DoRename2 $i $new $op
   }
   set Comment "" ; update
   SelNone
   ForceRead 1
   ForceRead 2
}

proc DoRename1 {old new op} {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName MVcmd RMcmd RSHcmd

   switch $op {
      LL - LR - LC {
            set cmd "$MVcmd $old $new"
            set Comment "Moving to $DirName2" ; update
            eval "exec $cmd"
         }
      RL - RR - RC {
            set cmd "$RSHcmd $WorkStation1 $MVcmd $old $new"
            set Comment "Moving at $WorkStation1 to $DirName2" ; update
            eval "exec $cmd"
         }
   }
}

proc DoRename2 {old new op} {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName MVcmd RMcmd RSHcmd

   switch $op {
      LL - RL {
            set cmd "$MVcmd $old $new"
            set Comment "Moving to $DirName2" ; update
            eval "exec $cmd"
         }
      LR - RR {
            set cmd "$RSHcmd $WorkStation2 $MVcmd $old $new"
            set Comment "Moving at $WorkStation2 to $DirName2" ; update
            eval "exec $cmd"
         }
      LC - RC {
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               set cmd "$RSHcmd $i $MVcmd $old $new"
               set Comment "Moving at $i to $DirName2" ; update
               eval "exec $cmd"
            }
         }
   }
}

proc DoLink { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName LNcmd
   
   set op [OperationMode]
   switch $op {
      LL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            foreach i "$s1" {
               set f [file tail $i]
               set Comment "Linking $f" ; update
               set cmd "$LNcmd $i [GlobDir2]/$f"
               eval "exec $cmd"
            }
            foreach i "$s2" {
               set f [file tail $i]
               set Comment "Linking $f" ; update
               set cmd "$LNcmd $i [GlobDir1]/$f"
               eval "exec $cmd"
            }
         }
 default {
      tk_dialog .err "Error:" "You are trying to link files \n \
between Workstations." warning -1 OK
         }
   }
   set Comment "" ; update
   SelNone
   ForceRead 1
   ForceRead 2
}

proc DoCompare { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName DIFFcmd
   
   set op [OperationMode]
   switch $op {
      LL {
         set files "[GetSelect 1 0] [GetSelect 2 0]"
         set cmd "$DIFFcmd $files &"
         eval "exec $cmd"
         }
 default {
      tk_dialog .err "Error:" "Not Supported yet\n \
between Workstations." warning -1 OK
         }
   }
   set Comment "" ; update
   SelNone
}

proc DoMakeDir { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName RSHcmd MKDIRcmd
          
   set name [AskUser "Please enter name" ""]
   if {[string length $name] == 0} return
   set op [OperationMode]
   switch $op {
      LL - RL {
         set cmd "$MKDIRcmd [GlobDir2]/$name"
         eval "exec $cmd"
         }
      LR - RR {
         set cmd "$RSHcmd $WorkStation2 $MKDIRcmd [GlobDir2]/$name"
         eval "exec $cmd"
         }
      LC - RC {
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               set cmd "$RSHcmd $i $MKDIRcmd [GlobDir2]/$name &"
               set Comment "Creating on $i $MKDIRcmd $DirName2/$name" ; update
               eval "exec $cmd"
            }
         }
   }
   set Comment "" ; update
   ForceRead 2
}

proc DoChange {rmcmd files} {
   global Comment
   if {$files == ""} return
   set cmd "$rmcmd $files"
   set Comment "$cmd" ; update
   eval "exec $cmd"
}
proc DoChmod { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName RSHcmd CHMODcmd 

   set arg [AskUser "Argument for $CHMODcmd" ""]
   if {[string length $arg] == 0} return
   set op [OperationMode]
   switch $op {
      LL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHMODcmd $arg" "$s1"
            DoChange "$CHMODcmd $arg" "$s2"
         }
      LR {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHMODcmd $arg" "$s1"
            DoChange "$RSHcmd $WorkStation2 $CHMODcmd $arg" "$s2"
         }
      LC {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHMODcmd $arg" "$s1"
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               DoChange "$RSHcmd $i $CHMODcmd $arg &" "$s2"
            }
         }
      RL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHMODcmd $arg" "$s2"
            DoChange "$RSHcmd $WorkStation1 $CHMODcmd $arg" "$s1"
         }
      RR {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$RSHcmd $WorkStation1 $CHMODcmd $arg" "$s1"
            DoChange "$RSHcmd $WorkStation2 $CHMODcmd $arg" "$s2"
         }
      RC {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$RSHcmd $WorkStation1 $CHMODcmd $arg &" "$s1"
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               DoChange "$RSHcmd $i $CHMODcmd $arg" "$s2"
            }
         }
   }
   set Comment "" ; update
   SelNone
   ForceRead 1
   ForceRead 2
}

proc DoChgrp { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName RSHcmd CHGRPcmd 

   set arg [AskUser "Argument for $CHGRPcmd" ""]
   if {[string length $arg] == 0} return
   set op [OperationMode]
   switch $op {
      LL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHGRPcmd $arg" "$s1"
            DoChange "$CHGRPcmd $arg" "$s2"
         }
      LR {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHGRPcmd $arg" "$s1"
            DoChange "$RSHcmd $WorkStation2 $CHGRPcmd $arg" "$s2"
         }
      LC {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHGRPcmd $arg" "$s1"
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               DoChange "$RSHcmd $i $CHGRPcmd $arg &" "$s2"
            }
         }
      RL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHGRPcmd $arg" "$s2"
            DoChange "$RSHcmd $WorkStation1 $CHGRPcmd $arg" "$s1"
         }
      RR {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$RSHcmd $WorkStation1 $CHGRPcmd $arg" "$s1"
            DoChange "$RSHcmd $WorkStation2 $CHGRPcmd $arg" "$s2"
         }
      RC {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$RSHcmd $WorkStation1 $CHGRPcmd $arg" "$s1"
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               DoChange "$RSHcmd $i $CHGRPcmd $arg &" "$s2"
            }
         }
   }
   set Comment "" ; update
   SelNone
   ForceRead 1
   ForceRead 2
}

proc DoChown { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName RSHcmd CHOWNcmd 

   set arg [AskUser "Argument for $CHOWNcmd" ""]
   if {[string length $arg] == 0} return
   set op [OperationMode]
   switch $op {
      LL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHOWNcmd $arg" "$s1"
            DoChange "$CHOWNcmd $arg" "$s2"
         }
      LR {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHOWNcmd $arg" "$s1"
            DoChange "$RSHcmd $WorkStation2 $CHOWNcmd $arg" "$s2"
         }
      LC {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHOWNcmd $arg" "$s1"
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               DoChange "$RSHcmd $i $CHOWNcmd $arg &" "$s2"
            }
         }
      RL {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$CHOWNcmd $arg" "$s2"
            DoChange "$RSHcmd $WorkStation1 $CHOWNcmd $arg" "$s1"
         }
      RR {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$RSHcmd $WorkStation1 $CHOWNcmd $arg" "$s1"
            DoChange "$RSHcmd $WorkStation2 $CHOWNcmd $arg" "$s2"
         }
      RC {
            set s1 [GetSelect 1 0]
            set s2 [GetSelect 2 0]
            DoChange "$RSHcmd $WorkStation1 $CHOWNcmd $arg &" "$s1"
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               DoChange "$RSHcmd $i $CHOWNcmd $arg" "$s2"
            }
         }
   }
   set Comment "" ; update
   SelNone
   ForceRead 1
   ForceRead 2
}




#
#
#
proc GetSelect {box flg} {
   global ThisHostName

   switch $box  {
      1 {
         upvar #0 Tagged1 Tagged DirName1 DirName WorkStation1 WorkStation
         set filebox ".filebox1"
        }
      2 {
         upvar #0 Tagged2 Tagged DirName2 DirName WorkStation2 WorkStation
         set filebox ".filebox2"
        }
   }
   set result ""
   foreach i [array names Tagged] {
      if $Tagged($i) {
         set x [$filebox get $i.0 "$i.0 lineend"]
         if {$flg == -1} {set result "$result $x"; continue}
         set f "[GetGlobName $DirName]/$x"
         if {($ThisHostName == $WorkStation) || ($flg == 0)} {
            set result "$result $f"
         } else {
            set result "$result $WorkStation:$f"
         }
      }
   }
   return $result
}

proc PrintSelect { } {

   set result [GetSelect 1 1]
   set result "$result [GetSelect 2 1]"
   puts stdout "$result"
}

proc GetFileType {lr l} {
   global FileTypes FSMode
   
   set mb [.modebox$lr get $l]
   if {$mb == "d"} {return "dir"}
   if {$mb == "l"} {return "link"}
   if {$FSMode} {return "select"}
   set name [.filebox$lr get $l "$l lineend"]
   set ln [string length $name]
   set max [llength $FileTypes]
   set i 0
   while {$i < $max} {
      set s [lindex $FileTypes $i]
      set len [string length $s]
      set j [expr $ln - $len]
      if {[string range $name $j $ln] == $s} {
         incr i
         set erg [lindex $FileTypes $i]
         return $erg
      }
      incr i ; incr i
   }
   return "text"
}

proc DoExecute {win index} {
   global env FSMode ThisHostName Comment TempName RSHcmd RCPcmd \
              XMOREcmd PSVIEWcmd GIFVIEWcmd DVIVIEWcmd IFFVIEWcmd HTMLVIEWcmd

   set lr [string index $win [expr [string length $win] - 1]]
   set line [$win index "$index linestart"]

   switch $lr  {
      1 {
         upvar #0 Tagged1 Tagged Dirs1 Dirs DirName1 DirName \
         WorkStation1 WorkStation
        }
      2 {
         upvar #0 Tagged2 Tagged Dirs2 Dirs DirName2 DirName \
         WorkStation2 WorkStation
        }
   }

   scan $line %d l
   set x [.filebox$lr get $line "$line lineend"]
   set f [GetGlobName "$DirName/$x"]   
   set ftype [GetFileType $lr $line]
   
   switch $ftype {
    "link" {
            set m [.linkbox$lr get $line "$line lineend"]
            if {[string index $m 0] == "/"} {
               set DirName $m
               ReadDir $lr
               return
            }
            if {[string range $m 0 1] == ".."} {
               set DirName "[file dirname $DirName]/$m"
               ReadDir $lr
               return
            }
            if {[string length $m] > 1} {
               set s "$DirName/$m"
               regsub "//" "$s" "/" DirName
               ReadDir $lr
               return
            }
           }
    "dir"  {
            if {$x == "."} return
            if {$x == ".."} {
               UpDir $lr
            } else {
               set s "$DirName/$x"
               regsub "//" "$s" "/" DirName
               ReadDir $lr
            }
           }
    "select" {
            if {$ThisHostName == $WorkStation} {
               puts stdout "$f"
            } else {
               puts stdout "$WorkStation:$f"
            }
            exit
           }
    "text" {
            OpenTextWin
            set Comment "Reading file"
            update
            if {$ThisHostName == $WorkStation} {
               .help.win insert end "[eval "exec cat $f"]\n"
            } else {
            .help.win insert end "[eval "exec $RSHcmd $WorkStation cat $f"]\n"
            }
            update
            set Comment ""
           }
    "tar" - "tarz" - "targz" {
            DoTarT
           }
    "dvi"  {StartViewer $WorkStation $f $DVIVIEWcmd none} 
    "ps"   {StartViewer $WorkStation $f $PSVIEWcmd none}
    "psz"  {StartViewer $WorkStation $f $PSVIEWcmd Z}
    "psgz" {StartViewer $WorkStation $f $PSVIEWcmd gz}
    "gif"  {StartViewer $WorkStation $f $GIFVIEWcmd none}
    "iff"  {StartViewer $WorkStation $f $IFFVIEWcmd none}
    "html" {StartViewer $WorkStation $f $HTMLVIEWcmd none}
    "gif"  {StartViewer $WorkStation $f $GIFVIEWcmd none}
    "obj" - "lib" {
            tk_dialog .err "Error:" "Object File not Viewable" warning -1 OK
           }
   }
}

proc StartViewer {WorkStation File Viewer compression} {
   global env FSMode ThisHostName Comment TempName RSHcmd RCPcmd 
   
   if {$WorkStation == $ThisHostName} {
      switch $compression {
         none {
                eval "exec $Viewer $File"
              }
         gz   {
                eval "exec cp $File $TempName.gz"
                eval "exec gunzip $TempName.gz"
                eval "exec $Viewer $TempName"
                eval "exec rm -f $TempName"
              }
         Z    {
                eval "exec cp $File $TempName.Z"
                eval "exec uncompress $TempName.Z"
                eval "exec $Viewer $TempName"
                eval "exec rm -f $TempName"
              }
      }
   } else {
      switch $compression {
         none {
                eval "exec $RCPcmd $WorkStation:/$File $TempName"
                eval "exec $Viewer $TempName"
                eval "exec rm -f $TempName"
              }
         gz   {
                eval "exec $RCPcmd $WorkStation:/$File $TempName.gz"
                eval "exec gunzip $TempName.gz"
                eval "exec $Viewer $TempName"
                eval "exec rm -f $TempName"
              }
         Z    {
                eval "exec $RCPcmd $WorkStation:/$File $TempName.Z"
                eval "exec uncompress $TempName.Z"
                eval "exec $Viewer $TempName"
                eval "exec rm -f $TempName"
              }
      }
   }
}

proc UpDir {box} {
   switch $box  {
      1 { upvar #0 DirName1 DirName WorkStation1 WorkStation }
      2 { upvar #0 DirName2 DirName WorkStation2 WorkStation }
   }
   set i [string last "/" $DirName]
   if {$i == 0} {
      set DirName "/"
   }
   if {$i > 0} {
      set i [expr $i - 1]
      set DirName [string range $DirName 0 $i]
   }
   ReadDir $box
}

#
# Stack handling for directories
#
proc StackUp {box WorkStation DirName} {
   switch $box  {
      1 { upvar #0 DirStack1 DirStack DirSPtr1 ptr ActPtr1 act}
      2 { upvar #0 DirStack2 DirStack DirSPtr2 ptr ActPtr2 act}
   }
   set x "$WorkStation:$DirName"
   catch {if {"$DirStack($act)" == "$x"} return}
   set DirStack($ptr) $x
   set act $ptr
   incr ptr
}

proc DirUp {box} {
   switch $box  {
      1 { upvar #0 DirStack1 Stack ActPtr1 act WorkStation1 WS DirName1 Name}
      2 { upvar #0 DirStack2 Stack ActPtr2 act WorkStation2 WS DirName2 Name}
   }
   if {$act == 0} return
   set act [expr $act - 1]
   set x [split $Stack($act) ":"]
   set WS [lindex $x 0]
   set Name [lindex $x 1]
   ReadDir $box
}

proc DirDown {box} {
   switch $box  {
      1 { upvar #0 DirStack1 Stack DirSPtr1 ptr \
             ActPtr1 act WorkStation1 WS DirName1 Name
        }
      2 { upvar #0 DirStack2 Stack DirSPtr2 ptr \
             ActPtr2 act WorkStation2 WS DirName2 Name
        }
   }
   incr act
   if {$act >= $ptr} {set act [expr $ptr - 1] ; return}
   set x [split $Stack($act) ":"]
   set WS [lindex $x 0]
   set Name [lindex $x 1]
   ReadDir $box
}

proc DirCp {src dest} {
   global  WorkStation1  WorkStation2 DirName1 DirName2 SortMode

   set tmp $SortMode
   set SortMode "none"
   
   switch $src {
      1 {
         set WorkStation2 $WorkStation1
         set DirName2 $DirName1
         ReadDir 2
        }
      2 {
         set WorkStation1 $WorkStation2
         set DirName1 $DirName2
         ReadDir 1
        }
   }
   set SortMode $tmp
}

proc DirExc { } {
   global  WorkStation1  WorkStation2 DirName1 DirName2 SortMode

   set tmp $SortMode
   set SortMode "none"
   
   set t $WorkStation2
   set WorkStation2 $WorkStation1
   set WorkStation1 $t
   set t $DirName2
   set DirName2 $DirName1
   set DirName1 $t
   ReadDirs

   set SortMode $tmp
}

#
# Extended Functions (third row)
#

proc DoEdit { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName EDITcmd
   
   set op [OperationMode]
   switch $op {
      LL {
            set files "[GetSelect 1 0] [GetSelect 2 0]"
         }
      LR {
            set files "[GetSelect 1 0] [GetSelect 2 1]"
         }
      RL {
            set files "[GetSelect 1 1] [GetSelect 2 0]"
         }
      RR {
            set files "[GetSelect 1 1] [GetSelect 2 1]"
         }
      LC - RC {
            set files "[GetSelect 1 1]" 
            set files2 "[GetSelect 2 0]"
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               foreach j "$files2" {
                  set files "$files $i:$j"
               }
            }
            
         }
   }
   eval "exec $EDITcmd $files &"
   SelNone
}
proc DoView { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName VIEWcmd
   
   set op [OperationMode]
   switch $op {
      LL {
            set files "[GetSelect 1 0] [GetSelect 2 0]"
         }
      LR {
            set files "[GetSelect 1 0] [GetSelect 2 1]"
         }
      RL {
            set files "[GetSelect 1 1] [GetSelect 2 0]"
         }
      RR {
            set files "[GetSelect 1 1] [GetSelect 2 1]"
         }
      LC - RC {
tk_dialog .err "Error:" "Viewing in Cluster Mode not supported" warning -1 OK
            return
         }
   }
   eval "exec $VIEWcmd $files &"
   SelNone
}
proc DoTarX { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName TARXcmd TARXZcmd TARXGZcmd
   
   set op [OperationMode]
   switch $op {
      LL {
            set files "[GetSelect 1 0] [GetSelect 2 0]"
            DoTarX1 $files $DirName2
         }
      RL {
            set files "[GetSelect 1 1] [GetSelect 2 0]"
            DoTarX1 $files $DirName2
         }
      LC - RC - LR - RR {
tk_dialog .err "Error:" "Remote Destination not supported (yet)" warning -1 OK
            return
         }
   }
   SelNone
   set Comment ""
   update
   ForceRead 2
}

proc DoTarX1 {files dest} {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName TARXcmd TARXZcmd TARXGZcmd

   set cwd [pwd]
   cd $dest

   foreach i "$files" {
      set typ [file extension $i]
      set Comment "Extracting $i"
      update
      switch $typ {
            ".tar" { catch { eval "exec  $TARXcmd $i" }}
            ".gz"  { catch { eval "exec  $TARXGZcmd $i" }}
            ".Z"   { catch { eval "exec  $TARXZcmd $i" }}
      }
   }
   cd $cwd
}

proc DoTarC { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName TARCcmd
   
   set op [OperationMode]
   switch $op {
      LL {
            set name [AskUser "Arcive name ?" "Unnamed.tar"]
            set files "[GetSelect 1 -1]"
            set dir [GlobDir1]
            if {$files == ""} {
               set files "[GetSelect 2 -1]"
               set dir [GlobDir1]
            }
            DoTarC1 $files $name $dir $DirName2
         }
      RL - LC - RC - LR - RR {
tk_dialog .err "Error:" "Only local files are supported yet" warning -1 OK
            return
         }
   }
   SelNone
   ForceRead 2
}

proc DoTarC1 {files name src dest} {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName TARCcmd

   set cwd [pwd]
   cd $dest

   eval "exec  $TARCcmd $name -C $src $files"

   cd $cwd
}

proc DoTarT { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName TARTcmd TARTZcmd TARTGZcmd
   
   set op [OperationMode]
   switch $op {
      LL {
            set files "[GetSelect 1 0] [GetSelect 2 0]"
            DoTarT1 $files
         }
      RL {
            set files "[GetSelect 1 1] [GetSelect 2 0]"
            DoTarT1 $files
         }
      LR {
            set files "[GetSelect 1 0] [GetSelect 2 1]"
            DoTarT1 $files
         }
      RR {
            set files "[GetSelect 1 1] [GetSelect 2 1]"
            DoTarT1 $files
         }
      LC - RC {
tk_dialog .err "Error:" "Cluster not supported with list" warning -1 OK
            return
         }
   }
   SelNone
}

proc DoTarT1 {files} {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment ThisHostName TARTcmd TARTZcmd TARTGZcmd XMOREcmd

   OpenTextWin
   foreach i "$files" {
      set typ [file extension $i]
      switch $typ {
            ".tar" {.help.win insert end [eval "exec  $TARTcmd $i"]}
            ".gz"  {.help.win insert end [eval "exec  $TARTGZcmd $i"]}
            ".Z"   {.help.win insert end [eval "exec  $TARTZcmd $i"]}
      }
   }
   update
}

proc DoConfig { } {
   RemoteExecute "configure"
}

proc DoXmkmf { } {
   RemoteExecute "xmkmf"
}

proc DoMake { } {
   RemoteExecute "make"
}

proc RemoteExecute {cmd} {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment RSHcmd

   set op [OperationMode]
   switch $op {
      LL - RL {
               set CWD [pwd]
               cd $DirName2
               set Comment "Working..." ; update
               eval "exec $cmd"
               cd $CWD
              }
      LR - RR {
               set Comment "Working..." ; update
               eval "exec $RSHcmd $WorkStation2 {cd [GlobDir2] \; $cmd}"
              }
      LC - RC {
            set Cluster [GetCluster]
            foreach i "$Cluster" {
               set Comment "Working at $i" ; update
               eval "exec $RSHcmd $i {cd [GlobDir2] \; $cmd}"
            }
         }
   }
   set Comment "" ; update
   ForceRead 2
}

proc DoCommand { } {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment RSHcmd

   set s [AskUser "Enter Command (% = files)" ""]
   Do_Command $s
}

proc Do_Command s {
   global ClusterModeYN DirName1 DirName2 WorkStation1 WorkStation2 \
          Comment RSHcmd TempName

   StackUpCmd $s
   set args [GetSelect 2 -1]
   regsub -all "\%" "$s" "$args" cmd
   regsub -all "2>/dev/null" "$RSHcmd" "2>$TempName" RSHcmd2
   set op [OperationMode]
   switch $op {
      LL - RL {
               set Comment "Working..." ; update
               OpenTextWin
               set CWD [pwd]
               cd $DirName2
               catch {eval exec $cmd} erg
               .help.win insert end "$erg\n"
               cd $CWD
              }
      LR - RR {
               set Comment "Working..." ; update
               OpenTextWin
               set erg [eval \
                    exec $RSHcmd2 $WorkStation2 {cd [GlobDir2] \; $cmd }]
               set f [open $TempName r]
               set err [read $f 32768]
               close $f
               exec rm -f $TempName
               .help.win insert end "$erg\n$err\n"
              }
      LC - RC {
               set Cluster [GetCluster]
               OpenTextWin
               foreach i "$Cluster" {
               set Comment "Working at $i" ; update
               .help.win insert end "------------ $i -------------\n"
               update
               set erg [eval \
                    exec $RSHcmd2 $i {cd [GlobDir2] \; $cmd }]
               set f [open $TempName r]
               set err [read $f 32768]
               close $f
               exec rm -f $TempName
               .help.win insert end "$erg\n$err\n"
               update
            }
         }
   }
   set Comment "" ; update
   ForceRead 2
}

proc GlobDir1 { } {
   global DirName1
   return [GetGlobName $DirName1]
}
proc GlobDir2 { } {
   global DirName2
   return [GetGlobName $DirName2]
}

proc GetGlobName Dir {
   if {[string index $Dir 0] == "~"} {
      set s [split $Dir / ]
      set x [glob [lindex $s 0]]
      set y [lreplace $s 0 0 $x]
      set Dir [join $y /]
   }
   return $Dir
}
#
# --------------------------------------------------
#

proc Commercial { } {
   tk_dialog .err "Commercial:" "\
Have you also tried tkedit ?\n \
An tcl-tk based Text editor supporting\n \
multiple buffers and split views\n \
and even folding of functions.\n \
Available now at:\n \
ftp.ifh.de:/pub/unix/edit/tkedit-i.j.k.tar.Z" questhead -1 OK
}

proc OpenTextWin { } {
   global FontString env XMOREcmd ViewBGColor ViewFGColor \
          XPrefBorderW XPrefButtonBack

   catch {destroy .help}
   toplevel .help -class Dialog
   frame .help.top -relief raised -bd 1
   pack .help.top -side top -expand 1 -fill both
   frame .help.bot -relief raised -bd 1
   pack .help.bot -side bottom -fill x
   text .help.win -width 80 -height 24 -font $FontString \
         -setgrid 1 -bg $ViewBGColor -fg $ViewFGColor \
         -yscrollcommand ".help.scroll set"
   pack .help.win -in .help.top -side left -expand 1 -fill both
   scrollbar .help.scroll -command ".help.win yview"  -borderwidth $XPrefBorderW
   pack .help.scroll -in .help.top -side left -fill y
   button .help.quit -text "OK" -width 10 -borderwidth $XPrefBorderW \
         -bg $XPrefButtonBack  -command {destroy .help}
   button .help.edit -text "--> $XMOREcmd" -width 15 -borderwidth $XPrefBorderW \
         -bg $XPrefButtonBack  -command {
      set f [open |$XMOREcmd r+]
      set s [.help.win get 1.0 end]
      puts $f "$s"
      close $f
      destroy .help
   }
   pack .help.quit .help.edit -in .help.bot -side left -expand 1 -fill x
   wm maxsize .help 200 100
   wm minsize .help 10 2
bind .help.win <1> {
    set tk_priv(selectMode) char
    %W mark set insert @%x,%y
    %W mark set anchor insert
    if {[lindex [%W config -state] 4] == "normal"} {focus %W}
}
bind .help.win <Double-1> {
    set tk_priv(selectMode) word
    %W mark set insert "@%x,%y wordstart"
    tk_textSelectTo %W insert
}
bind .help.win <Triple-1> {
    set tk_priv(selectMode) line
    %W mark set insert "@%x,%y linestart"
    tk_textSelectTo %W insert
}
bind .help.win <B1-Motion> {tk_textSelectTo %W @%x,%y}
}

proc LoadDoc { } {
   global FontString env

   OpenTextWin
   regsub -all "\:" $env(PATH) " " s
   set l [llength $s]
   for {set i 0} {$i < $l} {incr i} {
      set f "[lindex $s $i]/tkdir.txt"
      if {[file exists $f]} {
         set fp [open $f]
         while {![eof $fp]} {
            .help.win insert end [read $fp 8192]
         }
         close $fp
         break
      }
   }
}

proc FSEdit { } {
   set s [GetSelect 1 1]
   set s "$s [GetSelect 2 1]"
   set s [AskUser "Modify and Type Return" "$s"]
   puts stdout "$s"
   exit
}

proc ShowHotlist { } {
   global HotList HotListOn DirName1 WorkStation1 DirName2 WorkStation2 \
          FontString XPrefBorderW XPrefButtonBack

   set HotListOn 1
   
   catch {destroy .hot}
   toplevel .hot -class Dialog
   frame .hot.top -relief raised -bd 1
   pack .hot.top -side top -expand 1 -fill both
   frame .hot.bot -relief raised -bd 1
   pack .hot.bot -side bottom -fill x
   text .hot.win -width 40 -height 10 -font $FontString \
         -yscrollcommand ".hot.scroll set"  -setgrid 1
   pack .hot.win -in .hot.top -side left -expand 1 -fill both
   scrollbar .hot.scroll -command ".hot.win yview" -borderwidth $XPrefBorderW
   pack .hot.scroll -in .hot.top -side left -fill y
   button .hot.quit -text "Dismiss" -width 10 -borderwidth $XPrefBorderW \
         -bg $XPrefButtonBack  -command {
      destroy .hot
      set HotListOn 0
   }
   pack .hot.quit -in .hot.bot -side left -expand 1 -fill x
   wm maxsize .hot 200 100
   wm minsize .hot 10 2
bind .hot.win <1> {
       %W mark set insert @%x,%y
       set name [%W get "insert linestart" "insert lineend"]
       if {[string first ":" $name] > 1} {
         set WorkStation1 [lindex [split $name ":"] 0]
         set DirName1 [lindex [split $name ":"] 1]
       } else {
         set DirName1 $name
       }
       ReadDir 1
    }
bind .hot.win <2> {
       %W mark set insert @%x,%y
       set name [%W get "insert linestart" "insert lineend"]
       if {[string first ":" $name] > 1} {
         set WorkStation2 [lindex [split $name ":"] 0]
         set DirName2 [lindex [split $name ":"] 1]
       } else {
         set DirName2 $name
       }
       ReadDir 2
    }
bind .hot.win <3> {
       %W mark set insert @%x,%y
       set name [%W get "insert linestart" "insert lineend"]
       if {[string first ":" $name] > 1} {
         set WorkStation2 [lindex [split $name ":"] 0]
         set DirName2 [lindex [split $name ":"] 1]
       } else {
         set DirName2 $name
       }
       ReadDir 2
    }

   foreach i "$HotList" {
      .hot.win insert end "$i\n"
   }
}
proc AddHot {box flg} {
   global HotList HotListOn DirName1 WorkStation1 DirName2 WorkStation2
   set a1 $DirName1
   set a2 $DirName2
   if {$flg == 1} {
      set a1 "$WorkStation1:$a1"
      set a2 "$WorkStation2:$a2"
   }
   if {$box == 1} {
      set HotList "$HotList $a1"
   } else {
      set HotList "$HotList $a2"
   }
   if {$HotListOn == 1} {
      ShowHotlist
   }
}

proc DoX11Select { } {
global Comment

   set Comment [GetSelect 1 1]
   set Comment "$Comment [GetSelect 2 1]"
   .comment select from 1
   .comment select to end
}

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

SetBW

for {set i 0} {$i < 256} {incr i} {set Taggedx($i) 0}

if {[file exists "/etc/tkdir.cfg"]} {
    source "/etc/tkdir.cfg"
}

if {[file exists "~/.default_cluster"]} {
    Load_Cluster "~/.default_cluster"
}

if {[file exists "~/.tkdirrc"]} {
    source "~/.tkdirrc"
}

set DirSPtr1 0
set DirSPtr2 0

set ActPtr1 0
set ActPtr2 0

set FSMode 0
set Patt1 "*"
set Patt2 "*"

set WorkStation1 [exec hostname]
set WorkStation2 $WorkStation1
set ThisHostName $WorkStation1

set DirName1 [pwd]
set DirName2 [pwd]

set i [lsearch $argv "-fs"]
if {$i >=0} {
   set FSMode 1
   button .b30 -text "--> OK" -width $width -borderwidth $XPrefBorderW \
         -padx 0 -pady 0 -bg $XPrefButtonBack  -command {PrintSelect ; exit}
   button .b31 -text "Edit & OK" -width $width -borderwidth $XPrefBorderW \
         -padx 0 -pady 0 -bg $XPrefButtonBack  -command {FSEdit}

pack .b30 .b31 -in .c03 -side left
}

set i [lsearch $argv "-patt"]
if {$i >= 0} {
   incr i
   set Patt1 [lindex $argv $i]
   set Patt2 [lindex $argv $i]
}

set i [lsearch $argv "-patt1"]
if {$i >= 0} {
   incr i
   set Patt1 [lindex $argv $i]
}

set i [lsearch $argv "-patt2"]
if {$i >= 0} {
   incr i
   set Patt2 [lindex $argv $i]
}

set i [lsearch $argv "-dir"]
if {$i >= 0} {
   incr i
   set DirName1 [lindex $argv $i]
   set DirName2 [lindex $argv $i]
}

set i [lsearch $argv "-dir1"]
if {$i >= 0} {
   incr i
   set DirName1 [lindex $argv $i]
}

set i [lsearch $argv "-dir2"]
if {$i >= 0} {
   incr i
   set DirName2 [lindex $argv $i]
}


wm title . "tkdir"

ReadDir 1
ReadDir 2

close stdin

