################################################################################
#
# fsel.tcl -- realize a file select box
#
# (c) 1994 HighTec EDV-Systeme GmbH
#          Neue Bahnhofstr. 71
#          66386 St.Ingbert, Germany
#          Email: tgdb@HighTec.saarlink.de
#
# *** ALL RIGHTS RESERVED ***
#
################################################################################
proc FileSelectBox { args } {
  # find mount path for file select box widget
  set nr 0
  while {1} {
    if { [winfo exists .fselbox$nr] } {
      incr nr
      continue
    }
    set MountPath .fselbox$nr
    break
  }
  rename FileSelectBox FSel_box$nr

  # initialize global variables
  global FSel_origpath$nr
  global FSel_geometry$nr
  global FSel_title$nr
  global FSel_status$nr
  global FSel_path$nr
  global FSel_file$nr
  global FSel_pattern$nr
  global FSel_readperm$nr
  global FSel_writeperm$nr
  global FSel_execperm$nr
  global FSel_show_hidden$nr
  global FSel_sort$nr
  global FSel_return$nr
  global FSel_cmderror$nr
  upvar #0 FSel_origpath$nr origpath
  upvar #0 FSel_geometry$nr geometry
  upvar #0 FSel_title$nr title
  upvar #0 FSel_status$nr status
  upvar #0 FSel_path$nr path
  upvar #0 FSel_file$nr file
  upvar #0 FSel_pattern$nr pattern
  upvar #0 FSel_readperm$nr readperm
  upvar #0 FSel_writeperm$nr writeperm
  upvar #0 FSel_execperm$nr execperm
  upvar #0 FSel_show_hidden$nr show_hidden
  upvar #0 FSel_sort$nr sortorder
  upvar #0 FSel_return$nr FSel_return
  upvar #0 FSel_cmderror$nr FSel_cmderror

  # set default values
  set origpath [pwd]
  set geometry "+100+100"
  set title "FileSelectBox V1.2"
  set status ""
  set path [pwd]
  set file ""
  set pattern "*"
  set readperm 0
  set writeperm 0
  set execperm 0
  set show_hidden 0
  set sortorder name 
  set FSel_return ""
  set FSel_cmderror 0

  # try to load default file "~/.fselrc"
  catch {source "~/.fselrc"}

  # try to load default file "~/.Xdefaults" if this is a stand alone version
  if { [string first fsel [winfo name .]] != -1 } {
    if { [file exists "~/.Xdefaults"] } {
      option clear
      catch {option readfile "~/.Xdefaults"}
    }
  }

  # process command line options
  if { $args != "{}" } {
    set xargc 0
    set xargs ""
    set args [split $args " \{\}"]
    set nargs [llength $args]
    set curr_arg ""
    for { set n 0 } { $n < $nargs } { incr n } {
      set i [string trim [lindex $args $n]]
      if { $i != "" } {
	if { [string index $i 0] == "-" } {
	  if { $curr_arg != "" } {
	    incr xargc
	    lappend xargs $curr_arg
	  }
	  incr xargc
	  lappend xargs $i
	  set curr_arg ""
	} else {
	  set curr_arg [concat $curr_arg $i]
	}
      }
    }
    if { $curr_arg != "" } {
      incr xargc
      lappend xargs $curr_arg
    }

    set argn 0
    while { $argn < $xargc } {
      set option [lindex $xargs $argn]
      if { $argn == [expr $xargc - 1] } {
	set status "No argument following \"$option\" option"
	set FSel_cmderror 1
	break
      }
      incr argn
      set arg [lindex $xargs $argn]
      incr argn
      if { $option == "-title" } {
	set title $arg
	continue
      }
      if { $option == "-file" } {
	set path [file dirname $arg]
	set file [file tail $arg]
	continue
      }
      if { $option == "-pattern" } {
	set pattern $arg
	continue
      }
      if { $option == "-sort" } {
	if {   ($arg == "name") || ($arg == "date")
	    || ($arg == "size") || ($arg == "ext") } {
	  set sortorder $arg
	} else {
	  set status "Illegal sort order \"$arg\""
	  set FSel_cmderror 1
	}
	continue
      }
      if { $option == "-perm" } {
	set arg [string trim [string tolower $arg]]
	for { set i [expr [string length $arg] - 1] } { $i >=0 } { incr i -1 } {
	  set perm [string index $arg $i]
	  if { $perm == "r" } {
	    set readperm 1
	  } elseif { $perm == "w" } {
	    set writeperm 1
	  } elseif { $perm == "x" } {
	    set execperm 1
	  } elseif { $perm == "h" } {
	    set show_hidden 1
	  } else {
	    set status "Illegal file permission \"$perm\""
	    set FSel_cmderror 1
	  }
        }
	continue
      }
      set status "Illegal option \"$option\""
      set FSel_cmderror 1
    }
  }

  # return to calling function if "Cancel" or "OK" button was hit
  proc FSel_exit$nr { nr why } {
    upvar #0 FSel_return$nr FSel_return
    upvar #0 FSel_status$nr status
    upvar #0 Path_entry$nr Path_entry
    upvar #0 File_entry$nr File_entry
    upvar #0 FSel_path$nr path
    upvar #0 FSel_file$nr file
    upvar #0 FSel_pattern$nr pattern
    upvar #0 FSel_readperm$nr readperm
    upvar #0 FSel_writeperm$nr writeperm
    upvar #0 FSel_execperm$nr execperm
    upvar #0 FSel_show_hidden$nr show_hidden
    upvar #0 FSel_sort$nr sortorder
    upvar #0 FSel_cmderror$nr FSel_cmderror


    set status ""
    if { $why == "cancel" } {
      set FSel_return ""
      return
    }
    if { [$File_entry get] == "" } {
      set status "No file name specified"
      return
    }
    if { ![file isdirectory [$Path_entry get]] } {
      set status "No such path \"[$Path_entry get]\""
      return
    }
    if { [catch {cd [$Path_entry get]} status] } \
      return

    # write default file "~/.fselrc"
    catch {
      scan [wm geometry .fselbox$nr] "%dx%d%s" dummy dummy xypos
      set desc [open "~/.fselrc" w]
      puts $desc "# ~/.fselrc -- default values for FileSelectBox"
      puts $desc "set geometry \"$xypos\""
      puts $desc "set path \"$path\""
      puts $desc "set file \"$file\""
      puts $desc "set pattern \"$pattern\""
      puts $desc "set readperm $readperm"
      puts $desc "set writeperm $writeperm" 
      puts $desc "set execperm $execperm"
      puts $desc "set show_hidden $show_hidden"
      puts $desc "set sortorder $sortorder"
      close $desc
    }

    # changing FSel_return will end the application...
    set FSel_return [concat [pwd]/[$File_entry get]]
  }

  # reposition cursor of an entry
  proc FSel_curpos$nr { widget } {
    set c [$widget index insert]
    set left [$widget index @0]
    if {$left >= $c} {
	if {$c > 0} {
	    $widget view [expr $c-1]
	} else {
	    $widget view $c
	}
	return
    }
    set x [expr [winfo width $widget] - [lindex [$widget config -bd] 4] - 1]
    while {([$widget index @$x] < $c) && ($left < $c)} {
	set left [expr $left+1]
	$widget view $left
    }
  }

  # reposition entry's string so that the insertion cursor is visible
  proc FSel_view_entry$nr { widget } {
    set c [$widget index insert]
    set left [$widget index @0]
    if {$left >= $c} {
      if {$c > 0} {
	$widget view [expr $c-1]
      } else {
	$widget view $c
      }
      return
    }
    set x [expr [winfo width $widget] - [lindex [$widget config -bd] 4] - 1]
    while {([$widget index @$x] < $c) && ($left < $c)} {
      set left [expr $left+1]
      $widget view $left
    }
  }


  # scroll entry's cursor left or right
  proc FSel_screntry$nr { nr where widget } {
    if { $where == "left" } {
      set pos [$widget index insert]
      if { $pos > 0 } {
	$widget icursor [incr pos -1]
	FSel_view_entry$nr $widget
      }
      return
    }
    if { $where == "right" } {
      set pos [$widget index insert]
      if { $pos < [string length [$widget get]] } {
	$widget icursor [incr pos 1]
	FSel_view_entry$nr $widget
      }
      return
    }
  }

  # rescan directory and update listbox entries
  proc FSel_rescan$nr { nr widget } {
    upvar #0 FSel_path$nr path
    upvar #0 FSel_status$nr status
    upvar #0 FSel_pattern$nr pattern
    upvar #0 FSel_show_hidden$nr show_hidden
    upvar #0 FSel_readperm$nr readperm
    upvar #0 FSel_writeperm$nr writeperm
    upvar #0 FSel_execperm$nr execperm
    upvar #0 Path_entry$nr Path_entry
    upvar #0 Path_rescan$nr Path_rescan
    upvar #0 FSel_sort$nr sortorder
    upvar #0 FSel_cmderror$nr FSel_cmderror

    $Path_rescan flash
    $widget delete 0 end
    if { [catch {file isdirectory $path} errtext] != 0 } {
      set status $errtext
      return
    }
    if {![file isdirectory $path]} {
      set status "No such path \"$path\""
      return
    }
    if { [catch { cd $path }] != 0 } {
      set status "Cannot cd to \"$path\""
      return
    }
    catch {set path [pwd]}; FSel_view_entry$nr $Path_entry

    if { $show_hidden == 1 } {
      set flist "* .*"
    } else {
      set flist "*"
    }
    if {[catch {set entries [eval glob -nocomplain $flist]} result] != 0 } {
      set status $result
      return
    }
    if { $FSel_cmderror == 1 } {
      set FSel_cmderror 0
    } else {
      set status ""
    }
    # get each file's status and sort them according to user's preference
    set entries2 ""
    foreach file $entries {
      if {   [catch {file lstat $file struct_stat}]
	  || ![string compare "." $file]
	  || ![string compare ".." $file] } \
	continue
      lappend entries2 $file
      set fstat($file,time) $struct_stat(mtime)
      set fstat($file,size) $struct_stat(size)
      set fstat($file,ext) [file extension $file]
      set fstat($file,link) ""
      if { $struct_stat(type) == "link" } {
        set fstat($file,link) [file readlink $file]
      }
    }
    set entries $entries2; unset entries2
    proc FSel_compare_date$nr { f1 f2 } {
      upvar fstat stat

      return [expr $stat($f2,time) - $stat($f1,time)]
    }
    proc FSel_compare_size$nr { f1 f2 } {
      upvar fstat stat

      return [expr $stat($f1,size) - $stat($f2,size)]
    }
    proc FSel_compare_exts$nr { f1 f2 } {
      upvar fstat stat

      set res [string compare $stat($f1,ext) $stat($f2,ext)]
      return [expr ($res != 0) ? $res : [string compare $f1 $f2]]
    }

    if { $sortorder == "name" } {
      set entries [lsort $entries]
    } elseif { $sortorder == "date" } {
      set entries [lsort -command FSel_compare_date$nr $entries]
    } elseif { $sortorder == "size" } {
      set entries [lsort -command FSel_compare_size$nr $entries]
    } elseif { $sortorder == "ext" } {
      set entries [lsort -command FSel_compare_exts$nr $entries]
    } else {
      tkerror "illegal sortorder $sortorder"
    }

    # handle directories first
    foreach file $entries {
      if { [file isdirectory $file] } {
	if { $fstat($file,link) != "" } {
	  set file [concat $file " -> " $fstat($file,link)]
	}
        $widget insert end "\[*\] $file"
      }
    }
    # now handle non-directories
    foreach file $entries {
      if {   ![file isdirectory $file]
	  && [string match $pattern $file]
	  && (($readperm == 0)  || [file readable $file])
	  && (($writeperm == 0) || [file writable $file])
	  && (($execperm == 0)  || [file executable $file]) } {
	if { $fstat($file,link) != "" } {
	  set file [concat $file " -> " $fstat($file,link)]
	}
        $widget insert end $file
      }
    }
  }

  # change directory and update path/listbox
  proc FSel_chdir$nr { nr widget newdir } {
    upvar #0 FSel_path$nr path
    upvar #0 FSel_status$nr status

    if {[catch { cd $newdir }]} {
      set status "No such directory \"$newdir\""
      return
    }
    set status ""
    set path [pwd]
    FSel_rescan$nr $nr $widget
  }

  # handle listbox selection
  proc FSel_select$nr { nr widget ypos nclicks } {
    upvar #0 FSel_file$nr file

    $widget select from [$widget nearest $ypos]
    set origfile ""
    catch {set origfile [$widget get [$widget curselection]]}
    if { [string first "\[*\]" $origfile] == 0 } {
      if { $nclicks == 2 } {
        set origfile [string range $origfile 4 end]
        if { [set index [string first " ->" $origfile]] != -1 } {
          set origfile [string range $origfile 0 [incr index -1]]
        }
        after 10 FSel_chdir$nr $nr $widget $origfile
      }
      return
    }
    set index [string first " ->" $origfile]
    if { $index == -1 } {
      set file $origfile
    } else {
      set file [string range $origfile 0 [incr index -1]]
    }
    if { $nclicks == 2 } {
      FSel_exit$nr $nr ok
    }
  }

  set widgetCode {
    catch "destroy $MountPath.top0"
    toplevel $MountPath.top0 -class FSel

    wm geometry $MountPath.top0 $geometry
    wm minsize $MountPath.top0 10 10
    wm title $MountPath.top0 "File Select Box"
    wm protocol $MountPath.top0 WM_DELETE_WINDOW \
      "set FSel_status$nr {Use \"Cancel\" or \"OK\" button to quit}"

    label $MountPath.top0.label0 -textvariable "FSel_title$nr"
    entry $MountPath.top0.status -state disabled -textvariable "FSel_status$nr"
    bind $MountPath.top0.status <B1-Motion> { }
    bind $MountPath.top0.status <Shift-1> { }
    bind $MountPath.top0.status <Shift-B1-Motion> { }

    frame $MountPath.top0.frame2  -relief {raised}
    label $MountPath.top0.frame2.label4 -text "Path: "
    entry $MountPath.top0.frame2.entry36 -exportselection 0 \
      -textvariable "FSel_path$nr"
    global Path_entry$nr
    set Path_entry$nr $MountPath.top0.frame2.entry36
    bind $MountPath.top0.frame2.entry36 <Return> "FSel_rescan$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8"
    bind $MountPath.top0.frame2.entry36 <KP_Enter> \
      [bind $MountPath.top0.frame2.entry36 <Return>]
    bind $MountPath.top0.frame2.entry36 <B1-Motion> { }
    bind $MountPath.top0.frame2.entry36 <Shift-1> { }
    bind $MountPath.top0.frame2.entry36 <Shift-B1-Motion> { }
    bind $MountPath.top0.frame2.entry36 <Control-d> { }
    bind $MountPath.top0.frame2.entry36 <Control-k> "%W delete insert end; \
      FSel_view_entry$nr %W"
    bind $MountPath.top0.frame2.entry36 <Tab> {
      if { [lindex [$MountPath.top0.frame12.frame38.f0 configure -relief] 4]
           == "sunken" } {
         $MountPath.top0.frame12.frame38.f0 configure -relief flat
         $MountPath.top0.frame12.frame38.f1 configure -relief sunken
      } else {
         $MountPath.top0.frame12.frame38.f0 configure -relief sunken
         $MountPath.top0.frame12.frame38.f1 configure -relief flat
      }
    }
    bind $MountPath.top0.frame2.entry36 <Control-c> {
      $MountPath.top0.frame12.frame38.f0.button39 flash
      $MountPath.top0.frame12.frame38.f0.button39 invoke
    }
    bind $MountPath.top0.frame2.entry36 <Left> "FSel_screntry$nr $nr left %W"
    bind $MountPath.top0.frame2.entry36 <Right> "FSel_screntry$nr $nr right %W"
    bind $MountPath.top0.frame2.entry36 <Up> \
      "focus $MountPath.top0.frame12.frame3.frame0.value; \
      FSel_curpos$nr $MountPath.top0.frame12.frame3.frame0.value"
    bind $MountPath.top0.frame2.entry36 <Down> \
      "focus $MountPath.top0.frame3.entry36; \
      FSel_curpos$nr $MountPath.top0.frame3.entry36"
    bind $MountPath.top0.frame2.entry36 <Shift-Left> "%W icursor 0; \
      FSel_view_entry$nr %W"
    bind $MountPath.top0.frame2.entry36 <Shift-Right> "%W icursor end; \
      FSel_view_entry$nr %W"
    bind $MountPath.top0.frame2.entry36 <Escape> { %W delete 0 end }
    pack append $MountPath.top0.frame2 \
      $MountPath.top0.frame2.label4 {left frame nw} \
      $MountPath.top0.frame2.entry36 {left frame nw expand fill}

    frame $MountPath.top0.frame3  -relief {raised}
    label $MountPath.top0.frame3.label4 -text "File: "
    entry $MountPath.top0.frame3.entry36 -exportselection 0 \
      -textvariable "FSel_file$nr"
    global File_entry$nr
    set File_entry$nr $MountPath.top0.frame3.entry36
    bind $MountPath.top0.frame3.entry36 <Return> {
      if { [lindex [$MountPath.top0.frame12.frame38.f0 configure -relief] 4]
           == "sunken" } {
        $MountPath.top0.frame12.frame38.f0.button39 flash
        $MountPath.top0.frame12.frame38.f0.button39 invoke
      } else {
        $MountPath.top0.frame12.frame38.f1.button44 flash
        $MountPath.top0.frame12.frame38.f1.button44 invoke
      }
    }
    bind $MountPath.top0.frame3.entry36 <KP_Enter> \
      [bind $MountPath.top0.frame3.entry36 <Return>]
    bind $MountPath.top0.frame3.entry36 <B1-Motion> { }
    bind $MountPath.top0.frame3.entry36 <Shift-1> { }
    bind $MountPath.top0.frame3.entry36 <Shift-B1-Motion> { }
    bind $MountPath.top0.frame3.entry36 <Control-d> { }
    bind $MountPath.top0.frame3.entry36 <Control-k> "%W delete insert end; \
      FSel_view_entry$nr %W"
    bind $MountPath.top0.frame3.entry36 <Tab> {
      if { [lindex [$MountPath.top0.frame12.frame38.f0 configure -relief] 4]
           == "sunken" } {
         $MountPath.top0.frame12.frame38.f0 configure -relief flat
         $MountPath.top0.frame12.frame38.f1 configure -relief sunken
      } else {
         $MountPath.top0.frame12.frame38.f0 configure -relief sunken
         $MountPath.top0.frame12.frame38.f1 configure -relief flat
      }
    }
    bind $MountPath.top0.frame3.entry36 <Control-c> {
      $MountPath.top0.frame12.frame38.f0.button39 flash
      $MountPath.top0.frame12.frame38.f0.button39 invoke
    }
    bind $MountPath.top0.frame3.entry36 <Left> "FSel_screntry$nr $nr left %W"
    bind $MountPath.top0.frame3.entry36 <Right> "FSel_screntry$nr $nr right %W"
    bind $MountPath.top0.frame3.entry36 <Up> \
      "focus $MountPath.top0.frame2.entry36; \
      FSel_curpos$nr $MountPath.top0.frame2.entry36"
    bind $MountPath.top0.frame3.entry36 <Down> \
      "focus $MountPath.top0.frame12.frame3.frame0.value; \
      FSel_curpos$nr $MountPath.top0.frame12.frame3.frame0.value"
    bind $MountPath.top0.frame3.entry36 <Shift-Left> "%W icursor 0; \
      FSel_view_entry$nr %W"
    bind $MountPath.top0.frame3.entry36 <Shift-Right> "%W icursor end; \
      FSel_view_entry$nr %W"
    bind $MountPath.top0.frame3.entry36 <Escape> { %W delete 0 end }
    pack append $MountPath.top0.frame3 \
      $MountPath.top0.frame3.label4 {left frame nw} \
      $MountPath.top0.frame3.entry36 {left frame nw expand fill}

    frame $MountPath.top0.frame12  -borderwidth {2}  -relief {raised}
    frame $MountPath.top0.frame12.frame1 -borderwidth {2} -relief {raised}
    frame $MountPath.top0.frame12.frame1.frame0  -borderwidth {2}
    frame $MountPath.top0.frame12.frame1.frame0.frame1
    frame $MountPath.top0.frame12.frame1.frame0.frame1.frame3 -borderwidth {2}

    listbox $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 \
      -xscrollcommand \
      {$MountPath.top0.frame12.frame1.frame0.frame2.frame5.scrollbar10 set} \
      -yscrollcommand \
      {$MountPath.top0.frame12.frame1.frame0.frame1.frame4.scrollbar9 set}
    global Path_listbox$nr
    set Path_listbox$nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8

    bind $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 \
      <B1-Motion> [list FSel_select$nr $nr {%W} {%y} 1]
    bind $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 \
      <Shift-B1-Motion> [list FSel_select$nr $nr {%W} {%y} 1]
    bind $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 \
      <Shift-Button-1> [list FSel_select$nr $nr {%W} {%y} 1]
    bind $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 \
      <1> [list FSel_select$nr $nr {%W} {%y} 1]
    bind $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 \
      <Double-1> [list FSel_select$nr $nr {%W} {%y} 2]

    pack append $MountPath.top0.frame12.frame1.frame0.frame1.frame3 \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 \
      {left frame center expand fill}

    frame $MountPath.top0.frame12.frame1.frame0.frame1.frame4  -borderwidth {2}
    scrollbar $MountPath.top0.frame12.frame1.frame0.frame1.frame4.scrollbar9 \
      -command \
      {$MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 yview} \
      -relief {sunken}  -width {13}

    pack append $MountPath.top0.frame12.frame1.frame0.frame1.frame4 \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame4.scrollbar9 \
      {top frame center expand filly}

    pack append $MountPath.top0.frame12.frame1.frame0.frame1 \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3 \
      {left frame center expand fill} \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame4 \
      {right frame center filly}

    frame $MountPath.top0.frame12.frame1.frame0.frame2  -borderwidth {1}
    frame $MountPath.top0.frame12.frame1.frame0.frame2.frame5  -borderwidth {2}
    scrollbar $MountPath.top0.frame12.frame1.frame0.frame2.frame5.scrollbar10 \
      -command \
      {$MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 xview} \
      -orient {horizontal}  -relief {sunken}  -width {13}

    pack append $MountPath.top0.frame12.frame1.frame0.frame2.frame5 \
      $MountPath.top0.frame12.frame1.frame0.frame2.frame5.scrollbar10 \
      {left frame center expand fillx}

    frame $MountPath.top0.frame12.frame1.frame0.frame2.frame6  -borderwidth {2}

    frame $MountPath.top0.frame12.frame1.frame0.frame2.frame6.frame11 \
      -borderwidth {2}  -height {13}  -width {16}

    pack append $MountPath.top0.frame12.frame1.frame0.frame2.frame6 \
      $MountPath.top0.frame12.frame1.frame0.frame2.frame6.frame11 \
      {top frame center expand fill}

    pack append $MountPath.top0.frame12.frame1.frame0.frame2 \
      $MountPath.top0.frame12.frame1.frame0.frame2.frame5 \
      {left frame center expand fill} \
      $MountPath.top0.frame12.frame1.frame0.frame2.frame6 \
      {right frame center filly}

    pack append $MountPath.top0.frame12.frame1.frame0 \
      $MountPath.top0.frame12.frame1.frame0.frame1 \
      {top frame center expand fill} \
      $MountPath.top0.frame12.frame1.frame0.frame2 \
      {bottom frame center fillx}

    pack append $MountPath.top0.frame12.frame1 \
      $MountPath.top0.frame12.frame1.frame0 {top frame center expand fill}

    frame $MountPath.top0.frame12.frame3 -border 0 -relief flat
    label $MountPath.top0.frame12.frame3.lb1 -text {Which files to show...} \
      -pady 5m -relief raised

    checkbutton $MountPath.top0.frame12.frame3.checkbutton8  -anchor {nw}  \
      -text {Show hidden files}  -variable "FSel_show_hidden$nr" \
      -command "FSel_rescan$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8"

    frame $MountPath.top0.frame12.frame3.frame0  -borderwidth {2} \
      -relief {raised}

    label $MountPath.top0.frame12.frame3.frame0.label1 -text "Pattern: "

    entry $MountPath.top0.frame12.frame3.frame0.value \
      -textvariable "FSel_pattern$nr"
    bind $MountPath.top0.frame12.frame3.frame0.value <B1-Motion> { }
    bind $MountPath.top0.frame12.frame3.frame0.value <Shift-1> { }
    bind $MountPath.top0.frame12.frame3.frame0.value <Shift-B1-Motion> { }
    bind $MountPath.top0.frame12.frame3.frame0.value <Return> \
      "FSel_rescan$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8"
    bind $MountPath.top0.frame12.frame3.frame0.value <KP_Enter> \
      [bind $MountPath.top0.frame12.frame3.frame0.value <Return>]
    bind $MountPath.top0.frame12.frame3.frame0.value <Control-d> { }
    bind $MountPath.top0.frame12.frame3.frame0.value <Control-k> \
      "%W delete insert end; FSel_view_entry$nr %W"
    bind $MountPath.top0.frame12.frame3.frame0.value <Tab> {
      if { [lindex [$MountPath.top0.frame12.frame38.f0 configure -relief] 4]
           == "sunken" } {
         $MountPath.top0.frame12.frame38.f0 configure -relief flat
         $MountPath.top0.frame12.frame38.f1 configure -relief sunken
      } else {
         $MountPath.top0.frame12.frame38.f0 configure -relief sunken
         $MountPath.top0.frame12.frame38.f1 configure -relief flat
      }
    }
    bind $MountPath.top0.frame12.frame3.frame0.value <Control-c> {
      $MountPath.top0.frame12.frame38.f0.button39 flash
      $MountPath.top0.frame12.frame38.f0.button39 invoke
    }
    bind $MountPath.top0.frame12.frame3.frame0.value <Left> \
      "FSel_screntry$nr $nr left %W"
    bind $MountPath.top0.frame12.frame3.frame0.value <Right> \
      "FSel_screntry$nr $nr right %W"
    bind $MountPath.top0.frame12.frame3.frame0.value <Up> \
      "focus $MountPath.top0.frame3.entry36; \
      FSel_curpos$nr $MountPath.top0.frame3.entry36"
    bind $MountPath.top0.frame12.frame3.frame0.value <Down> \
      "focus $MountPath.top0.frame2.entry36; \
      FSel_curpos$nr $MountPath.top0.frame2.entry36"
    bind $MountPath.top0.frame12.frame3.frame0.value <Shift-Left> \
      "%W icursor 0; FSel_view_entry$nr %W"
    bind $MountPath.top0.frame12.frame3.frame0.value <Shift-Right> \
      "%W icursor end; FSel_view_entry$nr %W"
    bind $MountPath.top0.frame12.frame3.frame0.value <Escape> { %W delete 0 end}

    menubutton $MountPath.top0.frame12.frame3.frame0.menubutton2  -menu \
      {$MountPath.top0.frame12.frame3.frame0.menubutton2.m}  -text {v}

    menu $MountPath.top0.frame12.frame3.frame0.menubutton2.m
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*} ; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*.c}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*.c}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*.h}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*.h}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*.cc}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*.cc}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*.hh}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*.hh}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*.o}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*.o}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*.a}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*.a}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*.tcl}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*.tcl}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*.t}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*.t}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*.bak}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*.bak}
    $MountPath.top0.frame12.frame3.frame0.menubutton2.m add command \
      -command "set FSel_pattern$nr {*~}; \
	       FSel_rescan$nr $nr [set [concat Path_listbox$nr]]" \
      -label {*~}

    pack append $MountPath.top0.frame12.frame3.frame0  \
      $MountPath.top0.frame12.frame3.frame0.label1 {left frame center fill} \
      $MountPath.top0.frame12.frame3.frame0.value \
      {left frame center expand fill} \
      $MountPath.top0.frame12.frame3.frame0.menubutton2 \
      {right frame center fill}

    checkbutton $MountPath.top0.frame12.frame3.checkbutton29  -anchor {nw} \
      -text {Read permission}  -variable "FSel_readperm$nr" \
      -command "FSel_rescan$nr $nr [set [concat Path_listbox$nr]]"
    checkbutton $MountPath.top0.frame12.frame3.checkbutton33  -anchor {nw} \
      -text {Write permission}  -variable "FSel_writeperm$nr" \
      -command "FSel_rescan$nr $nr [set [concat Path_listbox$nr]]"
    checkbutton $MountPath.top0.frame12.frame3.checkbutton34  -anchor {nw} \
      -text {Execute permission}  -variable "FSel_execperm$nr" \
      -command "FSel_rescan$nr $nr [set [concat Path_listbox$nr]]"

    button $MountPath.top0.frame12.frame3.button37 \
      -command "set FSel_show_hidden$nr 1; \
		set FSel_readperm$nr 0; \
		set FSel_writeperm$nr 0; \
		set FSel_execperm$nr 0; \
		set FSel_pattern$nr {*}; \
		FSel_rescan$nr $nr \
		$MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8" \
      -text {Show all files}

    label $MountPath.top0.frame12.frame3.lb2 -text {Sort files by...} \
      -pady 5m -relief raised
    radiobutton $MountPath.top0.frame12.frame3.rb1 -anchor nw \
      -text {name} -variable "FSel_sort$nr" -value {name} \
      -command "FSel_rescan$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8"
    radiobutton $MountPath.top0.frame12.frame3.rb2 -anchor nw \
      -text {date} -variable "FSel_sort$nr" -value {date} \
      -command "FSel_rescan$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8"
    radiobutton $MountPath.top0.frame12.frame3.rb3 -anchor nw \
      -text {size} -variable "FSel_sort$nr" -value {size} \
      -command "FSel_rescan$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8"
    radiobutton $MountPath.top0.frame12.frame3.rb4 -anchor nw \
      -text {extension} -variable "FSel_sort$nr" -value {ext} \
      -command "FSel_rescan$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8"

    pack append $MountPath.top0.frame12.frame3 \
      $MountPath.top0.frame12.frame3.lb1 {top frame center fillx} \
      $MountPath.top0.frame12.frame3.frame0 {top frame w fillx} \
      $MountPath.top0.frame12.frame3.button37 {top frame nw fillx} \
      $MountPath.top0.frame12.frame3.checkbutton8 {top frame w fillx} \
      $MountPath.top0.frame12.frame3.checkbutton29 {top frame center fillx} \
      $MountPath.top0.frame12.frame3.checkbutton33 {top frame center fillx} \
      $MountPath.top0.frame12.frame3.checkbutton34 {top frame center fillx} \
      $MountPath.top0.frame12.frame3.lb2 {top frame center fillx} \
      $MountPath.top0.frame12.frame3.rb1 {top frame center fillx} \
      $MountPath.top0.frame12.frame3.rb2 {top frame center fillx} \
      $MountPath.top0.frame12.frame3.rb3 {top frame center fillx} \
      $MountPath.top0.frame12.frame3.rb4 {top frame center fillx}

    frame $MountPath.top0.frame12.frame38  -border 2 -relief raised
    frame $MountPath.top0.frame12.frame38.f0 -border 1 -relief flat
    button $MountPath.top0.frame12.frame38.f0.button39  -text " Cancel " \
      -command "FSel_exit$nr $nr cancel" -relief raised -border 4

    frame $MountPath.top0.frame12.frame38.f1 -border 1 -relief sunken
    button $MountPath.top0.frame12.frame38.f1.button44  -text "   OK   " \
      -command "FSel_exit$nr $nr ok" -relief raised -border 4

    pack $MountPath.top0.frame12.frame38.f1.button44 \
      -in $MountPath.top0.frame12.frame38.f1 -expand 1 -fill x -padx 6 -pady 6

    pack $MountPath.top0.frame12.frame38.f0.button39 \
      -in $MountPath.top0.frame12.frame38.f0 -expand 1 -fill x -padx 6 -pady 6

    pack $MountPath.top0.frame12.frame38.f1 -in $MountPath.top0.frame12.frame38\
      -side right -fill x -padx 10 -pady 10
    pack $MountPath.top0.frame12.frame38.f0 -in $MountPath.top0.frame12.frame38\
      -side right -fill x -padx 10 -pady 10

    pack append $MountPath.top0.frame12 \
      $MountPath.top0.frame12.frame1 {left frame nw expand fillx filly} \
      $MountPath.top0.frame12.frame3 {top frame center expand fillx filly} \
      $MountPath.top0.frame12.frame38 {bottom frame sw fillx}

    frame $MountPath.top0.frame13  -relief {raised}
    button $MountPath.top0.frame13.button14  -text {cd ..} \
      -command "FSel_chdir$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 .."
    global Path_rescan$nr
    set Path_rescan$nr $MountPath.top0.frame13.button15
    button $MountPath.top0.frame13.button15  -text {Rescan} \
      -command "FSel_rescan$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8"
    global env
    button $MountPath.top0.frame13.button35  -text {  cd  } \
      -command "FSel_chdir$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 $env(HOME)"
    button $MountPath.top0.frame13.button36  -text {cd  /} \
      -command "FSel_chdir$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 /"
    button $MountPath.top0.frame13.button37  -text {cd .} \
      -command "upvar #0 FSel_origpath$nr origpath; FSel_chdir$nr $nr \
      $MountPath.top0.frame12.frame1.frame0.frame1.frame3.listbox8 $origpath"
    pack append $MountPath.top0.frame13 \
      $MountPath.top0.frame13.button14 {left frame w expand fillx} \
      $MountPath.top0.frame13.button15 {left frame w expand fillx} \
      $MountPath.top0.frame13.button35 {left frame w expand fillx} \
      $MountPath.top0.frame13.button36 {left frame w expand fillx} \
      $MountPath.top0.frame13.button37 {left frame w expand fillx}
  }
  set subst ""
  append subst \\ [string trim { $MountPath.top0 }]
  regsub -all $subst $widgetCode $MountPath widgetCode
  regsub -all {%ThisTopWidget} $widgetCode $MountPath widgetCode
  eval $widgetCode

  set geometryCode {
    pack append $MountPath.top0 \
      $MountPath.top0.label0 {top frame center fillx} \
      $MountPath.top0.status {top frame nw fillx} \
      $MountPath.top0.frame2 {top frame nw fillx} \
      $MountPath.top0.frame3 {top frame nw fillx} \
      $MountPath.top0.frame13 {top frame center fillx} \
      $MountPath.top0.frame12 {top frame center expand fillx filly}

    bind $MountPath.top0 <Return> {
      $MountPath.top0.frame12.frame38.frame43.button44 flash;
      $MountPath.top0.frame12.frame38.frame43.button44 invoke;
    }
    bind $MountPath.top0 <KP_Enter> [bind $MountPath.top0 <Return>]
    global FSel_top$nr
    set FSel_top$nr $MountPath.top0
  }
  set subst ""
  append subst \\ [string trim { $MountPath.top0 }]
  regsub -all $subst $geometryCode $MountPath geometryCode
  regsub -all {\$MountPath} $geometryCode [winfo parent $MountPath] geometryCode
  eval $geometryCode

  upvar #0 FSel_top$nr FSel_top
  upvar #0 File_entry$nr File_entry
  # binding visibility to raising isn't a good idea, since the drop down
  # menu for selecting the file extension becomes invisible ...
# bind $FSel_top <Visibility> "raise $FSel_top"
  tkwait visibility $FSel_top
  set old_focus [focus]
  grab $FSel_top
  focus $File_entry
  FSel_rescan$nr $nr [set [concat Path_listbox$nr]]
  [set [concat Path_entry$nr]] view 0

  global FSel_return$nr
  upvar #0 FSel_return$nr FSel_return
  tkwait variable FSel_return$nr

  focus $old_focus
  set fsel_return $FSel_return
  if { [info commands XFDestroy] != "" } {
    XFDestroy $FSel_top
  } else {
    destroy $FSel_top
  }
  unset FSel_geometry$nr
  unset FSel_top$nr
  unset FSel_title$nr
  unset FSel_status$nr
  unset FSel_path$nr
  unset FSel_file$nr
  unset FSel_pattern$nr
  unset FSel_readperm$nr
  unset FSel_writeperm$nr
  unset FSel_execperm$nr
  unset FSel_show_hidden$nr
  unset FSel_sort$nr
  unset FSel_return$nr
  unset FSel_cmderror$nr
  unset File_entry$nr
  unset Path_entry$nr
  unset Path_rescan$nr
  unset Path_listbox$nr
  catch {cd $origpath}
  unset FSel_origpath$nr
  foreach fselproc [info procs FSel_*$nr] {
    rename $fselproc {}
  }
  return $fsel_return
}

if { [info script] == "" } {
  wm withdraw .
  puts [FileSelectBox $argv]
  exit 0
}
